src/Auth/Roles.php000064400000010556150732302400010034 0ustar00role_objects; $names = wp_roles()->role_names; return array_map(function($role, $name) { /** @var $role \WP_Role */ return [ 'name' => $role->name, 'capabilities' => $role->capabilities, 'label' => $name ]; }, $objects, $names); } /** * @return array */ public function capabilities() { $roles = wp_roles()->role_objects; $capabilities = []; foreach ($roles as $role) { foreach ($role->capabilities as $cap => $value) { $capabilities[$cap][] = $role->name; } } return $capabilities; } /** * @return array[] */ public function getEditableRoles() { return get_editable_roles(); } /** * @param string $role * @param array $capabilities * @param null|string $label * * @return $this */ public function add($role, array $capabilities, $label = null) { wp_roles()->add_role($role, $label ?? Str::makeWords($role, true), $capabilities); return $this; } /** * @param string $role * * @return $this * @throws \Exception */ public function remove($role) { if(in_array($role, $this->guardRoles)) { throw new \Exception('Can not delete guarded role: ' . $role); } wp_roles()->remove_role($role); return $this; } /** * @param $role * * @return bool */ public function exists($role) { return wp_roles()->is_role($role); } /** * @param $role * * @return \WP_Role|null */ public function get($role) { return wp_roles()->get_role($role); } /** * @param string $role * @param array $capabilities * @param bool $remove * * @return \WP_Role|null */ public function updateRolesCapabilities($role, array $capabilities, $remove = false) { $role = wp_roles()->get_role($role); if($role instanceof \WP_Role) { foreach ($capabilities as $capability) { if($remove) { $role->remove_cap($capability); } else { $role->add_cap($capability); } } } return $role; } /** * Get Post Type Capabilities * * @param string $singular * @param string $plural * * @return array */ public function getCustomPostTypeCapabilities($singular = 'post', $plural = 'posts') { return [ 'edit_post' => "edit_$singular", 'read_post' => "read_$singular", 'delete_post' => "delete_$singular", 'edit_posts' => "edit_$plural", 'edit_others_posts' => "edit_others_$plural", 'publish_posts' => "publish_$plural", 'read_private_posts' => "read_private_$plural", 'read' => "read", 'delete_posts' => "delete_$plural", 'delete_private_posts' => "delete_private_$plural", 'delete_published_posts' => "delete_published_$plural", 'delete_others_posts' => "delete_others_$plural", 'edit_private_posts' => "edit_private_$plural", 'edit_published_posts' => "edit_published_$plural", 'create_posts' => "create_$plural", ]; } /** * @param string $singular * @param string $plural * * @return string[] */ public function getTaxonomyCapabilities($singular = 'term', $plural = 'terms') { return [ 'manage_terms' => 'manage_' . $plural, 'edit_terms' => 'edit_' . $plural, 'delete_terms' => 'delete_' . $plural, 'assign_terms' => 'assign_' . $plural, ]; } /** * @param mixed ...$args * * @return static */ public static function new(...$args) { return new static(...$args); } }src/Auth/Policy.php000064400000000314150732302400010176 0ustar00user = $user; } }src/Html/Html.php000064400000024465150732302400007663 0ustar00getString(); } /** * Get string of tag * * @return string */ protected function getString(): string { return $this->tag->getString(); } /** * Create new Tag * * @param string $tag * @param array|string|null $attributes * @param string|array|null $text * * @return $this */ protected function el($tag, $attributes = null, $text = null ) { $this->tag = new Tag( $tag, $attributes, $text ); return $this; } /** * Create Form * * * @param $action * @param string $method * @param array|string $attributes * @param null|string $text * * @return $this */ protected function form($action, $method = 'GET', $attributes = null, $text = null) { if(is_string($attributes) || is_numeric($attributes)) { $text = $text ?? $attributes; $attributes = []; } $attributes = $attributes ?? []; $attributes = array_merge( ['action' => $action, 'method' => $method], $attributes ); $this->tag = new Tag( 'form', $attributes, $text ); return $this; } /** * Create new link * * @param string|array $text * @param string $url * @param array $attributes * * @return $this */ protected function a($text = '', $url = '#', array $attributes = []) { $attributes = array_merge( array_filter(['href' => $url], '\TypeRocket\Utility\Str::notBlank'), $attributes ); $this->tag = new Tag( 'a', $attributes, $text ); return $this; } /** * Create new image * * @param string $src * @param array $attributes * * @return $this */ protected function img($src = '', array $attributes = []) { $attributes = array_merge( ['src' => $src], $attributes ); $this->tag = new Tag( 'img', $attributes ); return $this; } /** * Create new input * * @param string $type * @param string $name * @param string $value * @param array $attributes * * @return $this */ protected function input($type, $name, $value, array $attributes = []) { $defaults = array_filter(['type' => $type, 'name' => $name, 'value' => $value], '\TypeRocket\Utility\Str::notBlank'); $this->tag = new Tag( 'input', array_merge( $defaults, $attributes ) ); return $this; } /** * Append inside of tag * * @param string|Tag|Html|array $tag * * @return $this */ protected function nest($tag) { $this->tag->nest( $tag ); return $this; } /** * Prepend Inside of tag * * @param string|Tag|Html $tag * * @return $this */ protected function nestAtTop($tag) { $this->tag->nestAtTop( $tag ); return $this; } /** * Tag * * @return Tag */ protected function tag() { return $this->tag; } /** * @param $name * @param $arguments * @return Html|string */ public function __call($name, $arguments) { if(method_exists($this, $name)) { return $this->{$name}(...$arguments); } return $this->el($name, ...$arguments); } /** * @param $name * @param $arguments * @return Html */ public static function __callStatic($name, $arguments) { return (new static)->{$name}(...$arguments); } } src/Html/Tag.php000064400000006675150732302400007475 0ustar00tag = $tag; $this->attrReset( $attributes ); $this->nest($nest); if( in_array($this->tag, ['img', 'br', 'hr', 'input']) ) { $this->closed = true; } return $this; } /** * @return string */ public function __toString(): string { return $this->getString(); } /** * Get string * * @return string */ public function getString(): string { return $this->open().$this->inner().$this->close(); } /** * Create Tag * * @param string $tag * @param array|string|null $attributes * @param string|array|null $nest * * @return $this */ public static function el($tag, $attributes = null, $nest = null ) { return new static( $tag, $attributes, $nest ); } /** * Append Inner Tag * * @param string|Tag|Html|array $tag * * @return $this */ public function nest($tag) { if(is_array($tag)) { foreach ($tag as $t) { array_push($this->nest, $t); } } else { array_push($this->nest, $tag); } return $this; } /** * Prepend inner tag * * @param Tag|Html|string|array $tag * * @return $this */ public function nestAtTop( $tag ) { if(is_array($tag)) { foreach ($tag as $t) { array_unshift($this->nest, $t); } } else { array_unshift($this->nest, $tag); } return $this; } /** * Get the opening tag in string form * * @return string */ public function open() { $openTag = "<{$this->tag}"; foreach($this->attr as $attribute => $value) { $value = esc_attr($value); $value = $value !== '' ? "=\"{$value}\"" : ''; $openTag .= " {$attribute}{$value}"; } $openTag .= $this->closed ? " />" : ">"; return $openTag; } /** * Get the closing tag as string * * @return string */ public function close() { return $this->closed ? '' : "tag}>"; } /** * Get the string with inner HTML * * @return string */ public function inner() { $html = ''; if( ! $this->closed ) { foreach($this->nest as $tag) { $html .= (string) $tag; } } return $html; } /** * @param string $tag * @param null|array $attributes * @param string|Tag|Html|array $nest * * @return static */ public static function new(string $tag, $attributes = null, $nest = null) { return new static(...func_get_args()); } } src/Html/Element.php000064400000002314150732302400010335 0ustar00 'tr-headline'], $attributes)); $tag->nest([ $icon ? "{$icon}" : null, "" . esc_html($title) . '' ]); return $tag; } /** * Accessible Close Button * * @param array $attributes * @param string $text close button symbol * * @return Tag */ public static function controlButton(array $attributes = [], $text = '×') { $static = ['type' => 'button']; $tag = new Tag( 'button', array_merge(['aria-label' => __('Close', 'typerocket-domain')], $attributes, $static) ); $tag->nest("{$text}"); return $tag; } }src/Register/Registrable.php000064400000015522150732302400012074 0ustar00id = Sanitize::underscore($id); $this->isReservedId(); return $this; } /** * @return int */ public function getMaxIdLength() { return $this->maxIdLength; } /** * Get the ID * * @return string */ public function getId() { return $this->id; } /** * Set Arguments * * @param array $args * * @return $this */ public function setArguments(array $args) { $this->args = $args; return $this; } /** * Get Arguments * * @return array */ public function getArguments() { return $this->args; } /** * Get Argument by key * * @param string $key * * @return string|array */ public function getArgument($key) { if ( ! array_key_exists($key, $this->args)) { return null; } return $this->args[$key]; } /** * Set Argument by key * * @param string $key * @param string|array $value * * @return $this */ public function setArgument($key, $value) { $this->args[$key] = $value; return $this; } /** * Remove Argument by key * * @param string $key * * @return $this */ public function removeArgument($key) { if (array_key_exists($key, $this->args)) { unset($this->args[$key]); } return $this; } /** * Check If Reserved */ protected function isReservedId() { if (in_array($this->id, $this->reservedNames)) { $exception = sprintf(__('You can not register a post type or taxonomy using the WordPress reserved name "%s".', 'typerocket-domain'), $this->id); Notice::admin(['type' => 'error', 'message' => $exception]); $this->blocked = true; return true; } return false; } /** * @return bool */ public function isBlocked() { return $this->blocked; } /** * Use other Registrable objects or string IDs * * @param array|MetaBox|PostType|Taxonomy|Page $args variadic * * @return $this * @throws \Exception */ public function apply($args) { if ( ! is_array($args)) { $args = func_get_args(); } if ( ! empty($args) && is_array($args)) { $this->use = array_merge($this->use, $args); } $this->uses(); return $this; } /** * Add Registrable to the registry * * @return $this */ public function addToRegistry() { if(!$this->blocked) { Registry::addRegistrable($this); } return $this; } /** * @param mixed ...$args * * @return static */ public static function add(...$args) { return (new static(...$args))->addToRegistry(); } /** * Register with WordPress * * Override this in concrete classes * * @return $this */ abstract public function register(); /** * Used with the apply method to connect Registrable objects together. * @throws \Exception */ protected function uses() { foreach ($this->use as $obj) { if ($obj instanceof Registrable) { $class = get_class($obj); $class = substr(strrchr($class, "\\"), 1); $method = 'add' . $class; if (method_exists($this, $method)) { $this->$method($obj); } else { $current_class = get_class($this); throw new \Exception('TypeRocket: You are passing the unsupported object ' . $class . ' into ' . $current_class . '.'); } } } } /** * @param string $id the registered ID * * @return Registrable|PostType|Page|Taxonomy|MetaBox * @throws \Exception */ public function getAppliedById($id) { foreach ($this->use as $obj) { if ($obj instanceof Registrable) { if($obj->getId() === $id) { return $obj; } } } throw new \Exception('TypeRocket: Registrable object of ID ' . $id . ' not found.'); } /** * Get the Use * * @return array */ public function getApplied() { return $this->use; } /** * @param mixed ...$args * * @return static */ public static function new(...$args) { return new static(...$args); } } src/Register/Taxonomy.php000064400000032403150732302400011444 0ustar00applyQuickLabels($labelSingular, $labelPlural, $keep_case); } $existing = get_taxonomy( $id ); if ($existing) { $this->existing = $existing; $singular = Sanitize::underscore( $singular ); $plural = Sanitize::underscore( $plural ); $this->id = $this->existing->name; $args = (array) $this->existing; $this->resource = Registry::getTaxonomyResource($this->id) ?? [ 'singular' => $singular, 'plural' => $plural, 'model' => null, 'controller' => null ]; $this->postTypes = $this->existing->object_type; $this->args = array_merge($args, $this->args, $settings); return $this; } // setup object for later use $plural = Sanitize::underscore( $plural ); $singular = Sanitize::underscore( $singular ); // obj is set on registration $this->resource = [ 'singular' => $singular, 'plural' => $plural, 'model' => null, 'controller' => null ]; $this->setId($this->id ?: ($id ?? $singular)); if (array_key_exists( 'capabilities', $settings ) && $settings['capabilities'] === true) : $settings['capabilities'] = (new Roles)->getTaxonomyCapabilities($singular, $plural); endif; $defaults = [ 'show_admin_column' => false, 'rewrite' => ['slug' => Sanitize::dash( $plural )], ]; $this->args = array_merge( $this->args, $defaults, $settings ); if(class_exists( $model = \TypeRocket\Utility\Helper::modelClass($singular, false) ) ) { $this->setModelClass($model); } return $this; } /** * Set Model Class * * @param string $modelClass * * @return $this */ public function setModelClass(string $modelClass) { $this->modelClass = $modelClass; // Default resource model is not the same as the modelClass $this->resource['model'] = $this->modelClass; return $this; } /** * Get Model Class * * @return string */ public function getModelClass() { return $this->modelClass; } /** * Use Custom Capabilities * * @return Taxonomy $this */ public function customCapabilities() { $cap = (new Roles)->getTaxonomyCapabilities($this->resource['singular'], $this->resource['plural']); return $this->setArgument('capabilities', $cap); } /** * Apply Quick Labels * * @param string $singular * @param string $plural * @param bool $keep_case * @return Taxonomy $this */ public function applyQuickLabels($singular, $plural = null, $keep_case = false) { if(!$plural) { $plural = Inflect::pluralize($singular); } // make lowercase $upperPlural = $keep_case ? $plural : Str::uppercaseWords( $plural ); $upperSingular = $keep_case ? $singular : Str::uppercaseWords( $singular ); $lowerPlural = $keep_case ? $plural : mb_strtolower( $plural ); $context = 'taxonomy:' . $this->getId(); $labels = [ 'add_new_item' => sprintf( _x( 'Add New %s', $context, 'typerocket-core' ), $upperSingular), 'add_or_remove_items' => sprintf( _x( 'Add or remove %s', $context, 'typerocket-core' ), $lowerPlural), 'all_items' => sprintf( _x( 'All %s', $context, 'typerocket-core' ), $upperPlural), 'back_to_items' => sprintf( _x( '← Back to %s', $context, 'typerocket-core' ), $lowerPlural), 'choose_from_most_used' => sprintf( _x( 'Choose from the most used %s', $context, 'typerocket-core' ), $lowerPlural), 'edit_item' => sprintf( _x( 'Edit %s', $context, 'typerocket-core' ), $upperSingular), 'name' => sprintf( _x( '%s', $context . ':taxonomy general name', 'typerocket-core' ), $upperPlural), 'menu_name' => sprintf( _x( '%s', $context . ':admin menu', 'typerocket-core' ), $upperPlural), 'new_item_name' => sprintf( _x( 'New %s Name', $context, 'typerocket-core' ), $upperSingular), 'no_terms' => sprintf( _x( 'No %s', $context, 'typerocket-core' ), $lowerPlural), 'not_found' => sprintf( _x( 'No %s found.', $context, 'typerocket-core' ), $lowerPlural), 'parent_item' => sprintf( _x( 'Parent %s', $context, 'typerocket-core' ), $upperSingular), 'parent_item_colon' => sprintf( _x( 'Parent %s:', $context, 'typerocket-core' ), $upperSingular), 'popular_items' => sprintf( _x( 'Popular %s', $context, 'typerocket-core' ), $upperPlural), 'search_items' => sprintf( _x( 'Search %s', $context, 'typerocket-core' ), $upperPlural), 'separate_items_with_commas' => sprintf( _x( 'Separate %s with commas', $context, 'typerocket-core' ), $lowerPlural), 'singular_name' => sprintf( _x( '%s', $context . ':taxonomy singular name', 'typerocket-core' ), $upperSingular), 'update_item' => sprintf( _x( 'Update %s', $context, 'typerocket-core' ), $upperSingular), 'view_item' => sprintf( _x( 'View %s', $context, 'typerocket-core' ), $upperSingular), ]; return $this->setLabels($labels, $upperPlural, false);; } /** * Set Labels * * @param array $labels * @param string $plural * @param bool $merge * * @return Taxonomy $this */ public function setLabels(array $labels, $plural = null, $merge = true) { $this->args['labels'] = $merge ? array_merge($this->args['labels'] ?? [], $labels) : $labels; $this->args['label'] = $plural ?? $this->args['label']; return $this; } /** * Set Hierarchical * * @param bool $bool * * @return Taxonomy $this */ public function setHierarchical($bool = true) { return $this->setArgument('hierarchical', $bool); } /** * Get Existing Post Type * * @return \WP_Taxonomy|null */ public function getExisting() { return $this->existing; } /** * Set the rewrite slug for the post type * * @param string $slug * @param null|bool $withFront * * @return Taxonomy $this */ public function setSlug( $slug, $withFront = null ) { if(!is_array($this->args['rewrite'])) { $this->args['rewrite'] = []; } $this->args['rewrite']['slug'] = Sanitize::dash( $slug ); if(isset($withFront)) { $this->args['rewrite']['with_front'] = $withFront; } return $this; } /** * Disable Slug With Front * * @return $this */ public function disableSlugWithFront() { $this->args['rewrite']['with_front'] = false; return $this; } /** * Enable Hierarchical Rewrite * * @return $this */ public function enableHierarchicalSlug() { $this->args['rewrite']['hierarchical'] = true; return $this; } /** * Set the resource * * @param array $resource * * @return Taxonomy $this */ public function setResource( array $resource ) { $this->resource = $resource; return $this; } /** * Get the form hook value by key * * @return mixed */ public function getMainForm() { return $this->form['main'] ?? null; } /** * Set the form main hook * * From hook to be added just above the title field * * @param bool|true|callable $value * * @return Taxonomy $this */ public function setMainForm( $value = true ) { if (is_callable( $value )) { $this->form['main'] = $value; } else { $this->form['main'] = true; } return $this; } /** * Get the slug * * @return mixed */ public function getSlug() { return $this->args['rewrite']['slug']; } /** * Show Quick Edit * * @param bool $bool * * Whether to show the taxonomy in the quick/bulk edit panel. * * @return Taxonomy */ public function showQuickEdit($bool = true) { return $this->setArgument('show_in_quick_edit', $bool); } /** * Show Post Type Admin Column * * Whether to allow automatic creation of taxonomy columns on associated post-types table. * * @param bool $bool * * @return Taxonomy */ public function showPostTypeAdminColumn($bool = true) { return $this->setArgument('show_admin_column', $bool); } /** * @param bool|string $rest_base the REST API base path * @param null|string $controller the REST controller default is \WP_REST_Terms_Controller::class * * @return Taxonomy $this */ public function setRest( $rest_base = false, $controller = null ) { $this->args['rest_base'] = $rest_base ? $rest_base : $this->id; $this->args['show_in_rest'] = true; $controller ? $this->args['rest_controller_class'] = $controller : null; return $this; } /** * Set the taxonomy to only show in WordPress Admin * * @return Taxonomy $this */ public function setAdminOnly() { $this->args['public'] = false; $this->args['show_ui'] = true; $this->args['show_in_nav_menus'] = true; return $this; } /** * Hide Frontend * * @param bool $bool * * @return $this */ public function hideFrontend($bool = true) { $this->args['publicly_queryable'] = !$bool; return $this; } /** * Hide Admin * * @return Taxonomy $this */ public function hideAdmin() { $this->args['show_ui'] = false; $this->args['show_in_menu'] = false; $this->args['show_in_nav_menus'] = false; return $this; } /** * Register the taxonomy with WordPress * * @return Taxonomy $this */ public function register() { if(!$this->existing) { if($this->isReservedId()) { return $this; } } do_action('typerocket_register_taxonomy_' . $this->id, $this ); register_taxonomy( $this->id, $this->postTypes, $this->args ); $this->resource['object'] = $this; Registry::addTaxonomyResource($this->id, $this->resource); $this->attachHooks(); return $this; } /** * Apply post types * * @param string|PostType|array $s * * @return Taxonomy $this */ public function addPostType( $s ) { if ($s instanceof PostType) { $s = $s->getId(); } elseif (is_array( $s )) { foreach ($s as $n) { $this->addPostType( $n ); } } if ( is_string($s) && ! in_array( $s, $this->postTypes )) { $this->postTypes[] = $s; } return $this; } /** * Attach Hooks */ public function attachHooks() { if(!$this->hooksAttached) { Registry::taxonomyHooks($this); $this->hooksAttached = true; } } } src/Register/Registry.php000064400000053435150732302400011446 0ustar00 ['singular' => 'post', 'plural' => 'posts', 'controller' => null, 'object' => null, 'model' => null], 'page' => ['singular' => 'page', 'plural' => 'pages', 'controller' => null, 'object' => null, 'model' => null], ]; public static $taxonomies = [ 'category' => ['singular' => 'category', 'plural' => 'categories', 'controller' => null, 'object' => null, 'model' => null], 'post_tag' => ['singular' => 'tag', 'plural' => 'tags', 'controller' => null, 'object' => null, 'model' => null] ]; public static $customs = []; /** * Add a post type resource * * @param string $id post type id * @param array $resource resource name ex. posts, pages, books */ public static function addPostTypeResource($id, $resource = []) { self::$postTypes[$id] = array_pad($resource, 5, null); } /** * Get the post type resource * * @param string $id * * @return null */ public static function getPostTypeResource($id) { return ! empty(self::$postTypes[$id]) ? self::$postTypes[$id] : null; } /** * Get the taxonomy resource * * @param string $id * * @return null */ public static function getTaxonomyResource($id) { return ! empty(self::$taxonomies[$id]) ? self::$taxonomies[$id] : null; } /** * Add a taxonomy resource * * @param string $id post type id * @param array $resource resource name ex. posts, pages, books */ public static function addTaxonomyResource($id, $resource = []) { self::$taxonomies[$id] = array_pad($resource, 5, null); } /** * Add a custom resource * * @param string $id custom resource id * @param array $resource resource name ex. posts, pages, books */ public static function addCustomResource($id, $resource = []) { self::$customs[$id] = array_pad($resource, 3, null); } /** * Get the custom resource * * @param string $id * * @return null */ public static function getCustomResource($id) { return self::$customs[$id] ?? null; } /** * Add Registrable objects to collection * * @param null|Registrable|string $obj */ public static function addRegistrable( $obj = null ) { if ( $obj instanceof Registrable) { self::$collection[] = $obj; } } /** * Loop through each Registrable and add hooks automatically */ public static function initHooks() { $collection = []; $later = []; if(empty(self::$collection)) { return; } foreach(self::$collection as $obj) { if ( $obj instanceof Registrable) { $collection[] = $obj; $use = $obj->getApplied(); foreach($use as $objUsed) { if( ! in_array($objUsed, $collection) && ! $objUsed instanceof Page) { $later[] = $obj; array_pop($collection); break 1; } } if ($obj instanceof Page && ! empty( $obj->getParent() ) ) { $later[] = $obj; array_pop($collection); } } } $collection = array_merge($collection, $later); foreach ($collection as $obj) { if ($obj instanceof Taxonomy) { add_action( 'init', [$obj, 'register']); } elseif ($obj instanceof PostType) { /** @var PostType $obj */ add_action( 'init', [$obj, 'register']); } elseif ($obj instanceof MetaBox) { add_action( 'admin_init', [$obj, 'register']); add_action( 'add_meta_boxes', [$obj, 'register']); } elseif ($obj instanceof Page) { if($obj->getHandler()) { add_action( 'admin_init', [$obj, 'respond']); } add_action( 'admin_menu', [$obj, 'register']); } } add_action( 'init', function() { self::setAggregatePostTypeHooks(); }, 12); } /** * Taxonomy Hooks * * @param Taxonomy $obj */ public static function taxonomyHooks(Taxonomy $obj) { self::taxonomyFormContent($obj); if($custom_templates = $obj->getTemplates()) { foreach(['taxonomy', 'category', 'tag'] as $template_hook) { add_filter($template_hook . '_template', Closure::bind(function($template) use ($custom_templates) { /** @var WP_Term $term */ $term = get_queried_object(); if($term->taxonomy == $this->getId()) { $template = $custom_templates['archive']; } return $template; }, $obj), 0, 1); } } } /** * Post Type Hooks * * @param PostType $obj */ public static function postTypeHooks(PostType $obj) { if (is_string( $obj->getTitlePlaceholder() )) { add_filter( 'enter_title_here', function($title) use ($obj) { global $post; if(!empty($post)) { if ( $post->post_type == $obj->getId() ) { return $obj->getTitlePlaceholder(); } } return $title; } ); } if( !empty($obj->getArchiveQuery()) ) { add_action('pre_get_posts', Closure::bind(function( WP_Query $main_query ) { /** * @var PostType $this */ if(!$main_query->is_main_query() || $main_query->is_admin) { return; } $isTax = false; $id = $this->getId(); if($this->getArchiveQueryWithTaxonomies() && !empty($main_query->tax_query->queries)) { $taxonomyList = get_object_taxonomies($id); foreach($taxonomyList as $taxonomy){ if($taxonomy == 'category' && $main_query->is_category()) { $isTax = true; break; } elseif($taxonomy == 'post_tag' && $main_query->is_tag()) { $isTax = true; break; } elseif($main_query->is_tax($taxonomy)){ $isTax = true; break; } } } if($main_query->is_post_type_archive($id) || $isTax) { $query = $this->getArchiveQuery(); foreach ($query as $key => $value) { $main_query->set($key, $value); } } }, $obj)); } if($custom_templates = $obj->getTemplates()) { foreach(['single', 'archive', 'page'] as $template_hook) { if(!empty($custom_templates[$template_hook])) { add_filter($template_hook . '_template', Closure::bind(function($template, $type) use ($custom_templates) { /** @var WP_Post $post */ global $post; if($post->post_type == $this->getId()) { $template = $custom_templates[$type]; } return $template; }, $obj), 0, 2); } } } if(!empty($obj->getSaves())) { add_action('save_post', function ($id, $post) use ($obj) { if( $post->post_type != $obj->getId() || wp_is_post_revision($id) || $post->post_status == 'auto-draft' || $post->post_status == 'trash' ) { return; } global $wpdb; $saves = $obj->getSaves(); $class = $obj->getModelClass(); $model = (new $class)->wpPost($post, true)->load('meta'); $fields = []; foreach ($saves as $field => $fn) { $value = $fn($model); $value = sanitize_post_field($field, $value, $id, 'db' ); $fields[$field] = $value; } $wpdb->update( $wpdb->posts, $fields, ['ID' => $id]); }, 11, 2); } if(!is_null($obj->getRevisions())) { add_filter( 'wp_revisions_to_keep', function($num, $post) use ($obj) { if ( $post->post_type == $obj->getId() ) { return $obj->getRevisions(); } return $num; }, 10, 2 ); } if($obj->getRootSlug()) { self::$aggregateCollection['post_type']['root_slug'][] = $obj->getId(); } if($obj->getForceDisableGutenberg()) { self::$aggregateCollection['post_type']['use_gutenberg'][] = $obj->getId(); } self::setPostTypeColumns($obj); self::postTypeFormContent($obj); } /** * Add taxonomy form hooks * * @param Taxonomy $obj */ public static function taxonomyFormContent( Taxonomy $obj ) { $callback = function( $term, $obj ) { /** @var Taxonomy $obj */ if ( $term == $obj->getId() || $term->taxonomy == $obj->getId() ) { $func = 'add_form_content_' . $obj->getId() . '_taxonomy'; $form = $obj->getMainForm(); if (is_callable( $form )) { call_user_func( $form, $term ); } elseif (function_exists( $func )) { call_user_func( $func, $term ); } elseif ( Config::get('app.debug') ) { echo "
Add content here by defining: function {$func}() {}
"; } } }; if ($obj->getMainForm()) { add_action( $obj->getId() . '_edit_form', function($term) use ($obj, $callback) { echo BaseForm::nonceInput('hook'); echo '
'; call_user_func_array($callback, [$term, $obj]); echo '
'; }, 10, 2 ); add_action( $obj->getId() . '_add_form_fields', function($term) use ($obj, $callback) { echo BaseForm::nonceInput('hook'); echo '
'; call_user_func_array($callback, [$term, $obj]); echo '
'; }, 10, 2 ); } } /** * Add post type form hooks * * @param PostType $obj */ public static function postTypeFormContent( PostType $obj) { /** * @param WP_Post $post * @param string $type * @param PostType $obj */ $callback = function( $post, $type, $obj ) { if ($post->post_type == $obj->getId()) { $func = 'add_form_content_' . $obj->getId() . '_' . $type; echo '
'; echo BaseForm::nonceInput('hook'); $form = $obj->getForm( $type ); if (is_callable( $form )) { call_user_func( $form ); } elseif (function_exists( $func )) { call_user_func( $func, $post ); } elseif (Config::get('app.debug')) { echo "
Add content here by defining: function {$func}() {}
"; } echo '
'; } }; // edit_form_top if ($obj->getForm( 'top' )) { add_action( 'edit_form_top', function($post) use ($obj, $callback) { $type = 'top'; call_user_func_array($callback, [$post, $type, $obj]); } ); } // edit_form_after_title if ($obj->getForm( 'title' )) { add_action( 'edit_form_after_title', function($post) use ($obj, $callback) { $type = 'title'; call_user_func_array($callback, [$post, $type, $obj]); } ); } // edit_form_after_editor if ($obj->getForm( 'editor' )) { add_action( 'edit_form_after_editor', function($post) use ($obj, $callback) { $type = 'editor'; call_user_func_array($callback, [$post, $type, $obj]); } ); } // dbx_post_sidebar if ($obj->getForm( 'bottom' )) { add_action( 'dbx_post_sidebar', function($post) use ($obj, $callback) { $type = 'bottom'; call_user_func_array($callback, [$post, $type, $obj]); } ); } } /** * Add post type admin table columns hooks * * @param PostType $post_type */ public static function setPostTypeColumns( PostType $post_type) { $pt = $post_type->getId(); $new_columns = $post_type->getColumns(); $primary_column = $post_type->getPrimaryColumn(); $model = $post_type->getModelClass(); add_filter( "manage_edit-{$pt}_columns" , function($columns) use ($new_columns) { foreach ($new_columns as $key => $new_column) { if($new_column == false && array_key_exists($key, $columns)) { unset($columns[$key]); } else { $columns[$new_column['field']] = $new_column['label']; } } return $columns; }); add_action( "manage_{$pt}_posts_custom_column" , function($column, $post_id) use ($new_columns, $model) { $post = get_post($post_id); /** @var WPPost $post_temp */ $post_temp = (new $model)->wpPost($post, true)->load('meta'); foreach ($new_columns as $new_column) { if(!empty($new_column['field']) && $column == $new_column['field']) { $data = [ 'column' => $column, 'field' => $new_column['field'], 'post' => $post, 'post_id' => $post_id, 'model' => $post_temp ]; $value = $post_temp ->setProperty($post_temp->getIdColumn(), $post_id) ->getFieldValue($new_column['field']); if($result = call_user_func_array($new_column['callback'], [$value, $data])) { echo $result; } } } }, 10, 2); if( $primary_column ) { add_filter( 'list_table_primary_column', function ( $default, $screen ) use ( $pt, $primary_column ) { if ( $screen === 'edit-' . $pt ){ $default = $primary_column; } return $default; }, 10, 2 ); } foreach ($new_columns as $new_column) { // Only meta fields can be sortable if(!empty($new_column['sort']) && !Str::contains('.', $new_column['field'])) { add_filter( "manage_edit-{$pt}_sortable_columns", function($columns) use ($new_column) { $columns[$new_column['field']] = $new_column['field']; return $columns; } ); add_action( 'load-edit.php', function() use ($pt, $new_column) { add_filter( 'request', function( $vars ) use ($pt, $new_column) { if ( isset( $vars['post_type'] ) && $pt == $vars['post_type'] ) { if ( isset( $vars['orderby'] ) && $new_column['field'] == $vars['orderby'] ) { if( ! in_array($new_column['field'], (new WPPost())->getBuiltinFields())) { if( is_string($new_column['order_by']) ) { switch($new_column['order_by']) { case 'number': case 'num': case 'int': $new_vars['orderby'] = 'meta_value_num'; break; case 'decimal': case 'double': $new_vars['orderby'] = 'meta_value_decimal'; break; case 'date': $new_vars['orderby'] = 'meta_value_date'; break; case 'datetime': $new_vars['orderby'] = 'meta_value_datetime'; break; case 'time': $new_vars['orderby'] = 'meta_value_time'; break; case 'string': case 'str': break; default: $new_vars['orderby'] = $new_column['order_by']; break; } } $new_vars['meta_key'] = $new_column['field']; } else { $new_vars = [ 'orderby' => $new_column['field'] ]; } $vars = array_merge( $vars, $new_vars ); } } return $vars; }); } ); } } } /** * Run aggregate */ public static function setAggregatePostTypeHooks() { global $wp_rewrite; /** * Post Type Hooks */ $use_gutenberg = self::$aggregateCollection['post_type']['use_gutenberg'] ?? null; if($use_gutenberg) { add_filter('use_block_editor_for_post_type', function ($current_status, $post_type) use ($use_gutenberg) { if (in_array($post_type, $use_gutenberg)) return false; return $current_status; }, 10, 2); } $root_slugs = self::$aggregateCollection['post_type']['root_slug'] ?? null; if($root_slugs) { add_filter( 'post_type_link', function ( $post_link, $post ) use ($root_slugs) { if ( in_array($post->post_type, $root_slugs) ) { $post_link = str_replace( '?' . $post->post_type . '=', '', $post_link ); } return $post_link; }, 10, 2 ); add_action( 'pre_get_posts', function ( $query ) use ($root_slugs) { global $wpdb; /** @var WP_Query $query */ if ( ! $query->is_main_query() || empty( $query->query['name'] ) ) { return; } if (! isset($query->query['feed']) && ( ! isset( $query->query['page'] ) || 2 !== count( $query->query ) ) ) { return; } $types = "'" . implode("','", $root_slugs) . "'"; $check_sql = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN ({$types}) AND post_name = %s AND post_status IN ('publish','private') LIMIT 1"; if( $wpdb->get_var( $wpdb->prepare( $check_sql, $query->query['name'] ) ) ) { $query->set( 'post_type', $root_slugs ); } }); add_filter('wp_unique_post_slug', function($slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug) use ($root_slugs) { global $wpdb, $wp_rewrite; $post_types = array_merge(['post', 'page'], $root_slugs); $types = "'" . implode("','", $post_types) . "'"; if ( in_array($post_type, $post_types) || in_array( $slug, $wp_rewrite->feeds ) || 'embed' === $slug || apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $slug, $post_type ) ) { $suffix = 2; $check_sql = "SELECT post_name FROM {$wpdb->posts} WHERE post_type IN ({$types}) AND post_name = %s AND ID != %d LIMIT 1"; do { $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_ID ) ); $alt_post_name = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix"; if($post_name_check) { $slug = $alt_post_name; } $suffix++; } while ( $post_name_check ); } return $slug; }, 0, 6); } } } src/Register/PostType.php000064400000065437150732302400011432 0ustar00applyQuickLabels($labelSingular, $labelPlural, $keep_case); } $this->existing = get_post_type_object($id); if($this->existing) { $this->id = $this->existing->name; $args = (array) $this->existing; $singular = Sanitize::underscore( $singular ); $plural = Sanitize::underscore( $plural ); // obj is set on registration $this->resource = Registry::getPostTypeResource($this->id) ?? [ 'singular' => $singular, 'plural' => $plural, 'model' => null, 'controller' => null ]; $args['supports'] = array_keys(get_all_post_type_supports($this->id)); $this->args = array_merge($args, $this->args, $settings); return $this; } // setup object for later use $plural = Sanitize::underscore( $plural ); $singular = Sanitize::underscore( $singular ); $this->resource = [ 'singular' => $singular, 'plural' => $plural, 'model' => null, 'controller' => null ]; $this->setId( $this->id ?: ($id ?? $singular) ); if (array_key_exists( 'capabilities', $settings ) && $settings['capabilities'] === true) : $settings['capabilities'] = (new Roles)->getCustomPostTypeCapabilities($singular, $plural); endif; $defaults = [ 'description' => $plural, 'rewrite' => [ 'slug' => Sanitize::dash( $plural ) ], 'public' => true, 'supports' => [ 'title', 'editor' ], 'has_archive' => true, 'show_in_rest' => false, 'taxonomies' => [ ] ]; if (array_key_exists( 'taxonomies', $settings )) { $this->taxonomies = array_merge( $this->taxonomies, $settings['taxonomies'] ); $settings['taxonomies'] = $this->taxonomies; } $this->args = array_merge( $this->args, $defaults, $settings ); if(class_exists( $model = \TypeRocket\Utility\Helper::modelClass($singular, false) ) ) { $this->setModelClass($model); } return $this; } /** * Set Model Class * * @param string $modelClass * * @return $this */ public function setModelClass(string $modelClass) { $this->modelClass = $modelClass; // Default resource model is not the same as the modelClass $this->resource['model'] = $this->modelClass; return $this; } /** * Get Model Class * * @return string */ public function getModelClass() { return $this->modelClass; } /** * Use Custom Capabilities * * @return PostType $this */ public function customCapabilities() { $cap = (new Roles)->getCustomPostTypeCapabilities($this->resource['singular'], $this->resource['plural']); return $this->setArgument('capabilities', $cap); } /** * Apply Quick Labels * * @link https://developer.wordpress.org/reference/functions/get_post_type_labels/ * * @param string $singular * @param string|null $plural * @param bool $keep_case * @return PostType $this */ public function applyQuickLabels($singular, $plural = null, $keep_case = false) { if(!$plural) { $plural = Inflect::pluralize($singular); } $upperSingular = $keep_case ? $singular : Str::uppercaseWords( $singular ); $lowerSingular = $keep_case ? $singular : mb_strtolower( $singular ); $upperPlural = $keep_case ? $plural : Str::uppercaseWords( $plural ); $lowerPlural = $keep_case ? $plural : mb_strtolower( $plural ); $context = 'post_type:' . $this->getId(); $labels = [ 'add_new' => _x('Add New', $context, 'typerocket-core'), 'all_items' => sprintf( _x('All %s', $context, 'typerocket-core'), $upperPlural), 'archives' => sprintf( _x('%s Archives', $context, 'typerocket-core'), $upperSingular), 'add_new_item' => sprintf( _x('Add New %s', $context, 'typerocket-core'), $upperSingular), 'attributes' => sprintf( _x('%s Attributes', $context, 'typerocket-core'), $upperSingular), 'edit_item' => sprintf( _x('Edit %s', $context, 'typerocket-core'), $upperSingular), 'filter_items_list' => sprintf( _x('Filter %s list %s', $context, 'typerocket-core'), $lowerPlural, $upperSingular), 'insert_into_item' => sprintf( _x('Insert into %s', $context, 'typerocket-core'), $lowerSingular), 'item_published' => sprintf( _x('%s published.', $context, 'typerocket-core'), $upperSingular), 'item_published_privately' => sprintf( _x('%s published privately.', 'typerocket-core'), $upperSingular), 'item_updated' => sprintf( _x('%s updated.', $context, 'typerocket-core'), $upperSingular), 'item_reverted_to_draft'=> sprintf( _x('%s reverted to draft.', $context, 'typerocket-core'), $upperSingular), 'item_scheduled' => sprintf( _x('%s scheduled.', $context, 'typerocket-core'), $upperSingular), 'items_list' => sprintf( _x('%s list', $context, 'typerocket-core'), $upperPlural), 'menu_name' => sprintf( _x('%s', $context . ':admin menu', 'typerocket-core'), $upperPlural), 'name' => sprintf( _x('%s', $context . ':post type general name', 'typerocket-core'), $upperPlural), 'name_admin_bar' => sprintf( _x('%s', $context . ':add new from admin bar', 'typerocket-core'), $upperSingular), 'items_list_navigation' => sprintf( _x('%s list navigation', $context, 'typerocket-core'), $upperPlural), 'new_item' => sprintf( _x('New %s', $context, 'typerocket-core'), $upperSingular), 'not_found' => sprintf( _x('No %s found', $context, 'typerocket-core'), $lowerPlural), 'not_found_in_trash' => sprintf( _x('No %s found in Trash', $context, 'typerocket-core'), $lowerPlural), 'parent_item_colon' => sprintf( _x("Parent %s:", $context, 'typerocket-core'), $upperPlural), 'search_items' => sprintf( _x('Search %s', $context, 'typerocket-core'), $upperPlural), 'singular_name' => sprintf( _x('%s', $context . ':post type singular name', 'typerocket-core'), $upperSingular), 'uploaded_to_this_item' => sprintf( _x('Uploaded to this %s', $context, 'typerocket-core'), $lowerSingular), 'view_item' => sprintf( _x('View %s', $context, 'typerocket-core'), $upperSingular), 'view_items' => sprintf( _x('View %s', $context, 'typerocket-core'), $upperPlural), ]; return $this->setLabels($labels, $upperPlural, false); } /** * Set Labels * * @param array $labels * @param string $plural * @param bool $merge * * @return PostType $this */ public function setLabels(array $labels, $plural = null, $merge = true) { $this->args['labels'] = $merge ? array_merge($this->args['labels'] ?? [], $labels) : $labels; $this->args['label'] = $plural ?? $this->args['label']; return $this; } /** * Get Existing Post Type * * @return WP_Post_Type|null */ public function getExisting() { return $this->existing; } /** * Set the post type menu icon * * @link https://developer.wordpress.org/resource/dashicons/ * * @param string $name icon name does not require prefix. * * @return PostType $this */ public function setIcon( $name ) { $this->setArgument('menu_icon', 'dashicons-' . Str::trimStart($name, 'dashicons-')); return $this; } /** * @param callable $callback * * @return $this */ public function saveTitleAs(callable $callback) { $this->saves['post_title'] = $callback; return $this; } /** * @param callable $callback * * @return $this */ public function saveContentAs(callable $callback) { $this->saves['post_content'] = $callback; return $this; } /** * @param callable $callback * * @return $this */ public function saveMenuOrderAs(callable $callback) { $this->saves['menu_order'] = $callback; return $this; } /** * @param callable $callback * * @return $this */ public function saveExcerptAs(callable $callback) { $this->saves['post_excerpt'] = $callback; return $this; } /** * @param callable $callback * * @return $this */ public function savePostNameAs(callable $callback) { $this->saves['post_name'] = $callback; return $this; } /** * @param string $field * @param callable $callback * * @return $this */ public function saveFieldAs(string $field,callable $callback) { $this->saves[$field] = $callback; return $this; } /** * Get Saver * * @param string|null $key * * @return callable|null|array */ public function getSaves($key = null) { return is_null($key) ? $this->saves : ($this->saves[$key] ?? null); } /** * Get the post type icon * * @return null|string */ public function getIcon() { return $this->icon; } /** * Set Hierarchical * * @param bool $bool * * @return PostType $this */ public function setHierarchical($bool = true) { return $this->setArgument('hierarchical', $bool); } /** * Exclude from search * * @param bool $bool * * @return PostType */ public function excludeFromSearch($bool = true) { return $this->setArgument('exclude_from_search', $bool); } /** * Delete with user * * Whether to delete posts of this type when deleting a user. If true, posts of this type * belonging to the user will be moved to trash when then user is deleted. If false, * posts of this type belonging to the user will not be trashed or deleted. * * @param bool $bool * * @return PostType */ public function deleteWithUser($bool = true) { return $this->setArgument('delete_with_user', $bool); } /** * Set Position * * @param int $number range 5 - 100 and default is 25 * * @return PostType */ public function setPosition($number = 25) { return $this->setArgument('menu_position', $number); } /** * Get the placeholder title * * @return null|string */ public function getTitlePlaceholder() { return $this->title; } /** * Set the placeholder title for the title field * * @param string $text * * @return PostType $this */ public function setTitlePlaceholder( $text ) { $this->title = (string) $text; return $this; } /** * Get the form hook value by key * * @param string $key * * @return mixed */ public function getForm( $key ) { $form = null; if(array_key_exists($key, $this->form)) { $form = $this->form[$key]; } return $form; } /** * Set the form title hook * * From hook to be added just below the title field * * @param bool|true|callable $value * * @return PostType $this */ public function setTitleForm( $value = true ) { if (is_callable( $value )) { $this->form['title'] = $value; } else { $this->form['title'] = true; } return $this; } /** * Set the form top hook * * From hook to be added just above the title field * * @param bool|true|callable $value * * @return PostType $this */ public function setTopForm( $value = true ) { if (is_callable( $value )) { $this->form['top'] = $value; } else { $this->form['top'] = true; } return $this; } /** * Set the from bottom hook * * From hook to be added below the meta boxes * * @param bool|true|callable $value * * @return PostType $this */ public function setBottomForm( $value = true ) { if (is_callable( $value )) { $this->form['bottom'] = $value; } else { $this->form['bottom'] = true; } return $this; } /** * Set the form editor hook * * From hook to be added below the editor * * @param bool|true|callable $value * * @return PostType $this */ public function setMainForm($value = true) { return $this->setEditorForm($value); } /** * Set the form editor hook * * From hook to be added below the editor * * @param bool|true|callable $value * * @return PostType $this */ public function setEditorForm( $value = true ) { if (is_callable( $value )) { $this->form['editor'] = $value; } else { $this->form['editor'] = true; } return $this; } /** * Set Supports * * Options include: 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'trackbacks', * 'custom-fields', 'comments', 'revisions', 'page-attributes', 'post-formats' * * @param array $args * * @return PostType */ public function setSupports(array $args) { $this->args['supports'] = $args; return $this; } /** * Add Support * * Options include: 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'trackbacks', * 'custom-fields', 'comments', 'revisions', 'page-attributes', 'post-formats' * * @param string $type support option * @return $this */ public function addSupport($type) { $this->args['supports'][] = $type; $this->args['supports'] = array_unique($this->args['supports']); return $this; } /** * Get Supports * * @return array|bool */ public function getSupports() { return $this->args['supports']; } /** * Make Featureless * * Removes all base features from post type excluding custom meta boxes * * @return $this */ public function featureless() { $this->featureless = true; $this->setSupports([]); return $this; } /** * Keep Number of Revisions * * @param int $number * * @return $this */ public function setRevisions($number) { $this->revisions = (int) $number; return $this; } /** * Get Revisions * * @return int|null */ public function getRevisions() { return $this->revisions; } /** * Set the rewrite slug for the post type * * @param string $slug * @param null|bool $withFront * * @return PostType $this */ public function setSlug( $slug, $withFront = null ) { if(!is_array($this->args['rewrite'])) { $this->args['rewrite'] = []; } $this->args['rewrite']['slug'] = Sanitize::dash( $slug ); if(isset($withFront)) { $this->args['rewrite']['with_front'] = $withFront; } return $this; } /** * Disable Slug With Front * * @return $this */ public function disableSlugWithFront() { $this->args['rewrite']['with_front'] = false; return $this; } /** * Get the rewrite slug * * @return mixed */ public function getSlug() { return $this->args['rewrite']['slug']; } /** * Get Root Slug * * @return bool */ public function getRootSlug() { return $this->rootSlug; } /** * @param bool|string $rest_base the REST API base path * @param null|string $controller the REST controller default is \WP_REST_Posts_Controller::class * @return PostType $this */ public function setRest( $rest_base = false, $controller = null ) { $this->args['rest_base'] = $rest_base ? $rest_base : $this->id; $this->args['show_in_rest'] = true; $controller ? $this->args['rest_controller_class'] = $controller : null; return $this; } /** * Disable the Archive Page * * @return PostType $this */ public function disableArchivePage() { $this->args['has_archive'] = false; return $this; } /** * Enable Gutenberg * * @return PostType */ public function enableGutenberg() { $this->forceDisableGutenberg = false; return $this->addSupport('editor')->setArgument('show_in_rest', true); } /** * Force Disable Gutenberg * * @return PostType */ public function forceDisableGutenberg() { $this->forceDisableGutenberg = true; return $this; } /** * Get Force Disable Gutenberg * * @return bool */ public function getForceDisableGutenberg() { return $this->forceDisableGutenberg; } /** * Apply Archive Query to All Taxonomy Archives * * @param bool $bool * * @return $this */ public function setArchiveQueryWithTaxonomies($bool = true) { $this->archiveQueryTaxonomies = (bool) $bool; return $this; } /** * Get Archive Query Taxonomies * * @return bool */ public function getArchiveQueryWithTaxonomies() { return $this->archiveQueryTaxonomies; } /** * Change The Main Archive Page Query * * @param array $query the query modifiers * * @return PostType $this */ public function setArchiveQuery( array $query ) { $this->archiveQuery = $query; return $this; } /** * Set Archive Query Key * * @param string $key * @param mixed $value * * @return PostType $this */ public function setArchiveQueryKey($key, $value) { $this->archiveQuery[$key] = $value; return $this; } /** * Get Archive Query * * @return array */ public function getArchiveQuery() { return $this->archiveQuery; } /** * Remove Archive Query Key * * @param string $key * * @return PostType $this */ public function removeArchiveQueryKey($key) { if (array_key_exists($key, $this->args)) { unset($this->archiveQuery[$key]); } return $this; } /** * Show Number Of Items On Archive Page * * @param int $number * * @return PostType $this */ public function setArchivePostsPerPage($number = -1) { $this->archiveQuery['posts_per_page'] = (int) $number; return $this; } /** * Add Column To Admin Table * * @param string|null $field the name of the field * @param bool|string|callable $sort_by_c make column sortable (doubles as order_by when string) | callable override * @param string|null $label the label for the table header * @param callable|null $callback the function used to display the field data * * @return PostType $this */ public function addColumn($field, $sort_by_c = false, $label = null, $callback = null) { if( ! $label ) { $name_parts = explode('.', strrev($field), 2); $label = ucwords(strrev($name_parts[0])); $field = Sanitize::underscore( $field, true ); } $field = Sanitize::underscore( $field, true ); if( ! $callback ) { $callback = function($value) { return $value; }; } if(is_callable($sort_by_c)) { $callback = $sort_by_c; $sort_by_c = false; } $this->columns[$field] = [ 'field' => $field, 'sort' => $sort_by_c ? true : false, 'label' => $label, 'callback' => $callback, 'order_by' => $sort_by_c ]; return $this; } /** * Remove Column * * @param string $field * * @return PostType $this */ public function removeColumn($field) { $this->columns[$field] = false; return $this; } /** * Get Admin Page Table Columns * * @return array */ public function getColumns() { return $this->columns; } /** * Set Primary Column that will contain the "Edit | Quick Edit | Trash | View" controls * * @param string $field * * @return PostType $this */ public function setPrimaryColumn( $field ) { $this->primaryColumn = $field; return $this; } /** * Get Primary Column * * @return null */ public function getPrimaryColumn() { return $this->primaryColumn; } /** * Set the post type to only show in WordPress Admin * * @return PostType $this */ public function setAdminOnly() { $this->args['public'] = false; $this->args['has_archive'] = false; $this->args['show_ui'] = true; $this->args['show_in_nav_menus'] = true; return $this; } /** * Hide Admin * * @return $this */ public function hideAdmin() { $this->args['show_ui'] = false; $this->args['show_in_nav_menus'] = false; $this->args['show_in_admin_bar'] = false; $this->args['show_in_menu'] = false; return $this; } /** * Hide Frontend * * @return $this */ public function hideFrontend() { $this->args['publicly_queryable'] = false; $this->args['exclude_from_search'] = false; return $this; } /** * Set As Root * * This will make the post type use the root URL for * single posts and disable the archive page. * * @return PostType */ public function setRootOnly() { $this->setArgument('publicly_queryable', true); $this->setArgument('query_var', true); $this->setArgument('rewrite', false); $this->disableArchivePage(); $this->rootSlug = true; return $this; } /** * Register post type with WordPress * * Use the registered_post_type hook if you need to update * the post type. * * @return PostType $this */ public function register() { if(!$this->existing) { if($this->isReservedId()) { return $this; } } $supports = array_filter(array_unique(array_merge($this->args['supports'] ?: [], $this->metaBoxes))); $this->args['supports'] = $this->featureless && empty($supports) ? false : $supports; do_action('typerocket_post_type_register_' . $this->id, $this); register_post_type( $this->id, $this->args ); $this->resource['object'] = $this; Registry::addPostTypeResource($this->id, $this->resource); $this->attachHooks(); return $this; } /** * Add meta box to post type * * @param string|array|MetaBox $s * * @return PostType $this */ public function addMetaBox( $s ) { if ( $s instanceof MetaBox ) { $s = (string) $s->getId(); } elseif( is_array($s) ) { foreach($s as $n) { $this->addMetaBox($n); } return $this; } if(is_string($s)) { $this->metaBoxes[] = $s; } return $this; } /** * Add taxonomy to post type * * @param string|Taxonomy|array $s * * @return PostType $this */ public function addTaxonomy( $s ) { if ( $s instanceof Taxonomy) { $s = (string) $s->getId(); } elseif( is_array($s) ) { foreach($s as $n) { $this->addTaxonomy($n); } } if ( is_string($s) && ! in_array( $s, $this->taxonomies )) { $this->taxonomies[] = $s; $this->args['taxonomies'] = $this->taxonomies; } return $this; } /** * Attach Hooks */ public function attachHooks() { if(!$this->hooksAttached) { Registry::postTypeHooks($this); $this->hooksAttached = true; } } } src/Register/Page.php000064400000052073150732302400010507 0ustar00 'tools.php', 'dashboard' => 'index.php', 'media' => 'upload.php', 'appearance' => 'themes.php', 'plugins' => 'plugins.php', 'users' => 'users.php', 'settings' => 'options-general.php' ]; /** * Page constructor. * * @param string $resource set the resource or section the page belongs to * @param string $action set the action the page is responsible for * @param string $title set the title of the page and menu * @param array $settings menu, capability, position, view, slug * @param null|array|string|callable $handler */ public function __construct(string $resource, string $action, string $title, array $settings = [], $handler = null) { [$resource, $handle] = array_pad(explode('@', $resource), 2, null); $handler = $handler ?? $handle; $settings['capability'] = $settings['capability'] ?? $settings['cap'] ?? null; $this->setTitle($title); $this->resource = Sanitize::underscore( $resource ); $this->id = Sanitize::underscore( $this->title ); $this->action = Sanitize::underscore( $action ); $this->args = array_merge( [ 'menu' => $this->title, 'sub_menu' => $this->subMenuTitle, 'inherit_capability' => true, 'position' => 25, 'view' => null, 'slug' => $this->resource . '_' . $this->action, ], $settings ); if($handler) { $this->setHandler($handler); } } /** * Set View * * @param View|string|callable $view string value can be a file path or text block * * @return Page */ public function setView($view) { return $this->setArgument('view', $view); } /** * Set the page menu icon * * @link https://developer.wordpress.org/resource/dashicons/ * * @param string $name icon name does not require prefix. * * @return Page $this */ public function setIcon($name) { $this->icon = 'dashicons-' . Str::trimStart($name, 'dashicons-'); return $this; } /** * Get the page icon * * @return null */ public function getIcon() { return $this->icon; } /** * Set Position * * @param int $number * * @return Page */ public function setPosition($number) { return $this->setArgument('position', $number); } /** * Get Handler * * @return string|Controller|null */ public function getHandler() { return $this->handler; } /** * Get Pages * * @return array */ public function getPages() { return $this->pages; } /** * Is Action * * @param $action * @return bool */ public function isAction(string $action) { return $this->action == $action; } /** * Get Action * * @return mixed|string */ public function getAction() { return $this->action; } /** * Get the slug * * @return mixed */ public function getSlug() { return $this->args['slug']; } /** * Set the slug * * @param string $slug * * @return Page $this */ public function setSlug( $slug ) { $this->args['slug'] = $slug; return $this; } /** * Set the parent page * * @param Page $parent * * @return Page $this */ public function setParentPage( Page $parent ) { $this->parent = $parent; return $this; } /** * Get the parent page * * @return null|Page */ public function getParent() { return $this->parent; } /** * Get Title * * @return string */ public function getTitle() { return $this->title; } /** * Set Title * * The Page title. * * @param string $title * * @return Page $this */ public function setTitle( $title ) { $this->title = $title; return $this; } /** * Set Menu Title * * The main menu title if used. * * @param $title * * @return Page */ public function setMenuTitle($title) { $this->menuTitle = $title; return $this; } /** * Set Sub Menu Title * * The sub menu title if used. * * @param $title * * @return Page */ public function setSubMenuTitle($title) { $this->subMenuTitle = $title; return $this; } /** * Set Sub Menu * * Make page a submenu of another page. * * @param string|Page $page * * @return $this */ public function setParent($page) { if($page instanceof Page) { return $this->setParentPage($page); } $this->subMenu = $page; return $this; } /** * Remove title from page * * @return Page $this */ public function removeTitle() { $this->showTitle = false; return $this; } /** * Get admin page * * Get the page such as admin.php tools.php upload.php that Page belongs to * * @return mixed|string */ public function getAdminPage() { $resource = $this->resource; return !empty($this->builtin[$resource]) ? $this->builtin[$resource] : 'admin.php'; } /** * Get URL for admin page * * @param array $params * * @return string */ public function getUrl( $params = [] ) { $query = http_build_query( array_merge( [ 'page' => $this->getSlug() ], $this->routeArgsNamed, ['route_args' => $this->routeArgs], $params ) ); return admin_url() . $this->getAdminPage() . '?' . $query; } /** * Get URL for admin page with existing params in URL * * @param array $params * * @return string */ public function getUrlWithParams( $params = [] ) { parse_str(parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY), $request_params); $query = http_build_query( array_filter( array_merge( [ 'page' => $this->getSlug() ], $this->routeArgsNamed, ['route_args' => $this->routeArgs], $request_params, $params ) ) ); return admin_url() . $this->getAdminPage() . '?' . $query; } /** * @param string $key * @param string|int $value * * @return Page */ public function setRouteArg($key, $value = null) { if(func_num_args() == 1) { $this->routeArgs[] = $key; } else { $this->routeArgsNamed['route_' . $key] = $value; } return $this; } /** * Remove menu * * @return Page $this */ public function removeMenu() { $this->showMenu = false; return $this; } /** * Show new button * * @param bool $url * * @return Page $this */ public function addNewButton( $url = true ) { $this->showAddNewButton = $url; return $this; } /** * Set Handler * * The class name of the controller for the page to use. * * @param string $handler * @return Page $this */ public function setHandler($handler) { $this->handler = $handler; return $this; } /** * Set Middleware Groups * * @param array $middlewareGroups * @return $this */ public function setMiddlewareGroups(array $middlewareGroups) { $this->middlewareGroups = $middlewareGroups; return $this; } /** * Set Capability * * @param string $capability * * @return Page */ public function setCapability($capability) { return $this->setArgument('capability', $capability); } /** * Get Capability * * @return string */ public function getCapability() { $default_capability = 'administrator'; $capability = $this->args['capability'] ?? $default_capability; if( $this->getParent() && $this->args['inherit_capability'] && ! $this->args['capability'] ) { $parent_capability = $this->getParent()->getArgument('capability'); $capability = $parent_capability ?? $default_capability; } return $capability; } /** * Register with WordPress * * Override this in concrete classes * * @return Page $this */ public function register() { $menu_title = $this->menuTitle ?? $this->args['menu']; $capability = $this->getCapability(); $slug = $this->getSlug(); $position = $this->args['position']; $callback = function() { $url = $action = ''; if( $this->parent ) { $all_pages = $this->parent->getPages(); } else { $all_pages = $this->pages; } do_action('typerocket_page_start_view_' . $this->id, $this); echo '
'; foreach ($all_pages as $page) { /** @var Page $page */ if($page->action == 'add') { $url = $page->getUrl(); break; } } if( $url && $this->showAddNewButton ) { if( is_string($this->showAddNewButton) ) { $url = $this->showAddNewButton; } $add_text = __('Add New', 'typerocket-domain'); $action = ' '.$add_text.''; } $action = apply_filters('typerocket_page_title_actions', $action, $this); if( $this->showTitle ) { echo '

'. $this->title . $action . '

'; } echo '
'; $response = $this->args['view']; if( is_callable($response) ) { call_user_func($response, $this); } elseif ( $response instanceof View) { $response->render(); } elseif( is_string($response) && strlen( $response ) <= PHP_MAXPATHLEN && file_exists($response) ) { /** @noinspection PhpIncludeInspection */ include( $response ); } elseif ( is_string($response)) { echo $response; } elseif( Config::get('app.debug') ) { echo "
Add content here by creating or setting a view.
"; } echo '
'; }; if( $this->subMenu || array_key_exists( $this->resource, $this->builtin ) ) { $subMenu = $this->builtin[$this->subMenu ?? $this->resource] ?? $this->subMenu; add_submenu_page($subMenu, $this->title, $menu_title, $capability, $slug, Closure::bind( $callback, $this ) ); } elseif( ! $this->parent ) { add_menu_page( $this->title, $menu_title, $capability, $slug, Closure::bind( $callback, $this ), $this->icon, $position); if( $this->hasShownSubPages() ) { add_submenu_page( $slug, $this->title, $this->subMenuTitle ?? $menu_title, $capability, $slug ); } } else { $parent_slug = $this->parent->getSlug(); add_submenu_page( $parent_slug, $this->title, $menu_title, $capability, $slug, Closure::bind( $callback, $this ) ); if( ! $this->showMenu ) { add_action( 'admin_head', function() use ($parent_slug, $slug) { remove_submenu_page( $parent_slug, $slug ); } ); } } return $this; } /** * Add Admin Bar Menu Item * * @param string $id * @param null|string $title * @param string $parent_id * * @return Page $this */ public function adminBar( $id, $title = null, $parent_id = 'site-name') { add_action('admin_bar_menu', Closure::bind(function() use ($parent_id, $title, $id) { if( current_user_can( $this->getCapability() ) ) { /** @var $wp_admin_bar WP_Admin_Bar */ global $wp_admin_bar; $link = $this->getUrl(); $wp_admin_bar->add_menu([ 'id' => $id, 'parent' => $parent_id, 'meta' => [ 'class' => 'custom-page-admin-bar-item', ], 'title' => $title ? $title : $this->getTitle(), 'href' => $link ]); } }, $this), 80); return $this; } /** * Map Action * * Use to page controller actions for different request methods * * @param string $method use the string POST, GET, UPDATE, DELETE * @param string $action use the action on the controller you want to call * * @return Page $this */ public function mapAction($method, $action) { $this->actionMap[strtoupper($method)] = $action; return $this; } /** * Map Actions * * Used to reduce the number of page registrations needed * to map REST methods to actions. This allows for each * page=? to act as a single route that can respond * to any number of HTTP request methods. * * @param array $map ['POST' => 'create', 'GET' => 'add', 'DELETE' => 'destroy'] * @return Page $this */ public function mapActions($map) { $this->actionMap = $map; return $this; } /** * Invoked if $handler is set * @throws \Exception */ public function respond() { parse_str(parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY), $request_params); if( !empty($request_params['page']) && $request_params['page'] == $this->getSlug() ) { $args = []; if(isset($_GET)) { $get = $_GET; if(isset($get['route_args']) && is_array($get['route_args'])) { $args = $get['route_args']; unset($get['route_args']); } foreach ($get as $name => $value) { if( $name != 'route_args' && Str::starts('route_', $name) ) { if($route_arg = mb_substr($name, 6)) { $args[$route_arg] = $value; } else { $args[] = $value; } } } } $this->loadGlobalVars(); $method = (new Request)->getFormMethod(); $action = $this->actionMap[$method] ?? $this->action; $handler = [$this->handler, $action]; if(is_array($this->handler) || is_callable($this->handler)) { $handler = $this->handler; } $responder = new HttpResponder; $responder->getHandler() ->setController( $handler ) ->setMiddlewareGroups( $this->middlewareGroups ); $responder->respond( $args ); $response = \TypeRocket\Http\Response::getFromContainer(); $returned = $response->getReturn(); $rest = Request::new()->isMarkedAjax(); if( !$rest && $returned instanceof View) { status_header( $response->getStatus() ); $this->setArgument('view', $returned); } elseif( !$rest && is_string($returned) ) { status_header( $response->getStatus() ); $this->setArgument('view', $returned); } else { $response->finish($rest); } } } /** * Has shown sub pages * * @return bool */ public function hasShownSubPages() { if( ! empty( $this->pages ) ) { foreach($this->pages as $page) { if( $page->showMenu ) { return true; } } } return false; } /** * Add page to page * * @param string|Page $s * * @return Page $this */ public function addPage( $s ) { if ( $s instanceof Page && ! in_array( $s, $this->pages )) { $this->pages[] = $s; $s->setParentPage( $this ); } elseif( is_array($s) ) { foreach($s as $n) { $this->addPage($n); } } return $this; } /** * Apply post types * * @param array|PostType $post_type * * @return Page $this */ public function addPostType( $post_type ) { if ($post_type instanceof PostType) { $post_type->setArgument( 'show_in_menu', $this->getSlug() ); } elseif (is_array( $post_type )) { foreach ($post_type as $n) { $this->addPostType( $n ); } } return $this; } /** * Global Vars */ protected function loadGlobalVars() { $GLOBALS['_tr_page'] = $this; $class = \TypeRocket\Utility\Helper::appNamespace('Models\\' . Str::camelize($this->resource)); if( class_exists( $class ) ) { $GLOBALS['_tr_resource'] = new $class; } } /** * @param string $singular * @param string|array|null $plural * @param array $settings * @param null|string $resource * @param null|string $handler * * @return static * @throws \Exception */ public static function addResourcePages($singular, $plural = null, array $settings = [], $resource = null, $handler = null) { [$singular, $handle] = array_pad(explode('@', $singular), 2, null); $handler = $handler ?? $handle; if(is_array($plural)) { $settings = $plural; if(isset($settings['plural'])) { $plural = $settings['plural']; unset($settings['plural']); } else { $plural = null; } } if ( ! $plural) { $plural = \TypeRocket\Utility\Inflect::pluralize($singular); } if(!$handler) { $handler = \TypeRocket\Utility\Helper::controllerClass($singular, false); } if( ! $resource) { $resource = $singular; } $menu_id = 'add_resource_' . \TypeRocket\Utility\Sanitize::underscore($singular); $add = \TypeRocket\Register\Page::add($resource, 'add', __('Add ' . $singular)) ->setMenuTitle(__('Add New')) ->adminBar($menu_id, $singular, 'new-content') ->mapActions([ 'GET' => 'add', 'POST' => 'create', ]); $delete = \TypeRocket\Register\Page::add($resource, 'delete', 'Delete ' . $singular) ->removeMenu() ->mapActions([ 'GET' => 'delete', 'DELETE' => 'destroy', ]); $show = \TypeRocket\Register\Page::add($resource, 'show', $singular) ->addNewButton() ->removeMenu() ->mapActions([ 'GET' => 'show' ]); $edit = \TypeRocket\Register\Page::add($resource, 'edit', __('Edit ' . $singular)) ->addNewButton() ->removeMenu() ->mapActions([ 'GET' => 'edit', 'PUT' => 'update', ]); $index = \TypeRocket\Register\Page::add($resource, 'index', $plural, $settings) ->apply($edit, $show, $delete, $add) ->setSubMenuTitle(__('All ' . $plural)) ->addNewButton(); foreach ([$add, $edit, $delete, $show, $index] as $page) { /** @var \TypeRocket\Register\Page $page */ $page->setHandler($handler); } return $index; } } src/Register/Resourceful.php000064400000003624150732302400012127 0ustar00setRawId(Sanitize::underscore($id), $resource); return $this; } /** * Set the Registrable ID for WordPress to use. Don't use reserved names. * * @param string $id set the ID in raw form * @param boolean $resource update the resource binding * * @return $this */ public function setRawId($id, $resource = false) { $length = $this->getMaxIdLength(); $sub = substr($id, 0, $length); $this->id = $sub ?: $id; if($resource) { $this->resource['singular'] = $this->id; } return $this; } /** * Override Default Controller and Model * * @param string $controller_class * @return $this */ public function setHandler($controller_class) { $this->resource['controller'] = $controller_class; return $this; } /** * Set Templates * * @param array $templates * @return $this */ public function setTemplates($templates) { $this->templates = $templates; return $this; } /** * Get Templates * * @return null */ public function getTemplates() { return $this->templates; } /** * @param string $name options: controller, singular, plural, model, obj * * @return null */ public function getResource($name) { return $this->resource[$name] ?? null; } } src/Register/MetaBox.php000064400000020210150732302400011156 0ustar00label = $this->id = $name; $this->setId($id ?? $this->id); if ( ! empty( $screen )) { $this->screens = array_merge( $this->screens, (array) $screen ); } if ( ! empty( $settings['callback'] )) { $this->callback = $settings['callback']; } if ( ! empty( $settings['label'] )) { $this->label = $settings['label']; } unset( $settings['label'] ); $defaults = [ 'context' => 'normal', // 'normal', 'advanced', or 'side' 'priority' => 'default', // 'high', 'core', 'default' or 'low' 'args' => [] ]; // arguments to pass into your callback function. $settings = array_merge( $defaults, $settings ); $this->context = $settings['context']; $this->priority = $settings['priority']; $this->args = $settings['args']; } /** * Set Gutenberg Compatibility * * @param bool $editor Setting to true signifies that the you’ve confirmed that the meta box works in block editor * @param bool $compat Setting to true signifies that this meta box should only be loaded in the classic editor * @return $this */ public function gutenbergCompatibility($editor = true, $compat = true) { $this->args = array_merge($this->args, [ '__block_editor_compatible_meta_box' => $editor, '__back_compat_meta_box' => $compat, ]); return $this; } /** * Disable In Gutenberg * * @return $this */ public function gutenbergOff() { return $this->gutenbergCompatibility(false, true); } /** * Set the meta box label * * @param string $label * * @return MetaBox $this */ public function setLabel( $label ) { $this->label = (string) $label; return $this; } /** * Set the meta box label * * @return null|string */ public function getLabel() { return $this->label; } /** * Add meta box to a screen * * @param string|array $screen * * @return MetaBox $this */ public function addScreen( $screen ) { $this->screens = array_merge( $this->screens, (array) $screen ); return $this; } /** * Set Capability * * @param string|null $capability * * @return $this */ public function setCapability($capability) { $this->capability = $capability; return $this; } /** * Get Capability * * @return string|null */ public function getCapability() { return $this->capability; } /** * Add meta box to post type * * @param string|array|PostType $s * * @return MetaBox $this */ public function addPostType( $s ) { if ($s instanceof PostType) { $s = $s->getId(); } elseif (is_array( $s )) { foreach ($s as $n) { $this->addPostType( $n ); } } if ( ! in_array( $s, $this->screens )) { $this->screens[] = $s; } return $this; } /** * Register meta box with WordPress * * @return MetaBox $this */ public function register() { global $post, $comment; $postType = null; if($capability = $this->getCapability()) { if(!current_user_can($capability)) { return $this; } } if(!empty($post)) { $postType = get_post_type( $post->ID ); $pageTemplate = get_post_meta( $post->ID, '_wp_page_template', true ); } if (!empty($post) && post_type_supports( $postType, $this->id )) { $this->addPostType( $postType ); } foreach ($this->screens as $screen) { $isPageTemplate = $isFrontPage = $isPostsPage = false; if(isset($post)) { $isPageTemplate = $pageTemplate == $screen && $post->ID != get_option( 'page_on_front' ) && $post->ID != get_option( 'page_for_posts' ); $isFrontPage = $post->ID == get_option( 'page_on_front' ) && $screen == 'front_page'; $isPostsPage = $post->ID == get_option( 'page_for_posts' ) && $screen == 'posts_page'; } if ( $postType == $screen || $isPageTemplate || $isFrontPage || $isPostsPage || ( $screen == 'comment' && isset( $comment ) ) || ( $screen == 'dashboard' && ! isset( $post ) ) ) { $obj = $this; $callback = function () use ( $obj ) { $func = 'add_meta_content_' . $obj->getId(); $callback = $obj->getCallback(); echo '
'; echo BaseForm::nonceInput('hook'); if (is_callable( $callback )) : call_user_func_array( $callback, [$obj]); elseif (function_exists( $func )) : $func( $obj ); elseif ( Config::get('app.debug') ) : echo "
Add content here by defining: function {$func}() {}
"; endif; echo '
'; }; $used_screen = $isPageTemplate || $isFrontPage || $isPostsPage ? $postType : $screen; $used_context = $used_screen == 'dashboard' || $used_screen == 'comment' ? 'normal' : $this->context; add_meta_box( $this->id, $this->label, $callback, $used_screen, $used_context, $this->priority, $this->args ); } } return $this; } /** * Set Priority * * @return null|string */ public function getPriority() { return $this->priority; } /** * Set Priority * * @param null|string $priority 'high', 'core', 'default' or 'low' * * @return MetaBox $this */ public function setPriority( $priority ) { $this->priority = $priority ?? $this->priority; return $this; } /** * Set Context * * @param null|string $context 'normal', 'advanced', or 'side' * * @return MetaBox $this */ public function setContext( $context ) { $this->context = $context ?? $this->context; return $this; } /** * Get Context * * @return null|string */ public function getContext() { return $this->context; } /** * Set Callback * * @param callable|null $callback * @return MetaBox $this */ public function setCallback( $callback ) { if (is_callable( $callback )) { $this->callback = $callback; } else { $this->callback = null; } return $this; } /** * Set Callback * * @return mixed */ public function getCallback() { return $this->callback; } /** * @param callable|null $callback * * @return MetaBox */ public function setMainForm($callback) { return $this->setCallback($callback); } }src/Interfaces/Formable.php000064400000001131150732302400011646 0ustar00data = $data; $this->type = is_array($this->data) ? 'array' : 'object'; } /** * @param $key * * @return mixed|null */ public function __get($key) { return $this->type == 'array' ? ($this->data[$key] ?? null) : ($this->data->{$key} ?? null); } /** * @param $name * @param $arguments * * @return mixed */ public function __call($name, $arguments) { return $this->data->{$name}(...$arguments); } }src/Template/PostTypeModelComposer.php000064400000006123150732302400014075 0ustar00data->wpPost()); $content = apply_filters( 'the_content', $content ); $content = str_replace( ']]>', ']]>', $content ); return $content; } /** * @return string */ public function permalink() { return $this->data->permalink(); } /** * @return string */ public function excerpt() { return get_the_excerpt($this->data->wpPost()); } /** * @return string */ public function title() { return get_the_title($this->data->wpPost()); } /** * @param string $d * * @return false|int|string */ public function publishedOn($d = 'F j, Y') { return get_post_time($d, false, $this->data->wpPost()); } /** * @param string $size * @param string $classes * @param false $from_cache * * @return mixed|string */ public function featuredImage($size = 'thumbnail', $classes = '', $from_cache = false) { if($from_cache && $this->data->meta->_thumbnail_id) { $img = \TypeRocketPro\Utility\ImageCache::attachmentSrc($this->data->meta->_thumbnail_id, $size); if($img) { return $img; } } return get_the_post_thumbnail($this->data->wpPost(), $size, ['class' => $classes]); } /** * @param null|string $name * @param bool $url * * @return string|Html|null */ public function authorLink($name = null, $url = true) { $author_id = $this->data->post_author; if(!$name) { $name = get_userdata($author_id)->display_name; } if(!$url) { $url = get_author_posts_url($author_id); } if(!$url) { return $name; } return Html::a($name, $url); } /** * @param null|string $text * @param string $classes */ public function editLink($text = null, $classes = 'post-edit-link') { return edit_post_link($text, '', '', $this->data->wpPost(), $classes); } /** * @param int $size * @param string $alt * @param string $classes * * @return false|mixed|void */ public function authorAvatar($size = 100, $alt = '', $classes = '') { return get_avatar($this->data->post_author, $size, '', $alt, ['class' => $classes] ); } /** * @return false|string */ public function authorDescription() { ob_start(); the_author_meta('description', $this->data->post_author); return ob_get_clean(); } /** * @param string $field * * @return string */ public function authorMeta($field = '') { return get_the_author_meta($field, $this->data->post_author); } }src/Template/ErrorComponent.php000064400000001663150732302400012575 0ustar00thumbnail = \TypeRocket\Core\Config::get('urls.components') . '/tr-error-component.png'; } /** * Admin Fields */ public function fields() { $title = $this->title(); echo "
'{$title}' component not found
"; } /** * Render * * @var array $data component fields * @var array $info name, item_id, model, first_item, last_item, component_id, hash */ public function render(array $data, array $info) { $title = $this->title(); echo "
'{$title}' component not found
"; var_dump($data, $info); } }src/Template/ErrorTemplate.php000064400000002447150732302400012407 0ustar00set_404(); $new = get_query_template( $code ); if(file_exists($new)) { $template = $new; } else { $template = get_query_template( 404 ); } $title = get_status_header_desc($code); add_filter( 'document_title_parts', function($parts) use ($title) { $parts['title'] = $title; return $parts; }, 101, 3 ); add_filter('body_class', function($classes) use ($code) { array_push($classes, 'tr-error'.$code); return $classes; }); return $template; }; if($templates) { $temp = $caller(null); $temp = apply_filters( 'template_include', $temp ); /** @noinspection PhpIncludeInspection */ include $temp; } else { add_action( 'template_include', $caller, 100); } } }src/Template/View.php000064400000016100150732302400010523 0ustar00file = $dots; } else { $this->ext = $ext ?? '.php'; $this->location = str_replace('.', '/', $dots) . $this->ext; } if( !empty( $data ) ) { $this->data = $data; } $this->name = $dots; $this->init(); $this->setContext(); $this->setFolder($folder); } protected function init() {} /** * @param mixed ...$args * * @return static */ public static function new(...$args) { return new static(...$args); } /** * Get View Name * * @return string|null */ public function getName() { return $this->name; } /** * Get the file * * @return null|string */ public function getFile() { return $this->file; } /** * Get the Location * * @return null|string */ public function getLocation() { return $this->location; } /** * Get the data attached to a view. * * @return array */ public function getData() { return $this->data; } /** * Get file extension * * @return string|null */ public function getExtension() { return $this->ext ?? '.php'; } /** * Set the title attached to a view. * * Requires https://codex.wordpress.org/Title_Tag support AND * override SEO Meta when used on a template. * * @param string $title * * @return \TypeRocket\Template\View */ public function setTitle( $title ) { $this->title = $title; return $this; } /** * Get the title attached to a view. * * @return array */ public function getTitle() { return $this->title; } /** * Set SEO Meta Data * * Requires SEO plugin * * @param array $meta * @param null|string $url URL for the current page * * @return View * @throws \Exception */ public function setSeoMeta(array $meta, $url = null) { if(!defined('TYPEROCKET_SEO_EXTENSION')) { throw new \Exception('TypeRocket SEO Extension required for the `setMeta()` view method.'); } add_filter('typerocket_seo_meta', function($old_meta) use ($meta) { return $meta; }); add_filter('typerocket_seo_url', function($old_url) use ($url) { return $url ?? (new Request)->getUriFull(); }); return $this; } /** * Set Templating Engine * * @param $engine_class * * @return View */ public function setEngine($engine_class) { return $this->setViewsEngine($engine_class); } /** * Set Views Templating Engine * * @param $engine_class * * @return View */ public function setViewsEngine($engine_class) { $this->viewsEngine = $engine_class; return $this; } /** * @return array|mixed|null */ public function getComposedEngine() { return $this->viewsEngine ?? Config::get('app.templates.' . $this->getContext()); } /** * Load Other Context * * @param null|string $context */ protected function load($context = null) { $view_title = $this->getTitle(); $this->setContext($context); if($view_title) { add_filter('document_title_parts', function( $title ) use ($view_title) { if( is_string($view_title) ) { $title = []; $title['title'] = $view_title; } elseif ( is_array($view_title) ) { $title = $view_title; } return $title; }, 101); } $this->setFolder($this->getFolderPath()); $file = $this->getComposedFilePath(); $templateEngine = $this->viewsEngine ?? Config::get('app.templates.' . $context) ?? Config::get('app.templates.views'); (new $templateEngine($file, $this->getData(), $context, $this))->load(); } /** * Render View * * @param string|null $context the views context to use */ public function render($context = null) { $context = $context ?? $this->getContext() ?? 'views'; $this->load($context); } /** * Set Context * * Can be a key from config/paths like `views`. * * @param null|string $context the template engine context to use * * @return $this */ public function setContext($context = null) { $this->context = $context ?? $this->getContext(); return $this; } /** * @return null|string */ public function getContext() { return $this->context ?? 'views'; } /** * @param $folder * * @return $this */ public function setFolder($folder) { $this->folder = $folder ?? $this->folder; return $this; } /** * @return null */ public function getFolder() { return $this->folder; } /** * @return string */ public function getComposedFilePath() { return $this->getFile() ?? $this->getFolderPath() . DIRECTORY_SEPARATOR . $this->getLocation(); } /** * @return null|string */ public function getFolderPath() { if(is_dir($this->folder)) { $folder = rtrim($this->folder, DIRECTORY_SEPARATOR); } else { $folder = rtrim(Config::get('paths.' . $this->getContext()), DIRECTORY_SEPARATOR); } return $folder; } /** * @param string $key * @param int $time cache forever by default * @param string $folder * * @return string|null */ public function cache($key, $time = 9999999999, $folder = 'views') { return PersistentCache::new($folder)->getOtherwisePut($key, function() { return $this->toString(); }, $time); } /** * @return false|string */ public function __toString() { return $this->toString(); } /** * @return false|string */ public function toString() { ob_start(); $this->render(); return ob_get_clean(); } }src/Template/TemplateEngine.php000064400000003611150732302400012515 0ustar00file = $file; $this->data = $data; $this->view = $view; $this->ext = $view->getExtension(); $this->context = $context ?? $view->getContext(); $this->folder = $view->getFolder(); } /** * @return array */ public function getData() { return $this->data; } /** * @return string pages or views */ public function getContext() { return $this->context; } /** * @return mixed */ public function getFile() { return $this->file; } /** * @return View|null */ public function getView() { return $this->view; } /** * @return string|null */ public function getExtension() { return $this->ext; } /** * Load Template */ public function load() { extract( $this->data ); /** @noinspection PhpIncludeInspection */ include ( $this->file ); } /** * @return false|string */ public function __toString() { return $this->toString(); } /** * @return false|string */ public function toString() { ob_start(); $this->load(); return ob_get_clean(); } }src/Template/Component.php000064400000005605150732302400011563 0ustar00uuid = bin2hex(random_bytes(16)); $this->titleUnaltered = $this->title; } /** * Admin Fields */ public function fields() { } /** * Render * * @var array $data component fields * @var array $info name, item_id, model, first_item, last_item, component_id, hash */ public function render(array $data, array $info) { var_dump($data, $info); } /** * @return BaseForm|\App\Elements\Form|$this */ public function form($form = null) { if(func_num_args() == 0) { return $this->form; } $this->form = $form; return $this; } /** * @param null|string $title * * @return $this|string */ public function title($title = null) { if(func_num_args() == 0) { return $this->title ?? substr(strrchr(get_class($this), "\\"), 1); } $this->title = esc_attr($title); return $this; } /** * @return null|string */ public function titleUnaltered() { return $this->titleUnaltered; } /** * @param null|string $url * * @return $this|string */ public function thumbnail($url = null) { if(func_num_args() == 0) { return $this->thumbnail ?? \TypeRocket\Core\Config::get('urls.components') . '/' . $this->registeredAs() . '.png'; } $this->thumbnail = $url; return $this; } /** * @param null|Model|array $data * * @return $this|null|Model|array */ public function data($data = null) { if(func_num_args() == 0) { return $this->data; } $this->data = $data; return $this; } /** * @param null|string $name * * @return $this|string */ public function registeredAs($name = null) { if(func_num_args() == 0) { return $this->registeredAs; } $this->registeredAs = $name; return $this; } /** * Get a random id for this instance * * @return string */ public function uuid() { return $this->uuid; } /** * @return bool */ public function advanced() { return $this->advanced; } /** * @return mixed */ public function feature($name) { if($name == 'nameable') { return '
' . $this->title() . '
'; } return null; } }src/Utility/DataCollection.php000064400000000741150732302400012372 0ustar00data = $data; } /** * @return array|object */ public function getFormFields() { return $this->data; } }src/Utility/Value.php000064400000002510150732302400010555 0ustar00resolveCallable($value, $args) : $value; } /** * Provide access to optional objects. * * @param array|object|\ArrayObject $value * @return Nil */ public static function nils($value) { if($value instanceof Nil) { return new Nil($value->get()); } return new Nil($value); } /** * @param object|array $data an array to traverse * @param string $dots dot notation key.next.final * @param mixed|null $default * * @return mixed */ public static function data($data, $dots, $default = null) { $traverse = explode('.', $dots); foreach ($traverse as $step) { $v = is_object($data) ? ($data->$step ?? null) : ($data[$step] ?? null); if ( !isset($v) && ! is_string($data) ) { return $default; } $data = $v ?? $default; } return $data; } }src/Utility/Jobs/Queue.php000064400000013322150732302400011465 0ustar00 $data]); if(!$job instanceof JobCanQueue) { throw new \Exception( sprintf( __('Job must be instance of %s.', 'typerocket-core'), JobCanQueue::class) ); } $job->setActionSchedulerProperties($action, $actionId, $context); if($job instanceof WithoutOverlapping) { $ids = as_get_scheduled_actions([ 'hook' => $hookName, 'status' => [ActionScheduler_Store::STATUS_RUNNING] ], 'ids'); if (($key = array_search($actionId, $ids)) !== false) { unset($ids[$key]); } $time = null; if ( $scheduled_date = $action->get_schedule()->get_date() ) { $time = (int) $scheduled_date->format( 'U' ); } if( !empty($ids) && $job->willPostpone() ) { $newActionId = static::addJob($job, $time); $job->postponed($newActionId); $message = sprintf( __('#%d job postponed as a new action #%d. Job %s only one can be in-progress at a time.', 'typerocket-core'), $actionId, $newActionId, $jobClass); \ActionScheduler_Logger::instance()->log($actionId, $message); \ActionScheduler_Logger::instance()->log($newActionId, sprintf( __("Created from postponed action #%d", 'typerocket-core'), $actionId) ); return; } } $job->handle(); } catch (\Throwable $e) { \ActionScheduler_Logger::instance()->log($actionId, 'Error: ' . $e->getMessage()); if($job instanceof JobCanQueue) { $job->failed([ 'message' => $e->getMessage(), 'thrown' => $e, 'file' => $e->getFile(), 'payload' => $data, 'jobClass' => $jobClass, 'action' => $action, 'actionId' => $actionId, 'context' => $context, 'job' => $job, ]); } throw $e; } } /** * @param string $hook * @param array|null|string $args * @param string $group * @return false|int|null */ public static function findScheduledJob($hook, $args = null, $group = '') { if ( ! ActionScheduler::is_initialized( __FUNCTION__ ) ) { return false; } $query_args = array( 'hook' => $hook, 'status' => array( ActionScheduler_Store::STATUS_RUNNING, ActionScheduler_Store::STATUS_PENDING ), 'group' => $group, 'orderby' => 'none', ); if ( null !== $args ) { $query_args['args'] = $args; } return ActionScheduler::store()->query_action( $query_args ); } /** * @param string $jobClass * @return void * @throws \ReflectionException * @throws \Throwable */ public static function registerJob(string $jobClass) { /** * This need to happen before any other after execute * hooks fire because this is the execution. */ add_action('action_scheduler_after_execute', function($action_id, $action, $context) use ($jobClass) { $hookName = $action->get_hook(); $actionName = $jobClass; if('typerocket_job.' . $actionName === $hookName) { $args = $action->get_args(); Queue::runJobFromActionScheduler($hookName, $jobClass, $args[0], $action_id, $action, $context); } }, 0, 3); } /** * @param JobCanQueue $job * @param null|int $time * @return int */ public static function addJob(JobCanQueue $job, $time = null) { $class = get_class($job); $time = $time ?? (time() + $job::DELAY); $actionName = 'typerocket_job.' . $class; $jobLists = Config::getFromContainer()->locate('queue.jobs') ?? []; if(!in_array($class, $jobLists)) { throw new \Error( sprintf( __("Job %s is not registered.", 'typerocket-core'), $actionName) ); } if($job instanceof AllowOneInSchedule) { if ($firstFoundActionId = static::findScheduledJob($actionName) ) { $job->alreadyScheduled($firstFoundActionId); $message = sprintf( __("Attempted to add job %s but can only be queued once at any given time.", 'typerocket-core'), $actionName); \ActionScheduler_Logger::instance()->log($firstFoundActionId, $message); throw new \Error($message); } } return as_schedule_single_action( $time, $actionName, [$job->payload] ); } }src/Utility/Jobs/Interfaces/AllowOneInSchedule.php000064400000000414150732302400016146 0ustar00 null, 'action' => null, 'id' => null, 'context' => null, 'delay' => null, ]; /** * Payload will be json encoded by __set and then * stored in the database by ActionScheduler. * * @param array $payload */ public function __construct(array $payload = []) { $this->properties['payload'] = $payload; } /** * @param \ActionScheduler_Action $action * @param $actionId * @param $context * @return void */ public function setActionSchedulerProperties(\ActionScheduler_Action $action, $actionId, $context) { $this->properties = array_merge($this->properties, [ 'action' => $action, 'id' => $actionId, 'context' => $context, ]); } /** * @return bool */ public function willPostpone() : bool { return true; } /** * @param $newActionId * @return void */ public function postponed($newActionId) { // Do nothing by default } /** * @param $firstFoundActionId * @return void */ public function alreadyScheduled($firstFoundActionId) { // Do nothing by default } /** * @param array $data * @return void */ public function failed(array $data) { // Do nothing by default } /** * @param string $message * @return int */ public function logToAction(string $message) : int { return (int) \ActionScheduler_Logger::instance()->log($this->id, $message); } /** * @param array $payload * @return int */ public static function dispatch(array $payload = [], $time = null) { return Queue::addJob(new static($payload), $time); } /** * Look to properties for job and action data * * @param string $key * @return int|mixed|string|null */ public function __get($key) { if($key === 'payload') { $json = $this->properties['payload'] ?? null; return Data::isJson($json) ? json_decode($json, true) : $json; } if(in_array($key, ['id', 'action', 'context', 'delay'])) { return $this->properties[$key]; } return $this->{$key}; } /** * Disable the ability to set action related data * * @param string $key * @param $value * @return void */ public function __set($key, $value) { if($key === 'payload') { $this->properties['payload'] = Data::isJson($value) ? $value : json_encode($value); return; } if(in_array($key, ['id', 'action', 'context', 'delay'])) { return; } $this->{$key} = $value; } }src/Utility/Validator.php000064400000037503150732302400011440 0ustar00 null ]; protected $errorMessages = ['messages' => [], 'regex' => false]; protected $ran = false; protected $validatorMap = [ CallbackValidator::KEY => CallbackValidator::class, EmailValidator::KEY => EmailValidator::class, KeyValidator::KEY => KeyValidator::class, DateTimeLocalValidator::KEY => DateTimeLocalValidator::class, MaxLengthValidator::KEY => MaxLengthValidator::class, MinLengthValidator::KEY => MinLengthValidator::class, NumericValidator::KEY => NumericValidator::class, RequiredValidator::KEY => RequiredValidator::class, SizeValidator::KEY => SizeValidator::class, UniqueModelValidator::KEY => UniqueModelValidator::class, UrlValidator::KEY => UrlValidator::class, ]; /** * Validator * * Validate data mapped to fields * * @param array $rules the rules and validation handlers * @param array|\ArrayObject|null $fields the fields to be validated * @param null|string $modelClass must be a class of Model * @param bool $run run validation on new */ public function __construct(array $rules, $fields = null, $modelClass = null, $run = false) { $this->modelClass = $modelClass; $this->fields = $fields ?? (new Request)->getFields(); $this->rules = $rules; $this->validatorMap = apply_filters('typerocket_validator_map', $this->validatorMap); if($run) { $this->mapFieldsToValidation(); } } /** * @param mixed ...$args * * @return static */ public static function new(...$args) { return new static(...$args); } /** * Run Validation * * @param bool $returnSelf * * @return bool|$this */ public function validate($returnSelf = false) { $this->mapFieldsToValidation(); return $returnSelf ? $this : $this->passed(); } /** * @param string $key * * @return Redirect */ public function getRedirectWithFieldErrors($key = 'fields') { return Redirect::new()->withFieldErrors($this->getErrorFields(), $key); } /** * @param null|callable $callback * @param bool $flash flash errors to page * @param string $key * * @return $this * @throws RedirectError */ public function redirectWithErrorsIfFailed($callback = null, $flash = true, $key = 'fields') { if($this->failed()) { $redirect = $this->getRedirectIfFailedWithFieldsAndErrors($flash, $key)->back(); if(is_callable($callback)) { call_user_func($callback, $redirect); } throw (new RedirectError(__('Validation failed.', 'typerocket-domain')))->redirect( $redirect ); } return $this; } /** * @param bool $flash flash errors to page * @param string $key * * @return Redirect */ public function getRedirectIfFailedWithFieldsAndErrors($flash = true, $key = 'fields') { $redirect = null; if($this->failed()) { if($flash) { $response = Response::getFromContainer(); $this->flashErrors($response); $response->lockFlash(); } $redirect = $this->getRedirectWithFieldErrors($key)->withOldFields(); } return $redirect ?? Redirect::new(); } /** * @param null|callable $callback * @param bool $flash flash errors to page * @param string $key * * @return $this */ public function respondWithErrors($callback = null, $flash = true, $key = 'fields') { if( $this->failed() && $this->ran) { $response = Response::getFromContainer() ->withOldFields() ->setError($key, $this->getErrorFields()) ->withRedirectErrors(); if($flash) { $this->flashErrors($response->allowFlash()); $response->lockFlash(); } if(is_callable($callback)) { call_user_func($callback, $response); } } return $this; } /** * Get errors * * @return array */ public function getErrors() { return $this->errors; } /** * Has Errors * * @return bool */ public function hasErrors() { return !empty($this->errors); } /** * @param string $key * * @return mixed|null */ public function getError(string $key) { return $this->errors[$key] ?? null; } /** * @param string $key * * @return mixed|null */ public function getErrorField(string $key) { return $this->errorFields[$key] ?? null; } /** * Get passes * * @return array */ public function getPasses() { return $this->passes; } /** * @return array */ public function getErrorFields() { return $this->errorFields; } /** * Set Error Messages * * @param array $messages * @param bool $regex search for key using regex * @return $this */ public function setErrorMessages(array $messages, $regex = false) { $this->errorMessages = [ 'messages' => $messages, 'regex' => $regex ]; return $this; } /** * Check if passes * * @return bool */ public function passed() { return empty($this->errors) && $this->ran; } /** * Check of failed * * @return bool */ public function failed() { return !$this->passed(); } /** * Flash validator errors on next request * * @param Response $response * * @return $this */ public function flashErrors( Response $response ) { $errors = ''; $response->flashNext($errors, 'error'); return $this; } /** * Map fields to validators */ protected function mapFieldsToValidation() { foreach ($this->rules as $fullDotPath => $validationRules) { $this->walk($this->fields, $fullDotPath, $validationRules, $fullDotPath); } $this->ran = true; return $this; } /** * @return array|null */ public function getModelClass() { return $this->modelClass; } /** * Used to format fields * * @param array $fields array of fields to validate * @param string $dotPath seeking fields path in dot notation * @param array|string|ValidatorRule $validationRules * @param string $fullDotPath main fields path in dot notation * * @return array|null * @throws \Exception */ protected function walk(array &$fields, string $dotPath, $validationRules, string $fullDotPath) { $value = &$fields; $dots = explode('.', $dotPath); foreach($dots as $step) { array_shift($dots); if(in_array($step, ['*', '?']) && is_array($value)) { $new_loc = &$value; $indies = array_keys($new_loc); foreach($indies as $index) { if(isset($new_loc[$index])) { $newFullPath = preg_replace('(\*|\?)', "{$index}", $fullDotPath, 1); $this->walk($new_loc[$index], implode('.', $dots), $validationRules, $newFullPath); } } } elseif( $step === '?' && empty($value) ) { $this->passes[substr($fullDotPath, 0, strpos($fullDotPath, '.?'))] = $value; return null; } elseif( isset($value[$step]) ) { $value = &$value[$step]; } else { if( !empty($validationRules) && !isset($indies) ) { $this->validateField( $validationRules, null, $fullDotPath ); } return null; } } if(!isset($indies) && !empty($validationRules)) { $this->validateField( $validationRules, $value, $fullDotPath ); } return $value; } /** * @param $message * * @return $this */ public function appendToFlashErrorMessage($message) { $this->errors[] = $message; return $this; } /** * @param $message * * @return $this */ public function prependToFlashErrorMessage($message) { array_unshift($this->errors, $message); return $this; } /** * Set Error Message * * Pulls message override from $errorMessages * * @param ValidatorRule $class * @param string $fullDotPath name in dot notation */ protected function setErrorMessage(ValidatorRule $class, $fullDotPath) { $error_message = $class->getError(); $error_message_full = $class->getFieldLabel() . ' ' . $error_message; $type = $class::KEY; $index = $fullDotPath.':'.$type; $validate = $value = $matches = false; if($this->errorMessages['regex'] && !empty($this->errorMessages['messages'])) { foreach ($this->errorMessages['messages'] as $key => $value) { if(preg_match_all("/{$key}/", $index, $matches, PREG_SET_ORDER, 0)) { $validate = true; break; } } } else { $validate = !empty($this->errorMessages['messages'][$index]); if($validate) { $value = $this->errorMessages['messages'][$index]; } } if($validate) { if(is_callable($value)) { $error_message = $error_message_full = call_user_func($value, $fullDotPath, $type, $error_message_full, $matches, $error_message); } else { $error_message = $error_message_full = isset($value) ? str_replace('{error}', $error_message, $value) : $error_message; } if(is_array($error_message)) { $error_message_full = $error_message['full']; $error_message = $error_message['field']; } } $this->errors[$fullDotPath] = $this->errors[$fullDotPath] ?? $error_message_full; $this->errorFields[$fullDotPath] = $this->errorFields[$fullDotPath] ?? trim($error_message); } /** * @param string $key * @param callable $callback * * @return $this */ public function setCallback(string $key, callable $callback) { $this->callbacks[$key] = $callback; return $this; } /** * Validate the Field * * @param string|array|ValidatorRule $validationRules * @param array|string $value * @param string $fullDotPath * * @throws \Exception */ protected function validateField($validationRules, $value, string $fullDotPath) { if($this->callbacks['fieldLabel']) { $fieldLabel = call_user_func($this->callbacks['fieldLabel'], $fullDotPath, $this, $value); } else { $fieldLabel = '"' . Str::uppercaseWords(preg_replace('/\_|\./', ' ', $fullDotPath)) . '"'; } $args = [ 'validator' => $this, 'value' => $value, 'full_name' => $fullDotPath, 'field_name' => $fieldLabel, 'field_label' => $fieldLabel, ]; if($validationRules instanceof ValidatorRule) { $validationRules->setArgs($args); $this->runValidatorRule($validationRules, $fullDotPath, $value); return; } $list = []; $weak_all = null; if(is_string($validationRules)) { if($validationRules[0] === '?') { $weak_all = true; $validationRules = substr($validationRules, 1); } $validationRules = explode('|', (string) $validationRules); } if(is_array($validationRules)) { $list = $validationRules; } foreach($list as $validation) { $class = $weak = $subfields = null; $value_checked = $value; if(is_string($validation)) { [ $type, $option, $option2, $option3 ] = array_pad(explode(':', $validation, 4), 4, null); if($type[0] === '?') { $weak = true; $type = substr($type, 1); } $weak = $weak ?? $weak_all; if(Str::starts('only_subfields=', $option)) { $only_subfields = explode('/', $option)[0]; $subfields = explode(',', substr($only_subfields, 15)); $value_checked = Arr::only($value, $subfields); $value_checked = array_filter($value_checked, function($v) { return isset($v); }); $value_checked = Arr::isEmptyArray($value_checked) ? null : $value_checked; $option = substr($option, strlen($only_subfields) + 1) ?: null; } if(array_key_exists($type, $this->validatorMap)) { $class = $this->validatorMap[$type]; } else { $class = $type; } if(class_exists($class)) { $args = array_merge($args, [ 'option' => $option, 'option2' => $option2, 'option3' => $option3, 'weak' => $weak, 'value' => $value_checked, 'subfields' => $subfields, ]); $class = new $class; } } elseif ($validation instanceof ValidatorRule) { $class = $validation; } if($class instanceof ValidatorRule) { $class->setArgs($args); $this->runValidatorRule($class, $fullDotPath, $value_checked); continue; } throw new \Exception('Unknown validation option: ' . $type); } } /** * @param ValidatorRule $rule * @param string $fullDotPath * @param mixed $value */ protected function runValidatorRule(ValidatorRule $rule, string $fullDotPath, $value) { if($rule->isOptional() && Data::emptyOrBlankRecursive($value)) { $pass = true; } else { $pass = $rule->validate(); } if( !$pass ) { $this->setErrorMessage($rule, $fullDotPath); } else { $this->passes[$fullDotPath . ':' . $rule::KEY] = $value; } } }src/Utility/Data.php000064400000012705150732302400010361 0ustar00 $step) { unset($traverse[$i]); if($step === '*' && is_array($array)) { return array_map(function($item) use ($traverse, $default) { return static::walk($traverse, $item, $default); }, $array); } else { $v = is_object($array) ? ($array->$step ?? null) : ($array[$step] ?? null); } if ( !isset($v) && ! is_string($array) ) { return $default; } $array = $v ?? $default; } return $array; } /** * @param mixed $value * @param string|callable $type * * @return bool|float|int|mixed|string */ public static function cast($value, $type) { // Integer if ($type == 'int' || $type == 'integer') { return is_object($value) || is_array($value) ? null : (int) $value; } // Float if ($type == 'float' || $type == 'double' || $type == 'real') { return is_object($value) || is_array($value) ? null : (float) $value; } // JSON if ($type == 'json') { if(is_serialized($value)) { $value = unserialize($value); } if(static::isJson($value)) { return $value; } return json_encode($value); } // Serialize if ($type == 'serialize' || $type == 'serial') { if(static::isJson($value)) { $value = json_decode((string) $value, true); } if(is_serialized($value)) { return $value; } return serialize($value); } // String if ($type == 'str' || $type == 'string') { if(is_object($value) || is_array($value)) { $value = json_encode($value); } else { $value = (string) $value; } return $value; } // Bool if ($type == 'bool' || $type == 'boolean') { return (bool) $value; } // Array if ($type == 'array') { if(is_numeric($value)) { return $value; } elseif (is_string($value) && static::isJson($value)) { $value = json_decode($value, true); } elseif (is_string($value) && is_serialized($value)) { $value = unserialize($value); } elseif(!is_string($value)) { $value = (array) $value; } elseif (trim($value) == '""') { $value = null; } return $value; } // Object if ($type == 'object' || $type == 'obj') { if(is_numeric($value)) { return $value; } elseif (is_string($value) && static::isJson($value)) { $value = (object) json_decode($value); } elseif (is_string($value) && is_serialized($value)) { $value = (object) unserialize($value); } elseif(!is_string($value)) { $value = (object) $value; } elseif (is_array($value)) { $value = (object) $value; } elseif (trim($value) == '""') { $value = null; } return $value; } // Callback if (is_callable($type)) { return call_user_func($type, $value); } return $value; } /** * Detect is JSON * * @param $args * * @return bool */ public static function isJson(...$args) { if(is_array($args[0]) || is_object($args[0])) { return false; } $s = trim($args[0]); if($s === '' || $s === '""') { return false; } json_decode(...$args); return (json_last_error() == JSON_ERROR_NONE); } }src/Utility/Inflect.php000064400000015666150732302400011105 0ustar00 "$1zes", '/^(ox)$/i' => "$1en", '/([m|l])ouse$/i' => "$1ice", '/(matr|vert|ind)ix|ex$/i' => "$1ices", '/(x|ch|ss|sh)$/i' => "$1es", '/([^aeiouy]|qu)y$/i' => "$1ies", '/(hive)$/i' => "$1s", '/(?:([^f])fe|([lr])f)$/i' => "$1$2ves", '/(shea|lea|loa|thie)f$/i' => "$1ves", '/sis$/i' => "ses", '/([ti])um$/i' => "$1a", '/(tomat|potat|ech|her|vet)o$/i' => "$1oes", '/(bu)s$/i' => "$1ses", '/(alias)$/i' => "$1es", '/(octop)us$/i' => "$1i", '/(ax|test)is$/i' => "$1es", '/(us)$/i' => "$1es", '/s$/i' => "s", '/$/' => "s" ]; private static $singular = [ '/(quiz)zes$/i' => "$1", '/(matr)ices$/i' => "$1ix", '/(vert|ind)ices$/i' => "$1ex", '/^(ox)en$/i' => "$1", '/(alias)es$/i' => "$1", '/(octop|vir)i$/i' => "$1us", '/(cris|ax|test)es$/i' => "$1is", '/(shoe)s$/i' => "$1", '/(o)es$/i' => "$1", '/(bus)es$/i' => "$1", '/([m|l])ice$/i' => "$1ouse", '/(x|ch|ss|sh)es$/i' => "$1", '/(m)ovies$/i' => "$1ovie", '/(s)eries$/i' => "$1eries", '/([^aeiouy]|qu)ies$/i' => "$1y", '/([lr])ves$/i' => "$1f", '/(tive)s$/i' => "$1", '/(hive)s$/i' => "$1", '/(li|wi|kni)ves$/i' => "$1fe", '/(shea|loa|lea|thie)ves$/i' => "$1f", '/(^analy)ses$/i' => "$1sis", '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => "$1$2sis", '/([ti])a$/i' => "$1um", '/(n)ews$/i' => "$1ews", '/(h|bl)ouses$/i' => "$1ouse", '/(corpse)s$/i' => "$1", '/(us)es$/i' => "$1", '/s$/i' => "" ]; private static $irregular = [ 'move' => 'moves', 'foot' => 'feet', 'goose' => 'geese', 'sex' => 'sexes', 'child' => 'children', 'man' => 'men', 'tooth' => 'teeth', 'person' => 'people', 'valve' => 'valves' ]; private static $uncountable = [ 'sheep', 'fish', 'deer', 'series', 'species', 'money', 'rice', 'information', 'equipment' ]; public static function pluralize( $string ) { // save some time in the case that singular and plural are the same if (in_array( strtolower( $string ), self::$uncountable )) { return $string; } // check for irregular singular forms foreach (self::$irregular as $pattern => $result) { $pattern = '/' . $pattern . '$/i'; if (preg_match( $pattern, $string )) { return preg_replace( $pattern, $result, $string ); } } // check for matches using regular expressions foreach (self::$plural as $pattern => $result) { if (preg_match( $pattern, $string )) { return preg_replace( $pattern, $result, $string ); } } return $string; } public static function singularize( $string ) { // save some time in the case that singular and plural are the same if (in_array( strtolower( $string ), self::$uncountable )) { return $string; } // check for irregular plural forms foreach (self::$irregular as $result => $pattern) { $pattern = '/' . $pattern . '$/i'; if (preg_match( $pattern, $string )) { return preg_replace( $pattern, $result, $string ); } } // check for matches using regular expressions foreach (self::$singular as $pattern => $result) { if (preg_match( $pattern, $string )) { return preg_replace( $pattern, $result, $string ); } } return $string; } public static function pluralizeIf( $count, $string ) { if ($count == 1) { return "1 $string"; } else { return $count . " " . self::pluralize( $string ); } } }src/Utility/Sanitize.php000064400000023320150732302400011271 0ustar00 and . * * @param string $input * * @return string */ public static function textarea( $input ) { global $allowedposttags; return wp_kses( $input, $allowedposttags ); } /** * Sanitize nothing. * * @param string $input * * @return string */ public static function raw( $input ) { return $input; } /** * Sanitize Attribute. * * @param string $input * * @return string */ public static function attribute( $input ) { return esc_attr($input); } /** * Sanitize URL * * @param string $input * * @return string */ public static function url( $input ) { return esc_url($input); } /** * Sanitize SQL * * @param string $input * * @return string */ public static function sql( $input ) { return esc_sql($input); } /** * Sanitize text as plaintext. * * @param string $input * * @return string */ public static function plaintext( $input ) { return wp_kses( $input, [] ); } /** * Sanitize editor data. Much like textarea remove '; echo ''; } } /** * Is Front-end enabled * * @return bool */ public function frontendIsEnabled() { return $this->frontend_mode; } /** * Enable Front-end * * @return static */ public function frontendEnable() { if($this->frontend_mode) { return $this; } $this->frontend_mode = true; add_action( 'wp_enqueue_scripts', function() {wp_enqueue_style( 'dashicons' );} ); add_action( 'wp_enqueue_scripts', [ $this, 'addCss' ] ); add_action( 'wp_enqueue_scripts', [ $this, 'addJs' ] ); add_action( 'wp_head', [ $this, 'addTopJs' ] ); add_action( 'wp_footer', [ $this, 'addBottomJs' ] ); return $this; } /** * Maybe Init Front-end * * @param bool $force for typerocket on the front-end * * @return bool */ public function maybeFrontend($force = false) { $this->frontend_mode = $force || Config::get('app.frontend'); if ( is_admin() || !$this->frontend_mode ) { $this->frontend_mode = false; return $this->frontend_mode; } $this->frontendEnable(); return $this->frontend_mode; } /** * Load plugins */ public function loadExtensions() { $conf = Config::get('app'); $ext = apply_filters('typerocket_extensions', $conf['extensions'] ); foreach ($ext as $extClass) { if(class_exists($extClass)) { (new Resolver())->resolve($extClass); } } } /** * Load Responders */ public function loadResponders() { if( defined('WP_INSTALLING') && WP_INSTALLING) { return; } add_action( 'save_post', 'TypeRocket\Http\Responders\Hook::posts' ); add_action( 'edit_attachment', 'TypeRocket\Http\Responders\Hook::attachments' ); add_action( 'wp_insert_comment', 'TypeRocket\Http\Responders\Hook::comments' ); add_action( 'edit_comment', 'TypeRocket\Http\Responders\Hook::comments' ); add_action( 'edit_term', 'TypeRocket\Http\Responders\Hook::taxonomies', 10, 4 ); add_action( 'create_term', 'TypeRocket\Http\Responders\Hook::taxonomies', 10, 4 ); add_action( 'profile_update', 'TypeRocket\Http\Responders\Hook::users' ); add_action( 'user_register', 'TypeRocket\Http\Responders\Hook::users' ); } /** * Set flashing for admin notices */ public function setFlash() { if( !empty($_COOKIE[Redirect::KEY_ADMIN]) ) { $data = (new Cookie)->getTransient(Redirect::KEY_ADMIN); Notice::dismissible($data); } } /** * Add CSS */ public function addCss() { $url = $this->stash['url.typerocket']; $manifest = $this->stash['manifest.typerocket']; wp_enqueue_style( 'typerocket-styles', $url . $manifest['/css/core.css']); if (is_admin()) { wp_enqueue_style( 'wp-color-picker' ); } } /** * Add JavaScript */ public function addJs() { $url = $this->stash['url.typerocket']; $manifest = $this->stash['manifest.typerocket']; wp_enqueue_script( 'typerocket-scripts-global', $url . $manifest['/js/global.js'] ); } /** * Restrict Upload Mime Types * * https://wordpress.stackexchange.com/a/97025 * https://wordpress.stackexchange.com/a/174805 * * @param $file * @return mixed */ public function restrictUploadMimeTypes($file) { if ( empty( $_POST['allowed_mime_types'] ) || empty( $file['type'] ) ) { return $file; } $allowed_mime_types = explode( ',', $_POST['allowed_mime_types'] ); if ( in_array( $file['type'], $allowed_mime_types ) ) { return $file; } // Cater for "group" allowed mime types eg "image", "audio" etc. to match // files of type "image/png", "audio/mp3" etc. if ( ( $slash_pos = strpos( $file['type'], '/' ) ) > 0 ) { if ( in_array( substr( $file['type'], 0, $slash_pos ), $allowed_mime_types ) ) { return $file; } } $file['error'] = __('Sorry, you cannot upload this file type for this field.', 'typerocket-domain'); return $file; } /** * Add JavaScript to very bottom * * This is in place so that all other scripts from fields come * before the main typerocket script. */ public function addBottomJs() { $url = $this->stash['url.typerocket']; $manifest = $this->stash['manifest.typerocket']; wp_enqueue_script( 'typerocket-scripts', $url . $manifest['/js/core.js'], [ 'jquery', 'wp-i18n' ], false, true ); wp_set_script_translations( 'typerocket-scripts', 'typerocket-domain' ); do_action('typerocket_bottom_assets', $url, $manifest); } /** * Top JavaScript */ public function addTopJs() { $url = $this->stash['url.typerocket']; $manifest = $this->stash['manifest.typerocket']; $scheme = ''; if ( is_ssl() || ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) ) { $scheme = 'https'; } ?>getPath(); if(Str::contains('tr-api', $path) || Config::get('app.debug') ) { Route::new()->any() ->match('tr-api/rest/([^/]+)/?([^/]+)?', ['resource', 'id']) ->do([RestController::class, 'rest']); Route::new()->post() ->match('tr-api/(builder|matrix)/([^/]+)/([^/]+)', ['caller', 'group', 'type']) ->do([FieldsController::class, 'component']); Route::new()->get()->post() ->match('tr-api/search')->middleware('search') ->do([FieldsController::class, 'search']); } } /** * Check site state */ public function checkSiteStateChanged() { if ( $site_state = get_option(static::STATE) ) { if( is_array( $site_state ) ) { $site_state = array_unique( $site_state ); foreach ( $site_state as $site_state_func ) { if( function_exists( $site_state_func ) ) { call_user_func( $site_state_func ); } } } update_option(static::STATE, '0', 'yes'); } } /** * Updates _typerocket_site_state_changed option in database * * Should be called when a theme or plugin has been activated or deactivated. * Used to facilitate tasks like flushing rewrite rules for the registration * and de-registration of post types and taxonomies. * * @link https://core.trac.wordpress.org/ticket/47526 * * @param string|array $arg single function name or list of function names */ public static function updateSiteState($arg) { $value = []; if ($state = get_option(static::STATE)) { $value = maybe_unserialize($state); if (!is_array($value)) { $value = []; } } if (is_array($arg)) { $value = array_merge($value, $arg); } else { $value[] = $arg; } update_option(static::STATE, array_unique($value), 'yes'); } /** * @return static */ public static function getFromContainer() { return Container::resolve(static::ALIAS); } } src/Core/Container.php000064400000005405150732302400010656 0ustar00 $callback, 'make_singleton' => $singleton, 'singleton_instance' => null ]; if($alias && empty(self::$alias[$alias])) { self::$alias[$alias] = $class_name; } return true; } /** * Register Singleton * * @param string $class_name * @param callable $callback * @param null|string $alias * @return bool */ public static function singleton($class_name, $callback, $alias = null) { return self::register($class_name, $callback, true, $alias); } /** * Get Aliases * * @return array */ public function aliases() { return self::$alias; } /** * Resolve Singleton * * @param string $class_name * @param null|string $alias * * @return mixed|null */ public static function findOrNewSingleton($class_name, $alias = null) { self::register($class_name, function() use ($class_name) { return new $class_name; }, true, $alias); return self::resolve($class_name); } }src/Core/Resolver.php000064400000010454150732302400010535 0ustar00isInstantiable()) { throw new ResolverException($class . ' is not instantiable'); } $constructor = $reflector->getConstructor(); if ( ! $constructor ) { return new $class; } $parameters = $constructor->getParameters(); $dependencies = $this->getDependencies($parameters, $args); $instance = $reflector->newInstanceArgs($dependencies); return $this->onResolution($instance); } /** * On Resolution * * @param $instance * @return mixed */ public function onResolution($instance) { if($instance instanceof ResolvesWith) { $instance = $instance->onResolution(); } return $instance; } /** * Resolve Callable * * @param $handler * @param null|array $args * @return mixed * @throws \ReflectionException */ public function resolveCallable($handler, $args = null) { if ( is_array($handler) ) { $ref = new \ReflectionMethod($handler[0], $handler[1]); } else { $ref = new \ReflectionFunction($handler); } $params = $ref->getParameters(); $dependencies = $this->getDependencies($params, $args); return call_user_func_array( $handler, $dependencies ); } /** * Get Dependencies * * @param array $parameters * @param null|array $args * * @return array * @throws \ReflectionException */ public function getDependencies($parameters, $args = null) { $dependencies = []; $i = 0; foreach ($parameters as $parameter) { $varName = $parameter->getName(); $dependency = $parameter->getType(); if (isset($args[$varName])) { $v = $args[$varName]; } elseif (isset($args[$i])) { $v = $args[$i]; $i++; } elseif (isset($args['@first'])) { $v = $args['@first']; unset($args['@first']); } else { $v = null; } $isBuiltInType = false; if($dependency instanceof \ReflectionNamedType) { $isBuiltInType = $dependency->isBuiltin(); } if ( !$dependency || !$dependency instanceof \ReflectionNamedType || $isBuiltInType ) { $dependencies[] = $v ?? $this->resolveNonClass($parameter); } else { $dp_name = $dependency->getName(); $obj = $v instanceof $dp_name ? $v : $this->resolve($dp_name); if($v && method_exists($obj, 'onDependencyInjection')) { $obj->onDependencyInjection($v); } $dependencies[] = $obj; } } return $dependencies; } /** * Resolve none class * * Inject default value * * @param \ReflectionParameter $parameter * * @return mixed * @throws \ReflectionException */ public function resolveNonClass(\ReflectionParameter $parameter) { if ($parameter->isDefaultValueAvailable()) { return $parameter->getDefaultValue(); } throw new ResolverException('Resolver failed because there is no default value for the parameter: $' . $parameter->getName()); } /** * Resolve Class * * @param string $class * @param null|array $args * * @return object * @throws \ReflectionException */ public static function build($class, $args = null) { return (new static)->resolve($class, $args); } /** * @param mixed ...$args * * @return static */ public static function new(...$args) { return new static(...$args); } }src/Console/CommandCollection.php000064400000004344150732302400013041 0ustar00exchangeArray($this->commands); } /** * @param Config $config * * @return $this */ public function configure(Config $config) { $this->config = $config; return $this; } /** * Enable WordPress Commands */ public function enableWordPress() { foreach ( $this->wordpress as $command ) { $this->append($command); } } /** * Enable custom commands */ public function enableCustom() { $commands = $this->config->locate('galaxy.commands'); if( $commands) { foreach ( $commands as $command ) { $this->append($command); } } } /** * Enable custom commands */ public function enableAdvanced() { $file = $this->config->locate('paths.pro') . '/commands.php'; if(file_exists($file)) { $commands = require($file); } else { echo 'Can not load pro commands... ' . $file . PHP_EOL; } if( $commands) { foreach ( $commands as $command ) { $this->append($command); } } } } src/Console/GalaxyConsoleLauncher.php000064400000007203150732302400013676 0ustar00console = new Application(); $this->commands = new CommandCollection(); $this->commands->configure(Config::getFromContainer()); $wp_root = \TypeRocket\Core\Config::get('galaxy.wordpress'); $wp_root_load = \TypeRocket\Core\Config::get('galaxy.wordpress_load', true); // Set common headers, to prevent warnings from plugins. $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.0'; $_SERVER['HTTP_USER_AGENT'] = ''; $_SERVER['REQUEST_METHOD'] = 'GET'; $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; if( !empty($wp_root) && $wp_root_load !== 'no') { $this->wpRoot = $wp_root = realpath($wp_root); $is_file = is_file( $wp_root . '/wp-load.php' ); $has_config = is_file( $wp_root . '/wp-config.php' ); $has_config = $has_config ?: is_file( $wp_root . '/../wp-config.php' ); if($has_config && $is_file) { $this->wordpress = true; if(class_exists(System::ADVANCED)) { $this->advanced = true; } // bypass maintenance mode ApplicationKernel::addFilter('enable_maintenance_mode', function() {return false;}, 0, 0); // wp filters and actions are the same thing ApplicationKernel::addFilter('after_setup_theme', [$this, 'loadWordPressFunctions'], 28, 0); ApplicationKernel::addFilter('after_setup_theme', [$this, 'loadCommandsAndRun'], 30, 0); define('WP_USE_THEMES', true); global $wp, $wp_query, $wp_the_query, $wp_rewrite, $wp_did_header; /** @noinspection PhpIncludeInspection */ require( $wp_root . '/wp-load.php'); add_filter('enable_maintenance_mode', function(){ return true; }); } else { echo $is_file ? '' : 'WP root path might not be not correct:' . realpath($wp_root) .PHP_EOL; echo $has_config ? '' : 'wp-config.php not found'.PHP_EOL; echo "\033[0;31mWP Commands not enabled.\033[0m".PHP_EOL; } } if($wp_root_load === 'no') { echo "\033[0;31mWP loading is disabled in your Galaxy CLI config.\033[0m".PHP_EOL; } $this->loadCommandsAndRun(); } /** * Load WordPress Functions */ public function loadWordPressFunctions() { /** @noinspection PhpIncludeInspection */ require_once( $this->wpRoot . '/wp-admin/includes/upgrade.php' ); } /** * @throws Exception */ public function loadCommandsAndRun() { if($this->loaded) { return; } $this->commands->enableCustom(); if($this->wordpress) { $this->commands->enableWordPress(); } if($this->advanced) { $this->commands->enableAdvanced(); } foreach ($this->commands as $command ) { $this->console->add( new $command ); } $this->console->run(); $this->loaded = true; } }src/Console/Commands/PublishExtension.php000064400000002771150732302400014515 0ustar00addArgument('package', self::REQUIRED, 'The package: vendor/package or path.'); $this->addArgument('submodule', self::OPTIONAL, 'The package submodule to publish.'); $this->addOption('mode', 'M', InputOption::VALUE_OPTIONAL, 'Modes of publishing: publish or unpublish', 'publish'); } /** * Execute Command * * Example command: php galaxy make:controller base member * * @return int|null|void */ protected function exec() { // $this->confirm('Publishing can be destructive... Continue anyways? (y/n)'); $package = trim($this->getArgument('package'), '\\/'); $script = ltrim($this->getArgument('submodule', 'publish'), '/.\\'); if(is_file($path = TYPEROCKET_PATH . '/vendor/'.$package.'/ext/'.$script.'.php')) { /** @noinspection PhpIncludeInspection */ $cb = function($path) { require_once $path; }; $cb($path); $this->success(sprintf('Package %s published with %s', $package, $path)); } else { $this->error('Package script not found: ' . $path); } } }src/Console/Commands/MakeFields.php000064400000003260150732302400013210 0ustar00addArgument('name', self::REQUIRED, 'The service name.'); } /** * Execute Command * * Example command: php galaxy make:fields PostFields * * @return int|null|void */ protected function exec() { $name = $this->getClassArgument('name'); [$namespace, $class] = Str::splitAt('\\', $name, true); $namespace = implode('\\',array_filter([$this->getGalaxyMakeNamespace(), 'Http\Fields', $namespace])); $replacements = [ $namespace, $class]; $tags = ['{{namespace}}', '{{fields}}']; $app_path = \TypeRocket\Core\Config::get('paths.app'); $service_file = $app_path . '/Http/Fields/' . str_replace("\\",'/', $name) . ".php"; $service_path = substr($service_file, 0, -1 + -strlen(basename($service_file)) ) ; if( ! file_exists( $service_path ) ) { mkdir($service_path, 0755, true); } $template = __DIR__ . '/../../../templates/Fields.txt'; $file = new File( $template ); $service_file = $file->copyTemplateFile( $service_file, $tags, $replacements ); if( $service_file ) { $this->success('Fields created: ' . $name); } else { $this->error('TypeRocket ' . $name . ' already exists.'); } } }src/Console/Commands/DownloadWordPress.php000064400000014240150732302400014624 0ustar00archiveWP = TYPEROCKET_PATH . '/wp.zip'; $this->addArgument('type', self::OPTIONAL, 'Process WordPress themes and plugins: all, core, or cleanup'); $this->addArgument('path', self::OPTIONAL, 'The absolute path where WP will download'); $this->addOption('build', 'b', InputOption::VALUE_REQUIRED, 'Download nightly build or specific version of WordPress' ); } /** * Execute Command * * Example command: php galaxy wp:download * * @return void */ protected function exec() { $path = $this->getArgument('path'); $type = $this->getArgument('type'); $this->type = $type ?: 'all'; $this->path = rtrim( $path ? $path : Helper::wordPressRootPath(), '/'); switch($this->type) { case 'all' : $this->info('Downloading WordPress core with theme and plugin files.'); break; case 'core' : $this->info('Downloading WordPress core without theme and plugin files.'); break; case 'cleanup' : $this->warning('Default WordPress themes and plugins will be removed.'); $this->warning('If you have a theme name starting with twenty* if may have been removed.'); $this->confirm('Continue with download and cleanup? (y|n) '); break; default : $this->error('Invalid command options include: all, core, or cleanup'); die(); break; } $this->downloadWordPress(); $this->unArchiveWordPress(); $this->cleanWordPress(); } /** * Download WordPress */ protected function downloadWordPress() { // Remove old ZIP if(file_exists($this->archiveWP)) { unlink($this->archiveWP); } // Download $file = new File( $this->archiveWP ); $url = 'https://wordpress.org/latest.zip'; $build = $this->getOption('build'); if(!empty($build) && in_array($build, [ 'd', 'n', 'dev', 'develop', 'development', 'night', 'nightly'])) { $url = 'https://wordpress.org/nightly-builds/wordpress-latest.zip'; } elseif(!empty($build) && strpos($build, '.') !== false) { $url = 'https://wordpress.org/wordpress-'.$build.'.zip'; } $status = get_headers($url, 1); $code = $status[0] ?? null; if(strpos($code ?? '', '200') !== FALSE) { $this->success('Downloading WordPress from ' . $url); $file->download($url); } else { $this->error($status[0]); $this->error('Downloading WordPress failed ' . $url); die(); } } /** * Un-archive WordPress */ protected function unArchiveWordPress() { $zip = new \ZipArchive; if ( $zip->open( $this->archiveWP ) ) { $this->success('Extracting WordPress'); $location = $this->path . '/wp-unzip'; if( ! file_exists( $location ) ) { mkdir($location, File::DIR_PERMISSIONS, true); } $zip->extractTo( $location ); $zip->close(); $this->success('Moving files to ' . $this->path); $download = new File($location . '/wordpress'); $download->copyTo($this->path, false, true, $this->ignoreInDownload(), $this->getOption('verbose')); if(is_dir($location)) { rmdir($location); } } else { $this->error('Error opening archive file'); die(); } // Cleanup zip file if( file_exists( $this->archiveWP ) ) { unlink( $this->archiveWP ); $this->success('Downloaded archive deleted at ' . $this->archiveWP); } } /** * @return array|null */ protected function ignoreInDownload() { if($this->type !== 'core') { return null; } return [ 'wp-content/themes/twenty', 'wp-content/plugins/akismet', 'wp-content/plugins/hello.php', ]; } /** * Clean WordPress Themes */ protected function cleanWordPress() { if($this->type == 'cleanup') { $this->cleanWordPressThemes(); $this->cleanWordPressPlugins(); $this->info('Cleanup completed. Default WordPress themes and plugins removed.'); } return false; } /** * Clean WordPress Themes */ protected function cleanWordPressThemes() { $twentyThemes = glob( $this->path . "/wp-content/themes/twenty*/"); foreach ($twentyThemes as $value) { // Message $this->success('Deleting ' . $value); if( Str::starts( $this->path, $value) && file_exists( $value ) ) { // Delete theme ( new File($value) )->removeRecursiveDirectory(); } else { $this->error('Error deleting none project file ' . $value); } } } /** * Clean WordPress Themes */ protected function cleanWordPressPlugins() { $plugins = [ $this->path . '/wp-content/plugins/akismet', $this->path . '/wp-content/plugins/hello.php', ]; foreach ($plugins as $value) { // Message $this->success('Deleting ' . $value); if( Str::starts( $this->path, $value) && file_exists( $value ) ) { ( new File($value) )->removeRecursiveDirectory(); } else { $this->error('Error deleting none project file ' . $value); } } } }src/Console/Commands/MakeMigration.php000064400000003745150732302400013743 0ustar00addArgument('name', self::REQUIRED, 'The migration name.'); $this->addArgument('type', self::OPTIONAL, 'class or sql'); } /** * Execute Command * * Example command: php galaxy make:migration name_of_migration * * @return int|null|void */ protected function exec() { $name = Sanitize::underscore( $this->getArgument('name') ); $type = strtoupper($this->getArgument('type', 'sql')); $root = \TypeRocket\Core\Config::get('paths.migrations'); // Make directories if needed if( ! file_exists($root) ) { $this->warning('TypeRocket trying to locate ' . $root . ' for migrations.'); mkdir($root, 0755, true); $this->success('Location created...'); } $tags = ['{{name}}']; $replacements = [ $name ]; if($type === 'SQL') { $template = __DIR__ . '/../../../templates/Migration.txt'; $ext = ".sql"; } else { $template = __DIR__ . '/../../../templates/MigrationClass.txt'; $ext = ".php"; } // Make migration file $fileName = time() . '.' . $name . $ext; $new = $root . '/' . $fileName; $file = new File( $template ); $new = $file->copyTemplateFile( $new, $tags, $replacements ); if( $new ) { $this->success($type .' Migration created: ' . $name . ' as ' . $fileName ); } else { $this->error('TypeRocket migration ' . $name . ' already exists.'); } } }src/Console/Commands/MakePolicy.php000064400000003256150732302400013246 0ustar00addArgument('name', self::REQUIRED, 'The auth name.'); } /** * Execute Command * * Example command: php galaxy make:policy MyPolicy * * @return int|null|void */ protected function exec() { $name = $this->getClassArgument('name'); [$namespace, $class] = Str::splitAt('\\', $name, true); $namespace = implode('\\',array_filter([$this->getGalaxyMakeNamespace(), 'Auth', $namespace])); $replacements = [ $namespace, $class, Helper::appNamespace('Models\User') ]; $tags = ['{{namespace}}', '{{auth}}', '{{user}}']; $app_path = \TypeRocket\Core\Config::get('paths.app'); $policy_file = $app_path . '/Auth/' . str_replace("\\",'/', $name) . ".php"; $policy_path = substr($policy_file, 0, -1 + -strlen(basename($policy_file)) ) ; if( ! file_exists( $policy_path ) ) { mkdir($policy_path, 0755, true); } $template = __DIR__ . '/../../../templates/Auth.txt'; $file = new File( $template ); $policy_file = $file->copyTemplateFile( $policy_file, $tags, $replacements ); if( $policy_file ) { $this->success('Auth created: ' . $name ); } else { $this->error('TypeRocket ' . $name . ' already exists.'); } } }src/Console/Commands/Migrate.php000064400000005572150732302400012604 0ustar00addArgument('type', self::REQUIRED, 'The type of migration to run (up|down|reload|flush).'); $this->addArgument('steps', self::OPTIONAL, 'The limit of migrations to run as int.'); $this->addOption('path', 'p', self::OPTIONAL, 'Manually define migrations folder path.'); $this->addOption('wp_option', 'wo', self::OPTIONAL, 'Manually define migrations option name.'); } /** * Execute Command * * Example command: php galaxy wp:sql my_script * * @return int|null|void */ protected function exec() { $type = $this->getArgument('type'); $steps = $this->getArgument('steps'); $reload = false; if(!in_array($type, ['down','up','flush','reload'])) { $this->error('Migration type invalid. Use: up, down, reload, or flush.'); return; } if(!$steps && $type == 'up') { $steps = 99999999999999; } if(!$steps) { $steps = 1; } if($type == 'flush') { $type = 'down'; $steps = 99999999999999; } if($type == 'reload') { $type = 'down'; $reload = true; $steps = 99999999999999; } if($type === 'down') { $this->error('This action is highly destructive.'); if(!$this->continue()) { return; } } try { $path = $this->getOption('path'); $table = $this->getOption('wp_option'); $m = new \TypeRocket\Database\Migrate(); $results = $m->setOption($table)->runMigrationDirectory($type, $steps, $reload, $path, function($report, $result) { $this->success($report['message']); $this->success($result['message']); $this->warning("{$result['type']}:" ); $this->line($report['wpdb']); }); } catch (\Exception $e) { if(typerocket_env('WP_DEBUG', false)) { $this->error($e->getFile() . ':' . $e->getLine()); } $this->error($e->getMessage()); if($e instanceof SqlException) { $this->warning('Failed SQL:' ); $this->line( $e->getSql() ); $this->error( $e->getSqlError() ); } if($e instanceof MigrationException && $e->errorType === 'info') { return; } exit(1); } } }src/Console/Commands/MakeComponent.php000064400000006103150732302400013743 0ustar00addArgument('key', self::REQUIRED, 'The registered component config key.'); $this->addArgument('class', self::OPTIONAL, 'The component class name.'); $this->addArgument('title', self::OPTIONAL, 'The component title.'); } /** * Execute Command * * Example command: php galaxy make:command MyCommandClass space:name * * @return int|null|void */ protected function exec() { $command = $this->getClassArgument('class'); $title = $this->getArgument('title'); $key = $this->getArgument('key'); if(!$title) { $title = ucwords($key); } $key = Sanitize::underscore($key); if(!$command) { $command = Str::camelize($key); } [$namespace, $class] = Str::splitAt('\\', $command, true); $namespace = implode('\\',array_filter([$this->getGalaxyMakeNamespace(), 'Components', $namespace])); $tags = ['{{namespace}}', '{{component}}', '{{title}}']; $replacements = [ $namespace, $class, $title ]; $template = __DIR__ . '/../../../templates/Component.txt'; $app_path = \TypeRocket\Core\Config::get('paths.app'); $command_file = $app_path . '/Components/' . str_replace("\\",'/', $command) . ".php"; $command_path = substr($command_file, 0, -1 + -strlen(basename($command_file)) ) ; if( ! file_exists( $command_path ) ) { mkdir($command_path, 0755, true); } if( ! file_exists( $app_path . '/Components' ) ) { mkdir($app_path . '/Components', 0755, true); } $file = new File( $template ); $command_file = $file->copyTemplateFile( $command_file, $tags, $replacements ); if( $command_file ) { $this->success('Component created: ' . $command ); $file = new File(TYPEROCKET_CORE_CONFIG_PATH . '/components.php'); if($file->exists()) { $eol = PHP_EOL; $new = " '{$key}' => \\$namespace\\$class::class,{$eol}"; if(!$file->replaceOnLine("'registry' => [", "'registry' => [{$eol}{$new}")) { $this->warning('Register your new component ' . $command . ' to config/components.php' ); }; } $this->warning('Add your new component ' . $command . ' to a group in config/components.php' ); $this->warning('Add a thumbnail for your component: ' . \TypeRocket\Core\Config::get('urls.components') . '/' . Sanitize::underscore($command) . '.png' ); } else { $this->error('TypeRocket ' . $command . ' exists.'); } } }src/Console/Commands/MakeService.php000064400000003342150732302400013403 0ustar00addArgument('name', self::REQUIRED, 'The service name.'); } /** * Execute Command * * Example command: php galaxy make:service MyService * * @return int|null|void */ protected function exec() { $name = $this->getClassArgument('name'); [$namespace, $class] = Str::splitAt('\\', $name, true); $namespace = implode('\\',array_filter([$this->getGalaxyMakeNamespace(), 'Services', $namespace])); $replacements = [ $namespace, $class]; $tags = ['{{namespace}}', '{{service}}']; $app_path = \TypeRocket\Core\Config::get('paths.app'); $service_file = $app_path . '/Services/' . str_replace("\\",'/', $name) . ".php"; $service_path = substr($service_file, 0, -1 + -strlen(basename($service_file)) ) ; if( ! file_exists( $service_path ) ) { mkdir($service_path, 0755, true); } $template = __DIR__ . '/../../../templates/Service.txt'; $file = new File( $template ); $service_file = $file->copyTemplateFile( $service_file, $tags, $replacements ); if( $service_file ) { $this->success('Service created: ' . $name . ': Add your service to config/app.php under services.'); } else { $this->error('TypeRocket ' . $name . ' already exists.'); } } }src/Console/Commands/MakeCommand.php000064400000004627150732302400013370 0ustar00addArgument('class', self::REQUIRED, 'The command class name.'); $this->addArgument('name', self::REQUIRED, 'The command name used by galaxy.'); } /** * Execute Command * * Example command: php galaxy make:command MyCommandClass space:name * * @return int|null|void */ protected function exec() { $command = $this->getClassArgument('class'); $name = strtolower( $this->getArgument('name') ); [$namespace, $class] = Str::splitAt('\\', $command, true); $namespace = implode('\\',array_filter([$this->getGalaxyMakeNamespace(), 'Commands', $namespace])); $tags = ['{{namespace}}', '{{command}}', '{{name}}']; $replacements = [ $namespace, $class, $name ]; $template = __DIR__ . '/../../../templates/Command.txt'; $app_path = \TypeRocket\Core\Config::get('paths.app'); $command_file = $app_path . '/Commands/' . str_replace("\\",'/', $command) . ".php"; $command_path = substr($command_file, 0, -1 + -strlen(basename($command_file)) ) ; if( ! file_exists( $command_path ) ) { mkdir($command_path, 0755, true); } if( ! file_exists( $app_path . '/Commands' ) ) { mkdir($app_path . '/Commands', 0755, true); } $file = new File( $template ); $command_file = $file->copyTemplateFile( $command_file, $tags, $replacements ); if( $command_file ) { $this->success('Command created: ' . $command ); $file = new File(TYPEROCKET_CORE_CONFIG_PATH . '/galaxy.php'); if($file->exists()) { $eol = PHP_EOL; $new = " \\$namespace\\$class::class,{$eol}"; if(!$file->replaceOnLine("'commands' => [", "'commands' => [{$eol}{$new}")) { $this->warning('Register your new command ' . $command . ' to config/galaxy.php' ); }; } } else { $this->error('TypeRocket ' . $command . ' exists.'); } } }src/Console/Commands/ClearCache.php000064400000003263150732302400013161 0ustar00addArgument('folder', self::REQUIRED, 'The cache folder to delete all files from.'); } /** * Execute Command * * Example command: php galaxy make:controller base member * * @return int|null|void */ protected function exec() { $folder = Sanitize::underscore($this->getArgument('folder')); $cache_path = \TypeRocket\Core\Config::get('paths.cache'); if(!file_exists($cache_path)) { mkdir($cache_path, 0755, true); } if(!Str::starts( TYPEROCKET_ALT_PATH, $cache_path)) { $this->error('Error cache path found must be define in paths.php as "cache" using TYPEROCKET_ALT_PATH as root.'); } $location = $cache_path . "/{$folder}/*"; $glob = glob($location); if(empty($glob)) { $this->warning('No files found in: ' . $location); } foreach ($glob as $value) { if( Str::starts( TYPEROCKET_ALT_PATH, $value) && file_exists( $value ) ) { ( new File($value) )->removeRecursiveDirectory(); $this->warning('Deleted ' . $value); } else { $this->error('Error deleting none project file ' . $value); } } $this->success(sprintf('Cache %s cleared', $folder)); } }src/Console/Commands/MakeModel.php000064400000006750150732302400013051 0ustar00addArgument('directive', self::REQUIRED, 'The type: base, post or term.'); $this->addArgument('name', self::REQUIRED, 'The name of the model.'); $this->addArgument('id', self::OPTIONAL, 'The post, base or term WP ID. eg. post, page, category, post_tag...'); $this->addOption( 'controller', 'c', InputOption::VALUE_NONE, 'Make a controller as well' ); } /** * Execute Command * * Example command: php galaxy make:model base member * * @return int|null|void * @throws \Exception */ protected function exec() { $directive = $this->getArgument('directive'); $name = $this->getClassArgument('name'); $id = $this->getArgument('id'); switch ( strtolower($directive) ) { case 'base' : case 'post' : case 'term' : $directive = ucfirst($directive); break; default : $this->error('Type must be: base, post or term'); die(); break; } if( ! $id ) { if( $directive == 'Base') { $id = Str::splitAt('\\', strtolower(Inflect::pluralize($name)), true)[1]; } else { $id = strtolower($name); } } $this->makeFile($name, $directive, $id); } /** * Make file * * @param string $model * @param string $directive * @param string $id * * @throws \Exception */ protected function makeFile( $model, $directive, $id ) { [$namespace, $class] = Str::splitAt('\\', $model, true); $tags = ['{{namespace}}', '{{model}}', '{{id}}', '{{app}}']; $namespace = implode('\\',array_filter([$this->getGalaxyMakeNamespace(), 'Models', $namespace])); $replacements = [ $namespace, $class, str_replace('\\', '_', $id), $this->getGalaxyMakeNamespace() ]; $template = __DIR__ . '/../../../templates/Models/' . $directive . '.txt'; $app_path = \TypeRocket\Core\Config::get('paths.app'); $model_file = $app_path . '/Models/' . str_replace("\\",'/', $model) . ".php"; $model_path = substr($model_file, 0, -1 + -strlen(basename($model_file)) ) ; if( ! file_exists( $model_path ) ) { mkdir($model_path, 0755, true); } $file = new File( $template ); $model_file = $file->copyTemplateFile( $model_file, $tags, $replacements ); if( $model_file ) { $this->success('Model created: ' . $model . ' as ' . $directive . ''); } else { $this->error('TypeRocket ' . $model . ' already exists.'); } if ( $this->getOption('controller') ) { $command = $this->getApplication()->find('make:controller'); $input = new ArrayInput( [ 'directive' => $this->getArgument('directive'), 'name' => $model . 'Controller' ] ); $command->run($input, $this->output); } } }src/Console/Commands/MakeJob.php000064400000004511150732302400012514 0ustar00addArgument('class', self::REQUIRED, 'The job class name.'); } /** * Execute Command * * Example command: php galaxy make:job MyJobClass * * @return int|null|void */ protected function exec() { $className = $this->getClassArgument('class'); [$namespace, $class] = Str::splitAt('\\', $className, true); $namespace = implode('\\',array_filter([$this->getGalaxyMakeNamespace(), 'Jobs', $namespace])); $tags = ['{{namespace}}', '{{class}}']; $replacements = [ $namespace, $class ]; $template = __DIR__ . '/../../../templates/Job.txt'; $app_path = \TypeRocket\Core\Config::get('paths.app'); $job_file = $app_path . '/Jobs/' . str_replace("\\",'/', $className) . ".php"; $command_path = substr($job_file, 0, -1 + -strlen(basename($job_file)) ) ; if( ! file_exists( $command_path ) ) { mkdir($command_path, 0755, true); } if( ! file_exists( $app_path . '/Jobs' ) ) { mkdir($app_path . '/Jobs', 0755, true); } $file = new File( $template ); $job_file = $file->copyTemplateFile( $job_file, $tags, $replacements ); if( $job_file ) { $this->success('Job created: ' . $className ); $file = new File(TYPEROCKET_CORE_CONFIG_PATH . '/queue.php'); if($file->exists()) { $eol = PHP_EOL; $new = " \\$namespace\\$class::class,{$eol}"; if(!$file->replaceOnLine("'jobs' => [", "'jobs' => [{$eol}{$new}")) { $this->warning('Register your new job ' . $className . ' to config/queue.php' ); } else { $this->success('Your new job ' . $className . ' was added to config/queue.php' ); } } } else { $this->error('TypeRocket ' . $className . ' exists.'); } } }src/Console/Commands/CoreUpdate.php000064400000003103150732302400013233 0ustar00copyTo($path); $this->success('Core assets updated'); } else { $this->error('Core assets not found'); } if(file_exists($pro)) { File::new($pro)->copyTo($path); $this->success('Pro assets updated'); // merge manifests $mix = json_decode(file_get_contents($core . '/mix-manifest.json'), true); $mp = json_decode(file_get_contents($pro . '/mix-pro.json'), true); $both = array_merge($mix, $mp); $all = json_encode($both, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); file_put_contents($path . '/mix-manifest.json', $all); $this->success('mix-manifest.json and mix-pro.json merged'); } else { $this->info('TypeRocket Pro not found'); } } }src/Console/Commands/MakeController.php000064400000007573150732302400014140 0ustar00addArgument('directive', self::REQUIRED, 'The directive: base, thin, template, post or term.'); $this->addArgument('name', self::REQUIRED, 'The name of the resource for the controller.'); $this->addArgument('model', self::OPTIONAL, 'The model for the post or term controller.'); $this->addOption( 'model', 'm', InputOption::VALUE_NONE, 'Make a model as well' ); } /** * Execute Command * * Example command: php galaxy make:controller base member * * @return int|null|void * @throws \Exception */ protected function exec() { $directive = $this->getArgument('directive'); $name = $this->getClassArgument('name'); $model = $this->getArgument('model'); if( ! $model ) { if(Str::ends('Controller', $name)) { $model = substr($name, 0, -strlen('Controller')); } else { $model = $name; $name = $name . 'Controller'; } } switch ( strtolower($directive) ) { case 'base' : case 'post' : case 'thin' : case 'template' : case 'term' : $directive = ucfirst($directive); break; default : $this->error('Type must be: base, thin, template, post or term'); die(); break; } $this->makeFile($name, $directive, $model ); } /** * Make file * * @param string $controller * @param string $directive * @param string $model * @throws \Exception */ protected function makeFile( $controller, $directive, $model ) { [$namespace, $class] = Str::splitAt('\\', $controller, true); $mc = Str::splitAt('\\', $model, true)[1]; $tags = ['{{namespace}}', '{{controller}}', '{{model}}', '{{app}}', '{{mc}}', '{{var}}']; $namespace = implode('\\',array_filter([$this->getGalaxyMakeNamespace(), 'Controllers', $namespace])); $replacements = [ $namespace, $class, $model, $this->getGalaxyMakeNamespace(), $mc, Str::snake($mc) ]; $template = __DIR__ . '/../../../templates/Controllers/' . $directive . '.txt'; $app_path = \TypeRocket\Core\Config::get('paths.app'); $controller_file = $app_path . '/Controllers/' . str_replace("\\",'/', $controller) . ".php"; $controller_path = substr($controller_file, 0, -1 + -strlen(basename($controller_file)) ) ; if( ! file_exists( $controller_path ) ) { mkdir($controller_path, 0755, true); } $file = new File( $template ); $controller_file = $file->copyTemplateFile( $controller_file, $tags, $replacements ); if( $controller_file ) { $this->success('Controller created: ' . $controller . ' as ' . $directive ); } else { $this->error('TypeRocket ' . $controller . ' already exists.'); } if ( $this->getOption('model') ) { $directive = $this->getArgument('directive'); if( in_array($directive, ['thin', 'template']) ) { $directive = 'base'; } $command = $this->getApplication()->find('make:model'); $input = new ArrayInput( [ 'directive' => $directive, 'name' => $model ] ); $command->run($input, $this->output); } } }src/Console/Commands/GenerateSeed.php000064400000002026150732302400013536 0ustar00replaceOnLine('PUT_TYPEROCKET_SEED_HERE', $seed ); if($found) { $this->success('Seeded config/app.php with: ' . $seed ); } else { $this->error('Manually Seed config/app.php with: ' . $seed); } } catch ( \Exception $e ) { $this->error('File empty or missing'); } } }src/Console/Commands/RootInstall.php000064400000006754150732302400013471 0ustar00addArgument('database', self::REQUIRED, 'The database name'); $this->addArgument('username', self::REQUIRED, 'The database username'); $this->addArgument('password', self::REQUIRED, 'The database user password'); } /** * Execute Command * * Example command: php galaxy root:install * * @return int|null|void * @throws \Exception */ protected function exec() { // Check for WordPress folder if( ! file_exists( TYPEROCKET_PATH . '/wordpress' ) ) { $this->error('WordPress folder missing or moved'); die(); } // Define file paths $this->configSampleWP = TYPEROCKET_PATH . '/wordpress/wp-config-sample.php'; $this->configWP = TYPEROCKET_PATH . '/wp-config.php'; if(!defined('TYPEROCKET_ROOT_INSTALL')) define('TYPEROCKET_ROOT_INSTALL', true); // Fail if already installed if( file_exists( $this->configSampleWP ) ) { $this->error('WordPress may already be installed. Remove all old WordPress files to run root install.'); die(); } // Run $this->runCommand('wp:download'); $this->configWordPress(); $this->runCommand('config:seed'); $this->success('TypeRocket is connected, Happy coding!'); } /** * Configure WordPress * * @return bool * @throws \Exception */ protected function configWordPress() { // Check for wp-config.php if( file_exists($this->configWP) ) { $this->error('wp-config.php already exists in TypeRocket'); return false; } // Message $this->success('Creating wp-config.php'); // Copy files copy( $this->configSampleWP , $this->configWP ); $file = new File($this->configWP); // Add init.php $needle = '/require_once.*wp-settings.php.\s*?\)?\;/m'; $replace = "require __DIR__ . '/init.php'; // Init TypeRocket" . PHP_EOL; $replace .= "require_once( ABSPATH . 'wp-settings.php' );"; if( ! $file->replaceOnLine($needle, $replace, true) ) { $this->error('The TypeRocket init.php file was not included in wp-config.php'); } // WP config $file->replaceOnLine('database_name_here', $this->getArgument('database')); $file->replaceOnLine('username_here', $this->getArgument('username')); $file->replaceOnLine('password_here', $this->getArgument('password')); // Salts $lines = (array) file('https://api.wordpress.org/secret-key/1.1/salt/'); $regex = "/define(.*)here\'\s?\)\;/m"; preg_match_all($regex, file_get_contents( $file->file ) , $matches); if( !empty($lines) && count( $lines ) == count($matches[0]) ) { foreach ($lines as $index => $line ) { $file->replaceOnLine($matches[0][$index], $line ); } } else { // Error $this->error('WordPress salts failed'); } return true; } } src/Console/Commands/MakeRule.php000064400000003314150732302400012711 0ustar00addArgument('key', self::REQUIRED, 'The rule key.'); $this->addArgument('class', self::REQUIRED, 'The rule class name.'); } /** * Execute Command * * @return int|null|void */ protected function exec() { $ruleClass = $this->getClassArgument('class'); $ruleKey = $this->getClassArgument('key'); [$namespace, $class] = Str::splitAt('\\', $ruleClass, true); $namespace = implode('\\',array_filter([$this->getGalaxyMakeNamespace(), 'Rules', $namespace])); $tags = ['{{namespace}}', '{{class}}', '{{key}}']; $replacements = [ $namespace, $class, $ruleKey ]; $template = __DIR__ . '/../../../templates/Rule.txt'; $app_path = \TypeRocket\Core\Config::get('paths.app'); $rule_file = $app_path . '/Rules/' . str_replace("\\",'/', $ruleClass) . ".php"; $rule_folder = substr($rule_file, 0, -1 + -strlen(basename($rule_file)) ) ; if( ! file_exists( $rule_folder ) ) { mkdir($rule_folder, 0755, true); } $rule_file = File::new($template)->copyTemplateFile( $rule_file, $tags, $replacements ); if( $rule_file ) { $this->success('Rule created: ' . $ruleClass ); } else { $this->error('TypeRocket ' . $ruleClass . ' already exists.'); } } }src/Console/Commands/MakeMiddleware.php000064400000003705150732302400014063 0ustar00addArgument('name', self::REQUIRED, 'The name of the middleware using same letter case.'); } /** * Execute Command * * Example command: php galaxy make:middleware MiddlewareName * * @return int|null|void */ protected function exec() { $middleware = $this->getClassArgument('name'); $this->makeFile($middleware); } /** * Make file * * @param string $middleware */ protected function makeFile( $middleware ) { [$namespace, $class] = Str::splitAt('\\', $middleware, true); $tags = ['{{namespace}}', '{{middleware}}']; $namespace = implode('\\',array_filter([$this->getGalaxyMakeNamespace(), 'Http\Middleware', $namespace])); $replacements = [ $namespace, $class ]; $template = __DIR__ . '/../../../templates/Middleware.txt'; $app_path = \TypeRocket\Core\Config::get('paths.app'); $middleware_file = $app_path . '/Http/Middleware/' . str_replace("\\",'/', $middleware) . ".php"; $middleware_path = substr($middleware_file, 0, -1 + -strlen(basename($middleware_file)) ) ; if( ! file_exists( $middleware_path ) ) { mkdir($middleware_path, 0755, true); } $file = new File( $template ); $middleware_file = $file->copyTemplateFile( $middleware_file, $tags, $replacements ); if( $middleware_file ) { $this->success('Controller created: ' . $middleware ); } else { $this->error('TypeRocket ' . $middleware . ' already exists.'); } } }src/Console/Commands/MakeComposer.php000064400000004333150732302400013573 0ustar00addArgument('class', self::REQUIRED, 'The name of the view composer.'); $this->addArgument('type', self::OPTIONAL, 'The type of the view composer.'); } /** * Execute Command * * @return int|null|void * @throws \Exception */ protected function exec() { $class = $this->getClassArgument('class'); $type = $this->getArgument('type'); $this->makeFile($class, $type); } /** * Make file * * @param string $class * * @throws \Exception */ protected function makeFile($class, $type) { [$namespace, $class] = Str::splitAt('\\', $class, true); $tags = ['{{namespace}}', '{{class}}']; $namespace = implode('\\',array_filter([$this->getGalaxyMakeNamespace(), 'Composers', $namespace])); $replacements = [ $namespace, $class ]; switch ($type) { case 'post' : $template = __DIR__ . '/../../../templates/Composers/PostTypeModelComposer.txt'; break; default : $template = __DIR__ . '/../../../templates/Composers/Composer.txt'; break; } $app_path = \TypeRocket\Core\Config::get('paths.app'); $composer_file = $app_path . '/Composers/' . str_replace("\\",'/', $class) . ".php"; $composer_path = substr($composer_file, 0, -1 + -strlen(basename($composer_file)) ) ; if( ! file_exists( $composer_path ) ) { mkdir($composer_path, 0755, true); } $composer_file = File::new($template)->copyTemplateFile( $composer_file, $tags, $replacements ); if( $composer_file ) { $this->success('Composer ' . $class . ' created at ' . $composer_file); } else { $this->error('Composer ' . $class . ' already exists.'); } } }src/Console/Commands/SQL.php000064400000002447150732302400011651 0ustar00addArgument('name', self::REQUIRED, 'The name of the SQL script to run.'); } /** * Execute Command * * Example command: php galaxy wp:sql my_script * * @return int|null|void */ protected function exec() { $name = $this->getArgument('name'); $file_sql = TYPEROCKET_PATH . '/sql/' . $name . '.sql'; $this->warning("Running {$file_sql}:" ); try { (new SqlRunner())->runQueryFile($file_sql, function($report) use ($file_sql) { $this->success($report['message']); $this->line($report['wpdb']); }); } catch (\Exception $e) { $this->error($e->getMessage()); if($e instanceof SqlException) { $this->warning('Failed SQL:' ); $this->line( $e->getSql() ); $this->error( $e->getSqlError() ); } } } }src/Console/Command.php000064400000016312150732302400011023 0ustar00command[0], 2); $name = array_shift($signature); $this->setName($name) ->setDescription($this->command[1]) ->setHelp($this->command[2]); if($signature) { // Match Laravel style: name:command {?user*} {?name=kevin} {?--option=some value} preg_match_all('/(\{.+\})/mU', $signature[0], $matches, PREG_SET_ORDER, 0); foreach ($matches as [$arg, $other]) { $arg = substr($arg, 1, -1); $mode = static::REQUIRED; $shortcut = null; $is_option = false; [$arg, $default] = array_pad(explode('=', $arg, 2), 2, null); if(trim($arg, '?') !== $arg) { $mode = static::OPTIONAL; $arg = trim($arg, '?'); } if($arg[0] == '-') { $arg = ltrim($arg, '-'); [$shortcut, $arg] = array_pad(explode('|', $arg, 2), 2, null); if(is_null($arg)) { $arg = $shortcut; $shortcut = $arg[0]; } $is_option = true; } if(trim($arg, '*') !== $arg || ($default == '*' && $is_option)) { $mode = $mode + static::IS_ARRAY; $arg = trim($arg, '*'); $default = null; } if($is_option) { $bitWiseDiff = InputOption::VALUE_REQUIRED / static::REQUIRED; $this->addOption($arg, $shortcut, $mode * $bitWiseDiff, '', $default); } else { $this->addArgument($arg, $mode, '', $default); } } } $this->config(); } /** * @param InputInterface $input * @param OutputInterface $output * * @return int|null */ protected function execute(InputInterface $input, OutputInterface $output) { $this->input = $input; $this->output = $output; $this->exec(); return $this->success ?? 0; } /** * Add your configuration */ protected function config() { } /** * Add your execution */ protected function exec() { } /** * Output error line * * @param string $content */ protected function error( $content ) { $this->printedError = true; $this->output->writeln(''.$content.''); } /** * Output success line * * @param string $content */ protected function success($content) { $this->output->writeln(''.$content.''); } /** * Output warning line * * @param string $content */ protected function warning($content) { $this->output->writeln(''.$content.''); } /** * Output info line * * @param string $content */ protected function info($content) { $this->output->writeln(''.$content.''); } /** * Output line * * @param string $content */ protected function line($content) { $this->output->writeln($content); } /** * Confirm * * Die is not true. * * https://symfony.com/doc/3.4/components/console/helpers/questionhelper.html * * @param string|null $question The question to ask to the user * @param bool $default The default answer to return, true or false * @param string $trueAnswerRegex A regex to match the "yes" answer */ protected function confirm($question = null, $default = false, $trueAnswerRegex = '/^y/i') { if (!$this->continue(...func_get_args())) { die(); } } /** * Continue * * https://symfony.com/doc/3.4/components/console/helpers/questionhelper.html * * @param string|null $question The question to ask to the user * @param bool $default The default answer to return, true or false * @param string $trueAnswerRegex A regex to match the "yes" answer * * @return bool */ protected function continue($question = null, $default = false, $trueAnswerRegex = '/^y/i') { $question = new ConfirmationQuestion(($question ?? 'Continue with this action? (y|n)') . ' ', $default, $trueAnswerRegex); return $this->getHelper('question')->ask($this->input, $this->output, $question); } /** * Get Argument * * @param string $name * @param null|string $default * * @return mixed */ protected function getArgument( $name, ?string $default = null ) { return $this->input->getArgument($name) ?? $default; } /** * @param string $name * @param array $args * * @throws \Exception */ protected function runCommand($name, array $args = []) { $command = $this->getApplication()->find($name); $input = new ArrayInput( $args ); $command->run($input, $this->output); } /** * Get Option * * @param string $name * @param string|null $default * * @return mixed */ protected function getOption( $name, ?string $default = null ) { return $this->input->getOption($name) ?? $default; } /** * Get Class Arg * * @param $arg * * @return mixed|string|string[]|null */ public function getClassArgument($arg) { $arg = $this->getArgument($arg); $arg = str_replace("/",'\\', $arg); $arg = preg_replace('/(\\\\+)/m','\\', $arg); return $arg; } /** * @param null|string $append * * @return string */ public function getGalaxyMakeNamespace($append = null) { if(!defined('TYPEROCKET_GALAXY_MAKE_NAMESPACE')) { define('TYPEROCKET_GALAXY_MAKE_NAMESPACE', Helper::appNamespace()); } $space = $append ? "\\" . TYPEROCKET_GALAXY_MAKE_NAMESPACE . "\\" : TYPEROCKET_GALAXY_MAKE_NAMESPACE; return $space . ltrim($append, '\\'); } }src/Models/Traits/MetaData.php000064400000007713150732302400012221 0ustar00 null, 'foreign' => null, ]; } /** * Posts Meta Fields * * @param bool $withoutPrivate * * @return null|\TypeRocket\Models\Model */ public function meta( $withoutPrivate = false ) { $meta = $this->hasMany( $this->getMetaModelClass(), $this->getMetaIdColumns()['foreign'], function($rel) use ($withoutPrivate) { if( $withoutPrivate ) { $rel->notPrivate(); } } ); return $meta; } /** * Posts Meta Fields Without Private * * @return null|\TypeRocket\Models\Model */ public function metaWithoutPrivate() { return $this->meta( true ); } /** * Get Number of Meta Queries * * @return int */ public function resetNumMetaQueries() { return static::$metaQueries = 0; } /** * Where Meta * * @param string|array $key * @param string $operator * @param string|int|null|bool $value * @param string $condition * * @return Model|MetaData */ public function whereMeta($key, $operator = '=', $value = null, $condition = 'AND') { $counter = &static::$metaQueries; $num = func_num_args(); if($num == 2) { $value = $operator; $operator = '='; } $table = $this->getTable(); $idColumns = $this->getMetaIdColumns(); $modelMetaClass = $this->getMetaModelClass(); $meta_table = (new $modelMetaClass)->getTable(); if(is_array($key)) { $operator = strtoupper($operator); $condition = in_array($operator, ['AND', 'OR', '||', '&&']) ? $operator : 'AND'; $where = array_map(function($value) use ($meta_table, &$counter, $table, $idColumns) { if(is_string($value)) { return strtoupper($value); } $table_alias = 'tr_mt' . $counter++; $this->join( $meta_table . ' AS ' . $table_alias, "`{$table}`.`{$idColumns['local']}`", "`{$table_alias}`.`{$idColumns['foreign']}`" ); $key = $value['column']; $operator = $value['operator']; $value = $value['value']; return [ [ 'column' => "`{$table_alias}`.`meta_key`", 'operator' => '=', 'value' => $key, ], 'AND', [ 'column' => "`{$table_alias}`.`meta_value`", 'operator' => $operator, 'value' => $value, ] ]; }, $key); } else { $table_alias = 'tr_mt' . $counter++; $this->join( $meta_table . ' AS ' . $table_alias, "`{$table}`.`{$idColumns['local']}`", "`{$table_alias}`.`{$idColumns['foreign']}`" ); $where = [ [ 'column' => "`{$table_alias}`.`meta_key`", 'operator' => '=', 'value' => $key, ], 'AND', [ 'column' => "`{$table_alias}`.`meta_value`", 'operator' => $operator, 'value' => $value, ] ]; } return $this->where($where, $condition); } }src/Models/Traits/Searchable.php000064400000004061150732302400012563 0ustar00paginate($limit); $return = []; if($results) { foreach($results as $result) { $return[] = $this->formatSearchResult($result); } } return ['items' => $return, 'count' => $results ? $results->getCount() : 0]; } /** * Format Result * * @param $result * * @return array */ protected function formatSearchResult($result) { if(method_exists($result, 'getFieldOptionKey')) { $title = $result->getFieldOptionKey($result->{$this->getSearchColumn()}); } else { $title = $result->{$this->getSearchColumn()}; } return [ 'title' => $title, 'id' => $result->{$this->getSearchIdColumn()} ]; } /** * Get Search Column * * @return string */ public function getSearchColumn() { return $this->searchColumn ?? $this->getFieldOptions()['key'] ?? $this->getIdColumn(); } /** * Get Search ID Column * * @return string */ public function getSearchIdColumn() { return $this->searchIdColumn ?? $this->getFieldOptions()['value'] ?? $this->getIdColumn(); } /** * Find For Search * * @param $value * * @return mixed|Model */ public function findForSearch($value) { return $this->findById($value); } /** * Get Search Result * * @return array */ public function getSearchResult() { return $this->formatSearchResult($this); } /** * @return null|string */ public function getSearchUrl() { return null; } }src/Models/Traits/FieldValue.php000064400000002127150732302400012553 0ustar00getDots(); } $data = $this->getFormFields(); if( $this->old ) { $data = Data::walk($field, $this->old); $data = wp_unslash($data); } elseif( ! $this->onlyOld ) { $data = Data::walk($field, $data); } else { return null; } return $data; } public function getFormFields() { return []; } /** * Get old stored fields * * @param bool $load_only_old */ public function oldStore( $load_only_old = false) { if( !empty($_COOKIE[Redirect::KEY_OLD]) ) { $this->old = (new Cookie)->getTransient(Redirect::KEY_OLD); } $this->onlyOld = $load_only_old; } }src/Models/Traits/ArrayReplaceRecursiveValues.php000064400000005036150732302400016157 0ustar00arrayReplaceRecursiveKeys[$key] = $callback; return $this; } /** * @param string $key * * @return $this */ public function removeArrayReplaceRecursiveKey(string $key) { unset($this->arrayReplaceRecursiveKeys[$key]); return $this; } /** * @param array $stops * * @return $this */ public function extendArrayReplaceRecursiveStops(string $key, array $stops) { if(!array_key_exists($key, $this->arrayReplaceRecursiveKeys)) { $this->arrayReplaceRecursiveKeys[$key] = null; } $stops = array_merge($this->arrayReplaceRecursiveStops[$key] ?? [], $stops); $this->arrayReplaceRecursiveStops[$key] = array_unique(array_values($stops)); return $this; } /** * @param string $key * * @return $this */ public function setArrayReplaceRecursiveStops(string $key, array $stops) { if(!array_key_exists($key, $this->arrayReplaceRecursiveKeys)) { $this->arrayReplaceRecursiveKeys[$key] = null; } $this->arrayReplaceRecursiveStops[$key] = array_unique(array_values($stops)); return $this; } /** * @param string $key * * @return $this */ public function removeArrayReplaceRecursiveStops(string $key) { unset($this->arrayReplaceRecursiveKeys[$key]); return $this; } /** * @param string $key * @param mixed $current_value * @param mixed $new_value * * @return array|mixed */ public function getNewArrayReplaceRecursiveValue(string $key, $current_value, $new_value) { if(!array_key_exists($key, $this->arrayReplaceRecursiveKeys) || !is_array($new_value) || !is_array($current_value) ) { return $new_value; } if(is_callable($this->arrayReplaceRecursiveKeys[$key])) { $new_value = call_user_func($this->arrayReplaceRecursiveKeys[$key], $new_value, $current_value, $key); } return Arr::replaceRecursivePreferNew($current_value, $new_value, $this->arrayReplaceRecursiveStops[$key] ?? []); } }src/Models/WPUser.php000064400000026027150732302400010457 0ustar00 'user_email', 'value' => 'ID', ]; protected $builtin = [ 'user_login', 'user_nicename', 'user_email', 'user_url', 'user_activation_key', 'user_status', 'display_name', 'user_registered', 'id', 'user_pass' ]; protected $guard = [ 'id' ]; protected $private = [ 'user_pass' ]; /** * Return table name in constructor * * @param \wpdb $wpdb * * @return string */ public function initTable( $wpdb ) { return $wpdb->users; } /** * Get Meta Model Class * * @return string */ protected function getMetaModelClass() { return WPUserMeta::class; } /** * Get ID Columns * * @return array */ protected function getMetaIdColumns() { return [ 'local' => 'ID', 'foreign' => 'user_id', ]; } /** * @return string|null */ public function getRestMetaType() { return 'user'; } /** * Users Posts * * @param string $modelClass * * @return null|Model */ public function posts( $modelClass = WPPost::class ) { return $this->hasMany( $modelClass, 'post_author'); } /** * Find WP_User Instance * * @param \WP_User|int|null $user * @param bool $returnModel * * @return \WP_User|$this|null */ public function wpUser( $user = null, $returnModel = false ) { if( !$user && $this->wpUser instanceof \WP_User ) { return $this->wpUser; } if( !$user && $this->getID() ) { return $this->wpUser($this->getID()); } if( !$user ) { return $this->wpUser; } if( is_numeric($user) ) { $user = get_user_by( 'id', $user ); } if( $user instanceof \WP_User) { $this->wpUser = $user; $this->castProperties( $user->to_array() ); } return $returnModel ? $this : $this->wpUser; } /** * After Properties Are Cast * * Create an Instance of WP_Post * * @return Model */ protected function afterCastProperties() { if(!$this->wpUser && $this->getCache()) { $_user = (object) $this->properties; $this->wpUser = new \WP_User($_user); update_user_caches( $this->wpUser ); } return parent::afterCastProperties(); } /** * Is Capable * * @param $capability * @return bool */ public function isCapable($capability) { /** @var \WP_User|null $user */ $user = $this->wpUser(); if(!$user || !$user->has_cap($capability)) { return false; } return true; } /** * Has Role * * @param string $role * @return bool */ public function hasRole($role) { /** @var \WP_User|null $user */ $user = $this->wpUser(); return in_array($role, $user->roles) ? true : false; } /** * Change Users Role * * WordPress is not designed to give users multiple roles. * * @param $role * @param array $remove a blank array removes all old roles * @return $this * @throws \Exception */ public function changeRoleTo($role, $remove = []) { /** @var \WP_User|null $user */ $user = $this->wpUser(); if(!wp_roles()->get_role($role)) { throw new \Exception("Role {$role} does not exist. User's role can not be changed"); } foreach ($user->roles as $old) { if(empty($remove) || in_array($old, $remove)) { $user->remove_role( $old ); } } $user->add_role( $role ); return $this; } /** * Is Current User * * @return bool */ public function isCurrent() { return $this->getID() == Container::resolveAlias(AuthUser::ALIAS)->getID(); } /** * Create users from TypeRocket fields * * @param array|Fields $fields * * @return $this * @throws ModelException */ public function create( $fields = [] ) { $fields = $this->provisionFields( $fields ); $builtin = $this->getFilteredBuiltinFields( $fields ); $user = null; do_action('typerocket_model_create', $this, $fields); if ( ! empty( $builtin )) { $builtin = $this->slashBuiltinFields($builtin); remove_action( 'user_register', 'TypeRocket\Http\Responders\Hook::users' ); $user = wp_insert_user( $builtin ); add_action( 'user_register', 'TypeRocket\Http\Responders\Hook::users' ); if ($user instanceof WP_Error || ! is_int( $user )) { throw new ModelException('WPUser not created'); } else { $user = $this->findById($user); } } $this->saveMeta( $fields ); do_action('typerocket_model_after_create', $this, $fields, $user); return $user; } /** * Update user from TypeRocket fields * * @param array|Fields $fields * * @return $this * @throws ModelException */ public function update( $fields = [] ) { $id = $this->getID(); if ($id != null) { $fields = $this->provisionFields( $fields ); $builtin = $this->getFilteredBuiltinFields( $fields ); $user = null; do_action('typerocket_model_update', $this, $fields); if ( ! empty( $builtin )) { $builtin = $this->slashBuiltinFields($builtin); remove_action( 'profile_update', 'TypeRocket\Http\Responders\Hook::users' ); $builtin['ID'] = $id; $user_login = $builtin['user_login'] ?? null; $user_login_current = $this->getFieldValue('user_login'); if( !empty($user_login) && $user_login !== $user_login_current ) { throw new ModelException('WPUser not updated: You can not change the user_login'); } $user = wp_update_user( $builtin ); add_action( 'profile_update', 'TypeRocket\Http\Responders\Hook::users' ); if( empty($user) ) { throw new ModelException('WPUser not updated'); } $this->findById($id); } $this->saveMeta( $fields ); do_action('typerocket_model_after_update', $this, $fields, $user); } else { $this->errors = ['No item to update']; } return $this; } /** * Delete & Reassign User * * This will delete the user and resign their content to another user * * @param int $to_user_id * @param null|int $user_id * * @return $this * @throws ModelException */ public function deleteAndReassign($to_user_id, $user_id = null) { if(is_null($user_id) && $this->hasProperties()) { $user_id = $this->getID(); } do_action('typerocket_model_delete', $this, $user_id); $delete = wp_delete_user($user_id, $to_user_id); if ( !$delete ) { throw new ModelException('WPUser not deleted'); } do_action('typerocket_model_after_delete', $this, $to_user_id, $delete); return $this; } /** * Delete User * * This will delete the user and all of their posts * * @param null|int $ids * * @return $this * @throws ModelException */ public function delete($ids = null) { if(is_null($ids) && $this->hasProperties()) { $ids = $this->getID(); } if(is_array($ids)) { throw new ModelException(static::class . ' not deleted: bulk deleting not supported due to WordPress performance issues.'); } do_action('typerocket_model_delete', $this, $ids); $delete = wp_delete_user($ids); if ( !$delete ) { throw new ModelException('WPUser not deleted'); } do_action('typerocket_model_after_delete', $this, $ids, $delete); return $this; } /** * Save user meta fields from TypeRocket fields * * @param array|ArrayObject $fields * * @return $this */ public function saveMeta( $fields ) { $fields = $this->getFilteredMetaFields( $fields ); $id = $this->getID(); if ( ! empty( $fields ) && ! empty( $id )) : foreach ($fields as $key => $value) : if (is_string( $value )) { $value = trim( $value ); } $current_value = get_user_meta( $id, $key, true ); $value = $this->getNewArrayReplaceRecursiveValue($key, $current_value, $value); if (isset( $value ) && $value !== $current_value) : $value = wp_slash($value); update_user_meta( $id, $key, $value ); do_action('typerocket_after_save_meta_user', $id, $key, $value, $current_value, $this); elseif ( ! isset( $value ) || $value === "" && ( isset( $current_value ) || $current_value === "" )) : delete_user_meta( $id, $key ); endif; endforeach; endif; return $this; } /** * Get base field value * * Some fields need to be saved as serialized arrays. Getting * the field by the base value is used by Fields to populate * their values. * * @param string $field_name * * @return null */ public function getBaseFieldValue( $field_name ) { $id = $this->getID(); $field_name = $field_name === 'ID' ? 'id' : $field_name; if($field_name == 'user_pass') { $data = ''; } else { $data = $this->getProperty($field_name); } if(is_null($data)) { $data = get_metadata( 'user', $id, $field_name, true ); } return $this->getValueOrNull( $data ); } /** * Builtin * * @param array $builtin * @return mixed */ public function slashBuiltinFields( $builtin ) { $fields = [ 'display_name', ]; foreach ($fields as $field) { if(!empty($builtin[$field])) { $builtin[$field] = wp_slash( $builtin[$field] ); } } return $builtin; } }src/Models/AuthUser.php000064400000000645150732302400011030 0ustar00 'name', 'value' => 'term_id', ]; protected $builtin = [ 'description', 'name', 'slug', 'term_group' ]; protected $guard = [ 'term_id', 'term_taxonomy_id', 'taxonomy', 'term_group', 'parent', 'count', ]; public function __construct($taxonomy = null) { $this->setTaxonomy($taxonomy ?? static::TAXONOMY); parent::__construct(); } /** * Get Taxonomy * * @return string */ public function getTaxonomy() { return $this->taxonomy; } /** * Set Taxonomy * * @param string|null $taxonomy * @param bool $init init query when setting taxonomy * @return $this */ public function setTaxonomy($taxonomy = null, $init = false) { if($taxonomy) { $this->taxonomy = $taxonomy; } if($init) { $this->initQuery($this->query); } return $this; } /** * Return table name in constructor * * @param \wpdb $wpdb * * @return string */ public function initTable( $wpdb ) { return $wpdb->terms; } /** * Init Query * * @param Query $query * * @return mixed */ protected function initQuery(Query $query) { if($tax = $this->getTaxonomy()) { /** @var \wpdb $wpdb */ global $wpdb; $tt = $wpdb->term_taxonomy; $query->setSelectTable(null); $query->select($this->table.'.*', $tt.'.taxonomy', $tt.'.term_taxonomy_id', $tt.'.description'); $query->join($tt, $tt.'.term_id', $this->table.'.term_id'); $query->where($tt.'.taxonomy', $tax); } return $query; } /** * Get JsonApiResource * * @return string|null */ public function getRouteResource() { return $this->getTaxonomy(); } /** * @return string|null */ public function getRestMetaType() { return 'term'; } /** * @return string|null */ public function getRestMetaSubtype() { return $this->getTaxonomy(); } /** * Get Meta Model Class * * @return string */ protected function getMetaModelClass() { return WPTermMeta::class; } /** * Get ID Columns * * @return array */ protected function getMetaIdColumns() { return [ 'local' => 'term_id', 'foreign' => 'term_id', ]; } /** * Get Term Permalink * * @return string|\WP_Error */ public function permalink() { return get_term_link($this->wpTerm(), $this->getTaxonomy()); } /** * @return string|\WP_Error */ public function getSearchUrl() { return $this->permalink(); } /** * Belongs To Post * * @param string $modelClass * @param null|callable $scope * @param bool $reselect * * @return Model|null */ public function belongsToPost($modelClass, $scope = null, $reselect = true) { global $wpdb; return $this->belongsToMany($modelClass, $wpdb->term_relationships, 'term_taxonomy_id', 'object_id', $scope, $reselect); } /** * After Properties Are Cast * * Create an Instance of WP_Term * * @return Model */ protected function afterCastProperties() { if(!$this->wpTerm && $this->getTaxonomy() && $this->getCache()) { $_term = sanitize_term( (object) $this->properties, $this->getTaxonomy(), 'raw' ); wp_cache_add( $_term->term_id, $_term, 'terms' ); $this->wpTerm = new \WP_Term($_term); } return parent::afterCastProperties(); } /** * Get Term Taxonomy * * @return null|\TypeRocket\Models\Model */ public function termTaxonomies() { return $this->hasMany( WPTermTaxonomy::class, 'term_id' ); } /** * Get WP_Term Instance * * @param \WP_Term|null|int * @param bool $returnModel * * @return \WP_Term|$this|null */ public function wpTerm( $term = null, $returnModel = false) { if( !$term && $this->wpTerm instanceof \WP_Term ) { return $this->wpTerm; } if( !$term && $this->getID() ) { return $this->wpTerm($this->getID()); } if(!$term) { return $this->wpTerm; } $term = get_term( $term ); if( $term instanceof \WP_Term) { $this->setTaxonomy($term->taxonomy, true); $this->wpTerm = $term; $this->castProperties( $term->to_array() ); } return $returnModel ? $this : $this->wpTerm; } /** * Create term from TypeRocket fields * * Set the taxonomy property on extended model so they * are saved to the correct type. See the CategoriesModel * as example. * * @param array|\TypeRocket\Http\Fields $fields * * @return WPTerm * @throws \TypeRocket\Exceptions\ModelException */ public function create( $fields = [] ) { $fields = $this->provisionFields( $fields ); $builtin = $this->getFilteredBuiltinFields($fields); $term = null; do_action('typerocket_model_create', $this, $fields); if ( ! empty( $builtin ) ) { $builtin = $this->slashBuiltinFields($builtin); remove_action('create_term', 'TypeRocket\Http\Responders\Hook::taxonomies'); $name = $builtin['name']; unset($builtin['name']); $term = wp_insert_term( $name, $this->taxonomy, $builtin ); add_action('create_term', 'TypeRocket\Http\Responders\Hook::taxonomies'); if ( $term instanceof \WP_Error || empty($term['term_id']) ) { throw new ModelException('WPTerm not created: name field and taxonomy property are required'); } else { $term = (new self($this->taxonomy))->findById( $term['term_id'] ); } } $this->saveMeta( $fields ); do_action('typerocket_model_after_create', $this, $fields, $term); return $term; } /** * Update term from TypeRocket fields * * @param array|\TypeRocket\Http\Fields $fields * * @return $this * @throws \TypeRocket\Exceptions\ModelException */ public function update( $fields = [] ) { $id = $this->getID(); if($id != null) { $fields = $this->provisionFields( $fields ); $builtin = $this->getFilteredBuiltinFields($fields); $term = null; do_action('typerocket_model_update', $this, $fields); if ( ! empty( $builtin ) ) { $builtin = $this->slashBuiltinFields($builtin); remove_action('edit_term', 'TypeRocket\Http\Responders\Hook::taxonomies'); $term = wp_update_term( $id, $this->taxonomy, $builtin ); add_action('edit_term', 'TypeRocket\Http\Responders\Hook::taxonomies'); if ( $term instanceof \WP_Error || empty($term['term_id']) ) { throw new ModelException('WPTerm not updated: name is required'); } else { $this->findById($id); } } $this->saveMeta( $fields ); do_action('typerocket_model_after_update', $this, $fields, $term); } else { $this->errors = ['No item to update']; } return $this; } /** * Update Term Count * * @throws ModelException */ public function updateTermCount() { $id = $this->getID(); if(!$this->getTaxonomy() || !$id) { throw new ModelException('Taxonomy and ID required to use updateTermCount()'); } wp_update_term_count_now([$id], $this->getTaxonomy()); return $this; } /** * Delete Term * * @param null|int|\WP_Term $ids * * @return $this * @throws ModelException */ public function delete($ids = null) { if(is_null($ids) && $this->hasProperties()) { $ids = $this->getID(); } if(is_array($ids)) { throw new ModelException(static::class . ' not deleted: bulk deleting not supported due to WordPress performance issues.'); } do_action('typerocket_model_delete', $this, $ids); $delete = wp_delete_term($ids, $this->wpTerm($ids)->taxonomy); if ( $delete instanceof \WP_Error ) { throw new ModelException('WPTerm not deleted: ' . $delete->get_error_message()); } if ( !$delete ) { throw new ModelException('WPTerm not deleted'); } do_action('typerocket_model_after_delete', $this, $ids, $delete); return $this; } /** * Save term meta fields from TypeRocket fields * * @param array|\ArrayObject $fields * * @return $this */ public function saveMeta( $fields ) { $fields = $this->getFilteredMetaFields($fields); $id = $this->getID(); if ( ! empty($fields) && ! empty( $id ) ) : foreach ($fields as $key => $value) : if (is_string( $value )) { $value = trim( $value ); } $current_value = get_term_meta( $id, $key, true ); $value = $this->getNewArrayReplaceRecursiveValue($key, $current_value, $value); if (( isset( $value ) && $value !== "" ) && $value !== $current_value) : $value = wp_slash($value); update_term_meta( $id, $key, $value ); do_action('typerocket_after_save_meta_term', $id, $key, $value, $current_value, $this); elseif ( ! isset( $value ) || $value === "" && ( isset( $current_value ) || $current_value === "" )) : delete_term_meta( $id, $key ); endif; endforeach; endif; return $this; } /** * Get base field value * * Some fields need to be saved as serialized arrays. Getting * the field by the base value is used by Fields to populate * their values. * * @param string $field_name * * @return null */ public function getBaseFieldValue( $field_name ) { $id = $this->getID(); $data = $this->getProperty($field_name); if(is_null($data)) { $data = get_metadata( 'term', $id, $field_name, true ); } return $this->getValueOrNull($data); } /** * @param array $builtin * @return mixed */ public function slashBuiltinFields( $builtin ) { $fields = [ 'name', 'description' ]; foreach ($fields as $field) { if(!empty($builtin[$field])) { $builtin[$field] = wp_slash( $builtin[$field] ); } } return $builtin; } } src/Models/WPAttachment.php000064400000002651150732302400011626 0ustar00dataCache['url_sizes']['full']) ) { return $this->dataCache['url_sizes']['full']; } return $this->dataCache['url_sizes']['full'] = wp_get_attachment_url($this->wpPost()->ID); } /** * Get URL by Size * * @param string $size * @return string|mixed */ public function getUrlSize($size) { if ( !empty($this->dataCache['url_sizes'][$size]) ) { return $this->dataCache['url_sizes'][$size]; } $meta = maybe_unserialize($this->meta->_wp_attachment_metadata ?? null); $file = $meta['sizes'][$size]['file'] ?? wp_basename($meta['file']) ?? null; $url = $this->getUrl(); if(!$file) { return $file; } return $this->dataCache['url_sizes'][$size] = str_replace( wp_basename( $url ), $file, $url ); } /** * Get Image Tag * * @param $size * @param array $attr * * @return Html */ public function getImage($size, $attr = []) { $src = $this->getUrlSize($size); return Html::img($src, array_merge(['alt' => $this->post_excerpt ?? 'Photo'], $attr)); } }src/Models/WPComment.php000064400000023161150732302400011137 0ustar00 'comment_date', 'value' => 'comment_ID', ]; protected $builtin = [ 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_type', 'comment_parent', 'user_id', 'comment_date', 'comment_date_gmt', 'comment_content', 'comment_karma', 'comment_approved', 'comment_agent', 'comment_author_ip', 'comment_post_id', 'comment_id' ]; protected $guard = [ 'comment_id' ]; /** * Return table name in constructor * * @param \wpdb $wpdb * * @return string */ public function initTable( $wpdb ) { return $wpdb->comments; } /** * Get Meta Model Class * * @return string */ protected function getMetaModelClass() { return WPCommentMeta::class; } /** * Get ID Columns * * @return array */ protected function getMetaIdColumns() { return [ 'local' => 'comment_ID', 'foreign' => 'comment_id', ]; } /** * Get User ID * * @return string|int|null */ public function getUserID() { return $this->properties['user_id'] ?? null; } /** * @return string|null */ public function getRestMetaType() { return 'comment'; } /** * Get WP_Comment Instance * * @param \WP_Comment|null|int $comment * @param bool $returnModel * * @return \WP_Comment|$this|null */ public function wpComment($comment = null, $returnModel = false) { if( !$comment && $this->wpComment instanceof \WP_Comment ) { return $this->wpComment; } if( !$comment && $this->getID() ) { return $this->wpComment($this->getID()); } if(!$comment) { return $this->wpComment; } $comment = get_comment($comment); if($comment instanceof \WP_Comment) { $this->wpComment = $comment; $this->castProperties( $comment->to_array() ); } return $returnModel ? $this : $this->wpComment; } /** * Create comment from TypeRocket fields * * @param array|Fields $fields * * @return $this * @throws ModelException */ public function create( $fields = [] ) { $fields = $this->provisionFields($fields); $builtin = $this->getFilteredBuiltinFields( $fields ); $comment = null; do_action('typerocket_model_create', $this, $fields); if ( ! empty( $builtin['comment_post_id'] ) && ! empty( $builtin['comment_content'] ) ) { remove_action( 'wp_insert_comment', 'TypeRocket\Http\Responders\Hook::comments' ); $comment = wp_new_comment( $this->caseFieldColumns( wp_slash($builtin) ) ); add_action( 'wp_insert_comment', 'TypeRocket\Http\Responders\Hook::comments' ); if ( empty( $comment ) ) { throw new ModelException('WPComments not created'); } else { $comment = $this->findById($comment); } } else { $this->errors = [ 'Missing post ID `comment_post_id`.', 'Missing comment content `comment_content`.' ]; } $this->saveMeta( $fields ); do_action('typerocket_model_after_create', $this, $fields, $comment); return $comment; } /** * Update comment from TypeRocket fields * * @param array|Fields $fields * * @return $this * @throws ModelException */ public function update( $fields = [] ) { $id = $this->getID(); if ($id != null) { $fields = $this->provisionFields($fields); $builtin = $this->getFilteredBuiltinFields( $fields ); $comment = null; do_action('typerocket_model_update', $this, $fields); if ( ! empty( $builtin )) { remove_action( 'edit_comment', 'TypeRocket\Http\Responders\Hook::comments' ); $builtin['comment_id'] = $id; $builtin = $this->caseFieldColumns( $builtin ); $comment = wp_update_comment( wp_slash($builtin) ); add_action( 'edit_comment', 'TypeRocket\Http\Responders\Hook::comments' ); if (empty( $comment )) { throw new ModelException('WPComments not updated'); } $this->findById($id); } $this->saveMeta( $fields ); do_action('typerocket_model_after_update', $this, $fields, $comment); } else { $this->errors = ['No item to update']; } return $this; } /** * Delete Comment * * This will delete the comment * * @param null|int $ids * * @return $this * @throws ModelException */ public function delete($ids = null) { if(is_null($ids) && $this->hasProperties()) { $ids = $this->getID(); } if(is_array($ids)) { throw new ModelException(static::class . ' not deleted: bulk deleting not supported due to WordPress performance issues.'); } do_action('typerocket_model_delete', $this, $ids); $delete = wp_delete_comment($ids); if ( !$delete ) { throw new ModelException('WPComment not deleted'); } do_action('typerocket_model_after_delete', $this, $ids, $delete); return $this; } /** * Delete Comment Forever * * This will delete the comment * * @param null|int $ids * * @return $this * @throws ModelException */ public function deleteForever($ids = null) { if(is_null($ids) && $this->hasProperties()) { $ids = $this->getID(); } do_action('typerocket_model_delete', $this, $ids); $delete = wp_delete_comment($ids, true); if ( !$delete ) { throw new ModelException('WPComment not deleted'); } do_action('typerocket_model_after_delete', $this, $ids, $delete); return $this; } /** * Save comment meta fields from TypeRocket fields * * @param array|\ArrayObject $fields * * @return $this */ public function saveMeta( $fields ) { $fields = $this->getFilteredMetaFields( $fields ); $id = $this->getID(); if ( ! empty( $fields ) && ! empty( $id )) : foreach ($fields as $key => $value) : if (is_string( $value )) { $value = trim( $value ); } $current_value = get_comment_meta( $id, $key, true ); $value = $this->getNewArrayReplaceRecursiveValue($key, $current_value, $value); if (( isset( $value ) && $value !== "" ) && $value !== $current_value) : $value = wp_slash($value); update_comment_meta( $id, $key, $value ); do_action('typerocket_after_save_meta_comment', $id, $key, $value, $current_value, $this); elseif ( ! isset( $value ) || $value === "" && ( isset( $current_value ) || $current_value === "" )) : delete_comment_meta( $id, $key ); endif; endforeach; endif; return $this; } /** * Format irregular fields * * @param array|\ArrayObject $fields * * @return array */ protected function caseFieldColumns( $fields ) { if ( ! empty( $fields['comment_post_id'] )) { $fields['comment_post_ID'] = (int) $fields['comment_post_id']; unset( $fields['comment_post_id'] ); } if ( ! empty( $fields['comment_id'] )) { $fields['comment_ID'] = (int) $fields['comment_id']; unset( $fields['comment_id'] ); } if ( ! empty( $fields['comment_author_ip'] )) { $fields['comment_author_IP'] = $fields['comment_author_ip']; unset( $fields['comment_author_ip'] ); } return $fields; } /** * Get base field value * * Some fields need to be saved as serialized arrays. Getting * the field by the base value is used by Fields to populate * their values. * * @param string $field_name * * @return null */ public function getBaseFieldValue( $field_name ) { $data = $this->getProperty($field_name); if (is_null($data) && in_array($field_name, $this->builtin)) { switch ($field_name) { case 'comment_author_ip' : $data = $this->properties['comment_author_IP']; break; case 'comment_post_id' : $data = $this->properties['comment_post_ID']; break; case 'comment_id' : $data = $this->properties['comment_ID']; break; } } elseif(is_null($data)) { $data = get_metadata('comment', $this->getID(), $field_name, true); } return $this->getValueOrNull($data); } } src/Models/WPPost.php000064400000037542150732302400010472 0ustar00 'post_title', 'value' => 'ID', ]; protected $builtin = [ 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_excerpt', 'post_status', 'comment_status', 'ping_status', 'post_name', 'to_ping', 'pinged', 'post_modified', 'post_modified_gmt', 'post_content_filtered', 'post_parent', 'guid', 'menu_order', 'post_type', 'post_mime_type', 'comment_count', 'post_password', 'id' ]; protected $guard = [ 'post_type', 'id' ]; protected $private = [ 'post_password' ]; /** * WPPost constructor. * * @param null|string $postType * * @throws \Exception */ public function __construct($postType = null) { $this->setPostType($postType ?? static::POST_TYPE); parent::__construct(); } /** * @param null|string $postType * @param bool $init * * @return $this */ protected function setPostType($postType = null, $init = false) { if($postType) { $this->postType = $postType; } if($init) { $this->initQuery($this->query); } return $this; } /** * Get Post Type * * @return string */ public function getPostType() { return $this->postType; } /** * Return table name in constructor * * @param \wpdb $wpdb * * @return string */ public function initTable( $wpdb ) { return $wpdb->posts; } /** * Init Post Type * * @param Query $query * * @return Query */ protected function initQuery( Query $query ) { if($pt = $this->getPostType()) { $query->where('post_type', $pt); } return $query; } /** * Get JsonApiResource * * @return string|null */ public function getRouteResource() { return $this->getPostType() ?? 'post'; } /** * @return string|null */ public function getRestMetaType() { return 'post'; } /** * @return string|null */ public function getRestMetaSubtype() { return $this->getPostType(); } /** * Get WP_Post Instance * * @param WP_Post|null|int|false $post * @param bool $returnModel * * @return WP_Post|$this|null */ public function wpPost($post = null, $returnModel = false) { if( !$post && $this->wpPost instanceof \WP_Post ) { return $this->wpPost; } if( !$post && $this->getID() ) { return $this->wpPost($this->getID()); } if(!$post) { return $this->wpPost; } $post = get_post($post); if($post instanceof WP_Post) { $this->setPostType($post->post_type); $this->wpPost = $post; $this->castProperties( get_object_vars( $post ) ); } return $returnModel ? $this : $this->wpPost; } /** * Get Meta Model Class * * @return string */ protected function getMetaModelClass() { return WPPostMeta::class; } /** * Get User ID * * @return string|int|null */ public function getUserID() { return $this->properties['post_author'] ?? null; } /** * Get ID Columns * * @return array */ protected function getMetaIdColumns() { return [ 'local' => 'ID', 'foreign' => 'post_id', ]; } /** * Get Post Permalink * * @return string|\WP_Error */ public function permalink() { return get_permalink($this->wpPost()); } /** * @param mixed|null $value * * @return bool */ public function getIsPublishedProperty($value = null) { return (bool) ( $value ?? $this->post_status == 'publish' ); } /** * @return string|\WP_Error */ public function getSearchUrl() { return $this->permalink(); } /** * Limit Field Options * * @return $this */ public function limitFieldOptions() { return $this->published(); } /** * After Properties Are Cast * * Create an Instance of WP_Post * * @return Model */ protected function afterCastProperties() { if(!$this->wpPost && $this->getCache()) { $_post = sanitize_post((object) $this->properties, 'raw'); wp_cache_add($_post->ID, $_post, 'posts'); $this->wpPost = new WP_Post($_post); } return parent::afterCastProperties(); } /** * Posts Meta Fields * * @param bool $withoutPrivate * * @return null|\TypeRocket\Models\Model */ public function meta( $withoutPrivate = false ) { return $this->hasMany( WPPostMeta::class, 'post_id', function($rel) use ($withoutPrivate) { if( $withoutPrivate ) { $rel->notPrivate(); } }); } /** * Posts Meta Fields Without Private * * @return null|\TypeRocket\Models\Model */ public function metaWithoutPrivate() { return $this->meta( true ); } /** * Belongs To Taxonomy * * @param string $modelClass * @param string $taxonomy_id the registered taxonomy id: category, post_tag, etc. * @param null|callable $scope * @param bool $reselect * * @return Model|null */ public function belongsToTaxonomy($modelClass, $taxonomy_id, $scope = null, $reselect = false) { global $wpdb; return $this->belongsToMany([$modelClass, WPTermTaxonomy::class], $wpdb->term_relationships, 'object_id', 'term_taxonomy_id', function($rel, &$reselect_main = true) use ($scope, $taxonomy_id, $reselect) { global $wpdb; $rel->where($wpdb->term_taxonomy .'.taxonomy', $taxonomy_id); $reselect_main = $reselect; if(is_callable($scope)) { $scope($rel, $reselect_main); } }); } /** * Author * * @return $this|null */ public function author() { $user = \TypeRocket\Utility\Helper::appNamespace('Models\User'); return $this->belongsTo( $user, 'post_author' ); } /** * Published * * @return $this */ public function published() { return $this->where('post_status', 'publish'); } /** * Status * * @param string $type * * @return $this */ public function status($type) { return $this->where('post_status', $type); } /** * @return Composer|\TypeRocket\Template\PostTypeModelComposer */ public function composer() { return parent::composer(); } /** * Find by ID and Remove Where * * @param string $id * @return mixed|object|\TypeRocket\Database\Results|Model|null */ public function findById($id) { $results = $this->query->findById($id)->get(); return $this->getQueryResult($results); } /** * Create post from TypeRocket fields * * Set the post type property on extended model so they * are saved to the correct type. See the PagesModel * as example. * * @param array|\TypeRocket\Http\Fields $fields * * @return null|mixed|WPPost * @throws \TypeRocket\Exceptions\ModelException */ public function create( $fields = []) { $fields = $this->provisionFields($fields); $builtin = $this->getFilteredBuiltinFields($fields); $new_post = null; do_action('typerocket_model_create', $this, $fields); if ( ! empty( $builtin )) { $builtin = $this->slashBuiltinFields($builtin); remove_action('save_post', 'TypeRocket\Http\Responders\Hook::posts'); if(!empty($this->getPostType())) { $builtin['post_type'] = $this->getPostType(); } if( empty($builtin['post_title']) ) { $error = 'WPPost not created: post_title is required'; throw new ModelException( $error ); } $post = wp_insert_post( $builtin ); add_action('save_post', 'TypeRocket\Http\Responders\Hook::posts'); if ( $post instanceof \WP_Error || $post === 0 ) { $error = 'WPPost not created: An error accrued during wp_insert_post.'; throw new ModelException( $error ); } else { $modelClass = get_class($this); $new_post = (new $modelClass)->findById($post); // TODO v6: Remove this line. // Kept for breaking changes in v5 for now $this->findById($post); } } if($new_post) { $new_post->saveMeta( $fields ); } else { $this->saveMeta( $fields ); } do_action('typerocket_model_after_create', $this, $fields, $new_post); return $new_post; } /** * Update post from TypeRocket fields * * @param array|\TypeRocket\Http\Fields $fields * * @return $this * @throws \TypeRocket\Exceptions\ModelException */ public function update( $fields = [] ) { $id = $this->getID(); if( $id != null && ! wp_is_post_revision( $id ) ) { $fields = $this->provisionFields( $fields ); $builtin = $this->getFilteredBuiltinFields($fields); $result = null; do_action('typerocket_model_update', $this, $fields); if ( ! empty( $builtin ) ) { $builtin = $this->slashBuiltinFields($builtin); remove_action('save_post', 'TypeRocket\Http\Responders\Hook::posts'); $builtin['ID'] = $id; $builtin['post_type'] = $this->properties['post_type']; $result = wp_update_post( $builtin ); add_action('save_post', 'TypeRocket\Http\Responders\Hook::posts'); if ( $result instanceof \WP_Error || $result === 0 ) { $error = 'WPPost not updated: post_name (slug), post_title and post_content are required'; throw new ModelException( $error ); } else { $this->findById($id); } } $this->saveMeta( $fields ); do_action('typerocket_model_after_update', $this, $fields, $result); } else { $this->errors = ['No item to update']; } return $this; } /** * Delete Post * * @param null|int|\WP_Post $ids * * @return $this * @throws ModelException */ public function delete($ids = null) { if(is_null($ids) && $this->hasProperties()) { $ids = $this->getID(); } if(is_array($ids)) { throw new ModelException(static::class . ' not deleted: bulk deleting not supported due to WordPress performance issues.'); } do_action('typerocket_model_delete', $this, $ids); $delete = wp_delete_post($ids); if ( !$delete ) { throw new ModelException('WPPost not deleted'); } do_action('typerocket_model_after_delete', $this, $ids, $delete); return $this; } /** * Delete Post Forever * * @param null|int|\WP_Post $ids * * @return $this * @throws ModelException */ public function deleteForever($ids = null) { if(is_null($ids) && $this->hasProperties()) { $ids = $this->getID(); } do_action('typerocket_model_delete', $this, $ids); $delete = wp_delete_post($ids, true); if ( !$delete ) { throw new ModelException('WPPost not deleted'); } do_action('typerocket_model_after_delete', $this, $ids, $delete); return $this; } /** * Save post meta fields from TypeRocket fields * * @param array|\ArrayObject $fields * * @return $this */ public function saveMeta( $fields ) { $fields = $this->getFilteredMetaFields($fields); $id = $this->getID(); if ( ! empty($fields) && ! empty( $id )) : if ($parent_id = wp_is_post_revision( $id )) { $id = $parent_id; } foreach ($fields as $key => $value) : if (is_string( $value )) { $value = trim( $value ); } $current_value = get_post_meta( $id, $key, true ); $value = $this->getNewArrayReplaceRecursiveValue($key, $current_value, $value); if (( isset( $value ) && $value !== "" ) && $value !== $current_value) : $value = wp_slash($value); update_post_meta( $id, $key, $value ); do_action('typerocket_after_save_meta_post', $id, $key, $value, $current_value, $this); elseif ( ! isset( $value ) || $value === "" && ( isset( $current_value ) || $current_value === "" )) : delete_post_meta( $id, $key ); endif; endforeach; endif; return $this; } /** * Get base field value * * Some fields need to be saved as serialized arrays. Getting * the field by the base value is used by Fields to populate * their values. * * @param string $field_name * * @return null */ public function getBaseFieldValue( $field_name ) { $id = $this->getID(); $field_name = $field_name === 'ID' ? 'id' : $field_name; if($field_name == 'post_password') { $data = ''; } else { $data = $this->getProperty($field_name); } if( is_null($data) ) { $data = get_metadata( 'post', $id, $field_name, true ); } return $this->getValueOrNull($data); } /** * Slash Builtin Fields * * @param array $builtin * @return mixed */ public function slashBuiltinFields( $builtin ) { $fields = [ 'post_content', 'post_excerpt', 'post_title', ]; foreach ($fields as $field) { if(!empty($builtin[$field])) { $builtin[$field] = wp_slash( $builtin[$field] ); } } return $builtin; } } src/Models/Meta/WPCommentMeta.php000064400000001615150732302400012634 0ustar00belongsTo( $modelClass ?? WPComment::class, 'comment_id' ); } /** * Not Private * * @return WPCommentMeta */ public function notPrivate() { return $this->where('meta_key', 'NOT LIKE', '\_%'); } }src/Models/Meta/WPUserMeta.php000064400000001551150732302400012147 0ustar00belongsTo( $modelClass ?? WPUser::class, 'user_id' ); } /** * Not Private * * @return WPUserMeta */ public function notPrivate() { return $this->where('meta_key', 'NOT LIKE', '\_%'); } }src/Models/Meta/WPPostMeta.php000064400000001565150732302400012163 0ustar00belongsTo( $modelClass ?? WPPost::class, 'post_id' ); } /** * Not Private * * @return WPPostMeta */ public function notPrivate() { return $this->where('meta_key', 'NOT LIKE', '\_%'); } }src/Models/Meta/WPTermMeta.php000064400000001551150732302400012140 0ustar00belongsTo( $modelClass ?? WPTerm::class, 'term_id' ); } /** * Not Private * * @return WPTermMeta */ public function notPrivate() { return $this->where('meta_key', 'NOT LIKE', '\_%'); } }src/Models/WPOption.php000064400000006205150732302400011005 0ustar00 'option_name', 'value' => 'option_id', ]; /** * Return table name in constructor * * @param \wpdb $wpdb * * @return string */ public function initTable( $wpdb ) { return $wpdb->options; } /** * Do nothing since options are not true resources * * @param string $id * * @return $this */ public function findById( $id ) { return $this; } /** * Create options from TypeRocket fields * * @param array|\TypeRocket\Http\Fields $fields * * @return $this */ public function create( $fields = [] ) { $fields = $this->provisionFields( $fields ); $this->saveOptions( $fields ); return $this; } /** * Update options from TypeRocket fields * * @param array|\TypeRocket\Http\Fields $fields * * @return $this */ public function update( $fields = [] ) { $fields = $this->provisionFields( $fields ); $this->saveOptions( $fields ); return $this; } /** * Save options' fields from TypeRocket fields * * @param array|\ArrayObject $fields * * @return $this */ public function saveOptions( $fields ) { if ( ! empty( $fields )) { foreach ($fields as $key => $value) : if (is_string( $value )) { $value = trim( $value ); } $current_value = get_option( $key ); $value = $this->getNewArrayReplaceRecursiveValue($key, $current_value, $value); if (( isset( $value ) && $value !== "" ) && $current_value !== $value) : update_option( $key, $value ); do_action('typerocket_after_save_meta_option', null, $key, $value, $current_value, $this); elseif ( ! isset( $value ) || $value === "" && ( isset( $current_value ) || $current_value === "" )) : delete_option( $key ); endif; endforeach; } return $this; } /** * Get base field value * * Some fields need to be saved as serialized arrays. Getting * the field by the base value is used by Fields to populate * their values. * * @param string $field_name * * @return null */ public function getBaseFieldValue( $field_name ) { $data = get_option( $field_name, null ); return $this->getValueOrNull($data); } /** * Get ID as TRUE * * Always get the ID as true since wp_options is more * of a central store * * @return int */ public function getID() { return true; } }src/Models/WPMenu.php000064400000000161150732302400010434 0ustar00 null, 'value' => null, ]; /** @var array use this for your own custom caching at the model level */ protected $dataCache = []; /** * Construct Model based on resource * @throws \Exception */ public function __construct() { /** @var wpdb $wpdb */ global $wpdb; $type = null; try { $type = (new ReflectionClass( $this ))->getShortName(); } catch (ReflectionException $e) { throw new \Exception('Model failed: ' . $e->getMessage()); } if( ! $this->resource && $type ) { $this->resource = strtolower( Inflect::pluralize($type) ); } $this->table = $this->initTable( $wpdb ); $this->query = $this->initQuery( new Query ); $this->query->resultsClass = $this->resultsClass; $this->query->table($this->getTable()); $this->query->setIdColumn($this->idColumn); do_action('typerocket_model', $this ); $this->init(); } /** * Cast Array to Model Results * * @param array $resultsArray * * @return Results */ public static function castArrayToModelResults(array $resultsArray) { $results_class = (new static)->getResultsClass(); /** @var Results $results */ $results = new $results_class; return $results->exchangeAndCast($resultsArray, static::class); } /** * Init Query * * @param Query $query * * @return mixed */ protected function initQuery( Query $query) { return $query; } /** * Return table name in constructor * * @param wpdb $wpdb * * @return null|string */ protected function initTable($wpdb) { return $this->table ?? $wpdb->prefix . $this->resource; } /** * Basic initialization */ protected function init() { } /** * User Can * * @param $action * @param null|WPUser|Auth $user * @return mixed * @throws \Exception */ public function can($action, $user = null) { /** @var AuthorizerService $auth */ $auth = Container::resolveAlias(Auth::ALIAS); if(!$user) { $user = Container::resolveAlias(AuthUser::ALIAS); } return $auth->authRegistered($user, $this, $action); } /** * Set Static Fields * * Fields that are write protected by default unless fillable * * @param array|ArrayObject $static * * @return $this */ public function setStaticFields( $static ) { $this->static = $static; return $this; } /** * Set Fillable * * Fields that are write protected by default unless fillable * * @param array|ArrayObject $fillable * * @return $this */ public function setFillableFields( $fillable ) { $this->fillable = $fillable; return $this; } /** * Set Format * * Fields that are write protected by default unless fillable * * @param array|ArrayObject $format * * @return $this */ public function setFormatFields( $format ) { $this->format = $format; return $this; } /** * Set Guard * * Fields that are write protected by default unless fillable * * @param array|ArrayObject $guard * * @return $this */ public function setGuardFields( $guard ) { $this->guard = $guard; return $this; } /** * Append Fillable * * Add a fillable field. * * @param string $field_name * * @return $this */ public function appendFillableField( string $field_name ) { if ( ! in_array( $field_name, $this->fillable ) && ! in_array( $field_name, $this->guard ) ) { $this->fillable[] = $field_name; } return $this; } /** * Might Need to Be Fillable * * Use this to detect if fillable fields are active * and if so add more to the list. * * @param $field_name * @return $this */ public function mightNeedFillable($field_name) { $fields = $field_name; if(!is_array($field_name)) { $fields = [$field_name]; } if ( ! empty( $this->fillable )) { foreach ($fields as $field) { $this->appendFillableField( $field ); } } return $this; } /** * Append Guard * * Add a field to guard if not set to fillable. * * @param string $field_name * * @return $this */ public function appendGuardField( string $field_name ) { if ( ! in_array( $field_name, $this->fillable ) && ! in_array( $field_name, $this->guard ) ) { $this->guard[] = $field_name; } return $this; } /** * Append Format * * Add a field to format. * * @param string $field_name dot notation with support for wild card * * @param callable $callback function or method to call on $field_name * * @return $this */ public function appendFormatField( $field_name, $callback ) { if ( ! array_key_exists( $field_name, $this->format )) { $this->format[$field_name] = $callback; } return $this; } /** * Extend Fillable * * @param array $fields * * @return $this */ public function extendFillableFields(array $fields) { $this->fillable = array_merge($this->fillable, $fields); return $this; } /** * Extend Guard * * @param array $fields * * @return $this */ public function extendGuardFields(array $fields) { $this->guard = array_merge($this->guard, $fields); return $this; } /** * Extend Format * * @param array $fields * * @return $this */ public function extendFormatFields(array $fields) { $this->format = array_merge($this->format, $fields); return $this; } /** * Append Private * * Add a field to guard if not set to fillable. * * @param string $field_name * * @return $this */ public function appendPrivateField( string $field_name ) { if ( ! in_array( $field_name, $this->private ) ) { $this->private[] = $field_name; } return $this; } /** * Remove Guard * * Remove field from guard. * * @param string $field_name * * @return $this */ public function removeGuardField( $field_name ) { if ( in_array( $field_name, $this->guard ) ) { unset($this->guard[array_search($field_name, $this->guard)]); } return $this; } /** * Remove Fillable * * Remove field from fillable. * * @param string $field_name * * @return $this */ public function removeFillableField( $field_name ) { if ( in_array( $field_name, $this->fillable ) ) { unset($this->fillable[array_search($field_name, $this->fillable)]); } return $this; } /** * Remove Format * * Remove field from format. * * @param string $field_name * * @return $this */ public function removeFormatField( $field_name ) { if ( array_key_exists( $field_name, $this->format ) ) { unset($this->format[$field_name]); } return $this; } /** * Unlock Field * * Unlock field by adding it to fillable and removing it from guard. * * @param string $field_name * * @return $this */ public function unlockField( $field_name ) { if ( in_array( $field_name, $this->guard ) ) { unset($this->guard[array_search($field_name, $this->guard)]); } if ( !empty($this->fillable) && ! in_array( $field_name, $this->fillable ) && ! in_array( $field_name, $this->guard ) ) { $this->fillable[] = $field_name; } return $this; } /** * @return array */ public function getRestMetaFieldsCompiled() { $fields = $this->getRestMetaFields(); $compiled = []; foreach ($fields as $field => $args) { if(in_array($field, $this->private)) { continue; } $compiled[$field] = array_filter( array_merge([ 'sanitize_callback' => $this->format[$field] ?? null, 'object_subtype' => $this->getRestMetaSubtype(), 'single' => true, 'show_in_rest' => true ], $args) ); } return $compiled; } /** * @return array */ public function getRestMetaFields() { return $this->restMetaFields; } /** * @return string|null */ public function getRestMetaType() { return $this->resource; } /** * @return string|null */ public function getRestMetaSubtype() { return null; } /** * Get Route Resource * * @return string|null * @throws ReflectionException */ public function getRouteResource() { if($this->routeResource) { return $this->routeResource; } $class = new \ReflectionClass($this); return Str::snake($class->getShortName()); } /** * Append Error * * Get any errors that have been logged * * @param string $value * * @return null */ public function appendError( $value ) { return $this->errors[] = $value; } /** * Get Errors * * Get any errors that have been logged * * @return null */ public function getErrors() { return $this->errors; } /** * Get Fillable Fields * * Get all the fields that can be filled * * @return array|mixed */ public function getFillableFields() { return $this->fillable; } /** * Get Guard Fields * * Get all the fields that have been write protected * * @return array|mixed */ public function getGuardFields() { return $this->guard; } /** * Get Builtin Fields * * Get all the fields that are not saved as meta fields * * @return array */ public function getBuiltinFields() { return $this->builtin; } /** * Get Format Fields * * Get all the fields that have been set for formatting * * @return array|mixed */ public function getFormatFields() { return $this->format; } /** * Set Property * * By key * * @param string $key * @param string $value * * @return $this */ public function setProperty( $key, $value = null ) { if($this->hasSetMutator($key)) { $value = $this->mutatePropertySet($key, $value); } if($current_value = $this->propertiesUnaltered[$key] ?? null) { $value = $this->getNewArrayReplaceRecursiveValue($key, $current_value, $value); } $this->properties[$key] = $value; $this->explicitProperties[$key] = $value; return $this; } /** * Set Properties * * @param array $properties * * @return $this */ public function setProperties( array $properties ) { foreach ($properties as $key => $value) { $this->setProperty($key, $value ?? null); } return $this; } /** * Get an attribute from the model. * * @param string $key * @return mixed */ public function getProperty($key) { if (array_key_exists($key, $this->properties) || $this->hasGetMutator($key)) { return $this->getPropertyValue($key); } return $this->getRelationValue($key); } /** * Get Properties * * @return array */ public function getProperties() { return $this->properties; } /** * Get Properties * * @return array */ public function getPublicProperties() { $diff = array_flip($this->private); return array_diff_key($this->properties, $diff); } /** * Has properties * * @return bool */ public function hasProperties() { return !empty($this->properties); } /** * Get Properties Unaltered * * @return array */ public function getPropertiesUnaltered() { return $this->propertiesUnaltered; } /** * @param string $field * * @return $this */ public function appendMetalessField(string $field) { if(!in_array($field, $this->metaless)) { $this->metaless[] = $field; } return $this; } /** * @param string $field * * @return $this */ public function removeMetalessField(string $field) { if(($key = array_search($field, $this->metaless)) !== false) { unset($this->metaless[$key]); } return $this; } /** * Get only the fields that are considered to * be meta fields. * * @param array|null|ArrayObject $fields * * @return array */ public function getFilteredMetaFields( $fields ) { $diff = array_flip( array_unique( array_merge($this->builtin, $this->metaless) ) ); return array_diff_key( $fields ?? [], $diff ); } /** * Get only the fields that are considered to * be builtin fields. * * @param array|ArrayObject $fields * * @return array */ public function getFilteredBuiltinFields( $fields ) { $builtin = array_flip( $this->builtin ); return array_intersect_key( $fields, $builtin ); } /** * @return $this */ public function disableCache() { $this->cache = false; return $this; } /** * @param bool $bool * * @return $this */ public function setCache($bool) { $this->cache = (bool) $bool; return $this; } /** * @return bool|null */ public function getCache() { return $this->cache; } /** * Provision Fields * * Get fields that have been checked against fillable and guard. * Fillable fields override guarded fields. Format fields to * specification. Override given values with static values. * * @param array|ArrayObject $fields * * @return mixed */ public function provisionFields( $fields ) { // Unlock fillable fields if( $fields instanceof Fields ) { foreach ( $fields->getFillable() as $field_name ) { $this->unlockField($field_name); } $fields = $fields->getModelFields(); } // Fillable $fillable = []; if ( ! empty( $this->fillable ) && is_array( $this->fillable )) { foreach ($this->fillable as $field_name) { if (isset( $fields[$field_name] )) { $fillable[$field_name] = $fields[$field_name]; } } $fields = $fillable; } // Closed if($this->closed && empty($fillable)) { $fields = []; } // Guard if ( ! empty( $this->guard ) && is_array( $this->guard )) { foreach ($this->guard as $field_name) { if (isset( $fields[$field_name] ) && ! in_array( $field_name, $this->fillable )) { unset( $fields[$field_name] ); } } } // Override with static values $fields = array_merge( $this->explicitProperties, $fields ?? [], $this->static); // Format if ( ! empty( $this->format ) && is_array( $this->format )) { $fields = $this->formatFields($fields); } return apply_filters('typerocket_model_provision_fields', $fields, $this ); } /** * Get value from database from typeRocket bracket syntax * * @param string $field * * @return array|mixed|null|string */ public function getFieldValue( $field ) { if ($field instanceof Field) { $field = $field->getDots(); } if ($this->getID() == null && ! $this->old ) { return null; } $keys = $this->getDotKeys( $field ); if( $this->old ) { if( ! empty($this->old[$keys[0]]) ) { $data = wp_unslash( $this->old[$keys[0]] ); } else { $data = null; } } elseif( !$this->onlyOld ) { $data = $this->getBaseFieldValue( $keys[0] ); } else { return null; } return $this->parseValueData( $data, $keys ); } /** * Parse data by walking through keys * * @param string $data * @param string $keys * * @return array|mixed|null|string */ protected function parseValueData( $data, $keys ) { $mainKey = $keys[0]; if (isset( $mainKey ) && ! empty( $data )) { if ( $data instanceof Formable) { $data = $data->getFormFields(); } if ( is_string($data) && Data::isJson($data) ) { $data = json_decode( $data, true ); } if ( is_string($data) && is_serialized( $data ) ) { $data = unserialize( $data ); } // unset first key since $data is already set to it unset( $keys[0] ); if ( ! empty( $keys ) && is_array( $keys )) { foreach ($keys as $name) { if(is_object($data)) { $data = ( isset( $data->$name ) && $data->$name !== '' ) ? $data->$name : null; } else { $data = ( isset( $data[$name] ) && $data[$name] !== '' ) ? $data[$name] : null; } } } } return $data; } /** * Format fields * * @param array|ArrayObject $fields * * @return array */ protected function formatFields($fields) { foreach ($this->format as $path => $fn) { Arr::format($path, $fields, $fn); } return $fields; } /** * Get keys from TypeRocket brackets * * @param string $str * * @return mixed */ protected function getDotKeys( $str ) { return explode('.', $str); } /** * Get the value of a field if it is not an empty string or null. * If the field is null, undefined or and empty string it will * return null. * * @param string $value * * @return null */ public function getValueOrNull( $value ) { return ( isset( $value ) && $value !== '' ) ? $value : null; } /** * Find by ID or IDs * * @param mixed ...$ids * @return mixed|Model */ public function find(...$ids) { $ids = is_array($ids[0]) ? $ids[0] : $ids; if(count($ids) > 1) { return $this->findAll($ids); } return $this->findById($ids[0]); } /** * Find all * * @param array|ArrayObject $ids * @param int|null $num * * @return Model $this */ public function findAll( $ids = [], $num = null ) { $this->query->findAll($ids, null, $num ?? func_num_args()); return $this; } /** * Get results from find methods * * @return array|null|object|Model|Results */ public function get() { $results = $this->query->get(); return $this->getQueryResult($results); } /** * Where * * @param string|array $column * @param string|null $arg1 * @param null|string $arg2 * @param string $condition * @param null|int $num * * @return $this */ public function where($column, $arg1 = null, $arg2 = null, $condition = 'AND', $num = null) { $this->query->where(...func_get_args()); return $this; } /** * Or Where * * @param string $column * @param string $arg1 * @param null|string $arg2\ * @param null|int $num * * @return Model $this */ public function orWhere($column, $arg1, $arg2 = null, $num = null) { $this->query->orWhere(...func_get_args()); return $this; } /** * Append Raw Where * * This method is not sanitized before it is run. Do not * use this method with user provided input. * * @param string $condition string|null * @param string $sql string * @return $this */ public function appendRawWhere($condition, $sql) { $this->query->appendRawWhere($condition, $sql); return $this; } /** * Remove Where * * Remove raw and standard where clauses. * * @return $this */ public function removeWhere() { $this->query->removeWhere(); return $this; } /** * Remove Take * * Remove take from query * * @return $this */ public function removeTake() { $this->query->removeTake(); return $this; } /** * Order by * * @param string $column name of column * @param string $direction default ASC other DESC * * @return $this */ public function orderBy($column = null, $direction = 'ASC') { if( ! $column ) { $column = $this->idColumn; } $this->query->orderBy($column, $direction); return $this; } /** * Append Raw Order By * * This method is not sanitized before it is run. Do not * use this method with user provided input. * * @param string $sql string * @return $this */ public function appendRawOrderBy($sql) { $this->query->appendRawOrderBy($sql); return $this; } /** * Reorder * * @param string $column * @param string $direction * * @return $this */ public function reorder($column = 'id', $direction = 'ASC') { $args = func_get_args(); $this->query->reorder(...$args); return $this; } /** * Take only a select group * * @param int $limit limit * @param int $offset offset * @param bool $returnOne if taking one return direct object * * @return $this */ public function take( $limit, $offset = 0, $returnOne = true ) { $this->query->take($limit, $offset, $returnOne); return $this; } /** * Group By * * @param string|string[] $column * * @return $this */ public function groupBy($column) { $this->query->groupBy($column); return $this; } /** * Get Results Class * * @return string */ public function getResultsClass() { return $this->resultsClass; } /** * Always Wrap In Results Class * * @return $this */ public function useResultsClass() { $this->query->useResultsClass(); return $this; } /** * Find the first record and set properties * * @return array|bool|false|int|null|object|Model */ public function first() { $results = $this->query->first(); return $this->getQueryResult($results); } /** * Create resource by TypeRocket fields * * When a resource is created the Model ID should be set to the * resource's ID. * * @param array|Fields $fields * * @return mixed */ public function create( $fields = [] ) { $fields = $this->provisionFields( $fields ); do_action('typerocket_model_create', $this, $fields); $v = $this->query->create($fields); do_action('typerocket_model_after_create', $this, $fields, $v); return $v; } /** * Update resource by TypeRocket fields * * @param array|Fields $fields * * @return mixed */ public function update( $fields = [] ) { $fields = $this->provisionFields( $fields ); do_action('typerocket_model_update', $this, $fields); if(is_array($fields)) { foreach ($fields as $field => $value) { if($current_value = $this->propertiesUnaltered[$field] ?? null) { $fields[$field] = $this->getNewArrayReplaceRecursiveValue($field, $current_value, $value); } } } $v = $this->query->where($this->idColumn, $this->getID())->update($fields); do_action('typerocket_model_after_update', $this, $fields, $v); return $v; } /** * Delete * * @param array|ArrayObject|int $ids * * @return array|false|int|null|object */ public function delete( $ids = null ) { if(is_null($ids) && $this->hasProperties()) { $ids = $this->getID(); } do_action('typerocket_model_delete', $this, $ids); $v = $this->query->delete($ids); do_action('typerocket_model_after_delete', $this, $ids, $v); return $v; } /** * Find resource by ID * * @param string $id * * @return mixed|Model */ public function findById($id) { $results = $this->query->findById($id)->get(); return $this->getQueryResult($results); } /** * Join * * Only selects distinctly the current model's table columns * * @param string $table * @param string $column * @param string $arg1 column or operator * @param null|string $arg2 column if arg1 is set to operator * @param string $type INNER (default), LEFT, RIGHT * * @return $this */ public function join($table, $column, $arg1, $arg2 = null, $type = 'INNER') { $this->query->setSelectTable()->distinct(); $this->query->join($table, $column, $arg1, $arg2, $type); return $this; } /** * Find by ID or die * * @param string $id * * @return object * @throws \Exception */ public function findOrDie($id) { $results = $this->query->findOrDie($id); return $this->getQueryResult($results); } /** * Find Or Create * * @param string $id * @param array $fields * @return mixed|Model * @throws \Exception */ public function findOrCreate($id, $fields = []) { if($item = $this->findById($id)) { return $item; } return (new static)->create($fields); } /** * Find Or New * * @param string $id * @return mixed|Model * @throws \Exception */ public function findOrNew($id) { if($item = $this->findById($id)) { return $item; } return new static; } /** * Find First Where Or Create With * * @param string $column column to search * @param string $value exact value lookup only * * @return static */ public function findFirstWhereOrNewWith($column, $value) { if(!$item = $this->where($column, $value)->first()) { $item = new static; $item->{$column} = $value; } return $item; } /** * Where * * @param string $column * @param string $arg1 * @param null|string $arg2 * @param string $condition * @param null|int $num * * @return static */ public function findFirstWhereOrNew($column, $arg1, $arg2 = null, $condition = 'AND', $num = null) { if($item = $this->where(...func_get_args())->first()) { return $item; } return new static; } /** * Find first where of die * * @param string $column * @param string $arg1 * @param null|string|array $arg2 * @param string $condition * @param null|int $num * * @return object * @throws \Exception * @internal param $id */ public function findFirstWhereOrDie($column, $arg1, $arg2 = null, $condition = 'AND', $num = null) { $results = $this->query->findFirstWhereOrDie(...func_get_args()); return $this->fetchResult( $results ); } /** * Fetch Result * * @param object|Model|Results $result * * @return mixed */ protected function fetchResult( $result ) { // Return Null if( ! $result ) { return null; } // Cast Results if( $result instanceof Results ) { if( $result->class == null ) { $result->class = static::class; } $result->setCache($this->getCache())->castResults(); if($result instanceof ResultsMeta) { $result->initKeyStore(); } } else { $result = $this->castProperties( (array) $result ); } return $this->load(null, $result); } /** * Eager Load * * @param string|array|null $with * @param null|array|Results $result * * @return mixed|null|Results */ public function load($with = null, $result = null) { if($with) { $this->with($with); } if(!empty($this->with)) { $compiledWithList = $this->getWithCompiled(); foreach ($compiledWithList as $name => $with) { $relation = $this->{$name}()->removeTake()->removeWhere(); foreach ($with as $index => $value) { if(is_callable($value)) { $value($relation); unset($with[$index]); } } $result = (new EagerLoader)->load([ 'name' => $name, 'relation' => $relation, ], $result ?? $this, $with); } } return $result; } /** * @param string $relationship * @param null|callable $scope * * @return $this * @throws \Exception */ public function has(string $relationship, $scope = null) { if(!method_exists($this, $relationship)) { throw new \Exception("No such relationship of '{$relationship}' exists for " . get_class($this)); } $rel = $this->{$relationship}(); if(!$rel instanceof Model) { throw new \Exception("Trying to get relationship of '{$relationship}' but no Model class is returned for " . get_class($this)); } $rel->getQuery()->modifyWhere(-1, [ 'value' => $this->getQuery()->getIdColumWithTable(), 'operator' => '=', 'raw' => true ]); if(is_callable($scope)) { $scope($rel); } $this->query->merge($rel->getQuery()); return $this; } /** * Count results * * @param string $column * * @return array|bool|false|int|null|object */ public function count($column = null) { if(!$column) { return $this->query->countDerived(); } return $this->query->count($column); } /** * Select only specific columns * * @param string $args * * @return $this */ public function select($args) { if( ! is_array($args) ) { $args = func_get_args(); } $this->query->select($args); return $this; } /** * Reselect * * @param string $args * @return $this */ public function reselect($args) { if( ! is_array($args) ) { $args = func_get_args(); } $this->query->reselect($args); return $this; } /** * Get base field value * * Some fields need to be saved as serialized arrays. Getting * the field by the base value is used by Fields to populate * their values. * * This method must be implemented to return the base value * of a field if it is saved as a bracket group. * * @param string $field_name * * @return null */ public function getBaseFieldValue($field_name) { $data = (array) $this->properties; if( $this->getID() && empty( $data[$field_name] ) ) { $data = (array) $this->query->findById($this->getID())->get(); } return $this->getValueOrNull( $data[$field_name] ?? null ); } /** * Search Deeply For Value * * This is best used with eager loading. * * @param string $dots * @param bool $decode * * @return mixed|Model|null */ public function getDeepValue($dots, $decode = false) { $keys = explode('.', $dots); $result = $this; foreach ($keys as $property) { if(method_exists($result, 'getProperty')) { $result = $result->getProperty($property); } else { $result = $result[$property] ?? $result->{$property} ?? null; } if( !$result ) { return null; } if($decode && is_string($result)) { if(is_serialized($result)) { $result = unserialize($result); } elseif(Data::isJson($result)) { $result = json_decode($result); } } } return $result; } /** * Get Date Time * * @return bool|string */ public function getDateTime() { return date('Y-m-d H:i:s', time()); } /** * Get the ID from properties * * @return mixed */ public function getID() { return !empty($this->properties[$this->idColumn]) ? $this->properties[$this->idColumn] : null; } /** * Get ID Column * * @return string */ public function getIdColumn() { return $this->idColumn; } /** * Has ID Column Set * * @return bool */ public function hasIdColumn() : bool { return isset( $this->properties[$this->getIdColumn()] ); } /** * Save Changes Then Get New Model * * Save model and then return a fresh instance of the model. * * @param array|Fields $fields * * @return mixed|Model|null */ public function saveAndGet($fields = []) { $current = $this->findById($this->getID()); if( $this->hasIdColumn() && $current ) { if($updated = $this->update($fields)) { if($updated instanceof Model) { return $updated; } $modelClass = get_class($this); return (new $modelClass)->findById($this->getID()); } return $current; } if($created = $this->create($fields)) { if($created instanceof Model) { return $created; } $modelClass = get_class($this); return (new $modelClass)->findById($created); } return null; } /** * Save changes directly * * - Return Model when using built-in WP models. * - Return bool when update on custom model. * - Return int when create on custom model. * * @param array|Fields $fields * * @return mixed|bool|int */ public function save( $fields = [] ) { if( isset( $this->properties[$this->idColumn] ) && $this->findById($this->properties[$this->idColumn]) ) { $update = $this->update($fields); if($update === 1 || $update === 0) { return (bool) $update; } } return $this->create($fields); } /** * @param null|array|Fields $fields * * @return mixed */ public function saveFields($fields = null) { $fields = $fields ?? (new Request)->getFields(); return $this->save($fields); } /** * Cast Properties * * @param array|ArrayObject $properties * * @return $this */ public function castProperties( $properties ) { // Create Unaltered copy $this->propertiesUnaltered = $this->propertiesUnaltered ?: (array) $properties; // Cast properties $cast = []; $this->properties = (array) $properties; foreach ($this->properties as $name => $property ) { $cast[$name] = $this->getCast($name); } $this->properties = apply_filters('typerocket_model_cast_fields', $cast, $this ); $this->afterCastProperties(); return $this; } /** * Run After Cast Properties * * @return $this */ protected function afterCastProperties() { return $this; } /** * Get Cast * * Get the cast value of a property * * @param string $property * * @return mixed */ public function getCast( $property ) { $value = $this->properties[$property] ?? null; if ( ! empty( $this->cast[$property] ) ) { $handle = $this->cast[$property]; $value = Data::cast($value, $handle); } return $this->properties[$property] = $value; } /** * Has One * * @param string $modelClass * @param null|string $id_foreign * * @param null|callable $scope * @return mixed|null */ public function hasOne($modelClass, $id_foreign = null, $scope = null) { $id = $this->getID(); if( ! $id_foreign && $this->resource ) { $id_foreign = $this->resource . '_id'; } /** @var Model $relationship */ $relationship = new $modelClass; $relationship->setRelatedModel( $this ); $relationship->relatedBy = [ 'type' => 'hasOne', 'query' => [ 'caller' => $this, 'class' => $modelClass, 'id_foreign' => $id_foreign, 'scope' => $scope ] ]; return $relationship->findAll()->where( $id_foreign, $id)->take(1); } /** * Belongs To * * @param string $modelClass * @param null|string $id_local * @param null|callable $scope * * @return $this|null */ public function belongsTo($modelClass, $id_local = null, $scope = null) { /** @var Model $relationship */ $relationship = new $modelClass; $relationship->setRelatedModel( $this ); $relationship->relatedBy = [ 'type' => 'belongsTo', 'query' => [ 'caller' => $this, 'class' => $modelClass, 'local_id' => $id_local, 'scope' => $scope ] ]; if( ! $id_local && $relationship->resource ) { $id_local = $relationship->resource . '_id'; } $id = $this->getProperty( $id_local ); return $relationship->where( $relationship->getIdColumn(), $id)->take(1); } /** * Has Many * * @param string $modelClass * @param null|string $id_foreign * @param null|callable $scope * * @return null|Model */ public function hasMany($modelClass, $id_foreign = null, $scope = null) { $id = $this->getID(); /** @var Model $relationship */ $relationship = new $modelClass; $relationship->setRelatedModel( $this ); $relationship->relatedBy = [ 'type' => 'hasMany', 'query' => [ 'caller' => $this, 'class' => $modelClass, 'id_foreign' => $id_foreign, 'scope' => $scope ] ]; if( ! $id_foreign && $this->resource ) { $id_foreign = $this->resource . '_id'; } if(is_callable($scope)) { $scope($relationship); } return $relationship->findAll()->where( $id_foreign, $id ); } /** * Belongs To Many * * This is for Many to Many relationships. * * @param string|array $modelClass * @param string $junction_table * @param null|string $id_column * @param null|string $id_foreign * @param null|callable $scope * @param bool $reselect * * @return null|Model */ public function belongsToMany( $modelClass, $junction_table, $id_column = null, $id_foreign = null, $scope = null, $reselect = true ) { [$modelClass, $modelClassOn] = array_pad((array) $modelClass, 2, null); // Column ID if( ! $id_column && $this->resource ) { $id_column = $this->resource . '_id'; } $id = $this->$id_column ?? $this->getID(); /** @var Model $relationship */ $relationship = new $modelClass; // Foreign ID if( ! $id_foreign && $relationship->resource ) { $id_foreign = $relationship->resource . '_id'; } $rel_table = $relationship->getTable(); // Set Junction: `attach` and `detach` will use inverse columns $relationship->setJunction( [ 'table' => $junction_table, 'columns' => [$id_foreign, $id_column], 'id_foreign' => $id ] ); if(isset($modelClassOn) && class_exists($modelClassOn)) { $relationshipOn = new $modelClassOn; } else { $relationshipOn = $relationship; } // Join $join_table = $junction_table; $rel_join = $relationshipOn->getTable().'.'.$relationshipOn->getIdColumn(); $foreign_join = $join_table.'.'.$id_foreign; $where_column = $join_table.'.'.$id_column; $relationship->getQuery()->distinct()->join($join_table, $foreign_join, $rel_join); $relationship->setRelatedModel( $this ); $relationship->relatedBy = [ 'type' => 'belongsToMany', 'query' => [ 'caller' => $this, 'class' => $modelClass, 'junction_table' => $junction_table, 'id_column' => $id_column, 'id_foreign' => $id_foreign, 'where_column' => $where_column, 'scope' => $scope ] ]; if(is_callable($scope)) { $scope($relationship, $reselect); } if($reselect) { $relationship->reselect($rel_table.'.*'); } return $relationship->where($where_column, $id)->findAll(); } /** * Attach to Junction Table * * @param array $args * * @return array $query */ public function attach( array $args ) { $rows = []; $query = new Query(); $junction = $this->getJunction(); $columns = $junction['columns']; $id_foreign = $junction['id_foreign']; foreach ( $args as $id ) { if( is_array($id) ) { $attach_id = array_shift($id); $names = array_keys($id); $rows[] = array_merge([ $attach_id, $id_foreign ], $id); $columns = array_merge($columns, $names); } else { $rows[] = [ $id, $id_foreign ]; } } $result = $query->table( $junction['table'] )->create($columns, $rows); return [$result, $query]; } /** * Detach from Junction Table * * @param array $args * * @return array */ public function detach( array $args = [] ) { $query = new Query(); $junction = $this->getJunction(); $id_foreign = $junction['id_foreign']; [ $local_column, $foreign_column ] = $junction['columns']; $query->where($foreign_column, '=', $id_foreign); if( !empty($args) ) { $query->where($local_column, 'IN', $args); } $result = $query->table( $junction['table'] )->delete(); return [$result, $query]; } /** * Sync Junction Table * * First detach and then attach new records. * * @param array $args * * @return array $results */ public function sync( array $args = [] ) { $results = []; $results['detach'] = $this->detach(); $results['attach'] = $this->attach( $args ); return $results; } /** * Get Table * * @return null */ public function getTable() { /** @var wpdb $wpdb */ global $wpdb; return $this->table ? $this->table : $wpdb->prefix . $this->resource; } /** * Set Table As * * @param $as * * @return $this */ public function as($as) { $this->query->setTableAs($as); return $this; } /** * Get Query * * @return Query */ public function getQuery() { return $this->query; } /** * Get Related Model * * @return null|Model */ public function getRelatedModel() { return $this->currentRelationshipModel; } /** * Set Related Model * * @param Model $model * * @return Model $this */ public function setRelatedModel( Model $model ) { $this->currentRelationshipModel = clone $model; return $this; } /** * Get Relationship * * @return array|null */ public function getRelatedBy() { return $this->relatedBy; } /** * Get Junction * * @return null|string */ public function getJunction() { return $this->junction; } /** * Set Junction * * @param array $junction * * @return $this */ public function setJunction( array $junction ) { $this->junction = $junction; return $this; } /** * Get Last SQL Query * * @return null|string */ public function getSuspectSQL() { if( ! $this->query->lastCompiledSQL ) { $this->query->compileFullQuery(); } return $this->query->lastCompiledSQL; } /** * Get the Query result * * @param string $results * * @return Model|Results|null|object * */ protected function getQueryResult( $results ) { return $this->fetchResult( $results ); } /** * Get attribute as property * * @param string $key * * @return mixed */ public function __get($key) { return $this->getProperty($key); } /** * Property Exists * * @param string $key * * @return bool */ public function __isset($key) { return !is_null($this->getProperty($key)); } /** * Unset Property * * @param string $key */ public function __unset($key) { if(isset($this->properties[$key])) { unset($this->properties[$key]); } } /** * Set attribute as property * * @param string $key * @param null|mixed $value */ public function __set($key, $value = null) { $this->setProperty($key, $value); } /** * Get a plain attribute (not a relationship). * * If the attribute has a get mutator, we will call that then return what * it returns as the value, which is useful for transforming values on * retrieval from the model to a form that is more useful for usage. * * @param string $key * @return mixed */ public function getPropertyValue($key) { return $this->getPropertyFromArray($key); } /** * Get Relationships * * @return array */ public function getRelationships() { return $this->relationships; } /** * Get a relationship. * * If the "attribute" exists as a method on the model, we will just assume * it is a relationship and will load and return results from the query * and hydrate the relationship's value on the "relationships" array. * * @param string $key * @return mixed */ public function getRelationValue($key) { if(array_key_exists($key, $this->relationships)) { return $this->relationships[$key]; } if (method_exists($this, $key)) { return $this->getRelationshipFromMethod($key); } return null; } /** * Get an attribute from the $this->properties array. * * If the attribute has a get mutator, we will call that then return what * it returns as the value, which is useful for transforming values on * retrieval from the model to a form that is more useful for usage. * * @param string $key * @return mixed */ protected function getPropertyFromArray($key) { $value = $this->properties[$key] ?? null; if ($this->hasGetMutator($key)) { return $this->mutatePropertyGet($key, $value); } return $value; } /** * @param string $key * * @return mixed|null */ public function getPropertyValueDirect(string $key) { return $this->properties[$key] ?? null; } /** * Get a relationship value from a method. * * @param string $method * @return mixed * */ protected function getRelationshipFromMethod($method) { $rel = $this->$method() ?? null; return is_object($rel) ? $rel->get() : null; } /** * Determine if a set mutator exists for an attribute. * * @param string $key * @return bool */ public function hasSetMutator($key) { return method_exists($this, 'set'.Str::camelize($key).'Property'); } /** * Determine if a get mutator exists for an attribute. * * @param string $key * @return bool */ public function hasGetMutator($key) { return method_exists($this, 'get'.Str::camelize($key).'Property'); } /** * Get the value of an attribute using its mutator. * * @param string $key * @param mixed $value * @return mixed */ protected function mutatePropertySet($key, $value) { return $this->{'set'.Str::camelize($key).'Property'}($value); } /** * Get the value of an attribute using its mutator. * * @param string $key * @param mixed $value * @return mixed */ protected function mutatePropertyGet($key, $value) { return $this->{'get'.Str::camelize($key).'Property'}($value); } /** * Get Form Fields * * @return array */ public function getFormFields() { $this->castProperties($this->properties); return $this->properties; } /** * Eager Load With * * @param string|array $name * * @return $this */ public function with($name) { $with = func_get_args(); if(is_array($name)) { $with = $name; } $this->with = array_filter($with); return $this; } /** * Get With Compiled * * @return array */ public function getWithCompiled() { if(is_string($this->with)) { $withList = [$this->with]; } else { $withList = $this->with ?? []; } $compiledWithList = []; foreach ($withList as $withName => $withArg) { if(is_callable($withArg)) { [$name, $with] = array_pad(explode('.', $withName, 2), 2, null); if($with) { $compiledWithList[$name][$with] = $withArg; } else { $compiledWithList[$name][] = $withArg; } } else { [$name, $with] = array_pad(explode('.', $withArg, 2), 2, null); $compiledWithList[$name][] = $with; } } return $compiledWithList; } /** * Set Relationship * * @param string $name * @param string $value */ public function setRelationship($name, $value) { $this->relationships[$name] = $value; } /** * Get Relationship * * @param string $name * @return mixed|null */ public function getRelationship($name) { $names = explode('.', $name); $rel = $this; foreach ($names as $name) { $rel = $rel->relationships[$name]; } return $rel; } /** * Get Field Options * * @return array */ public function getFieldOptions() { return $this->fieldOptions; } /** * Paginate * * @param int $number * @param null|int $page * @return \TypeRocket\Database\ResultsPaged|null */ public function paginate($number = 25, $page = null) { $obj = $this; return $this->query->paginate($number, $page, function($results) use ($obj) { return $obj->getQueryResult($results); }); } /** * @return mixed|\TypeRocket\Template\Composer */ public function composer() { $composer = $this->composer; return new $composer($this); } /** * Get Model Clone * * @return $this */ public function clone() { return clone $this; } /** * To Array * * Get array of model and loaded relationships * * @return array */ public function toArray() { $relationships = []; foreach($this->relationships as $key => $rel) { $value = $rel ? $rel->toArray() : null; $relationships[$key] = $value; } return array_merge($this->getPublicProperties(), $relationships); } /** * To JSON */ public function toJson() { return json_encode($this); } /** * Convert the model to its string representation. * * @return string */ public function __toString() { return $this->toJson(); } /** * @param mixed $value * @param callable $function * * @return $this */ public function when($value, callable $function) { if(!empty($value)) { $function($this, $value); } return $this; } /** * @param $value * * @return object * @throws \Exception */ public function onDependencyInjection($value) { if($value === $this) { return $this; } return $this->findFirstWhereOrDie($this->getDependencyInjectionKey(), $value); } /** * @return string */ public function getDependencyInjectionKey() { return $this->getIdColumn(); } /** * @inheritDoc */ #[\ReturnTypeWillChange] public function jsonSerialize() { return $this->toArray(); } /** * @param mixed ...$args * * @return static * @throws \Exception */ public static function new(...$args) { return new static(...$args); } } src/Models/WPTermTaxonomy.php000064400000001347150732302400012205 0ustar00term_taxonomy; } /** * @return WPTermTaxonomy|null */ public function term() { return $this->belongsTo( WPTerm::class, 'term_id' ); } }templates/MigrationRun.txt000064400000000023150732302400011710 0ustar00-- Ran At: {{time}}templates/Auth.txt000064400000000746150732302400010207 0ustar00>> Up >>> -- >>> Down >>>templates/Component.txt000064400000001000150732302400011230 0ustar00form(); } /** * Render * * @var array $data component fields * @var array $info name, item_id, model, first_item, last_item, component_id, hash */ public function render(array $data, array $info) { ?> request; $response = $this->response; // Do stuff before controller is called $this->next->handle(); // Do stuff after controller is called } }templates/Job.txt000064400000000512150732302400010007 0ustar00payload; } }templates/Rule.txt000064400000001164150732302400010210 0ustar00args); if( false ) { $this->error = "does not pass {{key}} rule."; } return !$this->error; } }templates/Controllers/Template.txt000064400000000210150732302400013351 0ustar00addArgument('arg', self::REQUIRED, 'Description'); } public function exec() { // When command executes $this->success('Execute!'); } }templates/Fields.txt000064400000001331150732302400010503 0ustar00 { .tr-divide + .tr-divide { box-shadow: none; } @media screen and (max-width: 782px) { .tr-control-section, .tr-control-row { padding: 8px 0; > .tr-control-label { font-size: 14px; font-weight: 600; } } } } @media screen and (min-width: 783px) { display: table; border-collapse: collapse; .tr-dev-field-helper .nav { max-width: 120px; } > { .tr-control-section { display: table-row; > .tr-control-label { color: #333; display: table-cell; font-size: 14px; height: auto; vertical-align: top; text-align: left; padding: 20px 10px 20px 0; width: 200px; line-height: 1.3; font-weight: 600; } > .control, > .controls { margin-bottom: 9px; padding: 15px 10px; line-height: 1.3; font-size: 14px; vertical-align: middle; display: table-cell; } > .controls { vertical-align: top; } &.tr-repeater > .tr-dev-field-helper { display: none; } } } } } /* WordPress Style Guide - Widgets ----------------------------------------------------------------------- */ .typerocket-wp-style-subtle { div.tr-control-label { font-weight: normal; font-size: 13px; line-height: 1.5; } > { .tr-control-section, .tr-control-row { padding: 8px 0; } .tr-divide + .tr-divide { box-shadow: none; } } } .tr-menu-container { padding-right: 10px; clear: both; div.tr-control-label { font-style: italic; color: #666; padding-bottom: 0; } } .tr-taxonomy-add-container { padding-right: 5%; }assets/sass/core.scss000064400000001523150732302400010641 0ustar00@import 'vars.scss'; @import "css_vars.scss"; @import "utility/style"; @import "utility/contextual"; @import "utility/sort"; @import "utility/form"; @import "utility/form-input-range"; @import "utility/icon-controls"; @import "utility/repeater"; @import "utility/matrix"; @import "utility/builder"; @import "utility/headings"; @import "utility/items"; @import "utility/alert"; @import "utility/search"; @import "utility/image"; @import "utility/gallery"; @import "utility/dev"; @import "utility/tabs"; @import "utility/toggle"; @import "utility/tables"; @import "utility/location"; @import "utility/swatches"; @import "utility/editor"; @import "utility/layout"; @import "tooling/style-guide"; @import "lib/ui-datepicker"; @import "lib/chosen"; @import "plugins/seo"; @import "plugins/dev"; @import "plugins/page-builder"; @import "admin-profiles";assets/sass/admin-profiles.scss000064400000003073150732302400012624 0ustar00/* Admin Profiles ----------------------------------------------------------------------- */ @each $name, $color, $bg in $themes { .admin-color-#{$name} { .tr-control-icon-clone { &:hover { color: $color; } } .tr-maxlength span { color: $color; } .chosen-container .chosen-results { li.highlighted { background-color: $color; } } .chosen-container-multi { .chosen-choices li { &.search-choice { border-color: $color; color: $color; } } } .chosen-container-active{ .chosen-single, .chosen-choices { border-color: $color; box-shadow: 0 0 0 1px $color; } } .tr-toggle-box { input:checked + label { background-color: $color; } label:focus { box-shadow: 0 0 3px rgba($color, 0.8); } } .tr-link-search-result { &:hover, &:focus, &:active { background: $color; } } .tr-tabbed-box { .tr-tab-layout-tabs { a { color: $color; } li:hover, li:active, li:focus, .active { border-left: 3px solid $color; .tr-tab-link { > .tab-icon { color: $color; } } } } } } } .wp-admin select:focus { border-color: var(--tr-profile-color, #007cba); color: var(--tr-profile-color-dark, #016087); box-shadow: 0 0 0 1px var(--tr-profile-color, #007cba); } .wp-admin select:hover { color: var(--tr-profile-color, #007cba); }assets/sass/_vars.scss000064400000004073150732302400011026 0ustar00/* Sync To TypeRocket Pro Core */ // Branding $blue: #3182bd; $dark: #085286; $light: #5199CC; $alt: #FFCB36; // WordPress Colors $wp_button: #007cba; // new color WP 5.3 $wp_button_hover: #0071a1; // new color WP 5.3 $wp_link: #0073aa; $wp_link_hover: #00a0d2; // Alerts $success: #46b450; $error: #dc3232; $warn: #ffb900; $info: #00a0d2; // Controls $delete: #A00; $delete_hover: #F00; // Grays $gray: #666; $gray_dark: #191e23; $gray_border: #ccd0d4; $gray_icon: #9B9B9B; $gray_border_input: #7e8993; // @link https://make.wordpress.org/core/2019/10/18/noteworthy-admin-css-changes-in-wordpress-5-3/ $gray_bg_disabled: #f7f7f7; $gray_color_disabled: #a0a5aa; $gray_border_disabled: #ddd; // SVG // 16px by 16px $icon_select_chevron_url: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%23555%22%2F%3E%3C%2Fsvg%3E'); $icon_select_chevron_url_disabled: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%23a0a5aa%22%2F%3E%3C%2Fsvg%3E'); @keyframes tr-shake { 10%, 90% { transform: translate3d(-1px, 0, 0); } 20%, 80% { transform: translate3d(2px, 0, 0); } 30%, 50%, 70% { transform: translate3d(-4px, 0, 0); } 40%, 60% { transform: translate3d(4px, 0, 0); } } .tr-shake { animation: tr-shake 0.82s cubic-bezier(.36,.07,.19,.97) both; transform: translate3d(0, 0, 0); } @mixin visually-hidden { position: absolute !important; height: 1px; width: 1px; overflow: hidden; clip: rect(1px, 1px, 1px, 1px); white-space: nowrap; } $themes: "default" #0073aa #333, "light" #04a4cc #999, "ectoplasm" #a3b745 #523f6d, "coffee" #c7a589 #59524c, "midnight" #e14d43 #363b3f, "ocean" #9ebaa0 #738e96, "sunrise" #dd823b #cf4944, "blue" #096484 #4796b3;assets/sass/_css_vars.scss000064400000000505150732302400011672 0ustar00:root { @each $name, $color, $bg in $themes { --tr-#{$name}-color: #{$color}; } --tr-profile-color: #{$wp_button}; } @each $name, $color, $bg in $themes { .admin-color-#{$name} { --tr-profile-color: #{$color}; --tr-profile-color-bg: #{$bg}; --tr-profile-color-dark: #{darken($color, 25%)}; } }assets/sass/plugins/page-builder.scss000064400000001132150732302400013726 0ustar00/* Builder Plugin */ #tr_page_type_toggle { text-align: center; clear: both; padding: 15px 12px 10px; box-sizing: border-box; width: 100%; } #tr_page_type_toggle:after { content: ''; display: block; clear: both; } #tr_page_type_toggle a { text-decoration: none; width: 50%; vertical-align: middle; box-sizing: border-box; outline: none; } #tr_page_type_toggle a:first-child { border-radius: 3px 0 0 3px; } #tr_page_type_toggle a:last-child { border-radius: 0 3px 3px 0; border-left: none; } #builderSelectRadio { display: none; }assets/sass/plugins/dev.scss000064400000001346150732302400012153 0ustar00/* Dev Page ----------------------------------------------------------------------- */ #dev-icon-search { width: 100%; max-width: 100%; } #debug-icon-list { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; grid-column-gap: 10px; grid-row-gap: 10px; margin: 20px 0 0; padding: 0; .tr-debug-icon { height: auto; width: auto; } strong, em { margin: 6px 0; display: block; } li { list-style: none; border: solid $gray_border 1px; border-radius: 4px; text-align: center; font-size: 12px; padding: 10px; i:before { font-size: 42px; display: block; } } }assets/sass/plugins/seo.scss000064400000003063150732302400012161 0ustar00/* SEO Plugin ----------------------------------------------------------------------- */ #tr-seo-preview h4 { margin: 0; } #tr-seo-preview p { margin-top: 0; } .tr-seo-preview-google { max-width: 600px; display: block; } #tr-seo-preview-google-title-orig, #tr-seo-preview-google-desc-orig { display: none; } #tr-seo-preview-google-title { display: block; color: #1a0dab; cursor: pointer; font-family: arial, sans-serif; font-size: 20px; line-height: 1.3em; font-weight: normal; height: auto; list-style-image: none; list-style-position: outside; list-style-type: none; text-align: left; text-decoration: none; visibility: visible; white-space: nowrap; width: auto; zoom: 1; &:hover { text-decoration: underline; } } #tr-seo-preview-google-url { color: #006621; font-family: arial, sans-serif; font-size: 16px; padding-top: 1px; line-height: 1.5; font-style: normal; font-weight: normal; list-style-image: none; list-style-position: outside; list-style-type: none; margin-bottom: 1px; text-align: left; visibility: visible; white-space: nowrap; zoom: 1; } #tr-seo-preview-google-desc { color: #545454; display: inline; font-family: arial, sans-serif; font-size: 14px; font-weight: normal; height: auto; line-height: 1.57; list-style-image: none; list-style-position: outside; list-style-type: none; text-align: left; visibility: visible; width: auto; zoom: 1; }assets/sass/lib/chosen.scss000064400000022152150732302400011737 0ustar00$chosen-sprite: url('../img/chosen-sprite.png') !default; $chosen-sprite-retina: url('../img/chosen-sprite@2x.png') !default; $chosen-border-radius: 3px; /* @group Base */ .chosen-container { position: relative; display: inline-block; vertical-align: middle; font-size: 13px; user-select: none; width: 100% !important; * { box-sizing: border-box; } .chosen-drop { position: absolute; top: 100%; z-index: 1010; width: 100%; border: 1px solid $gray_border_input; border-top: 0; background: #fff; clip: rect(0,0,0,0); clip-path: inset(100% 100%); } &.chosen-with-drop .chosen-drop { clip: auto; clip-path: none; } a{ cursor: pointer; } .search-choice, .chosen-single{ .group-name{ margin-right: 4px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-weight: normal; color: #999999; &:after { content: ":"; padding-left: 2px; vertical-align: top; } } } } /* @end */ /* @group Single Chosen */ .chosen-container-single{ .chosen-single { position: relative; display: block; overflow: hidden; padding: 0 0 0 8px; line-height: 26px; min-height: 26px; border: 1px solid $gray_border_input; border-radius: $chosen-border-radius; background: #fff $icon_select_chevron_url no-repeat right 5px top 55%; background-size: 16px 16px; background-clip: padding-box; color: #444; text-decoration: none; white-space: nowrap; } .chosen-default { color: #999; } .chosen-single span { display: block; overflow: hidden; margin-right: 26px; text-overflow: ellipsis; white-space: nowrap; } .chosen-single-with-deselect span { margin-right: 38px; } .chosen-single abbr { @include tr-dash-icon; position: absolute; top: 4px; right: 26px; display: block; width: 18px; height: 18px; &:before { content: "\f335"; } &:hover { color: $delete_hover; } } &.chosen-disabled .chosen-single abbr { display: none; } .chosen-single div { display: none; } .chosen-search { position: relative; z-index: 1010; margin: 0; padding: 3px 4px; white-space: nowrap; input[type="text"] { margin: 1px 0; padding: 4px 20px 4px 5px !important; width: 100%; height: auto; min-height: 10px; outline: 0; border: 1px solid $gray_border_input; background: $chosen-sprite no-repeat 100% -20px; font-size: 1em; line-height: normal; border-radius: 0; } } .chosen-drop { margin-top: -1px; border-radius: 0 0 $chosen-border-radius $chosen-border-radius; background-clip: padding-box; } &.chosen-container-single-nosearch .chosen-search { position: absolute; clip: rect(0,0,0,0); clip-path: inset(100% 100%); } } /* @end */ /* @group Results */ .chosen-container .chosen-results { color: #444; position: relative; overflow-x: hidden; overflow-y: auto; margin: 0 4px 4px 0; padding: 0 0 0 4px; max-height: 240px; -webkit-overflow-scrolling: touch; li { display: none; margin: 0; padding: 5px 6px; list-style: none; line-height: 15px; word-wrap: break-word; -webkit-touch-callout: none; &.active-result { display: list-item; cursor: pointer; } &.disabled-result { display: list-item; color: #ccc; cursor: default; } &.highlighted { background-color: $wp_button_hover; color: #fff; } &.no-results { color: #777; display: list-item; background: #f4f4f4; } &.group-result { display: list-item; font-weight: bold; cursor: default; } &.group-option { padding-left: 15px; } em { font-style: normal; text-decoration: underline; } } } /* @end */ /* @group Multi Chosen */ .chosen-container-multi{ .chosen-choices { position: relative; overflow: hidden; margin: 0; padding: 0 5px; width: 100%; height: auto; border: 1px solid $gray_border_input; background: #fff; cursor: text; border-radius: 3px; } .search-choice-close { transition-property: color; } .chosen-choices li { float: left; list-style: none; &.search-field { margin: 0; padding: 0; white-space: nowrap; input[type="text"] { margin: 1px 0; padding: 0 !important; width: 25px; height: 25px; min-height: 25px; outline: 0; border: 0 !important; background: transparent !important; box-shadow: none; color: #999; font-size: 100%; line-height: normal; border-radius: 0; } } &.search-choice { position: relative; margin: 3px 5px 3px 0; padding: 3px 20px 3px 5px; border: 1px solid $wp_button_hover; max-width: 100%; border-radius: $chosen-border-radius; color: $wp_button_hover; background: #f3f5f6; line-height: 13px; cursor: default; span { word-wrap: break-word; } .search-choice-close { @include tr-dash-icon; position: absolute; width: 18px; height: 18px; top: 1px; right: 0; display: block; color: inherit; &:before { content: "\f335"; } &:hover { color: $delete_hover; } } } &.search-choice-disabled { padding-right: 5px; border: 1px solid #ccc; background-color: #e4e4e4; background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); color: #666; } &.search-choice-focus { background: #d4d4d4; .search-choice-close { background-position: -42px -10px; } } } .chosen-results { margin: 0; padding: 0; } .chosen-drop .result-selected { display: list-item; color: #ccc; cursor: default; } } /* @end */ /* @group Active */ .chosen-container-active{ .chosen-single { border: 1px solid $wp_button_hover; box-shadow: 0 0 0 1px $wp_button_hover; } &.chosen-with-drop{ .chosen-single { border: 1px solid $gray_border_input; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } } .chosen-choices { box-shadow: 0 0 0 1px $wp_button_hover; border: 1px solid $wp_button_hover; li.search-field input[type="text"] { color: #222 !important; } } } /* @end */ /* @group Disabled Support */ .chosen-disabled { cursor: default; .chosen-single { cursor: default; color: $gray_color_disabled; background-color: $gray_bg_disabled; background-image: $icon_select_chevron_url_disabled; border-color: $gray_border_disabled; } .chosen-choices { cursor: default; color: $gray_color_disabled; background-color: $gray_bg_disabled; border-color: $gray_border_disabled; } .chosen-choices li.search-choice { color: $gray_color_disabled; border-color: $gray_border_disabled; background-color: $gray_bg_disabled; .search-choice-close { cursor: default; color: $gray_color_disabled; &:hover { color: inherit; } } } } /* @end */ /* @group Right to Left */ .chosen-rtl { text-align: right; .chosen-single { overflow: visible; padding: 0 8px 0 0; } .chosen-single span { margin-right: 0; margin-left: 26px; direction: rtl; } .chosen-single-with-deselect span { margin-left: 38px; } .chosen-single div { right: auto; left: 3px; } .chosen-single abbr { right: auto; left: 26px; } .chosen-choices li { float: right; &.search-field input[type="text"] { direction: rtl; } &.search-choice { margin: 3px 5px 3px 0; padding: 3px 5px 3px 19px; .search-choice-close { right: auto; left: 4px; } } } &.chosen-container-single .chosen-results { margin: 0 0 4px 4px; padding: 0 4px 0 0; } .chosen-results li.group-option { padding-right: 15px; padding-left: 0; } &.chosen-container-active.chosen-with-drop .chosen-single div { border-right: none; } .chosen-search input[type="text"] { padding: 4px 5px 4px 20px !important; background: $chosen-sprite no-repeat -30px -20px; direction: rtl; } &.chosen-container-single{ .chosen-single div b { background-position: 6px 2px; } &.chosen-with-drop{ .chosen-single div b { background-position: -12px 2px; } } } } /* @end */ /* @group Retina compatibility */ @media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi), only screen and (min-resolution: 1.5dppx) { .chosen-rtl .chosen-search input[type="text"], .chosen-container-single .chosen-search input[type="text"], .chosen-container .chosen-results-scroll-down span, .chosen-container .chosen-results-scroll-up span { background-image: $chosen-sprite-retina !important; background-size: 52px 37px !important; background-repeat: no-repeat !important; } } /* @end */assets/sass/lib/ui-datepicker.scss000064400000015361150732302400013212 0ustar00/* * jQuery UI Datepicker 1.10.3 * * Copyright 2013, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * http://jqueryui.com/datepicker/ */ .tr-datepicker-container { width: 17em; display: none; z-index: 1000 !important; .ui-datepicker-header { position:relative; padding: .2em 0; border: 0; font-weight: bold; width: 100%; background: #F1F1F1; color: #808080; border-bottom: 1px solid #dfdfdf; } .ui-datepicker-prev, .ui-datepicker-next { position: absolute; top: 2px; width: 1.8em; height: 1.8em; text-indent: -9999px; cursor: pointer; } .ui-datepicker-prev { left: 2px; } .ui-datepicker-prev:after { content: ''; display: block; border: 6px solid transparent; margin-left: 3px; margin-top: 6px; border-right-color: #999; } .ui-datepicker-next:after { content: ''; display: block; border: 6px solid transparent; margin-right: 3px; margin-top: 6px; border-left-color: #999; } .ui-datepicker-prev:hover:after { border-right-color: #21759B; border-right-color: var(--tr-profile-color, #21759B); } .ui-datepicker-next:hover:after { border-left-color: #21759B; border-left-color: var(--tr-profile-color, #21759B); } .ui-datepicker-next { right: 2px; } .ui-datepicker-prev span, .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; font-weight: normal; color: #333 } .ui-datepicker-title select { font-size: 1em; margin: 1px 0; } select.ui-datepicker-month-year { width: 100%; } select.ui-datepicker-month, select.ui-datepicker-year { width: 49%; } table { width: 96%; font-size: .9em; border-collapse: collapse; margin:0 .4em .4em; } td { border: 0; padding: 1px; } td span, td a { display: block; padding: .2em; text-align: right; text-decoration: none; } .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width: auto; overflow:visible; } .ui-datepicker-buttonpane button.ui-datepicker-current { float: left; } } .ui-datepicker.ui-datepicker-multi { width: auto; } .ui-datepicker-multi .ui-datepicker-group { float: left; } .ui-datepicker-multi .ui-datepicker-group table { width: 95%; margin: 0 auto .4em; } .ui-datepicker-multi-2 .ui-datepicker-group { width: 50%; } .ui-datepicker-multi-3 .ui-datepicker-group { width: 33.3%; } .ui-datepicker-multi-4 .ui-datepicker-group { width: 25%; } .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width: 0; } .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width: 0; } .ui-datepicker-multi .ui-datepicker-buttonpane { clear: left; } .ui-datepicker-row-break { clear: both; width: 100%; font-size: 0em; } /* RTL support */ .ui-datepicker-rtl { direction: rtl; } .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } .ui-datepicker-rtl .ui-datepicker-buttonpane { clear: right; } .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float: right; } .ui-datepicker-rtl .ui-datepicker-group { float: right; } .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width: 0; border-left-width: 1px; } .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width: 0; border-left-width: 1px; } /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ .ui-datepicker-cover { display: none; /*sorry for IE5*/ display/**/: block; /*sorry for IE5*/ position: absolute; /*must have*/ z-index: -1; /*must have*/ filter: mask(); /*must have*/ top: -4px; /*must have*/ left: -4px; /*must have*/ width: 200px; /*must have*/ height: 200px; /*must have*/ } .tr-datepicker-container th { color: gray; padding: .7em .3em; text-align: center; font-weight: normal; border: 0; } .ui-datepicker-today a:hover { background-color: #808080; color: #ffffff; } .ui-datepicker-today a { background-color: #BFBFBF; cursor: pointer; padding: 0 4px; margin-bottom: 0; } .tr-datepicker-container td a { margin-bottom: 0; border: 0; } .tr-datepicker-container td:hover { color: #ffffff; } .tr-datepicker-container td .ui-state-default { color: #333333; font-size: 13px; line-height: normal; border: 1px solid #ccc; border-bottom-color: #bbb; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); /* Safari 4 */ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); /* Firefox 3.6 */ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -webkit-transition: 0.1s linear background-image; -moz-transition: 0.1s linear background-image; -o-transition: 0.1s linear background-image; transition: 0.1s linear background-image; overflow: visible; border: 0; background: #fff; margin-bottom: 0; padding: 5px; color: gray; text-align: center; filter: none; } .tr-datepicker-container td .ui-state-highlight{ color: #404040; background: #ffeda4; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); border-color: #eedc94 #eedc94 #e4c652; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); } .tr-datepicker-container td .ui-state-active { background: #bfbfbf; margin-bottom: 0; font-size: 1em; text-shadow: 0; color: #ffffff; } .tr-datepicker-container td .ui-state-hover { background-color: #21759B; background-color: var(--tr-profile-color, #21759B); border-color: #21759B; border-color: var(--tr-profile-color, #21759B); border-bottom-color: #1E6A8D; border-bottom-color: var(--tr-profile-color, #21759B); box-shadow: inset 0 1px 0 rgba(120, 200, 230, 0.5); box-shadow: inset 0 1px 0 var(--tr-profile-color, #7cc8e3); color: #FFF; text-decoration: none; text-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); } #ui-datepicker-div { background: #F5F5F5; border: 1px solid #dfdfdf; margin-top: 5px; }assets/sass/utility/image.scss000064400000005675150732302400012512 0ustar00/* Images and Files ----------------------------------------------------------------------- */ .tr-data-full, .tr-data-full li { margin: 0; padding: 0; list-style: none; } @media screen and (max-width: 782px) { .tr-data-full li { padding: 3px 0; } } .tr-image-picker-placeholder, .tr-file-picker-placeholder { margin-top: 10px; position: relative; } .tr-image-picker-placeholder img, .tr-file-picker-placeholder a { padding: 0; border: solid $gray_border 1px; background: #fff; display: block; max-width: 100%; height: auto; overflow: hidden; box-sizing: border-box; } .tr-image-field-background { display: flex; flex-direction: column; } .tr-image-background-placeholder { position: relative; display: inline-block; margin: 10px 10px 40px; width: 40%; min-width: 150px; max-width: 300px; height: auto; img { width: 100%; height: auto; position: relative; z-index: 0; border: 1px solid $gray_border; box-shadow: 0 0 3px #000; } } .tr-image-field-background { .tr-position-image { background: var(--tr-image-field-bg-src) no-repeat var(--tr-image-field-bg-x) var(--tr-image-field-bg-y); background-size: cover; margin: 10px 0; border: 1px solid $gray_border; } .tr-position-inputs { display: flex; label { padding: 0; } label:last-child { margin-left: 10px; } input { width: 65px; margin-left: 5px; } } } .tr-image-background-placeholder:not(:empty):after { display: block; content: ''; height: 30px; width: 30px; border-radius: 100%; border: 2px solid rgba(255,255,255,0.8); box-shadow: 0 0 3px #000; position: absolute; top: var(--tr-image-field-bg-y); left: var(--tr-image-field-bg-x); z-index: 2; transform: translate(-50%, -50%); pointer-events: none; } .tr-image-background-placeholder:not(:empty):before { display: block; content: ''; height: 4px; width: 4px; border-radius: 100%; background: $wp_button; background: var(--tr-profile-color); position: absolute; top: var(--tr-image-field-bg-y); left: var(--tr-image-field-bg-x); box-shadow: 0 0 3px #000; z-index: 3; transform: translate(-50%, -50%); pointer-events: none; } .tr-file-picker-placeholder a { padding: 8px; } .tr-image-picker-placeholder img { background: repeating-linear-gradient( 45deg, #ffffff, #ffffff 10px, #f0f0f0 10px, #f0f0f0 20px ); } .tr-dark-image-background img { background: repeating-linear-gradient( 45deg, #222131, #222131 10px, #000000 10px, #000000 20px ); }assets/sass/utility/toggle.scss000064400000002452150732302400012677 0ustar00/* Toggle Field ----------------------------------------------------------------------- */ .tr-toggle-box { display: flex; position: relative; input[type=checkbox] { height: 0; width: 0; visibility: hidden; position: absolute; } .tr-toggle-box-text { margin: 4px 12px 0; } .tr-toggle-box-label { cursor: pointer; width: 50px; height: 24px; border: 3px solid #6c7781; display: block; border-radius: 100px; position: relative; padding: 0; line-height: 1.4em; &:focus { outline: none; box-shadow: 0 0 3px rgba(0,115,170,.8); border-color: #4c5761; } } .tr-toggle-box-label:after { content: ''; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; background: #6c7781; border-radius: 14px; transition: 0.3s; } input:checked + .tr-toggle-box-label { border-color: transparent; background: #11a0d2; padding: 0; &:after { background: #fff; } } input:checked + .tr-toggle-box-label:after { left: calc(100% - 2px); transform: translateX(-100%); } }assets/sass/utility/search.scss000064400000007663150732302400012674 0ustar00/* Search Field ----------------------------------------------------------------------- */ .tr-search-chosen-item-remove { color: $delete; position: absolute; top: 50%; transform: translateY(-50%); right: 1px; cursor: pointer; background: none; border: none; appearance: none; -webkit-appearance: none; -moz-appearance: none; &:hover, &:active { color: $delete_hover; } &:focus { color: $delete_hover; outline: none; box-shadow: none; text-shadow: 0 0 7px $delete; } } .tr-search-results { margin: 0; background: #fff; box-shadow: inset 0 1px 2px rgba(0,0,0,.07); list-style: none; padding: 0; border-radius: 3px; > li:only-child { border-radius: 3px; } > li:first-child { border-radius: 3px 3px 0 0; } > li:last-child { border-radius: 0 0 3px 3px; } } .tr-search-result-title { color: #666; cursor: pointer; font-weight: bold; font-size: 12px; padding: 8px; margin: 3px 0 0; border: solid $gray_border 1px; background: #fff; } .tr-search-input { background: none; outline: none; &:focus { outline: none; } } .tr-search-chosen-item, .tr-search-result { color: $wp_link; color: var(--tr-profile-color); cursor: pointer; font-size: 14px; padding: 8px; margin: 0; border: solid $gray_border 1px; border-top: none; background: #eee; display: block; overflow: hidden; text-overflow: ellipsis; span { font-weight: normal; color: $gray_dark; b { font-weight: bold; color: $blue; color: var(--tr-profile-color); } } &:hover, &:focus, &:active { background: $wp_link; background: var(--tr-profile-color); color: #fff; outline: none; -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.07); box-shadow: inset 0 1px 2px rgba(0,0,0,.07); span { font-weight: normal; color: #fff; b { font-weight: bold; color: #fff; } } } } .tr-search-selected { padding: 5px 32px 5px 7px; margin-top: 5px; font-size: 14px; border: 1px solid $gray_border; font-weight: normal; background: #fff; position: relative; border-radius: 3px; } /* Search Field - Multiple ----------------------------------------------------------------------- */ .tr-search-multiple { padding: 6px; border-radius: 3px; border: 1px solid $gray_border; display: flex; .tr-search-controls, .tr-search-selected { width: 50%; flex: 1; display: block; margin: 0; padding: 0; border: none; background: transparent; box-sizing: border-box; } .tr-search-controls { padding-right: 3px; } .tr-results-placeholder { display: none; } .tr-search-selected { list-style: none; padding-left: 3px; &:empty:after { content: attr(data-placeholder); display: block; border: solid $gray_border 1px; padding: 5px; border-radius: 3px; } > li { cursor: move; position: relative; padding: 5px 32px 5px 7px; margin: 0; border: solid $gray_border 1px; border-top: none; &:first-child { border-top: solid $gray_border 1px; } span { cursor: pointer; } &:focus { text-decoration: underline; } &.tr-search-chosen-item.tr-ui-sortable-helper { border-top: solid $gray_border 1px; } } } &:after { content: ''; display: block; clear: both; } }assets/sass/utility/form-input-range.scss000064400000010215150732302400014604 0ustar00@use "sass:math"; .tr-range-input { width: 100%; } .tr-range-selected { display: block; margin-bottom: 3px; color: #32373c; font-size: 1rem; } .tr-range-labels { display: flex; margin-top: 1px; color: #666666; font-size: .8rem; flex-grow: 1; min-width: 0; div { flex: 1; } div:last-child { margin-left: auto; text-align: right; } } // Styling Cross-Browser Compatible Range Inputs with Sass // Github: https://github.com/darlanrod/input-range-sass // Author: Darlan Rod https://github.com/darlanrod // Version 1.5.2 // MIT License $track-color: #d7dade !default; $track-color-progress: var(--tr-profile-color,#00669b) !default; $thumb-color: #607d8b !default; $thumb-radius: 10px !default; $thumb-height: 20px !default; $thumb-width: 20px !default; $thumb-shadow-size: 4px !default; $thumb-shadow-blur: 4px !default; $thumb-shadow-color: rgba(0, 0, 0, .2) !default; $thumb-border-width: 1px !default; $thumb-border-color: #eceff1 !default; $track-width: 100% !default; $track-height: 4px !default; $track-shadow-size: 1px !default; $track-shadow-blur: 1px !default; $track-shadow-color: rgba(0, 0, 0, .2) !default; $track-border-width: 0px !default; $track-border-color: #cfd8dc !default; $track-radius: 0px !default; $contrast: 5% !default; $ie-bottom-track-color: darken($track-color, $contrast) !default; @mixin shadow($shadow-size, $shadow-blur, $shadow-color) { box-shadow: $shadow-size $shadow-size $shadow-blur $shadow-color, 0 0 $shadow-size lighten($shadow-color, 5%); } @mixin track { cursor: default; height: $track-height; transition: all .2s ease; width: $track-width; } @mixin thumb { // @include shadow($thumb-shadow-size, $thumb-shadow-blur, $thumb-shadow-color); background: #fff; border: $thumb-border-width solid var(--tr-profile-color,#00669b); border-radius: $thumb-radius; box-sizing: border-box; cursor: default; height: $thumb-height; width: $thumb-width; } [type='range'] { -webkit-appearance: none; background: transparent; margin: math.div( $thumb-height, 2) 0; width: $track-width; cursor: pointer; &::-moz-focus-outer { border: 0; } &:focus { outline: 0; &::-webkit-slider-runnable-track { background: $track-color; } &::-ms-fill-lower { background: $track-color-progress; } &::-ms-fill-upper { background: $track-color; } } &::-webkit-slider-runnable-track { @include track; // @include shadow($track-shadow-size, $track-shadow-blur, $track-shadow-color); background: $track-color; border: $track-border-width solid $track-border-color; border-radius: $track-radius; } &::-webkit-slider-thumb { @include thumb; -webkit-appearance: none; margin-top: math.div($track-height, 2) - math.div($thumb-height, 2) + 1; } &::-moz-range-track { // @include shadow($track-shadow-size, $track-shadow-blur, $track-shadow-color); @include track; background: $track-color; border: $track-border-width solid $track-border-color; border-radius: $track-radius; height: math.div($track-height, 2); } &::-moz-range-thumb { @include thumb; } &::-ms-track { @include track; background: transparent; border-color: transparent; border-width: math.div($thumb-height, 2) 0; color: transparent; } &::-ms-fill-lower { // @include shadow($track-shadow-size, $track-shadow-blur, $track-shadow-color); background: $track-color-progress; border: none; border-radius: ($track-radius * 2); } &::-ms-fill-upper { // @include shadow($track-shadow-size, $track-shadow-blur, $track-shadow-color); background: $track-color; border: none; border-radius: ($track-radius * 2); } &::-moz-range-progress { background-color: $track-color-progress; } &::-ms-thumb { @include thumb; margin-top: math.div($track-height, 4); } ::-ms-ticks-after { display: none; } ::-ms-ticks-before { display: none; } &:disabled { &::-webkit-slider-thumb, &::-moz-range-thumb, &::-ms-thumb, &::-webkit-slider-runnable-track, &::-ms-fill-lower, &::-ms-fill-upper { cursor: not-allowed; } } }assets/sass/utility/gallery.scss000064400000002703150732302400013054 0ustar00/* Gallery ----------------------------------------------------------------------- */ .tr-gallery-list { margin: 5px -5px 0; .tr-image-picker-placeholder img { cursor: move; } .ui-sortable-helper a { display: none; } } .tr-gallery-item { margin: 5px; position: relative; list-style: none; padding: 0; display: inline-block; vertical-align: top; box-sizing: border-box; border: solid 1px transparent; // fixes sorting spacing placeholder bug &:focus { outline: none; border: solid 1px var(--tr-profile-color); box-shadow: 0 0 4px #0073aa; box-shadow: 0 0 4px var(--tr-profile-color); } img { margin: 0; display: block; cursor: move; } &:not(:hover) a:not(:focus):not(:active) { @include visually-hidden; } } .tr-gallery-remove, .tr-image-edit { color: #fff; position: absolute; left: 7px; top: 7px; z-index: 3; text-decoration: none; padding: 3px; border-radius: 25px; background: rgba(11, 11, 11, 0.69); backdrop-filter: blur(2px); box-shadow: none; display: block; &:hover, &:focus { color: #fff; background: $delete_hover; cursor: pointer; } } .tr-image-edit { .tr-gallery-item & { left: 40px; } &:hover, &:focus { background: $wp_link; background: var(--tr-profile-color, $wp_link); } }assets/sass/utility/sort.scss000064400000000700150732302400012377 0ustar00/* Sort Helper ----------------------------------------------------------------------- */ .tr-ui-sortable-helper { opacity: 0.8; cursor: move; overflow: hidden; z-index: 100000000 !important; } .tr-sortable-placeholder { border: dashed 1px #bbb !important; visibility: visible !important; background: none !important; z-index: 1; box-shadow: none; max-height: 300px !important; box-sizing: border-box; }assets/sass/utility/repeater.scss000064400000011161150732302400013222 0ustar00.tr-item-limit { vertical-align: top; font-size: 13px; line-height: 26px; height: 25px; margin-left: 5px; padding: 0 10px 1px; border: 1px solid $gray; color: $gray; border-radius: 100%; display: inline-block; } /* Field Groups ----------------------------------------------------------------------- */ .tr-repeater-group-template { display: none; } .tr-repeater-fields { position: relative; clear: both; margin: 0; list-style: none; padding: 0; } .tr-repeater-action-add-append { .tr-repeater-fields:empty + & { display: none; } margin-top: 10px !important; } .tr-repeater .controls { margin-bottom: 10px; } .tr-repeater-group { display: block; position: relative; border: solid 1px $gray_border; box-shadow: 0 1px 1px rgba(0, 0, 0, .04); margin: 0 0 10px; background: #fff; &:focus { outline: none; box-shadow: 0 0 3px #0073aa; box-shadow: 0 0 3px var(--tr-profile-color); } &:last-child { margin-bottom: 0; } } .tr-repeater-fields > .tr-sortable-placeholder { margin-bottom: 10px; &:last-child { margin-bottom: 0;} } .tr-cloned-item { border-color: #c2ddbf; transition: all .4s; > .tr-repeater-controls { color: #2c4d29; background: #d2f5b5; border-color: inherit; .tr-control-icon { color: inherit; text-shadow: 0 1px 0 rgba(221, 255, 229, 0.8); } } } .tr-repeater-controls { border-right: solid 1px $gray_border; position: absolute; display: flex; flex-flow: column; overflow: hidden; top: 0; bottom: 0; width: 39px; left: 0; z-index: 2; background: #f5f5f5; cursor: move; transition: all .4s; .tr-control-icon { position: relative; text-decoration: none; padding: 5px 0; width: 100%; border: none; background: none; &:hover, &:active, &:focus { background: none; } } .tr-control-icon-remove { bottom: 0; z-index: 3; margin-top: auto; &:focus { color: $delete_hover; outline: none; box-shadow: none; text-shadow: 0 0 7px $delete; } } .tr-control-icon-collapse { &:focus { color: var(--tr-profile-color); outline: none; box-shadow: none; text-shadow: 0 0 7px var(--tr-profile-color); } } .tr-control-icon-clone { z-index: 3; &:focus { color: var(--tr-profile-color); outline: none; box-shadow: none; text-shadow: 0 0 7px var(--tr-profile-color); } } .tr-control-icon-move { z-index: 3; } } .tr-repeater-inputs { padding-left: 40px; position: relative; > { h1, h2, h3, h4, h5, h6 { &:first-child { padding: 10px; margin: 0; box-shadow: 0 1px 1px rgba(0, 0, 0, .04); border-bottom: 1px solid $gray_border; font-weight: bold; font-size: 14px; line-height: 1.4; } } } } .tr-repeater-hide-clone { > .tr-repeater-group > .tr-repeater-controls { .tr-repeater-clone { display: none; } } } .tr-repeater-hide-contract { > .tr-repeater-group > .tr-repeater-controls { .tr-repeater-move, .move, .tr-repeater-collapse { display: none; } } } /* Repeater State ----------------------------------------------------------------------- */ .tr-repeater-group-collapsed, .tr-repeater-collapse { .tr-control-icon-collapse:before { content: '\f140'; } .redactor-toolbar { z-index: 19; } } .tr-repeater-group-expanded { .tr-control-icon-collapse:before { content: '\f142'; } } .tr-repeater-collapse > .tr-repeater-group, .tr-repeater-group-collapsed { height: 90px; overflow: hidden; &.tr-repeater-clones { height: 130px; } } .tr-repeater-collapse > .tr-repeater-group > .tr-repeater-inputs:after, .tr-repeater .tr-repeater-group-collapsed > .tr-repeater-inputs:after { opacity: 0.6; background: #fff; content: ''; z-index: 20; position: absolute; display: block; height: 100%; width: 100%; top: 0; left: 40px; } .tr-repeater-collapse > .tr-repeater-group-expanded > .tr-repeater-inputs:after { display: none; } .tr-repeater-collapse > .tr-repeater-group-expanded { height: 100%; &.tr-repeater-clones { height: 100%; } }assets/sass/utility/contextual.scss000064400000000566150732302400013610 0ustar00#wpwrap .postbox { .typerocket-container { margin: -6px -12px -12px; } } #post-body-content .typerocket-container { margin-bottom: 30px; } #titlediv + .typerocket-container, #postdivrich + .typerocket-container { margin-top: 20px; } #addtag .typerocket-container { margin-bottom: 20px; } #screen-meta + .tr-admin-notice { display: none; }assets/sass/utility/layout.scss000064400000004376150732302400012742 0ustar00/* Main Container ----------------------------------------------------------------------- */ //.typerocket-container .contextual-help-tabs-wrap .help-tab-content { // padding-bottom: 20px; //} .typerocket-container { box-sizing: border-box; clear: both; &:after { content: ''; display: block; clear: both; } } /* Grid ----------------------------------------------------------------------- */ .tr-flex-tight { display: flex; flex-flow: wrap; box-sizing: border-box; > * { box-sizing: border-box; padding: 0 5px; } > :first-child { padding-left: 0; } > :last-child { padding-right: 0; } } .tr-flex-list { display: flex; box-sizing: border-box; > * { flex: 1; box-sizing: border-box; padding: 0 5px; } > :first-child { padding-left: 0; } > :last-child { padding-right: 0; } } .tr-flex-justify { justify-content: flex-start } /* Helpers ----------------------------------------------------------------------- */ .tr-mr-10 { margin-right: 10px; } .tr-ml-10 { margin-left: 10px; } .tr-mb-10 { margin-bottom: 10px; } .tr-mt-10 { margin-top: 10px; } .tr-my-10 { margin-top: 10px; margin-bottom: 10px; } .tr-mx-10 { margin-left: 10px; margin-right: 10px; } .tr-m-10 { margin: 10px; } .tr-m-20 { margin: 20px; } .tr-pr-10 { padding-right: 10px; } .tr-pl-10 { padding-left: 10px; } .tr-pb-10 { padding-bottom: 10px; } .tr-pt-10 { padding-top: 10px; } .tr-py-10 { padding-top: 10px; padding-bottom: 10px; } .tr-px-10 { padding-left: 10px; padding-right: 10px; } .tr-p-10 { padding: 10px; } .tr-p-20 { padding: 20px; } .tr-d-inline { display: inline; } .tr-d-inline-block { display: inline-block; } .tr-d-block { display: block; } .tr-w-100 { width: 100% } .tr-w-50 { width: 50% } .tr-w-25 { width: 25% } .tr-w-10 { width: 10% } .tr-sr-only:not(:focus):not(:active) { clip: rect(0 0 0 0); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; } .tr-fl { float: left; } .tr-fr { float: right; } .cf:before, .cf:after { content: " "; /* 1 */ display: table; /* 2 */ } .cf:after { clear: both; } .cf { *zoom: 1; }assets/sass/utility/location.scss000064400000000363150732302400013225 0ustar00/* Location ----------------------------------------------------------------------- */ .tr_field_location_google_map { height: 150px; background: #ccc; width: 100%; } .tr_field_location_load_lat_lng_section { margin: 10px 0; }assets/sass/utility/swatches.scss000064400000002074150732302400013237 0ustar00/* Swatches ----------------------------------------------------------------------- */ .tr-swatches { display: flex; flex-flow: wrap; margin: 0; padding: 3px 0 0; .tr-swatch-box { height: 40px; width: 40px; overflow: hidden; border-radius: 4px; border: solid 1px #191e23; &:after { content: ''; display: block; height: 0; width: 0; border: solid 20px var(--tr-swatch-a); border-right-color:var(--tr-swatch-b); border-bottom-color:var(--tr-swatch-b); } } label { padding: 0 8px 0 0; display: inline-block; &:focus { outline: none; box-shadow: none; } } span { @include visually-hidden; } [type=radio] { position: absolute; opacity: 0; width: 0; height: 0; } .tr-swatch-box { cursor: pointer; max-width: 100%; height: auto; &:hover, &:focus { box-shadow: 0 0 0 3px $gray; } } label:focus .tr-swatch-box, [type=radio]:checked ~ .tr-swatch-box { box-shadow: 0 0 0 3px var(--tr-profile-color); } }assets/sass/utility/headings.scss000064400000000710150732302400013173 0ustar00.tr-admin-page-title { margin-bottom: 10px; font-size: 23px; font-weight: 400; padding: 9px 15px 4px 0; line-height: 29px; } .tr-headline { margin-top: 0; display: flex; line-height: 1.05em; margin-bottom: 15px; font-size: 23px; font-weight: 400; > .text { flex: 1; } > .icon { width: 30px; display: flex; justify-items: center; align-items: center; } }assets/sass/utility/editor.scss000064400000001615150732302400012704 0ustar00/* Editor ----------------------------------------------------------------------- */ .tr-control-section { .redactor-focus, .redactor-focus:focus { &.redactor-styles-on { border-color: var(--tr-profile-color, #007cba) !important; box-shadow: 0 0 0 1px var(--tr-profile-color, #007cba); } } .redactor-over:hover { &.redactor-styles-on { border-color: var(--tr-profile-color, #007cba) !important; } } } .redactor-styles { ul { list-style: disc; } .aligncenter { display: block; margin-left: auto; margin-right: auto; text-align: center; } .alignleft { float: left; margin: 0.5em 1em 0.5em 0; } .alignright { float: right; margin: 0.5em 0 0.5em 1em; } } .redactor-toolbar a.re-button-icon .dashicons { font-size: inherit; height: 18px; width: auto; box-sizing: border-box; vertical-align: inherit; }assets/sass/utility/dev.scss000064400000004133150732302400012172 0ustar00/* Function Helper ----------------------------------------------------------------------- */ .tr-dev-alert-helper { padding: 15px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; background: #fff; border: 1px solid $blue; border: 1px solid var(--tr-profile-color); color: #23282d; margin: 10px auto; code { background: rgba(238, 238, 238, 0.35); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.125); color: $blue; color: var(--tr-profile-color); padding: 4px; display: inline-block; border-radius: 4px; } } /* Input Helper ----------------------------------------------------------------------- */ .tr-dev-field-helper { font-weight: normal; display: inline-block; position: relative; top: 1px; color: #999999; transition: all 0.5s; -webkit-transition: all 0.5s; &:hover .nav .tr-dev-field-function { color: $blue; color: var(--tr-profile-color); } .nav .tr-dev-field-function { margin-left: 5px; } } .tr-repeater .tr-repeater .tr-dev-field-helper { display: none; } .tr-matrix > .tr-dev-field-helper, .tr-repeater > .tr-dev-field-helper { margin-bottom: 10px; } .tr-control-section .tr-dev-field-helper:hover > i, .tr-repeater-group .tr-control-section .tr-dev-field-helper:hover > i { color: $dark; color: var(--tr-profile-color); } .tr-control-section:hover .tr-dev-field-helper .nav, .tr-repeater-group .tr-control-section .tr-dev-field-helper:hover .nav { opacity: 1; } .tr-dev-field-helper .nav, .tr-repeater-group .tr-control-section .tr-dev-field-helper .nav { display: inline-block; -webkit-transition: opacity 0.5s ease-out; opacity: 0; max-width: 350px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; position: relative; line-height: 1em; } /* Mobile ----------------------------------------------------------------------- */ @media screen and (max-width: 782px) { #wpbody .tr-control-label .tr-dev-field-helper { display: none; } }assets/sass/utility/tables.scss000064400000001773150732302400012675 0ustar00/* Table ----------------------------------------------------------------------- */ .tr-table-container { margin-top: 20px; .tablenav { display: flex; margin: 6px 0; flex-flow: wrap; height: auto; input[type="search"], input[type="text"], input[type="url"] { width: auto; max-width: none; } button { margin-left: 6px; } select { width: auto; float: none; margin: 0; } .actions { float: none; overflow: initial; display: flex; align-items: center; padding: 0 8px 0 0; @media screen and (max-width: 782px) { display: none; &.bulkactions { display: flex; } } } .tablenav-pages { float: none; margin: 0 0 0 auto; display: flex; align-items: center; @media screen and (max-width: 782px) { margin: 15px 0; justify-content: center; } } } } .tr-table-wrapper { overflow-x: auto; }assets/sass/utility/icon-controls.scss000064400000002634150732302400014211 0ustar00/* Conrol Icons ----------------------------------------------------------------------- */ @mixin tr-dash-icon { font-family: dashicons; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; font-size: 18px; line-height: 18px; position: absolute; cursor: pointer; z-index: 10; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); color: $gray_icon; text-align: center; text-decoration: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; &:hover { color: #333; } } .tr-control-icon { @include tr-dash-icon; } .tr-control-icon-remove:before { content: "\f335"; } .tr-control-icon-clone { &:before { content: "\f316"; } &:hover { color: $wp_button_hover; color: var(--tr-profile-color); } } .tr-control-icon-remove { &:hover { color: $delete_hover; } &:focus { color: $delete_hover; outline: none; box-shadow: none; text-shadow: 0 0 7px $delete; } } .tr-control-icon-move:before { content: "\f333"; cursor: move; } .tr-control-icon-collapse:before { content: '\f142'; } .tr-control-icon-collapse-up:before { content: '\f140'; } .tr-dev-field-helper, .tab-icon { .dashicons { height: auto; width: auto; font-size: inherit; } }assets/sass/utility/form.scss000064400000016320150732302400012360 0ustar00[data-tr-conditions]:not(.tr-show-conditional) { display: none !important; } /* Inputs ----------------------------------------------------------------------- */ .tr-form-fields { border: 1px solid $gray_border; border-radius: 4px; + .tr-form-action { padding: 20px 0; } } #typerocket-admin-page .tr-form-fields { margin-top: 20px; } /* Input Errors ----------------------------------------------------------------------- */ .tr-field-has-error { background: #ffeeed; } .tr-field-error { display: block; color: $error; font-size: 12px; padding-left: 1px; padding-bottom: 4px; } /* Inputs ----------------------------------------------------------------------- */ .tr-control-section, div.tr-control-section { input[type=date], input[type=datetime-local], input[type=datetime], input[type=email], input[type=month], input[type=number], input[type=password], input[type=search], input[type=tel], input[type=text]:not(.tr-component-nameable-input), input[type=time], input[type=url], input[type=week], .tr-input-textexpand, textarea { box-sizing: border-box; width: 100%; max-width: 100%; padding: 0 8px; margin: 0; } .tr-input-textexpand { box-shadow: 0 0 0 transparent; border-radius: 4px; border: 1px solid #7e8993; background-color: #fff; color: #32373c; padding: 2px 8px; line-height: 1.6; font-size: 14px; &:focus { border-color: var(--tr-profile-color); box-shadow: 0 0 0 1px var(--tr-profile-color); } } .tr-component-nameable-input { width: 100%; border: none; border-left: 3px solid var(--tr-profile-color); border-radius: 0; } select { margin: 0 0 5px; box-sizing: border-box; width: 100%; max-width: 100%; min-height: 30px; } textarea { padding: 8px; min-height: 120px; } } .tr-text-input { display: flex; .with-after { border-bottom-right-radius: 0; border-top-right-radius: 0; } .with-before { border-bottom-left-radius: 0; border-top-left-radius: 0; } .before, .after { display: flex; justify-items: center; align-items: center; padding: 0 5px; border: 1px solid #7e8993; background: #f1f1f1; } .before { border-radius: 4px 0 0 4px; border-right: none; } .after { border-radius: 0 4px 4px 0; border-left: none; } } .tr-checkboxes { margin: 6px 0 0; li { padding: 0; display: block; margin-bottom: 6px; } } .tr-form-field-help p, .tr-field-help-top { color: $gray; font-style: italic; margin: 4px 0 0; font-size: 13px; } .tr-field-help-top { margin: 0 0 4px 0; } /* Radio Images ----------------------------------------------------------------------- */ .tr-radio-images { margin: 0; display: flex; flex-flow: wrap; [type=radio] { position: absolute; opacity: 0; width: 0; height: 0; } label { display: inline-block; padding: 0 8px 0 0; } label:focus { outline: none; box-shadow: none; } &.tr-radio-images-square { [type=radio] + span > img { width: 42px; height: 42px; } } img { cursor: pointer; width: 100%; max-width: 100%; height: auto; padding: 1px; box-sizing: border-box; &:hover, &:focus { box-shadow: 0 0 0 3px $gray; } } label:focus img, [type=radio]:checked + span > img { box-shadow: 0 0 0 3px $blue; box-shadow: 0 0 0 3px var(--tr-profile-color); } } /* Sections ----------------------------------------------------------------------- */ .tr-control-section, .tr-control-row { padding: 10px 12px; position: relative; } .tr-divide + .tr-divide { box-shadow: inset 0 1px 0 0 $gray_border; } .tr-tabbed-box .tr-tab-layout-content > { .tr-divide { box-shadow: none !important; } } .tr-control-row { display: flex; flex-wrap: wrap; div.tr-control-section { flex: 1; box-sizing: border-box; padding: 0 5px; box-shadow: none !important; } > div { &:first-of-type { padding-left: 0 } &:last-of-type { padding-right: 0 } } .tr-control-row-column { flex: 1; box-sizing: border-box; padding: 0 5px; &:first-child { padding-left: 0 } &:last-child { padding-right: 0 } .tr-control-section { padding: 5px 0; &:first-of-type { padding-top: 0 } &:last-of-type { padding-bottom: 0 } } } } div.tr-control-label { color: $gray_dark; display: block; font-size: 12px; font-weight: bold; height: auto; width: auto; padding-left: 1px; padding-bottom: 4px; label { line-height: 1.4em; padding: 0; } } .tr-field-control-title { margin: 0; font-size: 14px; line-height: 1.4; flex: 0 0 100%; display: block; color: $gray_dark; padding-bottom: 8px; } // keep outer focus from flashing .tr-label, .tr-label-thin { &:focus { outline: none; box-shadow: none; } } .typerocket-elements-fields-textexpand .tr-label { &:hover { cursor: pointer; } } /* Dark Mode ----------------------------------------------------------------------- */ .tr-input-dark { select { background-color: #000; color: #eee; } } /* Exception Nesting ----------------------------------------------------------------------- */ #post-body-content > .typerocket-container >, #edittag > .typerocket-container >, #addtag > .typerocket-container > { .tr-control-row, .tr-control-section, .tr-tabbed-top { box-shadow: none !important; padding: 10px 0; } } /* Maxlength ----------------------------------------------------------------------- */ .tr-maxlength { margin-top: 3px; margin-bottom: 6px; color: $gray; font-size: 12px; font-weight: normal; font-style: italic; } .tr-maxlength span { color: $blue; color: var(--tr-profile-color); font-weight: bold; } /* Frames, Meta Boxes and Repeaters ----------------------------------------------------------------------- */ .tr-frame-fields, .tr-repeater-inputs, .postbox-container .typerocket-container { .tr-control-section + .tr-tabbed-top { margin-top: 9px; padding-top: 0; &:after { padding: 0 10px; margin: 0px -5px; } } [class^=tr-control-row] + .tr-tabbed-top { margin-top: 9px; padding-top: 1px; &:after { padding: 0 10px; margin: 0px -5px; } } .tr-tabbed-top + .tr-control-section { padding-top: 12px; &:after { margin: 0px -5px; } } .tr-tabbed-top + [class^=tr-control-row] { padding-top: 9px; &:after { margin: 0px -5px; } } }assets/sass/utility/builder.scss000064400000020105150732302400013037 0ustar00/* Builder ----------------------------------------------------------------------- */ .tr-builder-inputs { background: #fff; box-shadow: 0 1px 1px rgba(0,0,0,.04); border: 1px solid $gray_border; float: left; width: 100%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; transition: all .4s; &:after { content:''; display: block; clear: both; height: 0; } > { h1, h2, h3, h4, h5, h6 { &:first-child { margin: 0; transition: all .4s; padding: 10px; box-shadow: 0 1px 1px rgba(0, 0, 0, .04); border-bottom: 1px solid $gray_border; font-weight: bold; font-size: 14px; line-height: 1.4; } } } } .tr-builder { position: relative; &:after { content:''; display: block; clear: both; height: 0; } .tr-builder-add-button { width: 100%; } .tr-builder-controls { float: left; .tr-components { width: 120px; li { border: 1px solid $gray_border; padding: 2px; text-align: center; position: relative; background: #fff; list-style: none; margin: 10px 0; min-height: 55px; cursor: pointer; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; display: flex; align-items: center; justify-content: center; img { max-width: 100%; height: auto; display: block; } .tr-builder-component-title { position: absolute; left: 0; bottom: 0; opacity: .9; background: rgba(0, 0, 0, 0.8); padding: 5px; width: 100%; z-index: 10; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; color: #fff; } &.active { border-color: #5b9dd9; border-color: var(--tr-profile-color); box-shadow: 0 0 3px 1px #ccc; outline: none; } &:focus, &:focus-within { box-shadow: 0 0 3px 1px #80b5e4; box-shadow: 0 0 3px 1px var(--tr-profile-color); outline: none; } &:not(:hover):not(:focus-within) a:not(:focus):not(:active) { @include visually-hidden; } &:hover, &:focus-within, &:focus, &.active { .tr-builder-component-title { display: block; } } span { display: none; } .remove, .clone { font-family: dashicons; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; position: absolute; text-align: center; text-decoration: none; z-index: 11; box-shadow: none; display: block; border-radius: 25px; font-size: 16px; line-height: 16px; height: 20px; width: 20px; padding: 3px; vertical-align: middle; color: #fff; left: 5px; top: 5px; background: rgba(11, 11, 11, 0.69); backdrop-filter: blur(2px); &:hover, &:focus { background: $delete_hover; cursor: pointer; } /* Better Font Rendering =========== */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; &:before { -webkit-font-smoothing: antialiased; font: normal 20px/1 'dashicons'; content: "\f335"; } } .clone { left: 38px; &:before { content: "\f316"; } &:hover, &:focus { background: $wp_button_hover; background: var(--tr-profile-color); outline: none; } } } } } .tr-frame-fields { margin-left: 135px; .tr-item-cloned { } } .tr-builder-select { flex-flow: wrap; display: none; position: absolute; border-radius: 3px; z-index: 100001; top: 35px; left: 0; padding: 5px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; max-width: 532px; background: #eee; border: solid 1px $gray_border; box-shadow: 0 0 8px rgba(0,0,0,.3); // top tick for triangle &:before, &:after { content: ''; display: block; position: absolute; top: -23px; left: 45px; z-index: 20; border: solid 12px transparent; border-bottom-color: #eee; } &:after { top: -24px; z-index: 19; border-bottom-color: $gray_border; } .builder-select-divider { width: 100%; margin: 5px; font-weight: 700; font-size: 14px; } } } .tr-builder-select-option { width: 120px; vertical-align: top; display: inline-block; padding: 10px; border-radius: 3px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; margin: 5px; box-shadow: 0 1px 1px rgba(0,0,0,.04); border: 1px solid $gray_border; background: #fff; text-align: center; cursor: pointer; &:focus { box-shadow: 0 0 3px 1px #80b5e4; box-shadow: 0 0 3px 1px var(--tr-profile-color); outline: none; } span { display: block; margin-bottom: 3px; color: #444; } img { max-width: 100%; height: auto; display: block; } &:hover, &:focus { span { color: $wp_button_hover; color: var(--tr-profile-color); } } } .tr-builder-select-overlay { position: fixed; top: 0; left: 0; height: 100%; width: 100%; background: #000; opacity: 0; z-index: 10000; } .builder-field-group { display: none; &.active { display: block; } } .tr-cloned-item { > .tr-builder-inputs { border-color: #c2ddbf; box-shadow: 0 1px 1px #d2f5b5; > h1, h2, h3 { &:first-child { color: #2c4d29; background: #d2f5b5; border-color: inherit; } } } } .tr-component-group-name { display: flex; align-items: center; gap: 10px; > div:first-child { flex: 1 } } .tr-save-component-as-block-wrap { text-align: right; cursor: pointer; } .tr-save-component-as-block { cursor: pointer; all: unset; cursor: pointer; } .tr-block-component-actions { margin-top: 2px; } .tr-search-results .tr-search-results-hide { display: none; }assets/sass/utility/matrix.scss000064400000000377150732302400012726 0ustar00/* Matrix ----------------------------------------------------------------------- */ .tr-matrix-controls { margin-bottom: 20px; select, select.matrix-select { display: inline-block; width: auto; margin: 0 10px 0 0; } }assets/sass/utility/tabs.scss000064400000021276150732302400012354 0ustar00/* Tabs General ----------------------------------------------------------------------- */ .tr-tab-section { width: 100%; display: none; } .tr-tab-section.active { display: block; } .tr-tabbed-sections { &.ui-tabs { padding: 0; } .tr-tabs li.hide { display: none; } .ui-tabs-hide { display: none !important; } .ui-widget-header { border: none; } } .tr-tabs { .tab-icon-i { height: auto; width: auto; font-size: inherit; } } /* Tabs Top ----------------------------------------------------------------------- */ .tr-tabbed-top { .tr-tabs { padding: 0 12px; margin: 0; overflow: hidden; zoom: 1; line-height: 1em; width: 100%; display: flex; box-sizing: border-box; box-shadow: inset 0 -1px 0 0 $gray_border; background: rgba(222, 222, 222, 0.49); } .tr-tabs > li { margin: 0 12px 0 0; font-weight: normal; font-size: 13px; line-height: 1em; position: relative; list-style: none; box-shadow: none; &.active a { color: #191e23; border-bottom-color: #444; } a { font-weight: bold; display: block; padding: 15px 9px 12px; text-decoration: none; color: #555; border-bottom: 4px solid transparent; box-shadow: none; em { color: #666; font-weight: normal; font-size: 11px; display: block; margin-top: 2px; } &:active, &:hover, &:focus { border-bottom-color: #00a0d2 !important; border-bottom-color: var(--tr-profile-color) !important; outline: none; box-shadow: none; } } } &.tr-tabs-layout-top-enclosed { background: #fff; border: 1px solid $gray_border; margin-top: 10px; > .tr-tabbed-sections { .tr-tabs { margin-bottom: 10px; .tr-tab-link { font-size: 16px; em { font-size: 12px; margin-top: 5px; } } .tab-icon { vertical-align: text-top; display: inline-block; margin-right: 3px; color: #00a0d2; color: var(--tr-profile-color); } } } } } /* Tabs Box ----------------------------------------------------------------------- */ .tr-tabbed-box { display: block; margin: 20px 0 -1px 0; position: relative; &.has-header { .tr-tab-layout-tabs { margin-top: 50px; } } label { line-height: inherit; } .tr-fieldset-group, .tr-table-container { padding: 20px; margin: 0; box-sizing: border-box; } .tr-tab-layout-tabs .active, .tr-tab-layout-tabs .active a, .tr-tab-layout-tabs .active a:hover { background: #fefefe; outline: none; box-shadow: none; } .tr-tab-layout-content { > .tr-control-section > .tr-control-row { padding-left: 20px; padding-right: 20px; } } .tr-tab-layout-tabs { margin: 0; position: relative; ul { margin: 1em 0; } li { list-style-type: none; border-style: solid; margin: 0 -1px 0 0; border-width: 0 0 0 3px; border-color: transparent; border-top: 1px solid $gray_border; border-bottom: 1px solid transparent; transition: all 0.2s; box-shadow: none; &:first-child { border-top: 1px solid transparent; } } .tab-text { max-width: 170px; min-width: 70px; box-sizing: border-box; padding-right: 10px; } .has-description { a { text-transform: uppercase; } } a { padding: 10px 10px 10px 12px; box-shadow: none; line-height: 18px; color: #00a0d2; color: var(--tr-profile-color); font-weight: bold; font-size: 13px; letter-spacing: 1px; text-decoration: none; border-right: none; border-left: none; display: flex; .tab-text { flex: 1; } } .tr-tab-link { > .tab-icon { width: 30px; text-align: center; color: #b4becb; display: flex; justify-items: center; align-items: center; font-size: 21px; > i { flex: 1; } } em { letter-spacing: normal; display: block; font-weight: normal; font-style: normal; font-size: 12px; margin-top: 2px; color: #666; text-transform: none; } } li:focus-within.active { .tab-text { color: var(--tr-profile-color, #00a0d2); } } li:hover, li:active, li:focus-within, .active { padding: 0; border-left: 3px solid #00a0d2; border-left: 3px solid var(--tr-profile-color, #00a0d2); transition: all 0.2s; &:first-child { border-top: 1px solid $gray_border; } &:last-child { border-bottom: 1px solid $gray_border; } .tr-tab-link { border-color: $gray_border; color: #32373c; > .tab-icon { color: var(--tr-profile-color, #00a0d2); } } } li.active { background: #fff; } } &.tr-tabs-layout-left-enclosed .tr-tab-layout-wrap { background: #fff; box-shadow: inset 0 0 0 1px $gray_border; } .tr-tab-layout-tabs-wrap { padding: 0; border: 1px solid $gray_border; background: #fefefe; flex: 1; overflow: visible; display: flex; flex-flow: column; min-width: 0; > .tr-tab-layout-content { flex: 1; box-sizing: border-box; } } .tr-tab-layout-sidebar { width: 150px; order: 2; padding: 0 8px 20px 12px; } @media screen and (max-width: 600px) { .tr-tab-layout-tabs { width: auto; } .tab-text { @include visually-hidden; } } } .tr-tab-layout-columns { position: relative; display: flex; align-items: stretch; flex-direction: row; } #post-body-content #screen-meta.tr-tabbed-box { margin: 0 0 20px 4px; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } .tr-builder-inputs > .tr-tabbed-box, .tr-repeater-inputs > .tr-tabbed-box { margin: -1px 0; } #wpwrap .postbox { .tr-tabbed-box { display: block; margin: 0; .tr-tab-layout-tabs-wrap { border-color: transparent; border-left-color: $gray_border; } .tr-tab-layout-content { padding: 0; } } } /* Fieldset ----------------------------------------------------------------------- */ .tr-repeater-inputs .tr-fieldset-group, .tr-fieldset-group { padding: 10px 12px; .tr-fieldset-group-title { font-size: 21px; font-weight: 400; margin: 0 0 5px; } .tr-fieldset-group-description { margin: 0 0 10px; } .tr-fieldset-group-content { background: #f5f5f5; border: 1px solid $gray_border; border-radius: 3px; min-width: 0; } } .postbox, .tr-repeater-inputs { .tr-fieldset-group .tr-fieldset-group-title { font-size: 14px; line-height: 1.4; font-weight: bold; } } /* Tab Extras ----------------------------------------------------------------------- */ .tr-tabbed-footer { background: #f5f5f5; border: 1px solid $gray_border; padding: 10px; position: relative; margin: 0 -1px -1px; } .tr-tabbed-header { padding: 10px; background: #f5f5f5; .tr-headline { margin: 10px; } }assets/sass/utility/style.scss000064400000000277150732302400012561 0ustar00/* Utility Styles ----------------------------------------------------------------------- */ .tr-round-image-corners img { border-radius: 4px; } .tr-round-corners { border-radius: 4px; }assets/sass/utility/alert.scss000064400000002547150732302400012532 0ustar00/* AJAX Alerts ----------------------------------------------------------------------- */ .tr-ajax-alert { position: fixed; top: 42px; right: 10px; z-index: 100000; padding: 15px; line-height: 1.4em; max-width: 520px; min-width: 320px; box-sizing: border-box; text-align: center; background: #fff; box-shadow: 0 1px 1px 0 rgba(0,0,0,.1); border-left: solid 5px; border-color: $success; &.tr-alert-error { border-color: $error; } &.tr-alert-warning { border-color: $warn; } &.tr-alert-info { border-color: $info; } } body:not(.wp-admin) .tr-admin-notice { padding: 15px; line-height: 1.4em; box-sizing: border-box; background: #fff; color: #444; margin-bottom: 1em; box-shadow: 0 1px 1px 0 rgba(0,0,0,.1); border-left: solid 5px; border-color: $success; p:only-child { margin: 0; } ul:only-child { margin: 0; } p, li { text-transform: none; text-decoration: none; letter-spacing: normal; } &.notice-error { border-color: $error; } &.notice-warning { border-color: $warn; } &.notice-info { border-color: $info; } } /* Mobile */ @media screen and (max-width: 782px) { .typerocket-rest-alert { top: 46px; } }assets/sass/utility/items.scss000064400000001750150732302400012537 0ustar00/* Item List Field ----------------------------------------------------------------------- */ .tr-items-list { margin: 10px 0 0 0; .tr-items-list-item, li { display: block; box-sizing: border-box; position: relative; min-height: 50px; padding: 10px 40px; border: solid 1px $gray_border; margin: -1px 0 0 !important; background: #fff; &:focus { outline: none; box-shadow: inset 0 0 0 2px #0073aa; box-shadow: inset 0 0 0 2px var(--tr-profile-color); } .remove { right: 12px; top: 17px; &:focus { outline: none; box-shadow: none; text-shadow: 0 0 7px $delete; } } .move { left: 12px; top: 17px; } } &:empty + .tr-items-append { display: none; } } .tr-items-append { margin-top: 10px !important; }assets/dist/css/core.css000064400000230071150732302400011242 0ustar00@-webkit-keyframes tr-shake{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}@keyframes tr-shake{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}.tr-shake{-webkit-animation:tr-shake .82s cubic-bezier(.36,.07,.19,.97) both;animation:tr-shake .82s cubic-bezier(.36,.07,.19,.97) both;transform:translateZ(0)}:root{--tr-default-color:#0073aa;--tr-light-color:#04a4cc;--tr-ectoplasm-color:#a3b745;--tr-coffee-color:#c7a589;--tr-midnight-color:#e14d43;--tr-ocean-color:#9ebaa0;--tr-sunrise-color:#dd823b;--tr-blue-color:#096484;--tr-profile-color:#007cba}.admin-color-default{--tr-profile-color:#0073aa;--tr-profile-color-bg:#333;--tr-profile-color-dark:#001d2b}.admin-color-light{--tr-profile-color:#04a4cc;--tr-profile-color-bg:#999;--tr-profile-color-dark:#023f4f}.admin-color-ectoplasm{--tr-profile-color:#a3b745;--tr-profile-color-bg:#523f6d;--tr-profile-color-dark:#515a22}.admin-color-coffee{--tr-profile-color:#c7a589;--tr-profile-color-bg:#59524c;--tr-profile-color-dark:#8d6543}.admin-color-midnight{--tr-profile-color:#e14d43;--tr-profile-color-bg:#363b3f;--tr-profile-color-dark:#8e1e17}.admin-color-ocean{--tr-profile-color:#9ebaa0;--tr-profile-color-bg:#738e96;--tr-profile-color-dark:#5a7f5d}.admin-color-sunrise{--tr-profile-color:#dd823b;--tr-profile-color-bg:#cf4944;--tr-profile-color-dark:#824617}.admin-color-blue{--tr-profile-color:#096484;--tr-profile-color-bg:#4796b3;--tr-profile-color-dark:#010a0d}.tr-round-corners,.tr-round-image-corners img{border-radius:4px}#wpwrap .postbox .typerocket-container{margin:-6px -12px -12px}#post-body-content .typerocket-container{margin-bottom:30px}#postdivrich+.typerocket-container,#titlediv+.typerocket-container{margin-top:20px}#addtag .typerocket-container{margin-bottom:20px}#screen-meta+.tr-admin-notice{display:none}.tr-ui-sortable-helper{opacity:.8;cursor:move;overflow:hidden;z-index:100000000!important}.tr-sortable-placeholder{border:1px dashed #bbb!important;visibility:visible!important;background:none!important;z-index:1;box-shadow:none;max-height:300px!important;box-sizing:border-box}[data-tr-conditions]:not(.tr-show-conditional){display:none!important}.tr-form-fields{border:1px solid #ccd0d4;border-radius:4px}.tr-form-fields+.tr-form-action{padding:20px 0}#typerocket-admin-page .tr-form-fields{margin-top:20px}.tr-field-has-error{background:#ffeeed}.tr-field-error{display:block;color:#dc3232;font-size:12px;padding-left:1px;padding-bottom:4px}.tr-control-section .tr-input-textexpand,.tr-control-section input[type=date],.tr-control-section input[type=datetime-local],.tr-control-section input[type=datetime],.tr-control-section input[type=email],.tr-control-section input[type=month],.tr-control-section input[type=number],.tr-control-section input[type=password],.tr-control-section input[type=search],.tr-control-section input[type=tel],.tr-control-section input[type=text]:not(.tr-component-nameable-input),.tr-control-section input[type=time],.tr-control-section input[type=url],.tr-control-section input[type=week],.tr-control-section textarea,div.tr-control-section .tr-input-textexpand,div.tr-control-section input[type=date],div.tr-control-section input[type=datetime-local],div.tr-control-section input[type=datetime],div.tr-control-section input[type=email],div.tr-control-section input[type=month],div.tr-control-section input[type=number],div.tr-control-section input[type=password],div.tr-control-section input[type=search],div.tr-control-section input[type=tel],div.tr-control-section input[type=text]:not(.tr-component-nameable-input),div.tr-control-section input[type=time],div.tr-control-section input[type=url],div.tr-control-section input[type=week],div.tr-control-section textarea{box-sizing:border-box;width:100%;max-width:100%;padding:0 8px;margin:0}.tr-control-section .tr-input-textexpand,div.tr-control-section .tr-input-textexpand{box-shadow:0 0 0 transparent;border-radius:4px;border:1px solid #7e8993;background-color:#fff;color:#32373c;padding:2px 8px;line-height:1.6;font-size:14px}.tr-control-section .tr-input-textexpand:focus,div.tr-control-section .tr-input-textexpand:focus{border-color:var(--tr-profile-color);box-shadow:0 0 0 1px var(--tr-profile-color)}.tr-control-section .tr-component-nameable-input,div.tr-control-section .tr-component-nameable-input{width:100%;border:none;border-left:3px solid var(--tr-profile-color);border-radius:0}.tr-control-section select,div.tr-control-section select{margin:0 0 5px;box-sizing:border-box;width:100%;max-width:100%;min-height:30px}.tr-control-section textarea,div.tr-control-section textarea{padding:8px;min-height:120px}.tr-text-input{display:flex}.tr-text-input .with-after{border-bottom-right-radius:0;border-top-right-radius:0}.tr-text-input .with-before{border-bottom-left-radius:0;border-top-left-radius:0}.tr-text-input .after,.tr-text-input .before{display:flex;justify-items:center;align-items:center;padding:0 5px;border:1px solid #7e8993;background:#f1f1f1}.tr-text-input .before{border-radius:4px 0 0 4px;border-right:none}.tr-text-input .after{border-radius:0 4px 4px 0;border-left:none}.tr-checkboxes{margin:6px 0 0}.tr-checkboxes li{padding:0;display:block;margin-bottom:6px}.tr-field-help-top,.tr-form-field-help p{color:#666;font-style:italic;margin:4px 0 0;font-size:13px}.tr-field-help-top{margin:0 0 4px}.tr-radio-images{margin:0;display:flex;flex-flow:wrap}.tr-radio-images [type=radio]{position:absolute;opacity:0;width:0;height:0}.tr-radio-images label{display:inline-block;padding:0 8px 0 0}.tr-radio-images label:focus{outline:none;box-shadow:none}.tr-radio-images.tr-radio-images-square [type=radio]+span>img{width:42px;height:42px}.tr-radio-images img{cursor:pointer;width:100%;max-width:100%;height:auto;padding:1px;box-sizing:border-box}.tr-radio-images img:focus,.tr-radio-images img:hover{box-shadow:0 0 0 3px #666}.tr-radio-images [type=radio]:checked+span>img,.tr-radio-images label:focus img{box-shadow:0 0 0 3px #3182bd;box-shadow:0 0 0 3px var(--tr-profile-color)}.tr-control-row,.tr-control-section{padding:10px 12px;position:relative}.tr-divide+.tr-divide{box-shadow:inset 0 1px 0 0 #ccd0d4}.tr-tabbed-box .tr-tab-layout-content>.tr-divide{box-shadow:none!important}.tr-control-row{display:flex;flex-wrap:wrap}.tr-control-row div.tr-control-section{flex:1;box-sizing:border-box;padding:0 5px;box-shadow:none!important}.tr-control-row>div:first-of-type{padding-left:0}.tr-control-row>div:last-of-type{padding-right:0}.tr-control-row .tr-control-row-column{flex:1;box-sizing:border-box;padding:0 5px}.tr-control-row .tr-control-row-column:first-child{padding-left:0}.tr-control-row .tr-control-row-column:last-child{padding-right:0}.tr-control-row .tr-control-row-column .tr-control-section{padding:5px 0}.tr-control-row .tr-control-row-column .tr-control-section:first-of-type{padding-top:0}.tr-control-row .tr-control-row-column .tr-control-section:last-of-type{padding-bottom:0}div.tr-control-label{color:#191e23;display:block;font-size:12px;font-weight:700;height:auto;width:auto;padding-left:1px;padding-bottom:4px}div.tr-control-label label{line-height:1.4em;padding:0}.tr-field-control-title{margin:0;font-size:14px;line-height:1.4;flex:0 0 100%;display:block;color:#191e23;padding-bottom:8px}.tr-label-thin:focus,.tr-label:focus{outline:none;box-shadow:none}.typerocket-elements-fields-textexpand .tr-label:hover{cursor:pointer}.tr-input-dark select{background-color:#000;color:#eee}#addtag>.typerocket-container>.tr-control-row,#addtag>.typerocket-container>.tr-control-section,#addtag>.typerocket-container>.tr-tabbed-top,#edittag>.typerocket-container>.tr-control-row,#edittag>.typerocket-container>.tr-control-section,#edittag>.typerocket-container>.tr-tabbed-top,#post-body-content>.typerocket-container>.tr-control-row,#post-body-content>.typerocket-container>.tr-control-section,#post-body-content>.typerocket-container>.tr-tabbed-top{box-shadow:none!important;padding:10px 0}.tr-maxlength{margin-top:3px;margin-bottom:6px;color:#666;font-size:12px;font-weight:400;font-style:italic}.tr-maxlength span{color:#3182bd;color:var(--tr-profile-color);font-weight:700}.postbox-container .typerocket-container .tr-control-section+.tr-tabbed-top,.tr-frame-fields .tr-control-section+.tr-tabbed-top,.tr-repeater-inputs .tr-control-section+.tr-tabbed-top{margin-top:9px;padding-top:0}.postbox-container .typerocket-container .tr-control-section+.tr-tabbed-top:after,.tr-frame-fields .tr-control-section+.tr-tabbed-top:after,.tr-repeater-inputs .tr-control-section+.tr-tabbed-top:after{padding:0 10px;margin:0 -5px}.postbox-container .typerocket-container [class^=tr-control-row]+.tr-tabbed-top,.tr-frame-fields [class^=tr-control-row]+.tr-tabbed-top,.tr-repeater-inputs [class^=tr-control-row]+.tr-tabbed-top{margin-top:9px;padding-top:1px}.postbox-container .typerocket-container [class^=tr-control-row]+.tr-tabbed-top:after,.tr-frame-fields [class^=tr-control-row]+.tr-tabbed-top:after,.tr-repeater-inputs [class^=tr-control-row]+.tr-tabbed-top:after{padding:0 10px;margin:0 -5px}.postbox-container .typerocket-container .tr-tabbed-top+.tr-control-section,.tr-frame-fields .tr-tabbed-top+.tr-control-section,.tr-repeater-inputs .tr-tabbed-top+.tr-control-section{padding-top:12px}.postbox-container .typerocket-container .tr-tabbed-top+.tr-control-section:after,.tr-frame-fields .tr-tabbed-top+.tr-control-section:after,.tr-repeater-inputs .tr-tabbed-top+.tr-control-section:after{margin:0 -5px}.postbox-container .typerocket-container .tr-tabbed-top+[class^=tr-control-row],.tr-frame-fields .tr-tabbed-top+[class^=tr-control-row],.tr-repeater-inputs .tr-tabbed-top+[class^=tr-control-row]{padding-top:9px}.postbox-container .typerocket-container .tr-tabbed-top+[class^=tr-control-row]:after,.tr-frame-fields .tr-tabbed-top+[class^=tr-control-row]:after,.tr-repeater-inputs .tr-tabbed-top+[class^=tr-control-row]:after{margin:0 -5px}.tr-range-input{width:100%}.tr-range-selected{display:block;margin-bottom:3px;color:#32373c;font-size:1rem}.tr-range-labels{display:flex;margin-top:1px;color:#666;font-size:.8rem;flex-grow:1;min-width:0}.tr-range-labels div{flex:1}.tr-range-labels div:last-child{margin-left:auto;text-align:right}[type=range]{-webkit-appearance:none;background:transparent;margin:10px 0;width:100%;cursor:pointer}[type=range]::-moz-focus-outer{border:0}[type=range]:focus{outline:0}[type=range]:focus::-webkit-slider-runnable-track{background:#d7dade}[type=range]:focus::-ms-fill-lower{background:var(--tr-profile-color,#00669b)}[type=range]:focus::-ms-fill-upper{background:#d7dade}[type=range]::-webkit-slider-runnable-track{cursor:default;height:4px;-webkit-transition:all .2s ease;transition:all .2s ease;width:100%;background:#d7dade;border:0 solid #cfd8dc;border-radius:0}[type=range]::-webkit-slider-thumb{background:#fff;border:1px solid var(--tr-profile-color,#00669b);border-radius:10px;box-sizing:border-box;cursor:default;height:20px;width:20px;-webkit-appearance:none;margin-top:-7px}[type=range]::-moz-range-track{cursor:default;height:4px;-moz-transition:all .2s ease;transition:all .2s ease;width:100%;background:#d7dade;border:0 solid #cfd8dc;border-radius:0;height:2px}[type=range]::-moz-range-thumb{background:#fff;border:1px solid var(--tr-profile-color,#00669b);border-radius:10px;box-sizing:border-box;cursor:default;height:20px;width:20px}[type=range]::-ms-track{cursor:default;height:4px;-ms-transition:all .2s ease;transition:all .2s ease;width:100%;background:transparent;border-color:transparent;border-width:10px 0;color:transparent}[type=range]::-ms-fill-lower{background:var(--tr-profile-color,#00669b);border:none;border-radius:0}[type=range]::-ms-fill-upper{background:#d7dade;border:none;border-radius:0}[type=range]::-moz-range-progress{background-color:var(--tr-profile-color,#00669b)}[type=range]::-ms-thumb{background:#fff;border:1px solid var(--tr-profile-color,#00669b);border-radius:10px;box-sizing:border-box;cursor:default;height:20px;width:20px;margin-top:1px}[type=range] ::-ms-ticks-after,[type=range] ::-ms-ticks-before{display:none}[type=range]:disabled::-moz-range-thumb,[type=range]:disabled::-ms-fill-lower,[type=range]:disabled::-ms-fill-upper,[type=range]:disabled::-ms-thumb,[type=range]:disabled::-webkit-slider-runnable-track,[type=range]:disabled::-webkit-slider-thumb{cursor:not-allowed}.tr-control-icon{font-family:dashicons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;font-size:18px;line-height:18px;position:absolute;cursor:pointer;z-index:10;text-shadow:0 1px 0 hsla(0,0%,100%,.8);color:#9b9b9b;text-align:center;text-decoration:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.tr-control-icon:hover{color:#333}.tr-control-icon-remove:before{content:"\F335"}.tr-control-icon-clone:before{content:"\F316"}.tr-control-icon-clone:hover{color:#0071a1;color:var(--tr-profile-color)}.tr-control-icon-remove:hover{color:red}.tr-control-icon-remove:focus{color:red;outline:none;box-shadow:none;text-shadow:0 0 7px #a00}.tr-control-icon-move:before{content:"\F333";cursor:move}.tr-control-icon-collapse:before{content:"\F142"}.tr-control-icon-collapse-up:before{content:"\F140"}.tab-icon .dashicons,.tr-dev-field-helper .dashicons{height:auto;width:auto;font-size:inherit}.tr-item-limit{vertical-align:top;font-size:13px;line-height:26px;height:25px;margin-left:5px;padding:0 10px 1px;border:1px solid #666;color:#666;border-radius:100%;display:inline-block}.tr-repeater-group-template{display:none}.tr-repeater-fields{position:relative;clear:both;margin:0;list-style:none;padding:0}.tr-repeater-action-add-append{margin-top:10px!important}.tr-repeater-fields:empty+.tr-repeater-action-add-append{display:none}.tr-repeater .controls{margin-bottom:10px}.tr-repeater-group{display:block;position:relative;border:1px solid #ccd0d4;box-shadow:0 1px 1px rgba(0,0,0,.04);margin:0 0 10px;background:#fff}.tr-repeater-group:focus{outline:none;box-shadow:0 0 3px #0073aa;box-shadow:0 0 3px var(--tr-profile-color)}.tr-repeater-group:last-child{margin-bottom:0}.tr-repeater-fields>.tr-sortable-placeholder{margin-bottom:10px}.tr-repeater-fields>.tr-sortable-placeholder:last-child{margin-bottom:0}.tr-cloned-item{border-color:#c2ddbf;transition:all .4s}.tr-cloned-item>.tr-repeater-controls{color:#2c4d29;background:#d2f5b5;border-color:inherit}.tr-cloned-item>.tr-repeater-controls .tr-control-icon{color:inherit;text-shadow:0 1px 0 rgba(221,255,229,.8)}.tr-repeater-controls{border-right:1px solid #ccd0d4;position:absolute;display:flex;flex-flow:column;overflow:hidden;top:0;bottom:0;width:39px;left:0;z-index:2;background:#f5f5f5;cursor:move;transition:all .4s}.tr-repeater-controls .tr-control-icon{position:relative;text-decoration:none;padding:5px 0;width:100%;border:none;background:none}.tr-repeater-controls .tr-control-icon:active,.tr-repeater-controls .tr-control-icon:focus,.tr-repeater-controls .tr-control-icon:hover{background:none}.tr-repeater-controls .tr-control-icon-remove{bottom:0;z-index:3;margin-top:auto}.tr-repeater-controls .tr-control-icon-remove:focus{color:red;outline:none;box-shadow:none;text-shadow:0 0 7px #a00}.tr-repeater-controls .tr-control-icon-collapse:focus{color:var(--tr-profile-color);outline:none;box-shadow:none;text-shadow:0 0 7px var(--tr-profile-color)}.tr-repeater-controls .tr-control-icon-clone{z-index:3}.tr-repeater-controls .tr-control-icon-clone:focus{color:var(--tr-profile-color);outline:none;box-shadow:none;text-shadow:0 0 7px var(--tr-profile-color)}.tr-repeater-controls .tr-control-icon-move{z-index:3}.tr-repeater-inputs{padding-left:40px;position:relative}.tr-repeater-inputs>h1:first-child,.tr-repeater-inputs>h2:first-child,.tr-repeater-inputs>h3:first-child,.tr-repeater-inputs>h4:first-child,.tr-repeater-inputs>h5:first-child,.tr-repeater-inputs>h6:first-child{padding:10px;margin:0;box-shadow:0 1px 1px rgba(0,0,0,.04);border-bottom:1px solid #ccd0d4;font-weight:700;font-size:14px;line-height:1.4}.tr-repeater-hide-clone>.tr-repeater-group>.tr-repeater-controls .tr-repeater-clone,.tr-repeater-hide-contract>.tr-repeater-group>.tr-repeater-controls .move,.tr-repeater-hide-contract>.tr-repeater-group>.tr-repeater-controls .tr-repeater-collapse,.tr-repeater-hide-contract>.tr-repeater-group>.tr-repeater-controls .tr-repeater-move{display:none}.tr-repeater-collapse .tr-control-icon-collapse:before,.tr-repeater-group-collapsed .tr-control-icon-collapse:before{content:"\F140"}.tr-repeater-collapse .redactor-toolbar,.tr-repeater-group-collapsed .redactor-toolbar{z-index:19}.tr-repeater-group-expanded .tr-control-icon-collapse:before{content:"\F142"}.tr-repeater-collapse>.tr-repeater-group,.tr-repeater-group-collapsed{height:90px;overflow:hidden}.tr-repeater-collapse>.tr-repeater-group.tr-repeater-clones,.tr-repeater-group-collapsed.tr-repeater-clones{height:130px}.tr-repeater-collapse>.tr-repeater-group>.tr-repeater-inputs:after,.tr-repeater .tr-repeater-group-collapsed>.tr-repeater-inputs:after{opacity:.6;background:#fff;content:"";z-index:20;position:absolute;display:block;height:100%;width:100%;top:0;left:40px}.tr-repeater-collapse>.tr-repeater-group-expanded>.tr-repeater-inputs:after{display:none}.tr-repeater-collapse>.tr-repeater-group-expanded,.tr-repeater-collapse>.tr-repeater-group-expanded.tr-repeater-clones{height:100%}.tr-matrix-controls{margin-bottom:20px}.tr-matrix-controls select,.tr-matrix-controls select.matrix-select{display:inline-block;width:auto;margin:0 10px 0 0}.tr-builder-inputs{background:#fff;box-shadow:0 1px 1px rgba(0,0,0,.04);border:1px solid #ccd0d4;float:left;width:100%;box-sizing:border-box;transition:all .4s}.tr-builder-inputs:after{content:"";display:block;clear:both;height:0}.tr-builder-inputs>h1:first-child,.tr-builder-inputs>h2:first-child,.tr-builder-inputs>h3:first-child,.tr-builder-inputs>h4:first-child,.tr-builder-inputs>h5:first-child,.tr-builder-inputs>h6:first-child{margin:0;transition:all .4s;padding:10px;box-shadow:0 1px 1px rgba(0,0,0,.04);border-bottom:1px solid #ccd0d4;font-weight:700;font-size:14px;line-height:1.4}.tr-builder{position:relative}.tr-builder:after{content:"";display:block;clear:both;height:0}.tr-builder .tr-builder-add-button{width:100%}.tr-builder .tr-builder-controls{float:left}.tr-builder .tr-builder-controls .tr-components{width:120px}.tr-builder .tr-builder-controls .tr-components li{border:1px solid #ccd0d4;padding:2px;text-align:center;position:relative;background:#fff;list-style:none;margin:10px 0;min-height:55px;cursor:pointer;box-sizing:border-box;display:flex;align-items:center;justify-content:center}.tr-builder .tr-builder-controls .tr-components li img{max-width:100%;height:auto;display:block}.tr-builder .tr-builder-controls .tr-components li .tr-builder-component-title{position:absolute;left:0;bottom:0;opacity:.9;background:rgba(0,0,0,.8);padding:5px;width:100%;z-index:10;box-sizing:border-box;color:#fff}.tr-builder .tr-builder-controls .tr-components li.active{border-color:#5b9dd9;border-color:var(--tr-profile-color);box-shadow:0 0 3px 1px #ccc;outline:none}.tr-builder .tr-builder-controls .tr-components li:focus,.tr-builder .tr-builder-controls .tr-components li:focus-within{box-shadow:0 0 3px 1px #80b5e4;box-shadow:0 0 3px 1px var(--tr-profile-color);outline:none}.tr-builder .tr-builder-controls .tr-components li:not(:hover):not(:focus-within) a:not(:focus):not(:active){position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px);white-space:nowrap}.tr-builder .tr-builder-controls .tr-components li.active .tr-builder-component-title,.tr-builder .tr-builder-controls .tr-components li:focus-within .tr-builder-component-title,.tr-builder .tr-builder-controls .tr-components li:focus .tr-builder-component-title,.tr-builder .tr-builder-controls .tr-components li:hover .tr-builder-component-title{display:block}.tr-builder .tr-builder-controls .tr-components li span{display:none}.tr-builder .tr-builder-controls .tr-components li .clone,.tr-builder .tr-builder-controls .tr-components li .remove{font-family:dashicons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;position:absolute;text-align:center;text-decoration:none;z-index:11;box-shadow:none;display:block;border-radius:25px;font-size:16px;line-height:16px;height:20px;width:20px;padding:3px;vertical-align:middle;color:#fff;left:5px;top:5px;background:rgba(11,11,11,.69);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.tr-builder .tr-builder-controls .tr-components li .clone:focus,.tr-builder .tr-builder-controls .tr-components li .clone:hover,.tr-builder .tr-builder-controls .tr-components li .remove:focus,.tr-builder .tr-builder-controls .tr-components li .remove:hover{background:red;cursor:pointer}.tr-builder .tr-builder-controls .tr-components li .clone:before,.tr-builder .tr-builder-controls .tr-components li .remove:before{-webkit-font-smoothing:antialiased;font:normal 20px/1 dashicons;content:"\F335"}.tr-builder .tr-builder-controls .tr-components li .clone{left:38px}.tr-builder .tr-builder-controls .tr-components li .clone:before{content:"\F316"}.tr-builder .tr-builder-controls .tr-components li .clone:focus,.tr-builder .tr-builder-controls .tr-components li .clone:hover{background:#0071a1;background:var(--tr-profile-color);outline:none}.tr-builder .tr-frame-fields{margin-left:135px}.tr-builder .tr-builder-select{flex-flow:wrap;display:none;position:absolute;border-radius:3px;z-index:100001;top:35px;left:0;padding:5px;box-sizing:border-box;max-width:532px;background:#eee;border:1px solid #ccd0d4;box-shadow:0 0 8px rgba(0,0,0,.3)}.tr-builder .tr-builder-select:after,.tr-builder .tr-builder-select:before{content:"";display:block;position:absolute;top:-23px;left:45px;z-index:20;border:12px solid transparent;border-bottom-color:#eee}.tr-builder .tr-builder-select:after{top:-24px;z-index:19;border-bottom-color:#ccd0d4}.tr-builder .tr-builder-select .builder-select-divider{width:100%;margin:5px;font-weight:700;font-size:14px}.tr-builder-select-option{width:120px;vertical-align:top;display:inline-block;padding:10px;border-radius:3px;box-sizing:border-box;margin:5px;box-shadow:0 1px 1px rgba(0,0,0,.04);border:1px solid #ccd0d4;background:#fff;text-align:center;cursor:pointer}.tr-builder-select-option:focus{box-shadow:0 0 3px 1px #80b5e4;box-shadow:0 0 3px 1px var(--tr-profile-color);outline:none}.tr-builder-select-option span{display:block;margin-bottom:3px;color:#444}.tr-builder-select-option img{max-width:100%;height:auto;display:block}.tr-builder-select-option:focus span,.tr-builder-select-option:hover span{color:#0071a1;color:var(--tr-profile-color)}.tr-builder-select-overlay{position:fixed;top:0;left:0;height:100%;width:100%;background:#000;opacity:0;z-index:10000}.builder-field-group{display:none}.builder-field-group.active{display:block}.tr-cloned-item>.tr-builder-inputs{border-color:#c2ddbf;box-shadow:0 1px 1px #d2f5b5}.tr-cloned-item>.tr-builder-inputs>h1:first-child,.tr-cloned-item>.tr-builder-inputs h2:first-child,.tr-cloned-item>.tr-builder-inputs h3:first-child{color:#2c4d29;background:#d2f5b5;border-color:inherit}.tr-component-group-name{display:flex;align-items:center;gap:10px}.tr-component-group-name>div:first-child{flex:1}.tr-save-component-as-block-wrap{text-align:right;cursor:pointer}.tr-save-component-as-block{all:unset;cursor:pointer}.tr-block-component-actions{margin-top:2px}.tr-search-results .tr-search-results-hide{display:none}.tr-admin-page-title{margin-bottom:10px;font-size:23px;font-weight:400;padding:9px 15px 4px 0;line-height:29px}.tr-headline{margin-top:0;display:flex;line-height:1.05em;margin-bottom:15px;font-size:23px;font-weight:400}.tr-headline>.text{flex:1}.tr-headline>.icon{width:30px;display:flex;justify-items:center;align-items:center}.tr-items-list{margin:10px 0 0}.tr-items-list .tr-items-list-item,.tr-items-list li{display:block;box-sizing:border-box;position:relative;min-height:50px;padding:10px 40px;border:1px solid #ccd0d4;margin:-1px 0 0!important;background:#fff}.tr-items-list .tr-items-list-item:focus,.tr-items-list li:focus{outline:none;box-shadow:inset 0 0 0 2px #0073aa;box-shadow:inset 0 0 0 2px var(--tr-profile-color)}.tr-items-list .tr-items-list-item .remove,.tr-items-list li .remove{right:12px;top:17px}.tr-items-list .tr-items-list-item .remove:focus,.tr-items-list li .remove:focus{outline:none;box-shadow:none;text-shadow:0 0 7px #a00}.tr-items-list .tr-items-list-item .move,.tr-items-list li .move{left:12px;top:17px}.tr-items-list:empty+.tr-items-append{display:none}.tr-items-append{margin-top:10px!important}.tr-ajax-alert{position:fixed;top:42px;right:10px;z-index:100000;padding:15px;line-height:1.4em;max-width:520px;min-width:320px;box-sizing:border-box;text-align:center;background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,.1);border-left:5px solid;border-color:#46b450}.tr-ajax-alert.tr-alert-error{border-color:#dc3232}.tr-ajax-alert.tr-alert-warning{border-color:#ffb900}.tr-ajax-alert.tr-alert-info{border-color:#00a0d2}body:not(.wp-admin) .tr-admin-notice{padding:15px;line-height:1.4em;box-sizing:border-box;background:#fff;color:#444;margin-bottom:1em;box-shadow:0 1px 1px 0 rgba(0,0,0,.1);border-left:5px solid;border-color:#46b450}body:not(.wp-admin) .tr-admin-notice p:only-child,body:not(.wp-admin) .tr-admin-notice ul:only-child{margin:0}body:not(.wp-admin) .tr-admin-notice li,body:not(.wp-admin) .tr-admin-notice p{text-transform:none;text-decoration:none;letter-spacing:normal}body:not(.wp-admin) .tr-admin-notice.notice-error{border-color:#dc3232}body:not(.wp-admin) .tr-admin-notice.notice-warning{border-color:#ffb900}body:not(.wp-admin) .tr-admin-notice.notice-info{border-color:#00a0d2}@media screen and (max-width:782px){.typerocket-rest-alert{top:46px}}.tr-search-chosen-item-remove{color:#a00;position:absolute;top:50%;transform:translateY(-50%);right:1px;cursor:pointer;background:none;border:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.tr-search-chosen-item-remove:active,.tr-search-chosen-item-remove:hover{color:red}.tr-search-chosen-item-remove:focus{color:red;outline:none;box-shadow:none;text-shadow:0 0 7px #a00}.tr-search-results{margin:0;background:#fff;box-shadow:inset 0 1px 2px rgba(0,0,0,.07);list-style:none;padding:0;border-radius:3px}.tr-search-results>li:only-child{border-radius:3px}.tr-search-results>li:first-child{border-radius:3px 3px 0 0}.tr-search-results>li:last-child{border-radius:0 0 3px 3px}.tr-search-result-title{color:#666;cursor:pointer;font-weight:700;font-size:12px;padding:8px;margin:3px 0 0;border:1px solid #ccd0d4;background:#fff}.tr-search-input{background:none;outline:none}.tr-search-input:focus{outline:none}.tr-search-chosen-item,.tr-search-result{color:#0073aa;color:var(--tr-profile-color);cursor:pointer;font-size:14px;padding:8px;margin:0;border:1px solid #ccd0d4;border-top:none;background:#eee;display:block;overflow:hidden;text-overflow:ellipsis}.tr-search-chosen-item span,.tr-search-result span{font-weight:400;color:#191e23}.tr-search-chosen-item span b,.tr-search-result span b{font-weight:700;color:#3182bd;color:var(--tr-profile-color)}.tr-search-chosen-item:active,.tr-search-chosen-item:focus,.tr-search-chosen-item:hover,.tr-search-result:active,.tr-search-result:focus,.tr-search-result:hover{background:#0073aa;background:var(--tr-profile-color);color:#fff;outline:none;box-shadow:inset 0 1px 2px rgba(0,0,0,.07)}.tr-search-chosen-item:active span,.tr-search-chosen-item:focus span,.tr-search-chosen-item:hover span,.tr-search-result:active span,.tr-search-result:focus span,.tr-search-result:hover span{font-weight:400;color:#fff}.tr-search-chosen-item:active span b,.tr-search-chosen-item:focus span b,.tr-search-chosen-item:hover span b,.tr-search-result:active span b,.tr-search-result:focus span b,.tr-search-result:hover span b{font-weight:700;color:#fff}.tr-search-selected{padding:5px 32px 5px 7px;margin-top:5px;font-size:14px;font-weight:400;background:#fff;position:relative}.tr-search-multiple,.tr-search-selected{border:1px solid #ccd0d4;border-radius:3px}.tr-search-multiple{padding:6px;display:flex}.tr-search-multiple .tr-search-controls,.tr-search-multiple .tr-search-selected{width:50%;flex:1;display:block;margin:0;padding:0;border:none;background:transparent;box-sizing:border-box}.tr-search-multiple .tr-search-controls{padding-right:3px}.tr-search-multiple .tr-results-placeholder{display:none}.tr-search-multiple .tr-search-selected{list-style:none;padding-left:3px}.tr-search-multiple .tr-search-selected:empty:after{content:attr(data-placeholder);display:block;border:1px solid #ccd0d4;padding:5px;border-radius:3px}.tr-search-multiple .tr-search-selected>li{cursor:move;position:relative;padding:5px 32px 5px 7px;margin:0;border:1px solid #ccd0d4;border-top:none}.tr-search-multiple .tr-search-selected>li:first-child{border-top:1px solid #ccd0d4}.tr-search-multiple .tr-search-selected>li span{cursor:pointer}.tr-search-multiple .tr-search-selected>li:focus{text-decoration:underline}.tr-search-multiple .tr-search-selected>li.tr-search-chosen-item.tr-ui-sortable-helper{border-top:1px solid #ccd0d4}.tr-search-multiple:after{content:"";display:block;clear:both}.tr-data-full,.tr-data-full li{margin:0;padding:0;list-style:none}@media screen and (max-width:782px){.tr-data-full li{padding:3px 0}}.tr-file-picker-placeholder,.tr-image-picker-placeholder{margin-top:10px;position:relative}.tr-file-picker-placeholder a,.tr-image-picker-placeholder img{padding:0;border:1px solid #ccd0d4;background:#fff;display:block;max-width:100%;height:auto;overflow:hidden;box-sizing:border-box}.tr-image-field-background{display:flex;flex-direction:column}.tr-image-background-placeholder{position:relative;display:inline-block;margin:10px 10px 40px;width:40%;min-width:150px;max-width:300px;height:auto}.tr-image-background-placeholder img{width:100%;height:auto;position:relative;z-index:0;border:1px solid #ccd0d4;box-shadow:0 0 3px #000}.tr-image-field-background .tr-position-image{background:var(--tr-image-field-bg-src) no-repeat var(--tr-image-field-bg-x) var(--tr-image-field-bg-y);background-size:cover;margin:10px 0;border:1px solid #ccd0d4}.tr-image-field-background .tr-position-inputs{display:flex}.tr-image-field-background .tr-position-inputs label{padding:0}.tr-image-field-background .tr-position-inputs label:last-child{margin-left:10px}.tr-image-field-background .tr-position-inputs input{width:65px;margin-left:5px}.tr-image-background-placeholder:not(:empty):after{height:30px;width:30px;border-radius:100%;border:2px solid hsla(0,0%,100%,.8);z-index:2}.tr-image-background-placeholder:not(:empty):after,.tr-image-background-placeholder:not(:empty):before{display:block;content:"";box-shadow:0 0 3px #000;position:absolute;top:var(--tr-image-field-bg-y);left:var(--tr-image-field-bg-x);transform:translate(-50%,-50%);pointer-events:none}.tr-image-background-placeholder:not(:empty):before{height:4px;width:4px;border-radius:100%;background:#007cba;background:var(--tr-profile-color);z-index:3}.tr-file-picker-placeholder a{padding:8px}.tr-image-picker-placeholder img{background:repeating-linear-gradient(45deg,#fff,#fff 10px,#f0f0f0 0,#f0f0f0 20px)}.tr-dark-image-background img{background:repeating-linear-gradient(45deg,#222131,#222131 10px,#000 0,#000 20px)}.tr-gallery-list{margin:5px -5px 0}.tr-gallery-list .tr-image-picker-placeholder img{cursor:move}.tr-gallery-list .ui-sortable-helper a{display:none}.tr-gallery-item{margin:5px;position:relative;list-style:none;padding:0;display:inline-block;vertical-align:top;box-sizing:border-box;border:1px solid transparent}.tr-gallery-item:focus{outline:none;border:1px solid var(--tr-profile-color);box-shadow:0 0 4px #0073aa;box-shadow:0 0 4px var(--tr-profile-color)}.tr-gallery-item img{margin:0;display:block;cursor:move}.tr-gallery-item:not(:hover) a:not(:focus):not(:active){position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px);white-space:nowrap}.tr-gallery-remove,.tr-image-edit{color:#fff;position:absolute;left:7px;top:7px;z-index:3;text-decoration:none;padding:3px;border-radius:25px;background:rgba(11,11,11,.69);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);box-shadow:none;display:block}.tr-gallery-remove:focus,.tr-gallery-remove:hover,.tr-image-edit:focus,.tr-image-edit:hover{color:#fff;background:red;cursor:pointer}.tr-gallery-item .tr-image-edit{left:40px}.tr-image-edit:focus,.tr-image-edit:hover{background:#0073aa;background:var(--tr-profile-color,#0073aa)}.tr-dev-alert-helper{padding:15px;box-sizing:border-box;background:#fff;border:1px solid #3182bd;border:1px solid var(--tr-profile-color);color:#23282d;margin:10px auto}.tr-dev-alert-helper code{background:hsla(0,0%,93.3%,.35);box-shadow:0 1px 1px rgba(0,0,0,.125);color:#3182bd;color:var(--tr-profile-color);padding:4px;display:inline-block;border-radius:4px}.tr-dev-field-helper{font-weight:400;display:inline-block;position:relative;top:1px;color:#999;transition:all .5s;-webkit-transition:all .5s}.tr-dev-field-helper:hover .nav .tr-dev-field-function{color:#3182bd;color:var(--tr-profile-color)}.tr-dev-field-helper .nav .tr-dev-field-function{margin-left:5px}.tr-repeater .tr-repeater .tr-dev-field-helper{display:none}.tr-matrix>.tr-dev-field-helper,.tr-repeater>.tr-dev-field-helper{margin-bottom:10px}.tr-control-section .tr-dev-field-helper:hover>i,.tr-repeater-group .tr-control-section .tr-dev-field-helper:hover>i{color:#085286;color:var(--tr-profile-color)}.tr-control-section:hover .tr-dev-field-helper .nav,.tr-repeater-group .tr-control-section .tr-dev-field-helper:hover .nav{opacity:1}.tr-dev-field-helper .nav,.tr-repeater-group .tr-control-section .tr-dev-field-helper .nav{display:inline-block;-webkit-transition:opacity .5s ease-out;opacity:0;max-width:350px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;position:relative;line-height:1em}@media screen and (max-width:782px){#wpbody .tr-control-label .tr-dev-field-helper{display:none}}.tr-tab-section{width:100%;display:none}.tr-tab-section.active{display:block}.tr-tabbed-sections.ui-tabs{padding:0}.tr-tabbed-sections .tr-tabs li.hide{display:none}.tr-tabbed-sections .ui-tabs-hide{display:none!important}.tr-tabbed-sections .ui-widget-header{border:none}.tr-tabs .tab-icon-i{height:auto;width:auto;font-size:inherit}.tr-tabbed-top .tr-tabs{padding:0 12px;margin:0;overflow:hidden;zoom:1;line-height:1em;width:100%;display:flex;box-sizing:border-box;box-shadow:inset 0 -1px 0 0 #ccd0d4;background:hsla(0,0%,87.1%,.49)}.tr-tabbed-top .tr-tabs>li{margin:0 12px 0 0;font-weight:400;font-size:13px;line-height:1em;position:relative;list-style:none;box-shadow:none}.tr-tabbed-top .tr-tabs>li.active a{color:#191e23;border-bottom-color:#444}.tr-tabbed-top .tr-tabs>li a{font-weight:700;display:block;padding:15px 9px 12px;text-decoration:none;color:#555;border-bottom:4px solid transparent;box-shadow:none}.tr-tabbed-top .tr-tabs>li a em{color:#666;font-weight:400;font-size:11px;display:block;margin-top:2px}.tr-tabbed-top .tr-tabs>li a:active,.tr-tabbed-top .tr-tabs>li a:focus,.tr-tabbed-top .tr-tabs>li a:hover{border-bottom-color:#00a0d2!important;border-bottom-color:var(--tr-profile-color)!important;outline:none;box-shadow:none}.tr-tabbed-top.tr-tabs-layout-top-enclosed{background:#fff;border:1px solid #ccd0d4;margin-top:10px}.tr-tabbed-top.tr-tabs-layout-top-enclosed>.tr-tabbed-sections .tr-tabs{margin-bottom:10px}.tr-tabbed-top.tr-tabs-layout-top-enclosed>.tr-tabbed-sections .tr-tabs .tr-tab-link{font-size:16px}.tr-tabbed-top.tr-tabs-layout-top-enclosed>.tr-tabbed-sections .tr-tabs .tr-tab-link em{font-size:12px;margin-top:5px}.tr-tabbed-top.tr-tabs-layout-top-enclosed>.tr-tabbed-sections .tr-tabs .tab-icon{vertical-align:text-top;display:inline-block;margin-right:3px;color:#00a0d2;color:var(--tr-profile-color)}.tr-tabbed-box{display:block;margin:20px 0 -1px;position:relative}.tr-tabbed-box.has-header .tr-tab-layout-tabs{margin-top:50px}.tr-tabbed-box label{line-height:inherit}.tr-tabbed-box .tr-fieldset-group,.tr-tabbed-box .tr-table-container{padding:20px;margin:0;box-sizing:border-box}.tr-tabbed-box .tr-tab-layout-tabs .active,.tr-tabbed-box .tr-tab-layout-tabs .active a,.tr-tabbed-box .tr-tab-layout-tabs .active a:hover{background:#fefefe;outline:none;box-shadow:none}.tr-tabbed-box .tr-tab-layout-content>.tr-control-section>.tr-control-row{padding-left:20px;padding-right:20px}.tr-tabbed-box .tr-tab-layout-tabs{margin:0;position:relative}.tr-tabbed-box .tr-tab-layout-tabs ul{margin:1em 0}.tr-tabbed-box .tr-tab-layout-tabs li{list-style-type:none;margin:0 -1px 0 0;border-bottom:0 solid transparent;border-top:0 solid transparent;border-color:#ccd0d4 transparent transparent;border-style:solid;border-width:1px 0 1px 3px;transition:all .2s;box-shadow:none}.tr-tabbed-box .tr-tab-layout-tabs li:first-child{border-top:1px solid transparent}.tr-tabbed-box .tr-tab-layout-tabs .tab-text{max-width:170px;min-width:70px;box-sizing:border-box;padding-right:10px}.tr-tabbed-box .tr-tab-layout-tabs .has-description a{text-transform:uppercase}.tr-tabbed-box .tr-tab-layout-tabs a{padding:10px 10px 10px 12px;box-shadow:none;line-height:18px;color:#00a0d2;color:var(--tr-profile-color);font-weight:700;font-size:13px;letter-spacing:1px;text-decoration:none;border-right:none;border-left:none;display:flex}.tr-tabbed-box .tr-tab-layout-tabs a .tab-text{flex:1}.tr-tabbed-box .tr-tab-layout-tabs .tr-tab-link>.tab-icon{width:30px;text-align:center;color:#b4becb;display:flex;justify-items:center;align-items:center;font-size:21px}.tr-tabbed-box .tr-tab-layout-tabs .tr-tab-link>.tab-icon>i{flex:1}.tr-tabbed-box .tr-tab-layout-tabs .tr-tab-link em{letter-spacing:normal;display:block;font-weight:400;font-style:normal;font-size:12px;margin-top:2px;color:#666;text-transform:none}.tr-tabbed-box .tr-tab-layout-tabs li:focus-within.active .tab-text{color:var(--tr-profile-color,#00a0d2)}.tr-tabbed-box .tr-tab-layout-tabs .active,.tr-tabbed-box .tr-tab-layout-tabs li:active,.tr-tabbed-box .tr-tab-layout-tabs li:focus-within,.tr-tabbed-box .tr-tab-layout-tabs li:hover{padding:0;border-left:3px solid #00a0d2;border-left:3px solid var(--tr-profile-color,#00a0d2);transition:all .2s}.tr-tabbed-box .tr-tab-layout-tabs .active:first-child,.tr-tabbed-box .tr-tab-layout-tabs li:active:first-child,.tr-tabbed-box .tr-tab-layout-tabs li:focus-within:first-child,.tr-tabbed-box .tr-tab-layout-tabs li:hover:first-child{border-top:1px solid #ccd0d4}.tr-tabbed-box .tr-tab-layout-tabs .active:last-child,.tr-tabbed-box .tr-tab-layout-tabs li:active:last-child,.tr-tabbed-box .tr-tab-layout-tabs li:focus-within:last-child,.tr-tabbed-box .tr-tab-layout-tabs li:hover:last-child{border-bottom:1px solid #ccd0d4}.tr-tabbed-box .tr-tab-layout-tabs .active .tr-tab-link,.tr-tabbed-box .tr-tab-layout-tabs li:active .tr-tab-link,.tr-tabbed-box .tr-tab-layout-tabs li:focus-within .tr-tab-link,.tr-tabbed-box .tr-tab-layout-tabs li:hover .tr-tab-link{border-color:#ccd0d4;color:#32373c}.tr-tabbed-box .tr-tab-layout-tabs .active .tr-tab-link>.tab-icon,.tr-tabbed-box .tr-tab-layout-tabs li:active .tr-tab-link>.tab-icon,.tr-tabbed-box .tr-tab-layout-tabs li:focus-within .tr-tab-link>.tab-icon,.tr-tabbed-box .tr-tab-layout-tabs li:hover .tr-tab-link>.tab-icon{color:var(--tr-profile-color,#00a0d2)}.tr-tabbed-box .tr-tab-layout-tabs li.active{background:#fff}.tr-tabbed-box.tr-tabs-layout-left-enclosed .tr-tab-layout-wrap{background:#fff;box-shadow:inset 0 0 0 1px #ccd0d4}.tr-tabbed-box .tr-tab-layout-tabs-wrap{padding:0;border:1px solid #ccd0d4;background:#fefefe;flex:1;overflow:visible;display:flex;flex-flow:column;min-width:0}.tr-tabbed-box .tr-tab-layout-tabs-wrap>.tr-tab-layout-content{flex:1;box-sizing:border-box}.tr-tabbed-box .tr-tab-layout-sidebar{width:150px;order:2;padding:0 8px 20px 12px}@media screen and (max-width:600px){.tr-tabbed-box .tr-tab-layout-tabs{width:auto}.tr-tabbed-box .tab-text{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px);white-space:nowrap}}.tr-tab-layout-columns{position:relative;display:flex;align-items:stretch;flex-direction:row}#post-body-content #screen-meta.tr-tabbed-box{margin:0 0 20px 4px;box-shadow:none}.tr-builder-inputs>.tr-tabbed-box,.tr-repeater-inputs>.tr-tabbed-box{margin:-1px 0}#wpwrap .postbox .tr-tabbed-box{display:block;margin:0}#wpwrap .postbox .tr-tabbed-box .tr-tab-layout-tabs-wrap{border-color:transparent transparent transparent #ccd0d4}#wpwrap .postbox .tr-tabbed-box .tr-tab-layout-content{padding:0}.tr-fieldset-group,.tr-repeater-inputs .tr-fieldset-group{padding:10px 12px}.tr-fieldset-group .tr-fieldset-group-title,.tr-repeater-inputs .tr-fieldset-group .tr-fieldset-group-title{font-size:21px;font-weight:400;margin:0 0 5px}.tr-fieldset-group .tr-fieldset-group-description,.tr-repeater-inputs .tr-fieldset-group .tr-fieldset-group-description{margin:0 0 10px}.tr-fieldset-group .tr-fieldset-group-content,.tr-repeater-inputs .tr-fieldset-group .tr-fieldset-group-content{background:#f5f5f5;border:1px solid #ccd0d4;border-radius:3px;min-width:0}.postbox .tr-fieldset-group .tr-fieldset-group-title,.tr-repeater-inputs .tr-fieldset-group .tr-fieldset-group-title{font-size:14px;line-height:1.4;font-weight:700}.tr-tabbed-footer{border:1px solid #ccd0d4;position:relative;margin:0 -1px -1px}.tr-tabbed-footer,.tr-tabbed-header{background:#f5f5f5;padding:10px}.tr-tabbed-header .tr-headline{margin:10px}.tr-toggle-box{display:flex;position:relative}.tr-toggle-box input[type=checkbox]{height:0;width:0;visibility:hidden;position:absolute}.tr-toggle-box .tr-toggle-box-text{margin:4px 12px 0}.tr-toggle-box .tr-toggle-box-label{cursor:pointer;width:50px;height:24px;border:3px solid #6c7781;display:block;border-radius:100px;position:relative;padding:0;line-height:1.4em}.tr-toggle-box .tr-toggle-box-label:focus{outline:none;box-shadow:0 0 3px rgba(0,115,170,.8);border-color:#4c5761}.tr-toggle-box .tr-toggle-box-label:after{content:"";position:absolute;top:2px;left:2px;width:20px;height:20px;background:#6c7781;border-radius:14px;transition:.3s}.tr-toggle-box input:checked+.tr-toggle-box-label{border-color:transparent;background:#11a0d2;padding:0}.tr-toggle-box input:checked+.tr-toggle-box-label:after{background:#fff;left:calc(100% - 2px);transform:translateX(-100%)}.tr-table-container{margin-top:20px}.tr-table-container .tablenav{display:flex;margin:6px 0;flex-flow:wrap;height:auto}.tr-table-container .tablenav input[type=search],.tr-table-container .tablenav input[type=text],.tr-table-container .tablenav input[type=url]{width:auto;max-width:none}.tr-table-container .tablenav button{margin-left:6px}.tr-table-container .tablenav select{width:auto;float:none;margin:0}.tr-table-container .tablenav .actions{float:none;overflow:initial;display:flex;align-items:center;padding:0 8px 0 0}@media screen and (max-width:782px){.tr-table-container .tablenav .actions{display:none}.tr-table-container .tablenav .actions.bulkactions{display:flex}}.tr-table-container .tablenav .tablenav-pages{float:none;margin:0 0 0 auto;display:flex;align-items:center}@media screen and (max-width:782px){.tr-table-container .tablenav .tablenav-pages{margin:15px 0;justify-content:center}}.tr-table-wrapper{overflow-x:auto}.tr_field_location_google_map{height:150px;background:#ccc;width:100%}.tr_field_location_load_lat_lng_section{margin:10px 0}.tr-swatches{display:flex;flex-flow:wrap;margin:0;padding:3px 0 0}.tr-swatches .tr-swatch-box{height:40px;width:40px;overflow:hidden;border-radius:4px;border:1px solid #191e23}.tr-swatches .tr-swatch-box:after{content:"";display:block;height:0;width:0;border-bottom-color:var(--tr-swatch-a);border-right-color:var(--tr-swatch-a);border-color:var(--tr-swatch-a) var(--tr-swatch-b) var(--tr-swatch-b) var(--tr-swatch-a);border-style:solid;border-width:20px}.tr-swatches label{padding:0 8px 0 0;display:inline-block}.tr-swatches label:focus{outline:none;box-shadow:none}.tr-swatches span{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px);white-space:nowrap}.tr-swatches [type=radio]{position:absolute;opacity:0;width:0;height:0}.tr-swatches .tr-swatch-box{cursor:pointer;max-width:100%;height:auto}.tr-swatches .tr-swatch-box:focus,.tr-swatches .tr-swatch-box:hover{box-shadow:0 0 0 3px #666}.tr-swatches [type=radio]:checked~.tr-swatch-box,.tr-swatches label:focus .tr-swatch-box{box-shadow:0 0 0 3px var(--tr-profile-color)}.tr-control-section .redactor-focus.redactor-styles-on,.tr-control-section .redactor-focus:focus.redactor-styles-on{border-color:var(--tr-profile-color,#007cba)!important;box-shadow:0 0 0 1px var(--tr-profile-color,#007cba)}.tr-control-section .redactor-over:hover.redactor-styles-on{border-color:var(--tr-profile-color,#007cba)!important}.redactor-styles ul{list-style:disc}.redactor-styles .aligncenter{display:block;margin-left:auto;margin-right:auto;text-align:center}.redactor-styles .alignleft{float:left;margin:.5em 1em .5em 0}.redactor-styles .alignright{float:right;margin:.5em 0 .5em 1em}.redactor-toolbar a.re-button-icon .dashicons{font-size:inherit;height:18px;width:auto;box-sizing:border-box;vertical-align:inherit}.typerocket-container{box-sizing:border-box;clear:both}.typerocket-container:after{content:"";display:block;clear:both}.tr-flex-tight{display:flex;flex-flow:wrap;box-sizing:border-box}.tr-flex-tight>*{box-sizing:border-box;padding:0 5px}.tr-flex-tight>:first-child{padding-left:0}.tr-flex-tight>:last-child{padding-right:0}.tr-flex-list{display:flex;box-sizing:border-box}.tr-flex-list>*{flex:1;box-sizing:border-box;padding:0 5px}.tr-flex-list>:first-child{padding-left:0}.tr-flex-list>:last-child{padding-right:0}.tr-flex-justify{justify-content:flex-start}.tr-mr-10{margin-right:10px}.tr-ml-10{margin-left:10px}.tr-mb-10{margin-bottom:10px}.tr-mt-10,.tr-my-10{margin-top:10px}.tr-my-10{margin-bottom:10px}.tr-mx-10{margin-left:10px;margin-right:10px}.tr-m-10{margin:10px}.tr-m-20{margin:20px}.tr-pr-10{padding-right:10px}.tr-pl-10{padding-left:10px}.tr-pb-10{padding-bottom:10px}.tr-pt-10,.tr-py-10{padding-top:10px}.tr-py-10{padding-bottom:10px}.tr-px-10{padding-left:10px;padding-right:10px}.tr-p-10{padding:10px}.tr-p-20{padding:20px}.tr-d-inline{display:inline}.tr-d-inline-block{display:inline-block}.tr-d-block{display:block}.tr-w-100{width:100%}.tr-w-50{width:50%}.tr-w-25{width:25%}.tr-w-10{width:10%}.tr-sr-only:not(:focus):not(:active){clip:rect(0 0 0 0);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}.tr-fl{float:left}.tr-fr{float:right}.cf:after,.cf:before{content:" ";display:table}.cf:after{clear:both}.cf{*zoom:1}.typerocket-wp-style-table{margin:.5em auto;width:100%;clear:both}.typerocket-wp-style-table>.tr-divide+.tr-divide{box-shadow:none}@media screen and (max-width:782px){.typerocket-wp-style-table>.tr-control-row,.typerocket-wp-style-table>.tr-control-section{padding:8px 0}.typerocket-wp-style-table>.tr-control-row>.tr-control-label,.typerocket-wp-style-table>.tr-control-section>.tr-control-label{font-size:14px;font-weight:600}}@media screen and (min-width:783px){.typerocket-wp-style-table{display:table;border-collapse:collapse}.typerocket-wp-style-table .tr-dev-field-helper .nav{max-width:120px}.typerocket-wp-style-table>.tr-control-section{display:table-row}.typerocket-wp-style-table>.tr-control-section>.tr-control-label{color:#333;display:table-cell;font-size:14px;height:auto;vertical-align:top;text-align:left;padding:20px 10px 20px 0;width:200px;line-height:1.3;font-weight:600}.typerocket-wp-style-table>.tr-control-section>.control,.typerocket-wp-style-table>.tr-control-section>.controls{margin-bottom:9px;padding:15px 10px;line-height:1.3;font-size:14px;vertical-align:middle;display:table-cell}.typerocket-wp-style-table>.tr-control-section>.controls{vertical-align:top}.typerocket-wp-style-table>.tr-control-section.tr-repeater>.tr-dev-field-helper{display:none}}.typerocket-wp-style-subtle div.tr-control-label{font-weight:400;font-size:13px;line-height:1.5}.typerocket-wp-style-subtle>.tr-control-row,.typerocket-wp-style-subtle>.tr-control-section{padding:8px 0}.typerocket-wp-style-subtle>.tr-divide+.tr-divide{box-shadow:none}.tr-menu-container{padding-right:10px;clear:both}.tr-menu-container div.tr-control-label{font-style:italic;color:#666;padding-bottom:0}.tr-taxonomy-add-container{padding-right:5%}.tr-datepicker-container{width:17em;display:none;z-index:1000!important}.tr-datepicker-container .ui-datepicker-header{position:relative;padding:.2em 0;border:0;font-weight:700;width:100%;background:#f1f1f1;color:grey;border-bottom:1px solid #dfdfdf}.tr-datepicker-container .ui-datepicker-next,.tr-datepicker-container .ui-datepicker-prev{position:absolute;top:2px;width:1.8em;height:1.8em;text-indent:-9999px;cursor:pointer}.tr-datepicker-container .ui-datepicker-prev{left:2px}.tr-datepicker-container .ui-datepicker-prev:after{content:"";display:block;margin-left:3px;margin-top:6px;border:6px solid transparent;border-right-color:#999}.tr-datepicker-container .ui-datepicker-next:after{content:"";display:block;margin-right:3px;margin-top:6px;border:6px solid transparent;border-left-color:#999}.tr-datepicker-container .ui-datepicker-prev:hover:after{border-right-color:#21759b;border-right-color:var(--tr-profile-color,#21759b)}.tr-datepicker-container .ui-datepicker-next:hover:after{border-left-color:#21759b;border-left-color:var(--tr-profile-color,#21759b)}.tr-datepicker-container .ui-datepicker-next{right:2px}.tr-datepicker-container .ui-datepicker-next span,.tr-datepicker-container .ui-datepicker-prev span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.tr-datepicker-container .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center;font-weight:400;color:#333}.tr-datepicker-container .ui-datepicker-title select{font-size:1em;margin:1px 0}.tr-datepicker-container select.ui-datepicker-month-year{width:100%}.tr-datepicker-container select.ui-datepicker-month,.tr-datepicker-container select.ui-datepicker-year{width:49%}.tr-datepicker-container table{width:96%;font-size:.9em;border-collapse:collapse;margin:0 .4em .4em}.tr-datepicker-container td{border:0;padding:1px}.tr-datepicker-container td a,.tr-datepicker-container td span{display:block;padding:.2em;text-align:right;text-decoration:none}.tr-datepicker-container .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.tr-datepicker-container .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}.tr-datepicker-container .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-cover{display:none;display:block;position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}.tr-datepicker-container th{color:grey;padding:.7em .3em;text-align:center;font-weight:400;border:0}.ui-datepicker-today a:hover{background-color:grey;color:#fff}.ui-datepicker-today a{background-color:#bfbfbf;cursor:pointer;padding:0 4px;margin-bottom:0}.tr-datepicker-container td a{margin-bottom:0;border:0}.tr-datepicker-container td:hover{color:#fff}.tr-datepicker-container td .ui-state-default{color:#333;font-size:13px;line-height:normal;box-shadow:inset 0 1px 0 hsla(0,0%,100%,.2),0 1px 2px rgba(0,0,0,.05);transition:background-image .1s linear;overflow:visible;border:0;background:#fff;margin-bottom:0;padding:5px;color:grey;text-align:center;filter:none}.tr-datepicker-container td .ui-state-highlight{color:#404040;background:#ffeda4;text-shadow:0 -1px 0 rgba(0,0,0,.25);border-color:#eedc94 #eedc94 #e4c652;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25)}.tr-datepicker-container td .ui-state-active{background:#bfbfbf;margin-bottom:0;font-size:1em;text-shadow:0;color:#fff}.tr-datepicker-container td .ui-state-hover{background-color:#21759b;background-color:var(--tr-profile-color,#21759b);border-color:#21759b #21759b #1e6a8d;border-color:var(--tr-profile-color,#21759b);box-shadow:inset 0 1px 0 rgba(120,200,230,.5);box-shadow:inset 0 1px 0 var(--tr-profile-color,#7cc8e3);color:#fff;text-decoration:none;text-shadow:0 1px 0 rgba(0,0,0,.1)}#ui-datepicker-div{background:#f5f5f5;border:1px solid #dfdfdf;margin-top:5px}.chosen-container{position:relative;display:inline-block;vertical-align:middle;font-size:13px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%!important}.chosen-container *{box-sizing:border-box}.chosen-container .chosen-drop{position:absolute;top:100%;z-index:1010;width:100%;border:1px solid #7e8993;border-top:0;background:#fff;clip:rect(0,0,0,0);-webkit-clip-path:inset(100% 100%);clip-path:inset(100% 100%)}.chosen-container.chosen-with-drop .chosen-drop{clip:auto;-webkit-clip-path:none;clip-path:none}.chosen-container a{cursor:pointer}.chosen-container .chosen-single .group-name,.chosen-container .search-choice .group-name{margin-right:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-weight:400;color:#999}.chosen-container .chosen-single .group-name:after,.chosen-container .search-choice .group-name:after{content:":";padding-left:2px;vertical-align:top}.chosen-container-single .chosen-single{position:relative;display:block;overflow:hidden;padding:0 0 0 8px;line-height:26px;min-height:26px;border:1px solid #7e8993;border-radius:3px;background:#fff url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%23555%22%2F%3E%3C%2Fsvg%3E") no-repeat right 5px top 55%;background-size:16px 16px;background-clip:padding-box;color:#444;text-decoration:none;white-space:nowrap}.chosen-container-single .chosen-default{color:#999}.chosen-container-single .chosen-single span{display:block;overflow:hidden;margin-right:26px;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{font-family:dashicons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;font-size:18px;line-height:18px;cursor:pointer;z-index:10;text-shadow:0 1px 0 hsla(0,0%,100%,.8);color:#9b9b9b;text-align:center;text-decoration:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;top:4px;right:26px;display:block;width:18px;height:18px}.chosen-container-single .chosen-single abbr:hover{color:#333}.chosen-container-single .chosen-single abbr:before{content:"\F335"}.chosen-container-single .chosen-single abbr:hover{color:red}.chosen-container-single.chosen-disabled .chosen-single abbr,.chosen-container-single .chosen-single div{display:none}.chosen-container-single .chosen-search{position:relative;z-index:1010;margin:0;padding:3px 4px;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{margin:1px 0;padding:4px 20px 4px 5px!important;width:100%;height:auto;min-height:10px;outline:0;border:1px solid #7e8993;background:url(../img/chosen-sprite.png) no-repeat 100% -20px;font-size:1em;line-height:normal;border-radius:0}.chosen-container-single .chosen-drop{margin-top:-1px;border-radius:0 0 3px 3px;background-clip:padding-box}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;clip:rect(0,0,0,0);-webkit-clip-path:inset(100% 100%);clip-path:inset(100% 100%)}.chosen-container .chosen-results{color:#444;position:relative;overflow-x:hidden;overflow-y:auto;margin:0 4px 4px 0;padding:0 0 0 4px;max-height:240px;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;margin:0;padding:5px 6px;list-style:none;line-height:15px;word-wrap:break-word;-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{background-color:#0071a1;color:#fff}.chosen-container .chosen-results li.no-results{color:#777;display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;overflow:hidden;margin:0;padding:0 5px;width:100%;height:auto;border:1px solid #7e8993;background:#fff;cursor:text;border-radius:3px}.chosen-container-multi .search-choice-close{transition-property:color}.chosen-container-multi .chosen-choices li{float:left;list-style:none}.chosen-container-multi .chosen-choices li.search-field{margin:0;padding:0;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{margin:1px 0;padding:0!important;width:25px;height:25px;min-height:25px;outline:0;border:0!important;background:transparent!important;box-shadow:none;color:#999;font-size:100%;line-height:normal;border-radius:0}.chosen-container-multi .chosen-choices li.search-choice{position:relative;margin:3px 5px 3px 0;padding:3px 20px 3px 5px;border:1px solid #0071a1;max-width:100%;border-radius:3px;color:#0071a1;background:#f3f5f6;line-height:13px;cursor:default}.chosen-container-multi .chosen-choices li.search-choice span{word-wrap:break-word}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{font-family:dashicons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;font-size:18px;line-height:18px;cursor:pointer;z-index:10;text-shadow:0 1px 0 hsla(0,0%,100%,.8);color:#9b9b9b;text-align:center;text-decoration:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;width:18px;height:18px;top:1px;right:0;display:block;color:inherit}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{color:#333}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:before{content:"\F335"}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{color:red}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;border:1px solid #ccc;background-color:#e4e4e4;background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee);color:#666}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{margin:0;padding:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border:1px solid #0071a1;box-shadow:0 0 0 1px #0071a1}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #7e8993;border-bottom-right-radius:0;border-bottom-left-radius:0}.chosen-container-active .chosen-choices{box-shadow:0 0 0 1px #0071a1;border:1px solid #0071a1}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#222!important}.chosen-disabled{cursor:default}.chosen-disabled .chosen-single{background-image:url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%23a0a5aa%22%2F%3E%3C%2Fsvg%3E")}.chosen-disabled .chosen-choices,.chosen-disabled .chosen-single{cursor:default;color:#a0a5aa;background-color:#f7f7f7;border-color:#ddd}.chosen-disabled .chosen-choices li.search-choice{color:#a0a5aa;border-color:#ddd;background-color:#f7f7f7}.chosen-disabled .chosen-choices li.search-choice .search-choice-close{cursor:default;color:#a0a5aa}.chosen-disabled .chosen-choices li.search-choice .search-choice-close:hover{color:inherit}.chosen-rtl{text-align:right}.chosen-rtl .chosen-single{overflow:visible;padding:0 8px 0 0}.chosen-rtl .chosen-single span{margin-right:0;margin-left:26px;direction:rtl}.chosen-rtl .chosen-single-with-deselect span{margin-left:38px}.chosen-rtl .chosen-single div{right:auto;left:3px}.chosen-rtl .chosen-single abbr{right:auto;left:26px}.chosen-rtl .chosen-choices li{float:right}.chosen-rtl .chosen-choices li.search-field input[type=text]{direction:rtl}.chosen-rtl .chosen-choices li.search-choice{margin:3px 5px 3px 0;padding:3px 5px 3px 19px}.chosen-rtl .chosen-choices li.search-choice .search-choice-close{right:auto;left:4px}.chosen-rtl.chosen-container-single .chosen-results{margin:0 0 4px 4px;padding:0 4px 0 0}.chosen-rtl .chosen-results li.group-option{padding-right:15px;padding-left:0}.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div{border-right:none}.chosen-rtl .chosen-search input[type=text]{padding:4px 5px 4px 20px!important;background:url(../img/chosen-sprite.png) no-repeat -30px -20px;direction:rtl}.chosen-rtl.chosen-container-single .chosen-single div b{background-position:6px 2px}.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b{background-position:-12px 2px}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-resolution:1.5dppx),only screen and (min-resolution:144dpi){.chosen-container-single .chosen-search input[type=text],.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span,.chosen-rtl .chosen-search input[type=text]{background-image:url(../img/chosen-sprite@2x.png)!important;background-size:52px 37px!important;background-repeat:no-repeat!important}}#tr-seo-preview h4{margin:0}#tr-seo-preview p{margin-top:0}.tr-seo-preview-google{max-width:600px;display:block}#tr-seo-preview-google-desc-orig,#tr-seo-preview-google-title-orig{display:none}#tr-seo-preview-google-title{display:block;color:#1a0dab;cursor:pointer;font-family:arial,sans-serif;font-size:20px;line-height:1.3em;font-weight:400;height:auto;list-style-image:none;list-style-position:outside;list-style-type:none;text-align:left;text-decoration:none;visibility:visible;white-space:nowrap;width:auto;zoom:1}#tr-seo-preview-google-title:hover{text-decoration:underline}#tr-seo-preview-google-url{color:#006621;font-size:16px;padding-top:1px;line-height:1.5;font-style:normal;margin-bottom:1px;white-space:nowrap}#tr-seo-preview-google-desc,#tr-seo-preview-google-url{font-family:arial,sans-serif;font-weight:400;list-style-image:none;list-style-position:outside;list-style-type:none;text-align:left;visibility:visible;zoom:1}#tr-seo-preview-google-desc{color:#545454;display:inline;font-size:14px;height:auto;line-height:1.57;width:auto}#dev-icon-search{width:100%;max-width:100%}#debug-icon-list{display:grid;grid-template-columns:1fr 1fr 1fr 1fr 1fr 1fr;grid-column-gap:10px;grid-row-gap:10px;margin:20px 0 0;padding:0}#debug-icon-list .tr-debug-icon{height:auto;width:auto}#debug-icon-list em,#debug-icon-list strong{margin:6px 0;display:block}#debug-icon-list li{list-style:none;border:1px solid #ccd0d4;border-radius:4px;text-align:center;font-size:12px;padding:10px}#debug-icon-list li i:before{font-size:42px;display:block}#tr_page_type_toggle{text-align:center;clear:both;padding:15px 12px 10px;box-sizing:border-box;width:100%}#tr_page_type_toggle:after{content:"";display:block;clear:both}#tr_page_type_toggle a{text-decoration:none;width:50%;vertical-align:middle;box-sizing:border-box;outline:none}#tr_page_type_toggle a:first-child{border-radius:3px 0 0 3px}#tr_page_type_toggle a:last-child{border-radius:0 3px 3px 0;border-left:none}#builderSelectRadio{display:none}.admin-color-default .tr-control-icon-clone:hover,.admin-color-default .tr-maxlength span{color:#0073aa}.admin-color-default .chosen-container .chosen-results li.highlighted{background-color:#0073aa}.admin-color-default .chosen-container-multi .chosen-choices li.search-choice{border-color:#0073aa;color:#0073aa}.admin-color-default .chosen-container-active .chosen-choices,.admin-color-default .chosen-container-active .chosen-single{border-color:#0073aa;box-shadow:0 0 0 1px #0073aa}.admin-color-default .tr-toggle-box input:checked+label{background-color:#0073aa}.admin-color-default .tr-toggle-box label:focus{box-shadow:0 0 3px rgba(0,115,170,.8)}.admin-color-default .tr-link-search-result:active,.admin-color-default .tr-link-search-result:focus,.admin-color-default .tr-link-search-result:hover{background:#0073aa}.admin-color-default .tr-tabbed-box .tr-tab-layout-tabs a{color:#0073aa}.admin-color-default .tr-tabbed-box .tr-tab-layout-tabs .active,.admin-color-default .tr-tabbed-box .tr-tab-layout-tabs li:active,.admin-color-default .tr-tabbed-box .tr-tab-layout-tabs li:focus,.admin-color-default .tr-tabbed-box .tr-tab-layout-tabs li:hover{border-left:3px solid #0073aa}.admin-color-default .tr-tabbed-box .tr-tab-layout-tabs .active .tr-tab-link>.tab-icon,.admin-color-default .tr-tabbed-box .tr-tab-layout-tabs li:active .tr-tab-link>.tab-icon,.admin-color-default .tr-tabbed-box .tr-tab-layout-tabs li:focus .tr-tab-link>.tab-icon,.admin-color-default .tr-tabbed-box .tr-tab-layout-tabs li:hover .tr-tab-link>.tab-icon{color:#0073aa}.admin-color-light .tr-control-icon-clone:hover,.admin-color-light .tr-maxlength span{color:#04a4cc}.admin-color-light .chosen-container .chosen-results li.highlighted{background-color:#04a4cc}.admin-color-light .chosen-container-multi .chosen-choices li.search-choice{border-color:#04a4cc;color:#04a4cc}.admin-color-light .chosen-container-active .chosen-choices,.admin-color-light .chosen-container-active .chosen-single{border-color:#04a4cc;box-shadow:0 0 0 1px #04a4cc}.admin-color-light .tr-toggle-box input:checked+label{background-color:#04a4cc}.admin-color-light .tr-toggle-box label:focus{box-shadow:0 0 3px rgba(4,164,204,.8)}.admin-color-light .tr-link-search-result:active,.admin-color-light .tr-link-search-result:focus,.admin-color-light .tr-link-search-result:hover{background:#04a4cc}.admin-color-light .tr-tabbed-box .tr-tab-layout-tabs a{color:#04a4cc}.admin-color-light .tr-tabbed-box .tr-tab-layout-tabs .active,.admin-color-light .tr-tabbed-box .tr-tab-layout-tabs li:active,.admin-color-light .tr-tabbed-box .tr-tab-layout-tabs li:focus,.admin-color-light .tr-tabbed-box .tr-tab-layout-tabs li:hover{border-left:3px solid #04a4cc}.admin-color-light .tr-tabbed-box .tr-tab-layout-tabs .active .tr-tab-link>.tab-icon,.admin-color-light .tr-tabbed-box .tr-tab-layout-tabs li:active .tr-tab-link>.tab-icon,.admin-color-light .tr-tabbed-box .tr-tab-layout-tabs li:focus .tr-tab-link>.tab-icon,.admin-color-light .tr-tabbed-box .tr-tab-layout-tabs li:hover .tr-tab-link>.tab-icon{color:#04a4cc}.admin-color-ectoplasm .tr-control-icon-clone:hover,.admin-color-ectoplasm .tr-maxlength span{color:#a3b745}.admin-color-ectoplasm .chosen-container .chosen-results li.highlighted{background-color:#a3b745}.admin-color-ectoplasm .chosen-container-multi .chosen-choices li.search-choice{border-color:#a3b745;color:#a3b745}.admin-color-ectoplasm .chosen-container-active .chosen-choices,.admin-color-ectoplasm .chosen-container-active .chosen-single{border-color:#a3b745;box-shadow:0 0 0 1px #a3b745}.admin-color-ectoplasm .tr-toggle-box input:checked+label{background-color:#a3b745}.admin-color-ectoplasm .tr-toggle-box label:focus{box-shadow:0 0 3px rgba(163,183,69,.8)}.admin-color-ectoplasm .tr-link-search-result:active,.admin-color-ectoplasm .tr-link-search-result:focus,.admin-color-ectoplasm .tr-link-search-result:hover{background:#a3b745}.admin-color-ectoplasm .tr-tabbed-box .tr-tab-layout-tabs a{color:#a3b745}.admin-color-ectoplasm .tr-tabbed-box .tr-tab-layout-tabs .active,.admin-color-ectoplasm .tr-tabbed-box .tr-tab-layout-tabs li:active,.admin-color-ectoplasm .tr-tabbed-box .tr-tab-layout-tabs li:focus,.admin-color-ectoplasm .tr-tabbed-box .tr-tab-layout-tabs li:hover{border-left:3px solid #a3b745}.admin-color-ectoplasm .tr-tabbed-box .tr-tab-layout-tabs .active .tr-tab-link>.tab-icon,.admin-color-ectoplasm .tr-tabbed-box .tr-tab-layout-tabs li:active .tr-tab-link>.tab-icon,.admin-color-ectoplasm .tr-tabbed-box .tr-tab-layout-tabs li:focus .tr-tab-link>.tab-icon,.admin-color-ectoplasm .tr-tabbed-box .tr-tab-layout-tabs li:hover .tr-tab-link>.tab-icon{color:#a3b745}.admin-color-coffee .tr-control-icon-clone:hover,.admin-color-coffee .tr-maxlength span{color:#c7a589}.admin-color-coffee .chosen-container .chosen-results li.highlighted{background-color:#c7a589}.admin-color-coffee .chosen-container-multi .chosen-choices li.search-choice{border-color:#c7a589;color:#c7a589}.admin-color-coffee .chosen-container-active .chosen-choices,.admin-color-coffee .chosen-container-active .chosen-single{border-color:#c7a589;box-shadow:0 0 0 1px #c7a589}.admin-color-coffee .tr-toggle-box input:checked+label{background-color:#c7a589}.admin-color-coffee .tr-toggle-box label:focus{box-shadow:0 0 3px rgba(199,165,137,.8)}.admin-color-coffee .tr-link-search-result:active,.admin-color-coffee .tr-link-search-result:focus,.admin-color-coffee .tr-link-search-result:hover{background:#c7a589}.admin-color-coffee .tr-tabbed-box .tr-tab-layout-tabs a{color:#c7a589}.admin-color-coffee .tr-tabbed-box .tr-tab-layout-tabs .active,.admin-color-coffee .tr-tabbed-box .tr-tab-layout-tabs li:active,.admin-color-coffee .tr-tabbed-box .tr-tab-layout-tabs li:focus,.admin-color-coffee .tr-tabbed-box .tr-tab-layout-tabs li:hover{border-left:3px solid #c7a589}.admin-color-coffee .tr-tabbed-box .tr-tab-layout-tabs .active .tr-tab-link>.tab-icon,.admin-color-coffee .tr-tabbed-box .tr-tab-layout-tabs li:active .tr-tab-link>.tab-icon,.admin-color-coffee .tr-tabbed-box .tr-tab-layout-tabs li:focus .tr-tab-link>.tab-icon,.admin-color-coffee .tr-tabbed-box .tr-tab-layout-tabs li:hover .tr-tab-link>.tab-icon{color:#c7a589}.admin-color-midnight .tr-control-icon-clone:hover,.admin-color-midnight .tr-maxlength span{color:#e14d43}.admin-color-midnight .chosen-container .chosen-results li.highlighted{background-color:#e14d43}.admin-color-midnight .chosen-container-multi .chosen-choices li.search-choice{border-color:#e14d43;color:#e14d43}.admin-color-midnight .chosen-container-active .chosen-choices,.admin-color-midnight .chosen-container-active .chosen-single{border-color:#e14d43;box-shadow:0 0 0 1px #e14d43}.admin-color-midnight .tr-toggle-box input:checked+label{background-color:#e14d43}.admin-color-midnight .tr-toggle-box label:focus{box-shadow:0 0 3px rgba(225,77,67,.8)}.admin-color-midnight .tr-link-search-result:active,.admin-color-midnight .tr-link-search-result:focus,.admin-color-midnight .tr-link-search-result:hover{background:#e14d43}.admin-color-midnight .tr-tabbed-box .tr-tab-layout-tabs a{color:#e14d43}.admin-color-midnight .tr-tabbed-box .tr-tab-layout-tabs .active,.admin-color-midnight .tr-tabbed-box .tr-tab-layout-tabs li:active,.admin-color-midnight .tr-tabbed-box .tr-tab-layout-tabs li:focus,.admin-color-midnight .tr-tabbed-box .tr-tab-layout-tabs li:hover{border-left:3px solid #e14d43}.admin-color-midnight .tr-tabbed-box .tr-tab-layout-tabs .active .tr-tab-link>.tab-icon,.admin-color-midnight .tr-tabbed-box .tr-tab-layout-tabs li:active .tr-tab-link>.tab-icon,.admin-color-midnight .tr-tabbed-box .tr-tab-layout-tabs li:focus .tr-tab-link>.tab-icon,.admin-color-midnight .tr-tabbed-box .tr-tab-layout-tabs li:hover .tr-tab-link>.tab-icon{color:#e14d43}.admin-color-ocean .tr-control-icon-clone:hover,.admin-color-ocean .tr-maxlength span{color:#9ebaa0}.admin-color-ocean .chosen-container .chosen-results li.highlighted{background-color:#9ebaa0}.admin-color-ocean .chosen-container-multi .chosen-choices li.search-choice{border-color:#9ebaa0;color:#9ebaa0}.admin-color-ocean .chosen-container-active .chosen-choices,.admin-color-ocean .chosen-container-active .chosen-single{border-color:#9ebaa0;box-shadow:0 0 0 1px #9ebaa0}.admin-color-ocean .tr-toggle-box input:checked+label{background-color:#9ebaa0}.admin-color-ocean .tr-toggle-box label:focus{box-shadow:0 0 3px rgba(158,186,160,.8)}.admin-color-ocean .tr-link-search-result:active,.admin-color-ocean .tr-link-search-result:focus,.admin-color-ocean .tr-link-search-result:hover{background:#9ebaa0}.admin-color-ocean .tr-tabbed-box .tr-tab-layout-tabs a{color:#9ebaa0}.admin-color-ocean .tr-tabbed-box .tr-tab-layout-tabs .active,.admin-color-ocean .tr-tabbed-box .tr-tab-layout-tabs li:active,.admin-color-ocean .tr-tabbed-box .tr-tab-layout-tabs li:focus,.admin-color-ocean .tr-tabbed-box .tr-tab-layout-tabs li:hover{border-left:3px solid #9ebaa0}.admin-color-ocean .tr-tabbed-box .tr-tab-layout-tabs .active .tr-tab-link>.tab-icon,.admin-color-ocean .tr-tabbed-box .tr-tab-layout-tabs li:active .tr-tab-link>.tab-icon,.admin-color-ocean .tr-tabbed-box .tr-tab-layout-tabs li:focus .tr-tab-link>.tab-icon,.admin-color-ocean .tr-tabbed-box .tr-tab-layout-tabs li:hover .tr-tab-link>.tab-icon{color:#9ebaa0}.admin-color-sunrise .tr-control-icon-clone:hover,.admin-color-sunrise .tr-maxlength span{color:#dd823b}.admin-color-sunrise .chosen-container .chosen-results li.highlighted{background-color:#dd823b}.admin-color-sunrise .chosen-container-multi .chosen-choices li.search-choice{border-color:#dd823b;color:#dd823b}.admin-color-sunrise .chosen-container-active .chosen-choices,.admin-color-sunrise .chosen-container-active .chosen-single{border-color:#dd823b;box-shadow:0 0 0 1px #dd823b}.admin-color-sunrise .tr-toggle-box input:checked+label{background-color:#dd823b}.admin-color-sunrise .tr-toggle-box label:focus{box-shadow:0 0 3px rgba(221,130,59,.8)}.admin-color-sunrise .tr-link-search-result:active,.admin-color-sunrise .tr-link-search-result:focus,.admin-color-sunrise .tr-link-search-result:hover{background:#dd823b}.admin-color-sunrise .tr-tabbed-box .tr-tab-layout-tabs a{color:#dd823b}.admin-color-sunrise .tr-tabbed-box .tr-tab-layout-tabs .active,.admin-color-sunrise .tr-tabbed-box .tr-tab-layout-tabs li:active,.admin-color-sunrise .tr-tabbed-box .tr-tab-layout-tabs li:focus,.admin-color-sunrise .tr-tabbed-box .tr-tab-layout-tabs li:hover{border-left:3px solid #dd823b}.admin-color-sunrise .tr-tabbed-box .tr-tab-layout-tabs .active .tr-tab-link>.tab-icon,.admin-color-sunrise .tr-tabbed-box .tr-tab-layout-tabs li:active .tr-tab-link>.tab-icon,.admin-color-sunrise .tr-tabbed-box .tr-tab-layout-tabs li:focus .tr-tab-link>.tab-icon,.admin-color-sunrise .tr-tabbed-box .tr-tab-layout-tabs li:hover .tr-tab-link>.tab-icon{color:#dd823b}.admin-color-blue .tr-control-icon-clone:hover,.admin-color-blue .tr-maxlength span{color:#096484}.admin-color-blue .chosen-container .chosen-results li.highlighted{background-color:#096484}.admin-color-blue .chosen-container-multi .chosen-choices li.search-choice{border-color:#096484;color:#096484}.admin-color-blue .chosen-container-active .chosen-choices,.admin-color-blue .chosen-container-active .chosen-single{border-color:#096484;box-shadow:0 0 0 1px #096484}.admin-color-blue .tr-toggle-box input:checked+label{background-color:#096484}.admin-color-blue .tr-toggle-box label:focus{box-shadow:0 0 3px rgba(9,100,132,.8)}.admin-color-blue .tr-link-search-result:active,.admin-color-blue .tr-link-search-result:focus,.admin-color-blue .tr-link-search-result:hover{background:#096484}.admin-color-blue .tr-tabbed-box .tr-tab-layout-tabs a{color:#096484}.admin-color-blue .tr-tabbed-box .tr-tab-layout-tabs .active,.admin-color-blue .tr-tabbed-box .tr-tab-layout-tabs li:active,.admin-color-blue .tr-tabbed-box .tr-tab-layout-tabs li:focus,.admin-color-blue .tr-tabbed-box .tr-tab-layout-tabs li:hover{border-left:3px solid #096484}.admin-color-blue .tr-tabbed-box .tr-tab-layout-tabs .active .tr-tab-link>.tab-icon,.admin-color-blue .tr-tabbed-box .tr-tab-layout-tabs li:active .tr-tab-link>.tab-icon,.admin-color-blue .tr-tabbed-box .tr-tab-layout-tabs li:focus .tr-tab-link>.tab-icon,.admin-color-blue .tr-tabbed-box .tr-tab-layout-tabs li:hover .tr-tab-link>.tab-icon{color:#096484}.wp-admin select:focus{border-color:var(--tr-profile-color,#007cba);color:var(--tr-profile-color-dark,#016087);box-shadow:0 0 0 1px var(--tr-profile-color,#007cba)}.wp-admin select:hover{color:var(--tr-profile-color,#007cba)}assets/dist/js/global.js000064400000000232150732302400011214 0ustar00window.TypeRocket={httpCallbacks:[],repeaterCallbacks:[],lastSubmittedForm:!1,redactor:{extend:{},lang:"en",plugins:[],override:{}},builderCallbacks:[]}; assets/dist/js/builder.ext.js000064400000003601150732302400012204 0ustar00!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=1)}({1:function(e,t,n){e.exports=n("rE4h")},rE4h:function(e,t){var n=wp.editPost,r=(n.PluginSidebar,n.PluginSidebarMoreMenuItem,n.PluginDocumentSettingPanel),o=wp.components,i=(o.TextControl,o.Panel,o.PanelBody,o.PanelRow,wp.plugins.registerPlugin),c=wp.data,a=(c.withSelect,c.withDispatch,wp.i18n.__),l=window.location;i("plugin-document-setting-typerocket-builder",{icon:!1,render:function(){return React.createElement(r,{name:"typerocket-builder",title:"Editor",className:"typerocket-builder"},React.createElement("p",null,a("Click a link below to switch your current editor.","typerocket-domain")),React.createElement("p",null,React.createElement("i",{class:"dashicons dashicons-external"})," ",React.createElement("a",{href:"".concat(l,"&tr_builder=1")},a("Use Page Builder","typerocket-domain"))),React.createElement("p",null,React.createElement("i",{class:"dashicons dashicons-external"})," ",React.createElement("a",{href:"".concat(l,"&tr_builder=0")},a("Use Classic Editor","typerocket-domain"))))}})}});assets/dist/js/core.js000064400000120174150732302400010714 0ustar00!function(t){var e={};function r(a){if(e[a])return e[a].exports;var n=e[a]={i:a,l:!1,exports:{}};return t[a].call(n.exports,n,n.exports,r),n.l=!0,n.exports}r.m=t,r.c=e,r.d=function(t,e,a){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:a})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var a=Object.create(null);if(r.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)r.d(a,n,function(e){return t[e]}.bind(null,n));return a},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="/",r(r.s=0)}({"+x+w":function(t,e){jQuery.fn.selectText=function(){var t,e,r,a;t=document,e=this[0],r=void 0,a=void 0,t.body.createTextRange?((r=document.body.createTextRange()).moveToElementText(e),r.select()):window.getSelection&&(a=window.getSelection(),(r=document.createRange()).selectNodeContents(e),a.removeAllRanges(),a.addRange(r))},jQuery(document).ready((function(t){t(document).on("click",".tr-dev-field-function",(function(){t(this).selectText()}))}))},"/OfD":function(t,e,r){"use strict";function a(t,e){for(var r=0;rt;)e=this.templateTagKeys[t],a=this.templateTagValues[t],this.templateString=this.templateString.replace(new RegExp(e),a),t++}}])&&a(e.prototype,r),n&&a(e,n),Object.defineProperty(e,"prototype",{writable:!1}),t}(),i=r("82zG"),o=r("jEt8"),s=window.jQuery,l=wp.i18n.__;window.Booyah=n,window.tr_apply_repeater_callbacks=i.b,window.tr_hash=i.e,r("IKsQ"),r("gmCF"),r("op53"),r("+x+w"),r("Yl8d"),r("v25N"),r("1KxY"),r("ifTW"),r("fLF1"),r("PAKe"),r("C1Vx"),r("bNGw"),s((function(){var t=s("#tr_page_type_toggle"),e=s(document);t.length>0&&(s("#tr_page_builder_control").hasClass("builder-active")?s("#builderStandardEditor").hide():s("#tr_page_builder").hide(),s(t).on("click","a",(function(t){var e,r,a;t.preventDefault(),a=s(this),r=s(a.siblings()[0]),e=s("#builderSelectRadio input")[1],a.addClass("builder-active button-primary"),r.removeClass("builder-active button-primary"),s(a.attr("href")).show(),s(r.attr("href")).hide(),"tr_page_builder_control"===a.attr("id")?s(e).attr("checked","checked"):(s(e).removeAttr("checked"),s("#content-html").click(),s("#content-tmce").click())})));var r=function(t){return t.closest(".tr-builder").first().children(".tr-frame-fields").first()},a=function(t){return r(t)};e.on("click",".tr-builder-add-button",(function(t){var e,r;t.preventDefault(),r=s(this).next(),e=s("
").addClass("tr-builder-select-overlay").on("click",(function(){s(this).remove(),s(".tr-builder-select").fadeOut()})),s("body").append(e),r.fadeIn()})),e.on("click keyup",".tr-builder-component-control",(function(t){var e,a,n;t.keyCode&&13!==t.keyCode||(t.preventDefault(),s(this).focus().parent().children().removeClass("active"),s(this).addClass("active"),n=s(this).index(),(a=r(s(this)).children()).removeClass("active"),e=a[n],s(e).addClass("active"))})),e.on("click keydown",".tr-clone-builder-component",(function(t){var e,r,n,c;if((!t.keyCode||13===t.keyCode)&&(t.preventDefault(),confirm(l("Clone component?","typerocket-domain"))))try{n=s(this).parent(),t.stopPropagation(),n.parent().children().removeClass("active"),c=n.index(),(r=a(s(this)).children()).removeClass("active");var d=(e=s(r[c])).clone(),u=n.clone(),p=Object(o.c)(d);Object(i.g)(d,p),Object(o.b)(e,d),s(e).after(d),d.addClass("active"),n.after(u),u.addClass("active").attr("data-tr-component-tile",d.attr("data-tr-component")).focus(),Object(o.d)(d)}catch(t){alert(l("Cloning is not available for this component.","typerocket-domain"))}})),e.on("click keydown",".tr-remove-builder-component",(function(t){var e,r,n;t.keyCode&&13!==t.keyCode||(t.preventDefault(),confirm(l("Remove component?","typerocket-domain"))&&((r=s(this).parent()).parent().children().removeClass("active"),n=s(this).parent().index(),e=a(s(this)).children()[n],s(e).remove(),r.remove()))})),e.on("click keydown",".tr-builder-select-option",(function(t){var e,a,n,o,l;if(t.keyCode&&13!==t.keyCode)t.preventDefault();else if((e=(a=s(this)).closest(".tr-builder-select").first()).fadeOut(),s(".tr-builder-select-overlay").remove(),!a.hasClass("disabled")){var c=r(a.parent()),d=a.attr("data-group"),u=(a.attr("data-thumbnail"),a.closest(".tr-builder-controls").first().children(".tr-components").first());o=a.attr("data-value"),a.addClass("disabled"),l=trHelpers.site_uri+"/tr-api/builder/"+d+"/"+o,n=e.attr("data-tr-group"),s.ajax({url:l,method:"POST",dataType:"html",data:{form_group:n,_tr_nonce_form:window.trHelpers.nonce},success:function(t){var e,r,n,o,l,d;for(l=(t=s(t)).first(),d=t.last(),r=c.children(".active"),e=u.children(".active"),c.children().removeClass("active"),u.children().removeClass("active"),n={data:l,tile:d.addClass("active")},o=0;TypeRocket.builderCallbacks.length>o;)"function"==typeof TypeRocket.builderCallbacks[o]&&TypeRocket.builderCallbacks[o](n),o++;e.length>0&&r.length>0?(n.data.insertAfter(r).addClass("active"),e.after(n.tile)):(n.data.prependTo(c).addClass("active"),u.prepend(n.tile)),Object(i.b)(n.data),a.removeClass("disabled")},error:function(t){a.val("Try again - Error "+t.status).removeAttr("disabled","disabled")}})}}))}))},0:function(t,e,r){r("/OfD"),t.exports=r("vvnB")},"0mxQ":function(t,e,r){"use strict";r.d(e,"e",(function(){return o})),r.d(e,"b",(function(){return s})),r.d(e,"c",(function(){return l})),r.d(e,"d",(function(){return c})),r.d(e,"a",(function(){return d}));var a=r("82zG");function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var i=wp.i18n.__;function o(t,e,r,n,o,s){var l,c,d,u,p,f,h,m;if(t)for(var v in f=t[o.items||"items"],h=Object(a.d)(t[o.count||"count"]||f.length),r.html(""),r.append('
  • '+i("Results:","typerocket-domain")+" "+h+"
  • "),d=[],f)l=(c=f[v])[o.id||"id"],u=c[o.title||"title"]||l,m=c[o.url||"url"]||null,s.secure||(u=Object(a.d)(u)),s.secure||(l=Object(a.d)(l)),p=(p=jQuery('
  • '+u+"
  • ")).on("click keyup",(function(t){t.preventDefault();var r=!1,a=!1;t.keyCode&&(r=!0,a=13===t.keyCode),r&&!a||e(n,jQuery(this),s)})),r.append(p),d.push(p)}function s(t,e,r){var a,n,o,s,l;n=e.attr("data-id"),o=e.find("span").html(),s=i("remove","typerocket-domain"),l=jQuery('
  • '+o+'
  • '),r.selectList.append(l),t.focus(),null!=r&&null!==(a=r.config)&&void 0!==a&&a.keepSearch||(t.val(""),e.parent().html(""))}function l(t,e,r){var a,n,o,s;n=e.data("id"),o=e.find("span").html(),s=i("remove","typerocket-domain"),e.parent().prev().html(""+o+' '),t.next().val(n).trigger("change"),t.focus(),null!=r&&null!==(a=r.config)&&void 0!==a&&a.keepSearch||(t.val(""),e.parent().html(""))}function c(t){return t&&(t=JSON.parse(t)),void 0!==n(t)&&t||(t={}),t}function d(t){return t&&(t=JSON.parse(t)),void 0!==n(t)&&t||(t={}),t}},"1KxY":function(t,e,r){"use strict";r.r(e);var a,n=r("0mxQ"),i=(r("82zG"),wp.i18n.__);(a=jQuery).fn.TypeRocketSearch=function(t,e,r,a,o){var s,l,c,d;if(null==t&&(t="any"),null==e&&(e=""),null==r&&(r=""),d=!0,""!==this.val()){var u=(c=this).next().next().next(),p=Object(n.a)(c.attr("data-search-config"));return this[0].addEventListener("search",(function(t){u.html("")})),u.html(""),u.append('
  • '+i("Searching...","typerocket-domain")+"
  • "),l=this.val().trim(),s="post_type="+t+"&s="+encodeURI(l),e&&(s+="&taxonomy="+e),a||(a=trHelpers.site_uri+"/tr-api/search?"+s),a.startsWith(trHelpers.site_uri)||(d=!1),jQuery.post(a,{_method:"POST",_tr_nonce_form:window.trHelpers.nonce,model:r,post_type:t,taxonomy:e,s:l},(function(t){Object(n.e)(t,n.c,u,c,o,{secure:d,config:p})}),"json"),this}},a(document).on("keydown",".tr-search-single .tr-search-input",(function(t){if(t.keyCode&&9===t.keyCode){var e=a(this).siblings(".tr-search-results").find(".tr-search-result").first();e.length>0&&(t.preventDefault(),e.focus())}else{var r,i,o,s,l,c;if(i=a(this),o=a(this).data("posttype"),r=a(this).data("taxonomy"),s=a(this).data("model"),l=a(this).data("endpoint"),c=Object(n.d)(a(this).attr("data-map")),t.keyCode&&27===t.keyCode)return i.focus().val(""),void a(this).siblings(".tr-search-results").html("");t.keyCode&&13===t.keyCode&&(t.preventDefault(),t.stopPropagation()),window.trUtil.delay((function(){i.TypeRocketSearch(o,r,s,l,c)}),250)}})),a(document).on("click keyup",".tr-search-single .tr-search-chosen-item-remove",(function(t){if(t.preventDefault(),!t.keyCode||13===t.keyCode){var e=a(this).parent();e.prev().val("").trigger("change"),e.prev().prev().focus(),e.text(i("No selection... Search and click on a result","typerocket-domain"))}}))},"82zG":function(t,e,r){"use strict";function a(t){return function(t){if(Array.isArray(t))return n(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(!t)return;if("string"==typeof t)return n(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return n(t,e)}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function n(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,a=new Array(e);r":">",'"':""","'":"'","/":"/","`":"`","=":"="};return String(t).replace(/[&<>"'`=\/]/g,(function(t){return e[t]}))}function d(t){var e,r;return r=a((e=o(t)).val()).length,parseInt(e.attr("maxlength"))-r}function u(t,e){e?t.addClass("disabled").attr("value",t.attr("data-limit")):t.removeClass("disabled").attr("value",t.attr("data-add"))}function p(t){for(var e=0;TypeRocket.repeaterCallbacks.length>e;)"function"==typeof TypeRocket.repeaterCallbacks[e]&&TypeRocket.repeaterCallbacks[e](t),e++;return t}function f(t,e){var r=function(t,e,r){return t.replace(r,e)},a=s(),n=t.find(".tr-repeater-group-template [data-tr-name]"),i=t.find(".dev .field span"),l=t.find("[name]"),c=t.find("[data-tr-component]"),d=t.find("[data-tr-name]"),u=t.find("[data-tr-group]"),f=t.find('[id^="tr_field_"],.tr-form-field-help[id]'),h=t.find("[data-tr-context]"),m=t.find("[data-tr-field]"),v=t.find(".tr-label[for], .tr-toggle-box-label[for]");o(h).each((function(){var t=r(o(this).attr("data-tr-context"),a,e);o(this).attr("data-tr-context",t)})),t.attr("data-tr-component")&&t.attr("data-tr-component","tr-clone-hash-parent-"+s()),o(c).each((function(){var e=o(this).attr("data-tr-component"),r="tr-clone-hash-"+s(),a=t.find("[data-tr-component-tile="+e+"]").first();o(this).attr("data-tr-component",r),console.log(r),a&&a.attr("data-tr-component-tile",r)})),o(f).each((function(){var t=r(o(this).attr("id"),a,e);o(this).attr("id",t)})),o(v).each((function(){var t=r(o(this).attr("for"),a,e),n=o(this).attr("aria-describedby")||!1;o(this).attr("for",t),n&&(t=r(n,a,e),o(this).attr("aria-describedby",t))})),o(m).each((function(){var t=r(o(this).attr("data-tr-field"),a,e);o(this).attr("data-tr-field",t)})),o(i).each((function(){var t=r(o(this).html(),a,e);o(this).html(t)})),o(u).each((function(){var t=r(o(this).attr("data-tr-group"),a,e);o(this).attr("data-tr-group",t)})),o(l).each((function(){var t=r(o(this).attr("name"),a,e);o(this).attr("name",t),o(this).attr("data-tr-name",null)})),o(d).each((function(){var t=r(o(this).attr("data-tr-name"),a,e);o(this).attr("name",t),o(this).attr("data-tr-name",null)})),o(n).each((function(){o(this).attr("data-tr-name",o(this).attr("name")),o(this).attr("name",null)})),p(t)}},C1Vx:function(t,e){jQuery(document).ready((function(t){var e,r,a,n;n="",e="",r=t("#tr-seo-preview-google-desc-orig").text(),a=t("#tr-seo-preview-google-title-orig").text(),t(".tr-js-seo-title-field").on("keyup",(function(){var e;n=t(this).val().substring(0,60),(e=t("#tr-seo-preview-google-title")).text(n),n.length>0?e.text(n):e.text(a)})),t(".tr-js-seo-desc-field").on("keyup",(function(){(e=t(this).val().substring(0,300)).length>0?t("#tr-seo-preview-google-desc").text(e):t("#tr-seo-preview-google-desc").text(r)})),t("#tr_seo_redirect_unlock").on("click",(function(e){t(".tr-js-seo-redirect-field").removeAttr("readonly").focus(),t(this).fadeOut(),e.preventDefault()}))}))},IKsQ:function(t,e){var r;window.trUtil={},window.trUtil.delay=(r=0,function(t,e){clearTimeout(r),r=setTimeout(t,e)}),window.trUtil.list_filter=function(t,e){var r,a,n;for(r=document.querySelector(t).value.toUpperCase(),a=document.querySelectorAll(e),n=0;n-1?a[n].style.display="":a[n].style.display="none"},window.trUtil.makeUrlHttpsMaybe=function(t){return"https:"===window.location.protocol?t.replace("http://","https://"):t},"function"!=typeof Object.assign&&Object.defineProperty(Object,"assign",{value:function(t,e){"use strict";if(null==t)throw new TypeError("Cannot convert undefined or null to object");for(var r=Object(t),a=1;a',p='',t(a).val(r.id).trigger("change"),t(e).parent().next().html(p+f)})),wp.media.frames.image_frame=o,wp.media.frames.image_frame.open()})),t(document).on("click",".tr-file-picker-button",(function(){var e,a,n,i;e=t(this),a=t(this).parent().prev()[0],i={title:r("Select a File","typerocket-domain"),button:{text:r("Use File","typerocket-domain")},library:{type:e.data("type")},multiple:!1},n=wp.media(i),i.library.type&&(n.uploader.options.uploader.params.allowed_mime_types=i.library.type),n.on("select",(function(){var r,i;i=''+r.url+"",t(a).val(r.id).trigger("change"),t(e).parent().next().html(i)})),wp.media.frames.file_frame=n,wp.media.frames.file_frame.open()})),t(document).on("click",".tr-image-picker-clear, .tr-file-picker-clear",(function(){var e,r;e=t(this),r=t(this).parent().prev()[0],t(r).val("").trigger("change"),t(e).parent().next().html("")})),t(document).on("click",".tr-image-bg-picker-button",(function(){var e,a,n,i,o,s;e=t(this),a=t(this).parent().prev()[0],n=n||"full",s=r("Select an Image","typerocket-domain"),i=r("Use Image","typerocket-domain"),(o=wp.media({title:s,button:{text:i},library:{type:"image"},multiple:!1})).uploader.options.uploader.params.allowed_mime_types="image",o.on("select",(function(){var r,i,s,l,c,d,u;s=t(e),r=o.state().get("selection").first().toJSON(),d=s.data("size")?s.data("size"):n,console.log(r),void 0!==r.sizes?(void 0===r.sizes[d]&&(d=n),void 0===r.sizes[d]&&(d="full"),u=r.sizes[d].url,l=r.sizes[d].height,c=r.sizes[d].width):(u=r.url,l="",c=""),i=window.trUtil.makeUrlHttpsMaybe(u),t(a).val(r.id).trigger("change"),t(a).parent().attr("style","--tr-image-field-bg-src: url(".concat(i,");")),t(a).siblings(".tr-position-image").find(".tr-image-background-placeholder").first().html('')})),wp.media.frames.image_frame=o,wp.media.frames.image_frame.open()})),t(document).on("click",".tr-image-bg-picker-clear",(function(){var e,r;e=t(this),r=t(this).parent().prev()[0],t(r).val("").trigger("change"),t(r).parent().attr("style","--tr-image-field-bg-src: transparent;"),t(e).parent().next().children().first().html("")})),t(document).on("click",".tr-image-background-placeholder img",(function(e){var r=t(this).offset().left,a=t(this).offset().top,n=t(this).width(),i=t(this).height(),o=e.pageX-r,s=e.pageY-a,l=Math.round(100*o/n),c=Math.round(100*s/i),d=t(this).parent(),u=d.parent().siblings(".tr-position-inputs").first();d.parent().attr("style","--tr-image-field-bg-x: ".concat(l,"%; --tr-image-field-bg-y: ").concat(c,"%;")),u.find(".tr-pos-y").first().val(c),u.find(".tr-pos-x").first().val(l)})),t(document).on("keyup input",".tr-pos-x",(function(e){var r=t(this);(""===e.target.value||e.target.value<1)&&(e.target.value=0),e.target.value>100&&(e.target.value=100),e.target.value=parseInt(e.target.value,10),window.trUtil.delay((function(){var t=r.parent().parent().find(".tr-pos-y").first().val(),e=r.val();r.parent().parent().siblings(".tr-position-image").first().attr("style","--tr-image-field-bg-x: ".concat(e,"%; --tr-image-field-bg-y: ").concat(t,"%;"))}),350)})),t(document).on("keyup input",".tr-pos-y",(function(e){var r=t(this);(""===e.target.value||e.target.value<1)&&(e.target.value=0),e.target.value>100&&(e.target.value=100),e.target.value=parseInt(e.target.value,10),window.trUtil.delay((function(){var t=r.parent().parent().find(".tr-pos-x").first().val(),e=r.val();r.parent().parent().siblings(".tr-position-image").first().attr("style","--tr-image-field-bg-x: ".concat(t,"%; --tr-image-field-bg-y: ").concat(e,"%;"))}),350)})),t(document).on("click",".tr-gallery-picker-button",(function(){var e,a,n,i,o,s;e=t(this),a=t(this).parent().next()[0],o=r("Select Images","typerocket-domain"),n=r("Use Images","typerocket-domain"),s=r("Edit","typerocket-domain"),(i=wp.media({title:o,button:{text:n},library:{type:"image"},multiple:"toggle"})).uploader.options.uploader.params.allowed_mime_types="image",i.on("select",(function(){var r,n,o,l,c,d,u,p,f,h,m,v;for(c=(r=i.state().get("selection").toJSON()).length,o=0;o',l=t(''),t(l).append(n.val(r[o].id).attr("name",n.attr("name")+"[]")).trigger("change"),t(a).append(l),o++})),wp.media.frames.gallery_frame=i,wp.media.frames.gallery_frame.open()})),t(document).on("click",".tr-gallery-picker-clear",(function(){var e;t(this),e=t(this).parent().next()[0],confirm(r("Remove all images?","typerocket-domain"))&&t(e).html("")})),t(document).on("click",".tr-gallery-item",(function(e){t(this).focus()})),t(document).on("click",".tr-gallery-remove",(function(e){e.preventDefault(),t(this).parent().remove()}))}))},Yl8d:function(t,e){var r=wp.i18n.__;jQuery.typerocketHttp={get:function(t,e){this.send("GET",t,e)},post:function(t,e){this.send("POST",t,e)},put:function(t,e){this.send("PUT",t,e)},delete:function(t,e){this.send("DELETE",t,e)},send:function(t,e,r,a,n,i){null==a&&(a=!0),a&&(e=this.tools.addTrailingSlash(e)),r instanceof URLSearchParams&&(r.append("_tr_ajax_request","1"),r=r.toString()),this.tools.ajax({method:t,data:r,url:e},{success:n,error:i})},tools:{entityMap:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="},stripTrailingSlash:function(t){return"/"===t.substr(-1)?t.substr(0,t.length-1):t},addTrailingSlash:function(t){return t.indexOf(".php")?t:t.replace(/\/?(\?|#|$)/,"/$1")},escapeHtml:function(t){var e=this;return String(t).replace(/[&<>"'`=\/]/g,(function(t){return e.entityMap[t]}))},ajax:function(t,e){var a,n;n=this,a={method:"GET",data:{},dataType:"json",success:function(t){t.redirect?window.location=t.redirect:n.checkData(t,3500,e.success,r("Success","typerocket-domain"))},error:function(t,a,i){if(t.responseText){var o=JSON.parse(t.responseText);n.checkData(o,5500,e.error,r("Error","typerocket-domain"))}else alert(r("Your request had an error.","typerocket-domain")+t.status+" - "+i)}},jQuery.extend(a,t),jQuery.ajax(a)},checkData:function(t,e,r,a){var n,i,o,s,l,c,d,u,p,f;for(d=0,this;TypeRocket.httpCallbacks.length>d;)"function"==typeof TypeRocket.httpCallbacks[d]&&TypeRocket.httpCallbacks[d](t),d++;p=t.message?t.message:a,!1!==(null===(s=f=null!==(n=null==t||null===(i=t.data)||void 0===i||null===(o=i._tr)||void 0===o?void 0:o.flashSettings)&&void 0!==n?n:{})||void 0===s?void 0:s.escapeHtml)&&(p=this.escapeHtml(p)),u=this.escapeHtml(t.messageType),e=null!==(l=null===(c=f)||void 0===c?void 0:c.delay)&&void 0!==l?l:e,!0===t.flash&&jQuery("body").prepend(jQuery('
    '+p+"
    ").fadeIn(200).delay(e).fadeOut(200,(function(){jQuery(this).remove()}))),void 0!==r&&r(t)}}}},bNGw:function(t,e){var r;(r=jQuery)(document).on("keyup",".tr-toggle-box-label",(function(t){13===t.keyCode&&r(this).trigger("click")}))},fLF1:function(t,e,r){"use strict";r.r(e);var a=r("82zG");jQuery(document).ready((function(t){t(document).on("click",".tr-matrix-add-button",(function(e){var r,n,i,o,s,l,c,d;(i=t(this)).is(":disabled")||(l=i.attr("data-tr-group"),r=i.parent().parent().siblings(".tr-matrix-fields"),n=i.parent().prev(),o=i.val(),c=n.val(),i.attr("disabled","disabled").val("Adding..."),d=trHelpers.site_uri+"/tr-api/matrix/"+l+"/"+c,s=n.attr("data-group"),t.ajax({url:d,method:"POST",dataType:"html",data:{form_group:s,_tr_nonce_form:window.trHelpers.nonce},success:function(e){(e=t(e)).prependTo(r).hide().delay(10).slideDown(300).scrollTop("100%"),Object(a.b)(e),i.val(o).removeAttr("disabled","disabled")},error:function(t){i.val("Try again - Error "+t.status).removeAttr("disabled","disabled")}}))}))}))},gmCF:function(t,e,r){"use strict";r.r(e);var a=window.jQuery;function n(t,e,r){var n=function(t){var e=_.defaults({id:"tr-insert-image",title:"Insert Image",allowLocalEdits:!0,displaySettings:!0,displayUserSettings:!0,multiple:!1,type:"image"},wp.media.controller.Library.prototype.defaults);return wp.media.controller.Library.extend({defaults:_.defaults(t||{},e)})}(r),i=wp.media(_.defaults(t,{button:{text:"Select Image"},state:"tr-insert-image",states:[new n]}));return i.on("select",e),i.on("open",(function(){var t=i.state("tr-insert-image").get("selection");t.each((function(e){var r=wp.media.attachment(e.attributes.id);r.fetch(),t.remove(r?[r]:[])})),a("#my_file_group_field").find('input[type="hidden"]').each((function(){var e=a(this);if(e.val()){var r=wp.media.attachment(e.val());r.fetch(),t.add(r?[r]:[])}}))})),i}var i=wp.i18n.__;"undefined"!=typeof Redactor&&Redactor.add("plugin","wpmedia",{init:function(t){this.app=t,this.insertion=t.insertion,this.toolbar=t.toolbar,this.component=t.component,this.inspector=t.inspector},start:function(){this.toolbar.addButton("wpmedia",{title:"WordPress Media",api:"plugin.wpmedia.toggle"}).setIcon('')},toggle:function(){this._media()},_media:function(){var t=i("Select an Image","typerocket-domain"),e=i("Use Image","typerocket-domain"),r=this,a=n({title:t,button:{text:e},editable:!0,library:{type:"image"}},(function(t){var e=a.state(),n=e.get("selection").first(),i=n.toJSON(),o=e.display(n).toJSON(),s=[],l=o.size||"full",c="",d="";"undefined"===i.sizes[l]&&(l="full");var u=window.trUtil.makeUrlHttpsMaybe(i.sizes[l].url),p=window.trUtil.makeUrlHttpsMaybe(i.sizes.full.url),f=i.sizes[l].height,h=i.sizes[l].width,m=i.alt,v={left:"alignleft",right:"alignright",center:"aligncenter"};"undefined"!==v[o.align]&&s.push(v[o.align]),"custom"===o.link?(c=''),d=""):"file"===o.link?(c=''),d=""):"post"===o.link&&(c=''),d=""),r._insert('
    ').concat(c,'').concat(m,'').concat(d,"
    "))}),{});a.uploader.options.uploader.params.allowed_mime_types="image",a.open()},_insert:function(t){this.insertion.insertHtml(t)}})},ifTW:function(t,e,r){"use strict";r.r(e);var a,n=r("0mxQ"),i=wp.i18n.__;(a=jQuery).fn.TypeRocketLinks=function(t,e,r,o,s,l){var c,d,u,p,f;if(null==t&&(t="any"),null==e&&(e=""),null==r&&(r=""),p=!0,""!==this.val()){u=this;var h=Object(n.a)(a(this).attr("data-search-config"));return f=u.next(),this[0].addEventListener("search",(function(t){f.html("")})),f.html(""),f.append('
  • '+i("Searching...","typerocket-domain")+"
  • "),d=this.val().trim(),c="post_type="+t+"&s="+encodeURI(d),e&&(c+="&taxonomy="+e),o||(o=trHelpers.site_uri+"/tr-api/search?"+c),o.startsWith(trHelpers.site_uri)||(p=!1),jQuery.post(o,{_method:"POST",_tr_nonce_form:window.trHelpers.nonce,model:r,post_type:t,taxonomy:e,s:d},(function(t){var e=u.parent().next(),r=e.siblings(".tr-search-controls").find(".tr-field-hidden-input").first().attr("name");Object(n.e)(t,l,f,u,s,{secure:p,inputName:r,selectList:e,config:h})}),"json"),this}},a(document).on("click keyup",".tr-search-multiple .tr-search-chosen-item-remove",(function(t){if(t.preventDefault(),!t.keyCode||13===t.keyCode){var e=a(this).parent().siblings().first();e.length>0?e.focus():a(this).closest(".tr-search-selected-multiple").siblings(".tr-search-controls").find(".tr-search-input").first().focus(),a(this).parent().remove()}})),a(document).on("click",".tr-search-multiple .tr-search-chosen-item",(function(t){t.preventDefault(),a(this).focus()})),a(document).on("keydown",".tr-search-multiple .tr-search-input",(function(t){if(!t.keyCode||9!==t.keyCode){var e,r,i,o,s,l;if(r=a(this),i=a(this).attr("data-posttype"),e=a(this).attr("data-taxonomy"),o=a(this).attr("data-model"),s=a(this).attr("data-endpoint"),l=Object(n.d)(a(this).attr("data-map")),t.keyCode&&27===t.keyCode)return r.focus().val(""),void a(this).siblings(".tr-search-results").html("");window.trUtil.delay((function(){r.TypeRocketLinks(i,e,o,s,l,n.b)}),250),t.keyCode&&13===t.keyCode&&(t.preventDefault(),t.stopPropagation())}})),a(document).on("input",".tr-url-input",(function(t){var e,r,i,o,s,l,c;if(!t.keyCode||9!==t.keyCode)if(!(c=(r=a(this)).val())||c.startsWith("#")||c.startsWith("/"))r.next().html("");else{if(i=r.attr("data-posttype"),e=r.attr("data-taxonomy"),o=r.attr("data-model"),s=r.attr("data-endpoint"),l=Object(n.d)(r.attr("data-map")),t.keyCode&&27===t.keyCode)return r.focus().val(""),void r.siblings(".tr-search-results").html("");window.trUtil.delay((function(){r.TypeRocketLinks(i,e,o,s,l,(function(t,e,r){var a,n=e.attr("data-url");t.focus(),t.val(n),console.log(r),null!=r&&null!==(a=r.config)&&void 0!==a&&a.keepSearch||e.parent().html("")}))}),250),t.keyCode&&13===t.keyCode&&(t.preventDefault(),t.stopPropagation())}}))},jEt8:function(t,e,r){"use strict";r.d(e,"a",(function(){return o})),r.d(e,"c",(function(){return l})),r.d(e,"d",(function(){return d})),r.d(e,"b",(function(){return u}));var a=r("82zG"),n=wp.i18n.__,i=window.jQuery;function o(){var t=function(t){return i(t).closest(".tr-repeater-group").first()},e=function(t){return i(t).closest(".tr-repeater-fields").first()};i(document).on("click keydown",".tr-repeater-clone",(function(r){var o=this;if(!r.keyCode||13===r.keyCode){r.preventDefault();try{var c=t(this);if(s(c.data("limit"),e(this).children(),1))i(this).addClass("tr-shake"),setTimeout((function(){i(o).removeClass("tr-shake")}),400);else{var p=c.clone(),f=l(p);Object(a.g)(p,f),u(c,p),t(this).after(p),d(p),p.focus()}}catch(t){console.error(t),alert(n("Cloning is not available for this group.","typerocket-domain"))}}})),i(document).on("click keydown",".tr-repeater-fields.tr-repeater-confirm-remove .tr-repeater-remove",(function(t){t.keyCode&&13!==t.keyCode||confirm(n("Permanently Remove?","typerocket-domain"))||t.stopImmediatePropagation()})),i(document).on("click keydown",".tr-repeater-remove",(function(r){if(!r.keyCode||13===r.keyCode){r.preventDefault();var a=t(this),n=a.data("limit"),i=e(this);a.slideUp(300,(function(){a.remove();var t=i.children();s(n,t,0)}))}})),i(document).on("click keydown",".tr-repeater-collapse",(function(r){var a,n,i,o;r.keyCode&&13!==r.keyCode||(r.preventDefault(),a=t(this),n=e(this),o=a.hasClass("tr-repeater-group-collapsed"),i=a.hasClass("tr-repeater-group-expanded"),o||!i&&n.hasClass("tr-repeater-collapse")?(a.removeClass("tr-repeater-group-collapsed"),a.addClass("tr-repeater-group-expanded")):(a.removeClass("tr-repeater-group-expanded"),a.addClass("tr-repeater-group-collapsed")))})),i(document).on("click",".tr-repeater-action-add",(function(t){t.preventDefault(),c(i(this).parents(".tr-repeater").first(),(function(t,e){t.prependTo(e).scrollTop("100%").focus()}))})),i(document).on("click",".tr-repeater-action-add-append",(function(t){t.preventDefault(),c(i(this).parents(".tr-repeater").first(),(function(t,e){t.appendTo(e).scrollTop("100%").focus()}))})),i(document).on("click",".tr-repeater-action-collapse",(function(t){var e;e=i(this).parent().parent().next().next(),i(this).hasClass("tr-repeater-expanded")?(i(this).val(i(this).data("expand")),i(this).removeClass("tr-repeater-expanded").removeClass("tr-repeater-group-expanded")):(i(this).val(i(this).data("contract")),i(this).addClass("tr-repeater-expanded"),e.find("> .tr-repeater-group").removeClass("tr-repeater-group-collapsed")),e.hasClass("tr-repeater-collapse")?(e.toggleClass("tr-repeater-collapse"),e.find("> .tr-repeater-group").removeClass("tr-repeater-group-collapsed")):(e.toggleClass("tr-repeater-collapse"),e.find("> .tr-repeater-group").removeClass("tr-repeater-group-expanded")),t.preventDefault()})),i(document).on("click",".tr-repeater-action-clear",(function(t){if(confirm(n("Remove all items?","typerocket-domain"))){i(this).parent().parent().next().next().html("");var e=i(this).parent().prev().children();e.removeClass("disabled").attr("value",e.data("add"))}t.preventDefault()})),i(document).on("click",".tr-repeater-action-flip",(function(t){if(confirm(n("Flip order of all items?","typerocket-domain"))){var e=i(this).parent().parent().next().next();e.children().each((function(t,r){e.prepend(r)}))}t.preventDefault()}))}function s(t,e,r){var n=e.length,i=e.first().parents(".tr-repeater").first(),o=i.children(".tr-repeater-action-add-button"),s=i.children(".controls").find(".tr-repeater-action-add-button");if(s.length>0){var l=n+r>=t;Object(a.a)(s,l),Object(a.a)(o,l)}return n>=t}function l(t){for(var e,r=t.find("[data-tr-context]").first().attr("data-tr-context"),a=[],n=/\.(\d{9,})\./g;null!==(e=n.exec(r));)a.push(e.pop()),e.index===n.lastIndex&&n.lastIndex++;return a.pop()}function c(t,e){var r=t.children(".tr-repeater-group-template").children().first().clone(),n=t.children(".tr-repeater-fields"),i=r.data("limit"),o="{{ "+r.data("id")+" }}";Object(a.g)(r,o),s(i,n.children(),1)||e(r,n)}function d(t){t.addClass("tr-cloned-item"),setTimeout((function(){return t.removeClass("tr-cloned-item")}),2400)}function u(t,e){var r=t.find("select");e.find("select").each((function(t,e){i(e).val(r.eq(t).val())}))}},op53:function(t,e,r){"use strict";r.r(e);var a=r("82zG"),n=r("jEt8"),i=window.jQuery;function o(t){i.isFunction(i.fn.wpColorPicker)&&i(t).find(".tr-color-picker[name]").each((function(){var t,e,r,a;(r=i(this)).hasClass("wp-color-picker")&&(a=r.parent().parent().parent().parent(),r=r.clone().off().removeClass("wp-color-picker"),i(this).parent().parent().parent().off().remove(),a.append(r)),t=i(this).data("palette"),e={palettes:window[t]},r.wpColorPicker(e)}))}var s=window.jQuery,l=wp.i18n.__;function c(t){s.isFunction(s.fn.chosen)&&s(t).find(".tr-chosen-select-js[name]").each((function(){var t=s(this).data("max")?s(this).data("max"):999999,e=s(this).data("threshold")?s(this).data("threshold"):5,r=!!s(this).data("empty");s(this).chosen("destroy"),s(this).chosen({no_results_text:l("Oops, nothing found!","typerocket-domain"),max_selected_options:t,disable_search_threshold:e,allow_single_deselect:r})}))}var d=window.jQuery;function u(t){t.find(".wp-editor-area").each((function(){tinyMCE.execCommand("mceAddEditor",!1,d(this).attr("id"))}))}var p=window.jQuery;function f(t){t.find(".tr-tabbed-top:not(.tr-repeater-group-template .tr-tabbed-top)").each((function(){p(this).find("> .tr-tabbed-sections > .tr-tabs > li").each((function(t){var e,r,n,i;e=p(this).attr("data-uid"),r=Object(a.e)(),p(this).attr("data-uid",r),n=p(this).find(".tr-tab-link"),i=p(p(this).parent().parent().next().children()[t]),p(this).attr("id",p(this).attr("id").replace(e,r)),n.attr("href",n.attr("href").replace(e,r)),i.attr("id",i.attr("id").replace(e,r))}))}))}var h=window.jQuery;function m(t){h.isFunction(h.fn.datepicker)&&h(t).find(".tr-date-picker[name]").each((function(){var t=h(this).data("format"),e="dd/mm/yy";t&&(e=t),h(this).off().removeClass("hasDatepicker").removeData("datepicker").datepicker({beforeShow:function(t,e){h("#ui-datepicker-div").addClass("tr-datepicker-container")},dateFormat:e})}))}var v=window.jQuery;function g(t){var e,r,a,n,i;v.isFunction(v.fn.sortable)&&(a=v(t).find(".tr-gallery-list"),n=v(t).find(".tr-search-selected-multiple"),e=v(t).find(".tr-items-list"),r=v(t).find(".tr-repeater-fields"),i=v(t).find(".tr-components"),a.length>0&&a.ksortable({placeholder:"tr-sortable-placeholder tr-gallery-item",forcePlaceholderSize:!0,update:function(t,e){e.item.focus()}}),n.length>0&&n.ksortable({placeholder:"tr-sortable-placeholder",forcePlaceholderSize:!0,update:function(t,e){e.item.focus()}}),r.length>0&&r.ksortable({connectWith:".tr-repeater-group",handle:".tr-repeater-controls",placeholder:"tr-sortable-placeholder",forcePlaceholderSize:!0,update:function(t,e){e.item.focus()}}),e.length>0&&e.ksortable({connectWith:".item",handle:".move",placeholder:"tr-sortable-placeholder",forcePlaceholderSize:!0,update:function(t,e){e.item.focus()}}),i.length>0&&i.sortable({placeholder:"tr-sortable-placeholder",forcePlaceholderSize:!0,start:function(t,e){return e.item.startPos=e.item.index()},update:function(t,e){var r,a,n,i,o;a=(n=e.item.parent().parent().siblings(".tr-frame-fields").first()).children().detach(),i=e.item.index(),o=e.item.startPos,r=a.splice(o,1),a.splice(i,0,r[0]),n.append(a)}}))}v.fn.extend({ksortable:function(t,e){this.sortable(t),e=e||"li",v(this).on("keydown","> "+e,(function(t){if(v(this).is(":focus")){if(37!==t.keyCode&&38!==t.keyCode||(v(this).insertBefore(v(this).prev()),t.preventDefault()),39!==t.keyCode&&40!==t.keyCode||(v(this).insertAfter(v(this).next()),t.preventDefault()),84!==t.keyCode&&33!==t.keyCode||v(this).parent().prepend(v(this)),66!==t.keyCode&&34!==t.keyCode||v(this).parent().append(v(this)),70===t.keyCode){var e=v(this).parent();e.children().each((function(){e.prepend(v(this))}))}v(this).focus()}}))}});window.jQuery;var y=wp.i18n.__;jQuery((function(t){Object(a.c)(),[g,m,o,c].forEach((function(e){e(t(document)),TypeRocket.repeaterCallbacks.push(e)})),TypeRocket.repeaterCallbacks.push(f),TypeRocket.repeaterCallbacks.push(u),t(document).on("input blur change",".tr-input-maxlength",(function(){var e=t(this),r=e.parent();(r.hasClass("redactor-box")||r.hasClass("tr-text-input"))&&(e=r),e.siblings(".tr-maxlength").find("span").text(Object(a.f)(this))})),t(document).on("submit",".tr-form-confirm",(function(t){if(confirm(y("Confirm Submit.","typerocket-domain")))return!0;t.preventDefault()})),t(document).on("submit",".tr-ajax-form",(function(e){e.preventDefault(),window.TypeRocket.lastSubmittedForm=t(this),t.typerocketHttp.send("POST",t(this).attr("action"),t(this).serialize())})),t(document).on("click",".tr-delete-row-rest-button",(function(e){var r,a;if(e.preventDefault(),confirm(y("Confirm Delete.","typerocket-domain")))return a=t(this).attr("data-target"),r={_tr_ajax_request:"1",_method:"DELETE",_tr_nonce_form:window.trHelpers.nonce},t.typerocketHttp.send("POST",t(this).attr("href"),r,!1,(function(){t(a).remove()}))})),t(document).on("keyup",".tr-radio-options-label",(function(e){e.target===this&&(e.preventDefault(),e.keyCode&&13===e.keyCode&&(t(this).trigger("click").focus(),e.preventDefault()))})),t(document).on("click",".tr-focus-on-click",(function(e){e.target===this&&(e.preventDefault(),t(this).focus())})),t(document).on("click",".tr-tabs > li",(function(e){t(this).addClass("active").siblings().removeClass("active");var r=t(this).find(".tr-tab-link").first().attr("href");t(r).addClass("active").siblings().removeClass("active"),Object(a.c)(),e.preventDefault()})),Object(n.a)()}))},v25N:function(t,e,r){"use strict";r.r(e);var a=r("82zG"),n=wp.i18n.__;jQuery((function(t){var e;function r(e,r){var a=e.attr("data-type"),i=e.attr("data-tr-name"),o=n("Remove Item","typerocket-domain"),s=t('
  • ');r?e.append(s):e.prepend(s),s.focus().scrollTop("100%")}e=function(e,r){if(confirm(n("Remove all items?","typerocket-domain"))){t(r).val(""),t(e).parent().next().html("");var a=e.prev();a.removeClass("disabled").attr("value",a.attr("data-add"))}return!1},t(document).on("click",".tr-items-list-item",(function(e){e.target===this&&(e.preventDefault(),t(this).focus())})),t(document).on("click",".tr-items-list-button",(function(){var e,n,i,o,s;(n=t(this).parent()).hasClass("button-group")&&(n=n.parent()),i=(e=n.children(".tr-items-list")).attr("name"),o=e.attr("data-limit"),i&&e.attr("data-tr-name",i);var l=e.children().length;l=o;Object(a.a)(t(this),c),Object(a.a)(s,c)})),t(document).on("click",".tr-items-list-clear",(function(){var r;r=t(this).parent().prev(),e(t(this),r[0])})),t(document).on("click",".tr-items-list-item-remove",(function(){var e=t(this).parent().parent();t(this).parent().remove();var r=e.children().length>=e.attr("data-limit"),n=e.prev().find(".tr-items-list-button"),i=e.next();Object(a.a)(n,r),Object(a.a)(i,r)}))}))},vvnB:function(t,e){}});assets/dist/js/lib/chosen.min.js000064400000070701150732302400012573 0ustar00/* Chosen v1.8.7 | (c) 2011-2018 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */ (function(){var t,e,s,i,n=function(t,e){return function(){return t.apply(e,arguments)}},r=function(t,e){function s(){this.constructor=t}for(var i in e)o.call(e,i)&&(t[i]=e[i]);return s.prototype=e.prototype,t.prototype=new s,t.__super__=e.prototype,t},o={}.hasOwnProperty;(i=function(){function t(){this.options_index=0,this.parsed=[]}return t.prototype.add_node=function(t){return"OPTGROUP"===t.nodeName.toUpperCase()?this.add_group(t):this.add_option(t)},t.prototype.add_group=function(t){var e,s,i,n,r,o;for(e=this.parsed.length,this.parsed.push({array_index:e,group:!0,label:t.label,title:t.title?t.title:void 0,children:0,disabled:t.disabled,classes:t.className}),o=[],s=0,i=(r=t.childNodes).length;s"+this.escape_html(t.group_label)+""+t.html:t.html},t.prototype.mouse_enter=function(){return this.mouse_on_container=!0},t.prototype.mouse_leave=function(){return this.mouse_on_container=!1},t.prototype.input_focus=function(t){if(this.is_multiple){if(!this.active_field)return setTimeout(function(t){return function(){return t.container_mousedown()}}(this),50)}else if(!this.active_field)return this.activate_field()},t.prototype.input_blur=function(t){if(!this.mouse_on_container)return this.active_field=!1,setTimeout(function(t){return function(){return t.blur_test()}}(this),100)},t.prototype.label_click_handler=function(t){return this.is_multiple?this.container_mousedown(t):this.activate_field()},t.prototype.results_option_build=function(t){var e,s,i,n,r,o,h;for(e="",h=0,n=0,r=(o=this.results_data).length;n=this.max_shown_results));n++);return e},t.prototype.result_add_option=function(t){var e,s;return t.search_match&&this.include_option_in_results(t)?(e=[],t.disabled||t.selected&&this.is_multiple||e.push("active-result"),!t.disabled||t.selected&&this.is_multiple||e.push("disabled-result"),t.selected&&e.push("result-selected"),null!=t.group_array_index&&e.push("group-option"),""!==t.classes&&e.push(t.classes),s=document.createElement("li"),s.className=e.join(" "),t.style&&(s.style.cssText=t.style),s.setAttribute("data-option-array-index",t.array_index),s.innerHTML=t.highlighted_html||t.html,t.title&&(s.title=t.title),this.outerHTML(s)):""},t.prototype.result_add_group=function(t){var e,s;return(t.search_match||t.group_match)&&t.active_options>0?((e=[]).push("group-result"),t.classes&&e.push(t.classes),s=document.createElement("li"),s.className=e.join(" "),s.innerHTML=t.highlighted_html||this.escape_html(t.label),t.title&&(s.title=t.title),this.outerHTML(s)):""},t.prototype.results_update_field=function(){if(this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing)return this.winnow_results()},t.prototype.reset_single_select_options=function(){var t,e,s,i,n;for(n=[],t=0,e=(s=this.results_data).length;t"+this.escape_html(s)+""+this.escape_html(p)),null!=a&&(a.group_match=!0)):null!=r.group_array_index&&this.results_data[r.group_array_index].search_match&&(r.search_match=!0)));return this.result_clear_highlight(),_<1&&h.length?(this.update_results_content(""),this.no_results(h)):(this.update_results_content(this.results_option_build()),(null!=t?t.skip_highlight:void 0)?void 0:this.winnow_results_set_highlight())},t.prototype.get_search_regex=function(t){var e,s;return s=this.search_contains?t:"(^|\\s|\\b)"+t+"[^\\s]*",this.enable_split_word_search||this.search_contains||(s="^"+s),e=this.case_sensitive_search?"":"i",new RegExp(s,e)},t.prototype.search_string_match=function(t,e){var s;return s=e.exec(t),!this.search_contains&&(null!=s?s[1]:void 0)&&(s.index+=1),s},t.prototype.choices_count=function(){var t,e,s;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,t=0,e=(s=this.form_field.options).length;t0?this.keydown_backstroke():this.pending_backstroke||(this.result_clear_highlight(),this.results_search());break;case 13:t.preventDefault(),this.results_showing&&this.result_select(t);break;case 27:this.results_showing&&this.results_hide();break;case 9:case 16:case 17:case 18:case 38:case 40:case 91:break;default:this.results_search()}},t.prototype.clipboard_event_checker=function(t){if(!this.is_disabled)return setTimeout(function(t){return function(){return t.results_search()}}(this),50)},t.prototype.container_width=function(){return null!=this.options.width?this.options.width:this.form_field.offsetWidth+"px"},t.prototype.include_option_in_results=function(t){return!(this.is_multiple&&!this.display_selected_options&&t.selected)&&(!(!this.display_disabled_options&&t.disabled)&&!t.empty)},t.prototype.search_results_touchstart=function(t){return this.touch_started=!0,this.search_results_mouseover(t)},t.prototype.search_results_touchmove=function(t){return this.touch_started=!1,this.search_results_mouseout(t)},t.prototype.search_results_touchend=function(t){if(this.touch_started)return this.search_results_mouseup(t)},t.prototype.outerHTML=function(t){var e;return t.outerHTML?t.outerHTML:((e=document.createElement("div")).appendChild(t),e.innerHTML)},t.prototype.get_single_html=function(){return'\n '+this.default_text+'\n
    \n
    \n
    \n \n
      \n
      '},t.prototype.get_multi_html=function(){return'
        \n
      • \n \n
      • \n
      \n
      \n
        \n
        '},t.prototype.get_no_results_html=function(t){return'
      • \n '+this.results_none_found+" "+this.escape_html(t)+"\n
      • "},t.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:!(/iP(od|hone)/i.test(window.navigator.userAgent)||/IEMobile/i.test(window.navigator.userAgent)||/Windows Phone/i.test(window.navigator.userAgent)||/BlackBerry/i.test(window.navigator.userAgent)||/BB10/i.test(window.navigator.userAgent)||/Android.*Mobile/i.test(window.navigator.userAgent))},t.default_multiple_text="Select Some Options",t.default_single_text="Select an Option",t.default_no_result_text="No results match",t}(),(t=jQuery).fn.extend({chosen:function(i){return e.browser_is_supported()?this.each(function(e){var n,r;r=(n=t(this)).data("chosen"),"destroy"!==i?r instanceof s||n.data("chosen",new s(this,i)):r instanceof s&&r.destroy()}):this}}),s=function(s){function n(){return n.__super__.constructor.apply(this,arguments)}return r(n,e),n.prototype.setup=function(){return this.form_field_jq=t(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex},n.prototype.set_up_html=function(){var e,s;return(e=["chosen-container"]).push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&e.push(this.form_field.className),this.is_rtl&&e.push("chosen-rtl"),s={"class":e.join(" "),title:this.form_field.title},this.form_field.id.length&&(s.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=t("
        ",s),this.container.width(this.container_width()),this.is_multiple?this.container.html(this.get_multi_html()):this.container.html(this.get_single_html()),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.results_build(),this.set_tab_index(),this.set_label_behavior()},n.prototype.on_ready=function(){return this.form_field_jq.trigger("chosen:ready",{chosen:this})},n.prototype.register_observers=function(){return this.container.on("touchstart.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.container.on("touchend.chosen",function(t){return function(e){t.container_mouseup(e)}}(this)),this.container.on("mousedown.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.container.on("mouseup.chosen",function(t){return function(e){t.container_mouseup(e)}}(this)),this.container.on("mouseenter.chosen",function(t){return function(e){t.mouse_enter(e)}}(this)),this.container.on("mouseleave.chosen",function(t){return function(e){t.mouse_leave(e)}}(this)),this.search_results.on("mouseup.chosen",function(t){return function(e){t.search_results_mouseup(e)}}(this)),this.search_results.on("mouseover.chosen",function(t){return function(e){t.search_results_mouseover(e)}}(this)),this.search_results.on("mouseout.chosen",function(t){return function(e){t.search_results_mouseout(e)}}(this)),this.search_results.on("mousewheel.chosen DOMMouseScroll.chosen",function(t){return function(e){t.search_results_mousewheel(e)}}(this)),this.search_results.on("touchstart.chosen",function(t){return function(e){t.search_results_touchstart(e)}}(this)),this.search_results.on("touchmove.chosen",function(t){return function(e){t.search_results_touchmove(e)}}(this)),this.search_results.on("touchend.chosen",function(t){return function(e){t.search_results_touchend(e)}}(this)),this.form_field_jq.on("chosen:updated.chosen",function(t){return function(e){t.results_update_field(e)}}(this)),this.form_field_jq.on("chosen:activate.chosen",function(t){return function(e){t.activate_field(e)}}(this)),this.form_field_jq.on("chosen:open.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.form_field_jq.on("chosen:close.chosen",function(t){return function(e){t.close_field(e)}}(this)),this.search_field.on("blur.chosen",function(t){return function(e){t.input_blur(e)}}(this)),this.search_field.on("keyup.chosen",function(t){return function(e){t.keyup_checker(e)}}(this)),this.search_field.on("keydown.chosen",function(t){return function(e){t.keydown_checker(e)}}(this)),this.search_field.on("focus.chosen",function(t){return function(e){t.input_focus(e)}}(this)),this.search_field.on("cut.chosen",function(t){return function(e){t.clipboard_event_checker(e)}}(this)),this.search_field.on("paste.chosen",function(t){return function(e){t.clipboard_event_checker(e)}}(this)),this.is_multiple?this.search_choices.on("click.chosen",function(t){return function(e){t.choices_click(e)}}(this)):this.container.on("click.chosen",function(t){t.preventDefault()})},n.prototype.destroy=function(){return t(this.container[0].ownerDocument).off("click.chosen",this.click_test_action),this.form_field_label.length>0&&this.form_field_label.off("click.chosen"),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},n.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field.disabled||this.form_field_jq.parents("fieldset").is(":disabled"),this.container.toggleClass("chosen-disabled",this.is_disabled),this.search_field[0].disabled=this.is_disabled,this.is_multiple||this.selected_item.off("focus.chosen",this.activate_field),this.is_disabled?this.close_field():this.is_multiple?void 0:this.selected_item.on("focus.chosen",this.activate_field)},n.prototype.container_mousedown=function(e){var s;if(!this.is_disabled)return!e||"mousedown"!==(s=e.type)&&"touchstart"!==s||this.results_showing||e.preventDefault(),null!=e&&t(e.target).hasClass("search-choice-close")?void 0:(this.active_field?this.is_multiple||!e||t(e.target)[0]!==this.selected_item[0]&&!t(e.target).parents("a.chosen-single").length||(e.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),t(this.container[0].ownerDocument).on("click.chosen",this.click_test_action),this.results_show()),this.activate_field())},n.prototype.container_mouseup=function(t){if("ABBR"===t.target.nodeName&&!this.is_disabled)return this.results_reset(t)},n.prototype.search_results_mousewheel=function(t){var e;if(t.originalEvent&&(e=t.originalEvent.deltaY||-t.originalEvent.wheelDelta||t.originalEvent.detail),null!=e)return t.preventDefault(),"DOMMouseScroll"===t.type&&(e*=40),this.search_results.scrollTop(e+this.search_results.scrollTop())},n.prototype.blur_test=function(t){if(!this.active_field&&this.container.hasClass("chosen-container-active"))return this.close_field()},n.prototype.close_field=function(){return t(this.container[0].ownerDocument).off("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale(),this.search_field.blur()},n.prototype.activate_field=function(){if(!this.is_disabled)return this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},n.prototype.test_active_click=function(e){var s;return(s=t(e.target).closest(".chosen-container")).length&&this.container[0]===s[0]?this.active_field=!0:this.close_field()},n.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=i.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},n.prototype.result_do_highlight=function(t){var e,s,i,n,r;if(t.length){if(this.result_clear_highlight(),this.result_highlight=t,this.result_highlight.addClass("highlighted"),i=parseInt(this.search_results.css("maxHeight"),10),r=this.search_results.scrollTop(),n=i+r,s=this.result_highlight.position().top+this.search_results.scrollTop(),(e=s+this.result_highlight.outerHeight())>=n)return this.search_results.scrollTop(e-i>0?e-i:0);if(s0)return this.form_field_label.on("click.chosen",this.label_click_handler)},n.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},n.prototype.search_results_mouseup=function(e){var s;if((s=t(e.target).hasClass("active-result")?t(e.target):t(e.target).parents(".active-result").first()).length)return this.result_highlight=s,this.result_select(e),this.search_field.focus()},n.prototype.search_results_mouseover=function(e){var s;if(s=t(e.target).hasClass("active-result")?t(e.target):t(e.target).parents(".active-result").first())return this.result_do_highlight(s)},n.prototype.search_results_mouseout=function(e){if(t(e.target).hasClass("active-result")||t(e.target).parents(".active-result").first())return this.result_clear_highlight()},n.prototype.choice_build=function(e){var s,i;return s=t("
      • ",{"class":"search-choice"}).html(""+this.choice_label(e)+""),e.disabled?s.addClass("search-choice-disabled"):((i=t("",{"class":"search-choice-close","data-option-array-index":e.array_index})).on("click.chosen",function(t){return function(e){return t.choice_destroy_link_click(e)}}(this)),s.append(i)),this.search_container.before(s)},n.prototype.choice_destroy_link_click=function(e){if(e.preventDefault(),e.stopPropagation(),!this.is_disabled)return this.choice_destroy(t(e.target))},n.prototype.choice_destroy=function(t){if(this.result_deselect(t[0].getAttribute("data-option-array-index")))return this.active_field?this.search_field.focus():this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.get_search_field_value().length<1&&this.results_hide(),t.parents("li").first().remove(),this.search_field_scale()},n.prototype.results_reset=function(){if(this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),this.trigger_form_field_change(),this.active_field)return this.results_hide()},n.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},n.prototype.result_select=function(t){var e,s;if(this.result_highlight)return e=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?e.removeClass("active-result"):this.reset_single_select_options(),e.addClass("result-selected"),s=this.results_data[e[0].getAttribute("data-option-array-index")],s.selected=!0,this.form_field.options[s.options_index].selected=!0,this.selected_option_count=null,this.is_multiple?this.choice_build(s):this.single_set_selected_text(this.choice_label(s)),this.is_multiple&&(!this.hide_results_on_select||t.metaKey||t.ctrlKey)?t.metaKey||t.ctrlKey?this.winnow_results({skip_highlight:!0}):(this.search_field.val(""),this.winnow_results()):(this.results_hide(),this.show_search_field_default()),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&this.trigger_form_field_change({selected:this.form_field.options[s.options_index].value}),this.current_selectedIndex=this.form_field.selectedIndex,t.preventDefault(),this.search_field_scale())},n.prototype.single_set_selected_text=function(t){return null==t&&(t=this.default_text),t===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.selected_item.find("span").html(t)},n.prototype.result_deselect=function(t){var e;return e=this.results_data[t],!this.form_field.options[e.options_index].disabled&&(e.selected=!1,this.form_field.options[e.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.trigger_form_field_change({deselected:this.form_field.options[e.options_index].value}),this.search_field_scale(),!0)},n.prototype.single_deselect_control_build=function(){if(this.allow_single_deselect)return this.selected_item.find("abbr").length||this.selected_item.find("span").first().after(''),this.selected_item.addClass("chosen-single-with-deselect")},n.prototype.get_search_field_value=function(){return this.search_field.val()},n.prototype.get_search_text=function(){return t.trim(this.get_search_field_value())},n.prototype.escape_html=function(e){return t("
        ").text(e).html()},n.prototype.winnow_results_set_highlight=function(){var t,e;if(e=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),null!=(t=e.length?e.first():this.search_results.find(".active-result").first()))return this.result_do_highlight(t)},n.prototype.no_results=function(t){var e;return e=this.get_no_results_html(t),this.search_results.append(e),this.form_field_jq.trigger("chosen:no_results",{chosen:this})},n.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},n.prototype.keydown_arrow=function(){var t;return this.results_showing&&this.result_highlight?(t=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(t):void 0:this.results_show()},n.prototype.keyup_arrow=function(){var t;return this.results_showing||this.is_multiple?this.result_highlight?(t=this.result_highlight.prevAll("li.active-result")).length?this.result_do_highlight(t.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight()):void 0:this.results_show()},n.prototype.keydown_backstroke=function(){var t;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(t=this.search_container.siblings("li.search-choice").last()).length&&!t.hasClass("search-choice-disabled")?(this.pending_backstroke=t,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0},n.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},n.prototype.search_field_scale=function(){var e,s,i,n,r,o,h;if(this.is_multiple){for(r={position:"absolute",left:"-1000px",top:"-1000px",display:"none",whiteSpace:"pre"},s=0,i=(o=["fontSize","fontStyle","fontWeight","fontFamily","lineHeight","textTransform","letterSpacing"]).length;s").css(r)).text(this.get_search_field_value()),t("body").append(e),h=e.width()+25,e.remove(),this.container.is(":visible")&&(h=Math.min(this.container.outerWidth()-10,h)),this.search_field.width(h)}},n.prototype.trigger_form_field_change=function(t){return this.form_field_jq.trigger("input",t),this.form_field_jq.trigger("change",t)},n}()}).call(this);assets/dist/img/chosen-sprite@2x.png000064400000001342150732302400013424 0ustar00PNG  IHDRhJqIDATh횿o@#P ?!dԅsft⇿'RJ0#[Ɉ+P{RW%ދ1 e,J4h'Y2NyH%?/4 Lj[ -85HqHqȱs6C+%0`QWXO5 ]:ڿhIg7oi 1n fHn' !- hjh؝lnzHAojQFEæhH 'wԲtc 8H۪/4 Lj`$8 qiDS %N9 J1Sp̶;Xk}\kN[[tk%sFp3KXR~CgYƬ,9A%w;8Qh H,]npY>$c )ƒ Khw~SʼnqP*wҶXy{$u%&Z'(8؜֜bҍ၊5R6emP0<F-F i# zH|YJZ\NIENDB`assets/dist/img/chosen-sprite.png000064400000001032150732302400013046 0ustar00PNG  IHDR4%^IDATH헱kSQƯ .-=$bo$((THw*"nupA@ PApqJ$p!PM1.;=\D.Yn0@}DMF >Fb1 c !61rb%GIJ(vfFyO H4B c1}^45FoGXٝvUn(Rspv*8sP*cOTQWŬj1QH}T+}֕d/LLcF6˔7,9ʼ1IkJ(dJjLc^z*"Huj)׿,?<._1a°x /b}T!i?Ou oc\eNc:99\@s uZ q|ypka6B|1 Ggqup+[*yIENDB`assets/dist/mix-manifest.json000064400000000401150732302400012274 0ustar00{ "/js/builder.ext.js": "/js/builder.ext.js?id=fdb787b2c8d8f73d1038", "/js/core.js": "/js/core.js?id=732a199902494c8e6718", "/css/core.css": "/css/core.css?id=83591618cbcda8ff6bb6", "/js/global.js": "/js/global.js?id=299b31f67ab20381e7c4" } assets/js/tooling/dev.js000064400000001302150732302400011241 0ustar00;jQuery.fn.selectText = function() { var doc, element, range, selection; doc = document; element = this[0]; range = void 0; selection = void 0; if (doc.body.createTextRange) { range = document.body.createTextRange(); range.moveToElementText(element); range.select(); } else if (window.getSelection) { selection = window.getSelection(); range = document.createRange(); range.selectNodeContents(element); selection.removeAllRanges(); selection.addRange(range); } }; jQuery(document).ready(function($) { $(document).on('click', '.tr-dev-field-function', function() { $(this).selectText(); }); });assets/js/tooling/links.js000064400000011456150732302400011616 0ustar00import {search_response, links_append, search_get_map, get_the_json} from "./fn/search-common"; const { __ } = wp.i18n; ;(function( $ ) { $.fn.TypeRocketLinks = function(type, taxonomy, model, url, map, fnSelect) { let param, search, that, secure, linkList; if (type == null) { type = 'any'; } if (taxonomy == null) { taxonomy = ''; } if (model == null) { model = ''; } secure = true if(this.val() === '') { return; } that = this; let config = get_the_json($(this).attr('data-search-config')); linkList = that.next(); this[0].addEventListener("search", function(event) { linkList.html(''); }); linkList.html(''); linkList.append('
      • '+__('Searching...', 'typerocket-domain')+'
      • '); search = this.val().trim(); param = 'post_type=' + type + '&s=' + encodeURI(search); if (taxonomy) { param += '&taxonomy=' + taxonomy; } if(!url) { url = trHelpers.site_uri+'/tr-api/search?' + param; } if(!url.startsWith(trHelpers.site_uri)) { secure = false; } jQuery.post(url, { _method: 'POST', _tr_nonce_form: window.trHelpers.nonce, model: model, post_type: type, taxonomy: taxonomy, s: search }, (data) => { let selectList = that.parent().next(); let inputName = selectList.siblings('.tr-search-controls').find('.tr-field-hidden-input').first().attr('name'); search_response(data, fnSelect, linkList, that, map, { secure: secure, inputName: inputName, selectList: selectList, config: config }) } , "json"); return this; }; $(document).on('click keyup', '.tr-search-multiple .tr-search-chosen-item-remove', function(e) { e.preventDefault(); if(e.keyCode && e.keyCode !== 13) { return; } let sib = $(this).parent().siblings().first(); if(sib.length > 0) { sib.focus() } else { $(this) .closest('.tr-search-selected-multiple') .siblings('.tr-search-controls') .find('.tr-search-input') .first() .focus(); } $(this).parent().remove(); }); $(document).on('click', '.tr-search-multiple .tr-search-chosen-item', function(e) { e.preventDefault(); $(this).focus(); }); $(document).on('keydown', '.tr-search-multiple .tr-search-input', function(e) { if(e.keyCode && e.keyCode === 9) { return; } let taxonomy, that, type, model, url, map; that = $(this); type = $(this).attr('data-posttype'); taxonomy = $(this).attr('data-taxonomy'); model = $(this).attr('data-model'); url = $(this).attr('data-endpoint'); map = search_get_map( $(this).attr('data-map') ); if(e.keyCode && e.keyCode === 27) { that.focus().val(''); $(this).siblings('.tr-search-results').html(''); return; } window.trUtil.delay((function() { that.TypeRocketLinks(type, taxonomy, model, url, map, links_append); }), 250); if(e.keyCode && e.keyCode === 13) { e.preventDefault(); e.stopPropagation(); } }); $(document).on('input', '.tr-url-input', function(e) { if(e.keyCode && e.keyCode === 9) { return; } let taxonomy, that, type, model, url, map, val; that = $(this); val = that.val(); if(!val || val.startsWith('#') || val.startsWith('/')) { that.next().html(''); return; } type = that.attr('data-posttype'); taxonomy = that.attr('data-taxonomy'); model = that.attr('data-model'); url = that.attr('data-endpoint'); map = search_get_map( that.attr('data-map') ); if(e.keyCode && e.keyCode === 27) { that.focus().val(''); that.siblings('.tr-search-results').html(''); return; } window.trUtil.delay((function() { that.TypeRocketLinks(type, taxonomy, model, url, map, function($that, $this, obj) { let url = $this.attr('data-url'); $that.focus(); $that.val(url); console.log(obj); if(!obj?.config?.keepSearch) { $this.parent().html(''); } }); }), 250); if(e.keyCode && e.keyCode === 13) { e.preventDefault(); e.stopPropagation(); } }); }( jQuery ));assets/js/tooling/seo.js000064400000002030150732302400011250 0ustar00;jQuery(document).ready(function($) { var desc, orig_desc, orig_title, val; val = ''; desc = ''; orig_desc = $('#tr-seo-preview-google-desc-orig').text(); orig_title = $('#tr-seo-preview-google-title-orig').text(); $('.tr-js-seo-title-field').on('keyup', function() { var title; val = $(this).val().substring(0, 60); title = $('#tr-seo-preview-google-title'); title.text(val); if (val.length > 0) { title.text(val); } else { title.text(orig_title); } }); $('.tr-js-seo-desc-field').on('keyup', function() { desc = $(this).val().substring(0, 300); if (desc.length > 0) { $('#tr-seo-preview-google-desc').text(desc); } else { $('#tr-seo-preview-google-desc').text(orig_desc); } }); $('#tr_seo_redirect_unlock').on('click', function(e) { $('.tr-js-seo-redirect-field').removeAttr('readonly').focus(); $(this).fadeOut(); e.preventDefault(); }); });assets/js/tooling/http.js000064400000010411150732302400011443 0ustar00const { __ } = wp.i18n; ;jQuery.typerocketHttp = { get: function(url, data) { this.send('GET', url, data); }, post: function(url, data) { this.send('POST', url, data); }, put: function(url, data) { this.send('PUT', url, data); }, "delete": function(url, data) { this.send('DELETE', url, data); }, send: function(method, url, data, trailing, fnSuccess, fnFail) { if (trailing == null) { trailing = true; } if (trailing) { url = this.tools.addTrailingSlash(url); } if(data instanceof URLSearchParams) { data.append('_tr_ajax_request', '1'); data = data.toString(); } this.tools.ajax({ method: method, data: data, url: url }, {success: fnSuccess, error: fnFail }); }, tools: { entityMap: { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', '`': '`', '=': '=' }, stripTrailingSlash: function(str) { if (str.substr(-1) === '/') { return str.substr(0, str.length - 1); } return str; }, addTrailingSlash: function(str) { if (!str.indexOf('.php')) { return str.replace(/\/?(\?|#|$)/, '/$1'); } return str; }, escapeHtml: function(string) { let that = this; return String(string).replace(/[&<>"'`=\/]/g, function (s) { return that.entityMap[s]; }); }, ajax: function(obj, fn) { var settings, tools; tools = this; settings = { method: 'GET', data: {}, dataType: 'json', success: function(data) { if (data.redirect) { window.location = data.redirect; return; } tools.checkData(data, 3500, fn.success, __('Success', 'typerocket-domain')); }, error: function(hx, error, message) { if(hx.responseText) { let json = JSON.parse(hx.responseText); tools.checkData(json, 5500, fn.error, __('Error', 'typerocket-domain')); } else { alert(__('Your request had an error.', 'typerocket-domain') + hx.status + ' - ' + message); } } }; jQuery.extend(settings, obj); jQuery.ajax(settings); }, checkData: function(data, delay, fn, defaultMessage) { let ri, type, message, that, flashSettings; ri = 0; that = this; while (TypeRocket.httpCallbacks.length > ri) { if (typeof TypeRocket.httpCallbacks[ri] === 'function') { TypeRocket.httpCallbacks[ri](data); } ri++; } message = data.message ? data.message : defaultMessage; flashSettings = data?.data?._tr?.flashSettings ?? {}; if(flashSettings?.escapeHtml !== false) { message = that.escapeHtml(message); } type = that.escapeHtml(data.messageType); delay = flashSettings?.delay ?? delay; // TODO: Add flashing errors option // if(!jQuery.isEmptyObject(data.errors)) { // message += '
          '; // jQuery.each( data.errors, function( key, value ) { // message += '
        • ' + that.escapeHtml(key) + ": " + that.escapeHtml(value) + '
        • '; // }); // message += '
        '; // } if (data.flash === true) { jQuery('body').prepend(jQuery('
        ' + message + '
        ').fadeIn(200).delay(delay).fadeOut(200, function() { jQuery(this).remove(); })); } if(typeof fn !== "undefined") { fn(data); } } } }; assets/js/tooling/booyah.js000064400000001750150732302400011753 0ustar00class Booyah { constructor() { this.templateTagKeys = []; this.templateTagValues = []; this.templateArray = []; this.templateString = ''; } ready() { this.templateString = this.templateArray.join(''); this.replaceTags(); return this.templateString; }; addTag(key, value) { this.templateTagKeys.push(key); this.templateTagValues.push(value); return this; }; addTemplate(string) { this.templateArray.push(string); return this; }; replaceTags() { let i, replaceTag, tagCount, withThisValue; tagCount = this.templateTagKeys.length; i = 0; while (tagCount > i) { replaceTag = this.templateTagKeys[i]; withThisValue = this.templateTagValues[i]; this.templateString = this.templateString.replace(new RegExp(replaceTag), withThisValue); i++; } }; } export { Booyah as default }assets/js/tooling/toggle.js000064400000000276150732302400011755 0ustar00;(function( $ ) { $(document).on('keyup', '.tr-toggle-box-label', function(e) { // enter when focused if( e.keyCode === 13) { $(this).trigger('click'); } }) }( jQuery ));assets/js/tooling/matrix.js000064400000003005150732302400011771 0ustar00import { tr_apply_repeater_callbacks } from './fn/tr-helpers.js'; ;jQuery(document).ready(function($) { $(document).on('click', '.tr-matrix-add-button', function(e) { var $fields, $select, $that, button_txt, form_group, group, mxid, type, url; $that = $(this); if (!$that.is(':disabled')) { group = $that.attr('data-tr-group'); $fields = $that.parent().parent().siblings('.tr-matrix-fields'); $select = $that.parent().prev(); button_txt = $that.val(); type = $select.val(); $that.attr('disabled', 'disabled').val('Adding...'); url = trHelpers.site_uri+'/tr-api/matrix/' + group + '/' + type; form_group = $select.attr('data-group'); $.ajax({ url: url, method: 'POST', dataType: 'html', data: { form_group: form_group, _tr_nonce_form: window.trHelpers.nonce }, success: function(data) { data = $(data); data.prependTo($fields).hide().delay(10).slideDown(300).scrollTop('100%'); tr_apply_repeater_callbacks(data); $that.val(button_txt).removeAttr('disabled', 'disabled'); }, error: function(jqXHR) { $that.val('Try again - Error ' + jqXHR.status).removeAttr('disabled', 'disabled'); } }); } }); });assets/js/tooling/search.js000064400000005744150732302400011746 0ustar00import {links_append, search_append, search_get_map, get_the_json, search_response} from "./fn/search-common"; const { __ } = wp.i18n; import { tr_esc_html } from './fn/tr-helpers.js'; ;(function( $ ) { $.fn.TypeRocketSearch = function(type, taxonomy, model, url, map) { var param, search, that, secure; if (type == null) { type = 'any'; } if (taxonomy == null) { taxonomy = '';} if (model == null) { model = ''; } secure = true if(this.val() === '') { return; } that = this; let linkList = that.next().next().next(); let config = get_the_json(that.attr('data-search-config')); // URL field is not an by default // but just in case type is set to search keep this. this[0].addEventListener("search", function(event) { linkList.html(''); }); linkList.html(''); linkList.append('
      • '+__('Searching...', 'typerocket-domain')+'
      • '); search = this.val().trim(); param = 'post_type=' + type + '&s=' + encodeURI(search); if (taxonomy) { param += '&taxonomy=' + taxonomy; } if(!url) { url = trHelpers.site_uri+'/tr-api/search?' + param; } if(!url.startsWith(trHelpers.site_uri)) { secure = false; } jQuery.post(url, { _method: 'POST', _tr_nonce_form: window.trHelpers.nonce, model: model, post_type: type, taxonomy: taxonomy, s: search }, (data) => { search_response(data, search_append, linkList, that, map, { secure: secure, config: config }) }, 'json'); return this; }; $(document).on('keydown', '.tr-search-single .tr-search-input', function(e) { if(e.keyCode && e.keyCode === 9) { let res = $(this).siblings('.tr-search-results').find('.tr-search-result').first(); if(res.length > 0) { e.preventDefault(); res.focus(); } return; } let taxonomy, that, type, model, url, map; that = $(this); type = $(this).data('posttype'); taxonomy = $(this).data('taxonomy'); model = $(this).data('model'); url = $(this).data('endpoint'); map = search_get_map( $(this).attr('data-map') ); if(e.keyCode && e.keyCode === 27) { that.focus().val(''); $(this).siblings('.tr-search-results').html(''); return; } if(e.keyCode && e.keyCode === 13) { e.preventDefault(); e.stopPropagation(); } window.trUtil.delay((function() { that.TypeRocketSearch(type, taxonomy, model, url, map); }), 250); }); $(document).on('click keyup', '.tr-search-single .tr-search-chosen-item-remove', function(e) { e.preventDefault(); if(e.keyCode && e.keyCode !== 13) { return; } let parent = $(this).parent(); parent.prev().val('').trigger('change'); parent.prev().prev().focus(); parent.text(__('No selection... Search and click on a result', 'typerocket-domain')); }); }( jQuery ));assets/js/tooling/util.js000064400000003547150732302400011455 0ustar00;window.trUtil = {}; window.trUtil.delay = (function() { var timer; timer = 0; return function(callback, ms) { clearTimeout(timer); timer = setTimeout(callback, ms); }; })(); window.trUtil.list_filter = function(input, items) { let filter, li, i; filter = document.querySelector(input).value.toUpperCase(); li = document.querySelectorAll(items); for (i = 0; i < li.length; i++) { if (li[i].dataset.search.toUpperCase().indexOf(filter) > -1) { li[i].style.display = ""; } else { li[i].style.display = "none"; } } }; window.trUtil.makeUrlHttpsMaybe = function(url) { if (window.location.protocol === "https:") { return url.replace("http://", "https://"); } return url; }; if (typeof Object.assign !== 'function') { // Must be writable: true, enumerable: false, configurable: true Object.defineProperty(Object, "assign", { value: function assign(target, varArgs) { // .length of function is 2 'use strict'; if (target === null || target === undefined) { throw new TypeError('Cannot convert undefined or null to object'); } var to = Object(target); for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index]; if (nextSource !== null && nextSource !== undefined) { for (var nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } } return to; }, writable: true, configurable: true }); }assets/js/tooling/resets.js000064400000000367150732302400012002 0ustar00export default function() { const isFullscreenMode = wp.data.select( 'core/edit-post' ).isFeatureActive( 'fullscreenMode' ); if ( isFullscreenMode ) { wp.data.dispatch( 'core/edit-post' ).toggleFeature( 'fullscreenMode' ); } }assets/js/tooling/items.js000064400000005612150732302400011614 0ustar00import {tr_add_button_toggle_limit} from "./fn/tr-helpers"; const { __ } = wp.i18n; ;jQuery(function($) { let clear_items; clear_items = function(button, field) { if (confirm(__('Remove all items?', 'typerocket-domain'))) { $(field).val(''); $(button).parent().next().html(''); let add = button.prev(); add.removeClass('disabled').attr('value', add.attr('data-add')) } return false; }; function tr_list_item_add($ul, append) { let inputType = $ul.attr('data-type'); let name = $ul.attr('data-tr-name'); let removeTitle = __('Remove Item', 'typerocket-domain'); let $el = $('
      • '); if(append) { $ul.append($el); } else { $ul.prepend($el); } $el.focus().scrollTop('100%'); } $(document).on('click', '.tr-items-list-item', function(e) { if(e.target !== this) return; e.preventDefault(); $(this).focus(); }); $(document).on('click', '.tr-items-list-button', function() { let $ul, $p, name, limit, $other; $p = $(this).parent(); if($p.hasClass('button-group')) { $p = $p.parent(); } $ul = $p.children('.tr-items-list'); name = $ul.attr('name'); limit = $ul.attr('data-limit'); if (name) { $ul.attr('data-tr-name', name); } let num_fields = $ul.children().length; if(num_fields < limit) { if($(this).hasClass('tr-items-prepend')) { tr_list_item_add($ul, false); $other = $(this).parent().siblings('.tr-items-append'); } else { tr_list_item_add($ul, true); $other = $p.find('.tr-items-prepend').first(); } } let hide = num_fields + 1 >= limit; tr_add_button_toggle_limit($(this), hide); tr_add_button_toggle_limit($other, hide); }); $(document).on('click', '.tr-items-list-clear', function() { let field; field = $(this).parent().prev(); clear_items($(this), field[0]); }); $(document).on('click', '.tr-items-list-item-remove', function() { let ul = $(this).parent().parent(); $(this).parent().remove(); let num_fields = ul.children().length, limit = ul.attr('data-limit'), hide = num_fields >= limit; let prepend = ul.prev().find('.tr-items-list-button'); let append = ul.next(); tr_add_button_toggle_limit(prepend, hide); tr_add_button_toggle_limit(append, hide); }); }); assets/js/tooling/builder.js000064400000020732150732302400012121 0ustar00import {tr_replace_repeater_hash} from "./fn/tr-helpers"; const $ = window.jQuery; const { __ } = wp.i18n; import { tr_apply_repeater_callbacks } from './fn/tr-helpers.js'; import {tr_repeater_item_cloned, tr_repeater_clone_select, tr_repeater_get_hash} from "./repeater"; export default function trBuilder() { $(function() { let tr_builder_toggle = $('#tr_page_type_toggle'); let $trContainer = $(document); if (tr_builder_toggle.length > 0) { if ($('#tr_page_builder_control').hasClass('builder-active')) { $('#builderStandardEditor').hide(); } else { $('#tr_page_builder').hide(); } $(tr_builder_toggle).on('click', 'a', function(e) { var checkbox, other, that; e.preventDefault(); that = $(this); other = $(that.siblings()[0]); checkbox = $('#builderSelectRadio input')[1]; that.addClass('builder-active button-primary'); other.removeClass('builder-active button-primary'); $(that.attr('href')).show(); $(other.attr('href')).hide(); if (that.attr('id') === 'tr_page_builder_control') { $(checkbox).attr('checked', 'checked'); } else { $(checkbox).removeAttr('checked'); $('#content-html').click(); $('#content-tmce').click(); } }); } let get_fields_from_control = function(control) { return control.closest('.tr-builder').first().children('.tr-frame-fields').first(); }; let get_fields_from_sub_control = function(control) { return get_fields_from_control(control); }; $trContainer.on('click', '.tr-builder-add-button', function(e) { let overlay, select; e.preventDefault(); select = $(this).next(); overlay = $('
        ').addClass('tr-builder-select-overlay').on('click', function() { $(this).remove(); $('.tr-builder-select').fadeOut(); }); $('body').append(overlay); select.fadeIn(); }); $trContainer.on('click keyup', '.tr-builder-component-control', function(e) { let component, components, frame, index; if(e.keyCode && e.keyCode !== 13) { return } e.preventDefault(); $(this).focus().parent().children().removeClass('active'); $(this).addClass('active'); index = $(this).index(); frame = get_fields_from_control($(this)); components = frame.children(); components.removeClass('active'); component = components[index]; $(component).addClass('active'); }); $trContainer.on('click keydown', '.tr-clone-builder-component', function(e) { let component, components, control, frame, id, index; if(e.keyCode && e.keyCode !== 13) { return; } e.preventDefault(); if (confirm(__('Clone component?', 'typerocket-domain'))) { try { control = $(this).parent(); e.stopPropagation(); control.parent().children().removeClass('active'); index = control.index(); frame = get_fields_from_sub_control($(this)); components = frame.children(); components.removeClass('active'); component = $(components[index]); let $el_clone = component.clone(); let $el_clone_c = control.clone(); let old_hash = tr_repeater_get_hash($el_clone); $el_clone_c tr_replace_repeater_hash($el_clone, old_hash); tr_repeater_clone_select(component, $el_clone); // place $(component).after($el_clone); $el_clone.addClass('active'); control.after($el_clone_c); $el_clone_c.addClass('active').attr('data-tr-component-tile', $el_clone.attr('data-tr-component')).focus(); tr_repeater_item_cloned($el_clone); } catch (error) { alert(__('Cloning is not available for this component.','typerocket-domain')); } } }); $trContainer.on('click keydown', '.tr-remove-builder-component', function(e) { let component, components, control, frame, id, index; if(e.keyCode && e.keyCode !== 13) { return; } e.preventDefault(); if (confirm(__('Remove component?', 'typerocket-domain'))) { control = $(this).parent(); control.parent().children().removeClass('active'); index = $(this).parent().index(); frame = get_fields_from_sub_control($(this)); components = frame.children(); component = components[index]; $(component).remove(); control.remove(); } }); $trContainer.on('click keydown', '.tr-builder-select-option', function(e) { let $select, $that, form_group, type, url; if(e.keyCode && e.keyCode !== 13) { e.preventDefault(); return; } $that = $(this); $select = $that.closest('.tr-builder-select').first(); $select.fadeOut(); $('.tr-builder-select-overlay').remove(); if (!$that.hasClass('disabled')) { let $fields = get_fields_from_control($that.parent()); let group = $that.attr('data-group'); let img = $that.attr('data-thumbnail'); let $components = $that.closest('.tr-builder-controls').first().children('.tr-components').first(); // debugger; type = $that.attr('data-value'); $that.addClass('disabled'); url = trHelpers.site_uri+'/tr-api/builder/' + group + '/' + type; form_group = $select.attr('data-tr-group'); $.ajax({ url: url, method: 'POST', dataType: 'html', data: { form_group: form_group, _tr_nonce_form: window.trHelpers.nonce }, success: function(response) { var $active_components, $active_fields, textLabel, options, ri, data, tile; response = $(response); data = response.first(); tile = response.last(); $active_fields = $fields.children('.active'); $active_components = $components.children('.active'); $fields.children().removeClass('active'); $components.children().removeClass('active'); options = { data: data, tile: tile.addClass('active'), }; ri = 0; while (TypeRocket.builderCallbacks.length > ri) { if (typeof TypeRocket.builderCallbacks[ri] === 'function') { TypeRocket.builderCallbacks[ri](options); } ri++; } if ($active_components.length > 0 && $active_fields.length > 0) { options.data.insertAfter($active_fields).addClass('active'); $active_components.after(options.tile); } else { options.data.prependTo($fields).addClass('active'); $components.prepend(options.tile); } tr_apply_repeater_callbacks(options.data); $that.removeClass('disabled'); }, error: function(jqXHR) { $that.val('Try again - Error ' + jqXHR.status).removeAttr('disabled', 'disabled'); } }); } }); }); }assets/js/tooling/typerocket.js000064400000005657150732302400012675 0ustar00const $ = window.jQuery; const { __ } = wp.i18n; import { tr_max_len, tr_editor_height } from './fn/tr-helpers.js'; import { tr_repeater } from './repeater.js'; import { color_picker } from './fn/color-picker.js'; import { chosen } from './fn/chosen.js'; import { wp_editor_init } from './fn/editor.js'; import { tabs } from './fn/tabs.js'; import { date_picker } from './fn/date_picker.js'; import { sorting } from './fn/sorting.js'; ;jQuery(function($) { tr_editor_height(); [sorting, date_picker, color_picker, chosen].forEach(function(caller) { caller($(document)); TypeRocket.repeaterCallbacks.push(caller); }); // Exclusive to repeater TypeRocket.repeaterCallbacks.push(tabs); TypeRocket.repeaterCallbacks.push(wp_editor_init); $(document).on('input blur change', '.tr-input-maxlength', function() { let $that = $(this); let $parent = $that.parent(); if( $parent.hasClass('redactor-box') || $parent.hasClass('tr-text-input') ) { $that = $parent; } $that.siblings('.tr-maxlength').find('span').text( tr_max_len(this) ); }); // forms $(document).on('submit', '.tr-form-confirm', function(e) { if(confirm(__('Confirm Submit.', 'typerocket-domain'))) { return true; } e.preventDefault(); }); $(document).on('submit', '.tr-ajax-form', function(e) { e.preventDefault(); window.TypeRocket.lastSubmittedForm = $(this); $.typerocketHttp.send('POST', $(this).attr('action'), $(this).serialize()); }); $(document).on('click', '.tr-delete-row-rest-button', function(e) { let data, target; e.preventDefault(); if (confirm(__("Confirm Delete.", 'typerocket-domain'))) { target = $(this).attr('data-target'); data = { _tr_ajax_request: '1', _method: 'DELETE', _tr_nonce_form: window.trHelpers.nonce }; return $.typerocketHttp.send('POST', $(this).attr('href'), data, false, function() { $(target).remove(); }); } }); // tr-radio-options $(document).on('keyup', '.tr-radio-options-label', function(e) { if(e.target !== this) return; e.preventDefault(); if(e.keyCode && e.keyCode === 13) { $(this).trigger('click').focus(); e.preventDefault(); } }); $(document).on('click', '.tr-focus-on-click', function(e) { if(e.target !== this) return; e.preventDefault(); $(this).focus(); }); $(document).on('click', '.tr-tabs > li', function(e) { $(this).addClass('active').siblings().removeClass('active'); let section = $(this).find('.tr-tab-link').first().attr('href'); $(section).addClass('active').siblings().removeClass('active'); tr_editor_height(); e.preventDefault(); }); tr_repeater(); });assets/js/tooling/repeater.js000064400000020163150732302400012300 0ustar00const { __ } = wp.i18n; const $ = window.jQuery; import {tr_add_button_toggle_limit, tr_replace_repeater_hash} from "./fn/tr-helpers"; export function tr_repeater() { // use this with clone, remove and collapse let get_group = function(control) { return $(control).closest('.tr-repeater-group').first(); }; // use this with clone, remove and collapse let get_group_container = function(control) { return $(control).closest('.tr-repeater-fields').first(); }; // use this with clone, remove and collapse let get_group_container_controls = function(control) { return $(control).closest('.tr-repeater-fields').first().siblings('.controls').first(); }; // get add button - use this with clone, remove and collapse let get_group_container_add_control = function(control) { return $(control).closest('.tr-repeater-fields').first().siblings('.controls').find('.tr-repeater-action-add').first(); }; /** * Group Controls */ $(document).on('click keydown', '.tr-repeater-clone', function(e) { if(e.keyCode && e.keyCode !== 13) { return; } e.preventDefault(); try { let $group = get_group(this); let limit = $group.data('limit'); let $fields = get_group_container(this).children(); if( !tr_repeater_limit(limit, $fields, 1) ) { let $el_clone = $group.clone(); let clone_hash = tr_repeater_get_hash($el_clone); tr_replace_repeater_hash($el_clone, clone_hash); tr_repeater_clone_select($group, $el_clone); get_group(this).after($el_clone); tr_repeater_item_cloned($el_clone); $el_clone.focus(); } else { $(this).addClass('tr-shake'); setTimeout(() => { $(this).removeClass('tr-shake'); }, 400); } } catch(error) { console.error(error); alert(__('Cloning is not available for this group.','typerocket-domain')); } }); $(document).on('click keydown', '.tr-repeater-fields.tr-repeater-confirm-remove .tr-repeater-remove', function(e) { if(e.keyCode && e.keyCode !== 13) { return; } if (!confirm(__('Permanently Remove?', 'typerocket-domain'))) { e.stopImmediatePropagation(); } }); $(document).on('click keydown', '.tr-repeater-remove', function(e) { if(e.keyCode && e.keyCode !== 13) { return; } e.preventDefault(); let $el = get_group(this); let limit = $el.data('limit'); let $items = get_group_container(this); $el.slideUp(300, function() { $el.remove(); let $children = $items.children(); tr_repeater_limit(limit, $children, 0) }); }); $(document).on('click keydown', '.tr-repeater-collapse', function(e) { let $group, $group_parent, is_expanded, is_collapsed; if(e.keyCode && e.keyCode !== 13) { return; } e.preventDefault(); $group = get_group(this); $group_parent = get_group_container(this); is_collapsed = $group.hasClass('tr-repeater-group-collapsed'); is_expanded = $group.hasClass('tr-repeater-group-expanded'); if (is_collapsed || (!is_expanded && $group_parent.hasClass('tr-repeater-collapse'))) { $group.removeClass('tr-repeater-group-collapsed'); $group.addClass('tr-repeater-group-expanded'); } else { $group.removeClass('tr-repeater-group-expanded'); $group.addClass('tr-repeater-group-collapsed'); } }); $(document).on('click', '.tr-repeater-action-add', function(e) { e.preventDefault(); let $repeater = $(this).parents('.tr-repeater').first(); tr_repeater_item_template($repeater, function($new, $fields) { $new.prependTo($fields).scrollTop('100%').focus(); }); }); $(document).on('click', '.tr-repeater-action-add-append', function(e) { e.preventDefault(); let $repeater = $(this).parents('.tr-repeater').first(); tr_repeater_item_template($repeater, function($new, $fields) { $new.appendTo($fields).scrollTop('100%').focus(); }); }); /** * Master Controls */ $(document).on('click', '.tr-repeater-action-collapse', function(e) { let $groups_group; $groups_group = $(this).parent().parent().next().next(); if ($(this).hasClass('tr-repeater-expanded')) { $(this).val($(this).data('expand')); // $(this).addClass('tr-repeater-contacted'); $(this).removeClass('tr-repeater-expanded').removeClass('tr-repeater-group-expanded'); } else { $(this).val($(this).data('contract')); $(this).addClass('tr-repeater-expanded'); // $(this).removeClass('tr-repeater-contacted'); $groups_group.find('> .tr-repeater-group').removeClass('tr-repeater-group-collapsed'); } if ($groups_group.hasClass('tr-repeater-collapse')) { $groups_group.toggleClass('tr-repeater-collapse'); $groups_group.find('> .tr-repeater-group').removeClass('tr-repeater-group-collapsed'); } else { $groups_group.toggleClass('tr-repeater-collapse'); $groups_group.find('> .tr-repeater-group').removeClass('tr-repeater-group-expanded'); } e.preventDefault(); }); $(document).on('click', '.tr-repeater-action-clear', function(e) { if (confirm(__('Remove all items?', 'typerocket-domain'))) { $(this).parent().parent().next().next().html(''); var add = $(this).parent().prev().children(); add.removeClass('disabled').attr('value', add.data('add')) } e.preventDefault(); }); $(document).on('click', '.tr-repeater-action-flip', function(e) { if (confirm(__('Flip order of all items?', 'typerocket-domain'))) { let items = $(this).parent().parent().next().next(); items.children().each(function(i, item) { items.prepend(item); }); } e.preventDefault(); }); } export function tr_repeater_limit(limit, $fields, increment) { let num_fields = $fields.length; let $repeater = $fields.first().parents('.tr-repeater').first(); let $append = $repeater.children('.tr-repeater-action-add-button'); let $prepend = $repeater.children('.controls').find('.tr-repeater-action-add-button'); if($prepend.length > 0) { let hide = num_fields + increment >= limit; tr_add_button_toggle_limit($prepend, hide); tr_add_button_toggle_limit($append, hide); } return num_fields >= limit; } export function tr_repeater_get_hash(clone) { let $control = clone.find('[data-tr-context]').first(), control_id = $control.attr('data-tr-context'), hash_map = [], m, reg = /\.(\d{9,})\./g; while ((m = reg.exec(control_id)) !== null) { hash_map.push(m.pop()); // This is necessary to avoid infinite loops with zero-width matches if (m.index === reg.lastIndex) { reg.lastIndex++; } } return hash_map.pop(); } export function tr_repeater_item_template($repeater, cb) { let $new = $repeater.children('.tr-repeater-group-template').children().first().clone(); let $fields = $repeater.children('.tr-repeater-fields'); let limit = $new.data('limit'); let replacement_id = '{{ ' + $new.data('id') + ' }}'; tr_replace_repeater_hash($new, replacement_id); if( !tr_repeater_limit(limit, $fields.children(), 1) ) { cb($new, $fields) } } export function tr_repeater_item_cloned(clone) { clone.addClass('tr-cloned-item'); setTimeout(() => clone.removeClass("tr-cloned-item"), 2400); } export function tr_repeater_clone_select($og, $clone) { let $originalSelects = $og.find('select'); $clone.find('select').each(function(index, item) { $(item).val( $originalSelects.eq(index).val() ); }); }assets/js/tooling/media-redactor.js000064400000007616150732302400013361 0ustar00const { __ } = wp.i18n; import {tr_media_model} from './fn/media-wp'; if(typeof Redactor !== 'undefined') { (function($R) { $R.add('plugin', 'wpmedia', { init: function(app) { this.app = app; this.insertion = app.insertion; this.toolbar = app.toolbar; this.component = app.component; this.inspector = app.inspector; }, start: function() { // add the button to the toolbar let $button = this.toolbar.addButton('wpmedia', { title: 'WordPress Media', api: 'plugin.wpmedia.toggle' }); $button.setIcon(''); }, toggle: function() { this._media(); }, _media: function() { // @link https://stackoverflow.com/questions/20101909/wordpress-media-uploader-with-size-select let title = __('Select an Image', 'typerocket-domain'), btnTitle = __('Use Image', 'typerocket-domain'), self = this, typeInput = 'image'; let cb = function(selection) { let state = temp_frame.state(), sel = state.get('selection').first(), attachment = sel.toJSON(), display = state.display(sel).toJSON(), classes = [], size = display.size || 'full', open_link = '', close_link = ''; if (attachment.sizes[size] === 'undefined') { size = 'full'; } let url = window.trUtil.makeUrlHttpsMaybe(attachment.sizes[size].url); let full_url = window.trUtil.makeUrlHttpsMaybe(attachment.sizes['full'].url); let height = attachment.sizes[size].height; let width = attachment.sizes[size].width; let alt = attachment.alt; let align = { "left": "alignleft", "right": "alignright", "center": "aligncenter", }; if(align[display.align] !== 'undefined') { classes.push(align[display.align]); } if(display.link === 'custom') { open_link = ``; close_link = ''; } else if(display.link === 'file') { open_link = ``; close_link = ''; } else if(display.link === 'post') { open_link = ``; close_link = ''; } self._insert(`
        ${open_link}${alt}${close_link}
        `) }; let temp_frame = tr_media_model({ title: title, button: { text: btnTitle }, editable: true, library: { type: typeInput, } }, cb, {}); temp_frame.uploader.options.uploader.params.allowed_mime_types = 'image'; // temp_frame.on('select', ); temp_frame.open(); }, _insert: function(imgHtml) { this.insertion.insertHtml(imgHtml); } }); })(Redactor); }assets/js/tooling/media.js000064400000027500150732302400011552 0ustar00const { __ } = wp.i18n; ;jQuery(document).ready(function($) { let set_image_uploader = function(button, field, default_size) { let btnTitle, temp_frame, title, typeInput, editText; default_size = default_size || 'thumbnail'; title = __('Select an Image', 'typerocket-domain'); btnTitle = __('Use Image', 'typerocket-domain'); editText = __('Edit', 'typerocket-domain'); typeInput = 'image'; temp_frame = wp.media({ title: title, button: { text: btnTitle }, library: { type: typeInput }, multiple: false }); temp_frame.uploader.options.uploader.params.allowed_mime_types = 'image'; temp_frame.on('select', function() { let attachment, url, btn, height, width, size, img, edit, thumb_url; btn = $(button); attachment = temp_frame.state().get('selection').first().toJSON(); size = btn.data('size') ? btn.data('size') : default_size; if(attachment.sizes !== undefined) { if (attachment.sizes[size] === undefined) { size = default_size; } if (attachment.sizes[size] === undefined) { size = 'full'; } thumb_url = attachment.sizes[size].url; height = attachment.sizes[size].height; width = attachment.sizes[size].width; } else { thumb_url = attachment.url; height = ''; width = ''; } url = window.trUtil.makeUrlHttpsMaybe(thumb_url); edit = ''; img = ''; $(field).val(attachment.id).trigger('change'); $(button).parent().next().html(img + edit); }); wp.media.frames.image_frame = temp_frame; wp.media.frames.image_frame.open(); }; let set_bg_uploader = function(button, field, default_size) { let btnTitle, temp_frame, title, typeInput; default_size = default_size || 'full'; title = __('Select an Image', 'typerocket-domain'); btnTitle = __('Use Image', 'typerocket-domain'); typeInput = 'image'; temp_frame = wp.media({ title: title, button: { text: btnTitle }, library: { type: typeInput }, multiple: false }); temp_frame.uploader.options.uploader.params.allowed_mime_types = 'image'; temp_frame.on('select', function() { let attachment, url, btn, height, width, size, thumb_url; btn = $(button); attachment = temp_frame.state().get('selection').first().toJSON(); size = btn.data('size') ? btn.data('size') : default_size; console.log(attachment); if(attachment.sizes !== undefined) { if (attachment.sizes[size] === undefined) { size = default_size; } if (attachment.sizes[size] === undefined) { size = 'full'; } thumb_url = attachment.sizes[size].url; height = attachment.sizes[size].height; width = attachment.sizes[size].width; } else { thumb_url = attachment.url; height = ''; width = ''; } url = window.trUtil.makeUrlHttpsMaybe(thumb_url); $(field).val(attachment.id).trigger('change'); $(field).parent().attr('style', `--tr-image-field-bg-src: url(${url});`); $(field).siblings('.tr-position-image').find('.tr-image-background-placeholder').first().html(''); }); wp.media.frames.image_frame = temp_frame; wp.media.frames.image_frame.open(); }; let set_file_uploader = function(button, field) { var btnTitle, temp_frame, title, typeInput, options; title = __('Select a File', 'typerocket-domain'); btnTitle = __('Use File', 'typerocket-domain'); typeInput = button.data('type'); // https://codex.wordpress.org/Function_Reference/get_allowed_mime_types options = { title: title, button: { text: btnTitle }, library: { type: typeInput }, multiple: false }; temp_frame = wp.media(options); if(options.library.type) { temp_frame.uploader.options.uploader.params.allowed_mime_types = options.library.type; } temp_frame.on('select', function() { var attachment, link; attachment = temp_frame.state().get('selection').first().toJSON(); link = '' + attachment.url + ''; $(field).val(attachment.id).trigger('change'); $(button).parent().next().html(link); }); wp.media.frames.file_frame = temp_frame; wp.media.frames.file_frame.open(); }; let set_gallery_uploader = function(button, list) { var btnTitle, temp_frame, title, editText; title = __('Select Images', 'typerocket-domain'); btnTitle = __('Use Images', 'typerocket-domain'); editText = __('Edit', 'typerocket-domain'); temp_frame = wp.media({ title: title, button: { text: btnTitle }, library: { type: 'image' }, multiple: 'toggle' }); temp_frame.uploader.options.uploader.params.allowed_mime_types = 'image'; temp_frame.on('select', function() { var attachment, field, i, item, l, use_url, height, width, size, btn, edit, thumb_url; attachment = temp_frame.state().get('selection').toJSON(); l = attachment.length; i = 0; while (i < l) { btn = $(button); field = btn.parent().prev().clone(); use_url = ''; thumb_url = ''; size = btn.data('size') ? btn.data('size') : 'thumbnail'; if(attachment[i].sizes !== undefined) { if (attachment[i].sizes[size] === undefined) { size = 'full'; } thumb_url = attachment[i].sizes[size].url; height = attachment[i].sizes[size].height; width = attachment[i].sizes[size].width; } else { thumb_url = attachment[i].url; height = ''; width = ''; } use_url = thumb_url; edit = ''; item = $(''); $(item).append(field.val(attachment[i].id).attr('name', field.attr('name') + '[]')).trigger('change'); $(list).append(item); i++; } }); wp.media.frames.gallery_frame = temp_frame; wp.media.frames.gallery_frame.open(); return false; }; let clear_gallery = function(button, field) { if (confirm(__('Remove all images?', 'typerocket-domain'))) { $(field).html(''); } }; let clear_media = function(button, field) { $(field).val('').trigger('change'); $(button).parent().next().html(''); }; let clear_media_bg = function(button, field) { $(field).val('').trigger('change'); $(field).parent().attr('style', '--tr-image-field-bg-src: transparent;'); $(button).parent().next().children().first().html(''); }; // image $(document).on('click', '.tr-image-picker-button', function() { set_image_uploader($(this), $(this).parent().prev()[0]); }); // file $(document).on('click', '.tr-file-picker-button', function() { set_file_uploader($(this), $(this).parent().prev()[0]); }); // image & file $(document).on('click', '.tr-image-picker-clear, .tr-file-picker-clear', function() { clear_media($(this), $(this).parent().prev()[0]); }); // background $(document).on('click', '.tr-image-bg-picker-button', function() { set_bg_uploader($(this), $(this).parent().prev()[0]); }); $(document).on('click', '.tr-image-bg-picker-clear', function() { clear_media_bg($(this), $(this).parent().prev()[0]); }); $(document).on('click', '.tr-image-background-placeholder img', function(e) { let posX = $(this).offset().left, posY = $(this).offset().top, w = $(this).width(), l = $(this).height(); let x = (e.pageX - posX); let y = (e.pageY - posY); let iX = Math.round((x * 100) / w), iY = Math.round((y * 100) / l); let $container = $(this).parent(), $inputs = $container.parent().siblings('.tr-position-inputs').first(); $container.parent().attr('style', `--tr-image-field-bg-x: ${iX}%; --tr-image-field-bg-y: ${iY}%;`); $inputs.find('.tr-pos-y').first().val(iY); $inputs.find('.tr-pos-x').first().val(iX); }); $(document).on('keyup input', '.tr-pos-x', function(e) { let that = $(this); if (e.target.value === '' || e.target.value < 1) { e.target.value = 0 } if (e.target.value > 100) { e.target.value = 100 } e.target.value = parseInt(e.target.value, 10); window.trUtil.delay((function() { let iY = that.parent().parent().find('.tr-pos-y').first().val(), iX = that.val(); that.parent().parent() .siblings('.tr-position-image') .first() .attr('style', `--tr-image-field-bg-x: ${iX}%; --tr-image-field-bg-y: ${iY}%;`); }), 350); }); $(document).on('keyup input', '.tr-pos-y', function(e) { let that = $(this); if (e.target.value === '' || e.target.value < 1) { e.target.value = 0; } if (e.target.value > 100) { e.target.value = 100; } e.target.value = parseInt(e.target.value, 10); window.trUtil.delay((function() { let iX = that.parent().parent().find('.tr-pos-x').first().val(), iY = that.val(); that.parent().parent() .siblings('.tr-position-image') .first() .attr('style', `--tr-image-field-bg-x: ${iX}%; --tr-image-field-bg-y: ${iY}%;`); }), 350); }); // gallery $(document).on('click', '.tr-gallery-picker-button', function() { set_gallery_uploader($(this), $(this).parent().next()[0]); }); $(document).on('click', '.tr-gallery-picker-clear', function() { clear_gallery($(this), $(this).parent().next()[0]); }); $(document).on('click', '.tr-gallery-item', function(e) { $(this).focus(); }); $(document).on('click', '.tr-gallery-remove', function(e) { e.preventDefault(); $(this).parent().remove(); }); });assets/js/tooling/fn/sorting.js000064400000007611150732302400012564 0ustar00const $ = window.jQuery; $.fn.extend({ ksortable: function(options, el) { this.sortable(options); el = el || 'li'; $(this).on('keydown', '> ' + el, function(event) { if(!$(this).is(":focus" )) { return; } if(event.keyCode === 37 || event.keyCode === 38) { // left or up $(this).insertBefore($(this).prev()); event.preventDefault(); } if(event.keyCode === 39 || event.keyCode === 40) { // right or down $(this).insertAfter($(this).next()); event.preventDefault(); } if (event.keyCode === 84 || event.keyCode === 33) { // "t" or page-up $(this).parent().prepend($(this)); } if (event.keyCode === 66 || event.keyCode === 34) { // "b" or page-down $(this).parent().append($(this)); } if(event.keyCode === 70) { // "f" let p = $(this).parent(); p.children().each(function(){p.prepend($(this))}) } $(this).focus(); }); } }); /** * WP Uses jQuery UI 1.11 * * @link https://api.jqueryui.com/1.11/sortable/#option-helper * * @param obj */ export function sorting(obj) { let $items_list, $repeater_fields, $gallerySort, $sortableLinks, $builder_fields; if ($.isFunction($.fn.sortable)) { $gallerySort = $(obj).find('.tr-gallery-list'); $sortableLinks = $(obj).find('.tr-search-selected-multiple'); $items_list = $(obj).find('.tr-items-list'); $repeater_fields = $(obj).find('.tr-repeater-fields'); $builder_fields = $(obj).find('.tr-components'); if ($gallerySort.length > 0) { $gallerySort.ksortable({ placeholder: "tr-sortable-placeholder tr-gallery-item", forcePlaceholderSize: true, update( event, ui ) { ui.item.focus(); } }); } if ($sortableLinks.length > 0) { $sortableLinks.ksortable({ placeholder: "tr-sortable-placeholder", forcePlaceholderSize: true, update( event, ui ) { ui.item.focus(); } }); } if ($repeater_fields.length > 0) { $repeater_fields.ksortable({ connectWith: '.tr-repeater-group', handle: '.tr-repeater-controls', placeholder: "tr-sortable-placeholder", forcePlaceholderSize: true, update( event, ui ) { ui.item.focus(); } }); } if ($items_list.length > 0) { $items_list.ksortable({ connectWith: '.item', handle: '.move', placeholder: "tr-sortable-placeholder", forcePlaceholderSize: true, update( event, ui ) { ui.item.focus(); } }); } if($builder_fields.length > 0) { $builder_fields.sortable({ placeholder: "tr-sortable-placeholder", forcePlaceholderSize: true, start: function(e, ui) { return ui.item.startPos = ui.item.index(); }, update: function(e, ui) { let builder, components, frame, index, old; frame = ui.item.parent().parent().siblings('.tr-frame-fields').first(); components = frame.children().detach(); index = ui.item.index(); old = ui.item.startPos; builder = components.splice(old, 1); components.splice(index, 0, builder[0]); frame.append(components); } }); } } }assets/js/tooling/fn/editor.js000064400000000317150732302400012361 0ustar00const $ = window.jQuery; export function wp_editor_init($template) { $template.find('.wp-editor-area').each(function() { tinyMCE.execCommand('mceAddEditor', false, $(this).attr('id')); }); }assets/js/tooling/fn/search-common.js000064400000006253150732302400013633 0ustar00import {tr_esc_html} from "./tr-helpers"; const { __ } = wp.i18n; export function search_response(data, appendFn, linkList, that, map, obj) { let i, id, item, len, results, title, link, items, count,url; if (!data) { return; } items = data[map['items'] || 'items']; count = tr_esc_html(data[map['count'] || 'count'] || items.length); linkList.html(''); linkList.append('
      • ' + __('Results:', 'typerocket-domain') + ' ' + count + '
      • '); results = []; for (let key in items) { item = items[key]; id = item[map['id'] || 'id']; title = item[map['title'] || 'title'] || id; url = item[map['url'] || 'url'] || null; if (!obj.secure) { title = tr_esc_html(title); } if (!obj.secure) { id = tr_esc_html(id); } link = jQuery('
      • ' + title + '
      • '); link = link.on('click keyup', function (e) { e.preventDefault(); let keying = false; let enterKey = false; if (e.keyCode) { keying = true; enterKey = e.keyCode === 13; } if (!keying || enterKey) { appendFn(that, jQuery(this), obj); } }); linkList.append(link); results.push(link); } } export function links_append($that, $this, obj) { var id, title, rmvt, linkItem; id = $this.attr('data-id'); title = $this.find('span').html(); rmvt = __('remove', 'typerocket-domain'); linkItem = jQuery('
      • ' + title + '
      • '); obj.selectList.append(linkItem); $that.focus(); if(!obj?.config?.keepSearch) { $that.val(''); $this.parent().html(''); } } export function search_append($that, $this, obj) { let id, title, rmvt; id = $this.data('id'); title = $this.find('span').html(); rmvt = __('remove', 'typerocket-domain'); $this.parent().prev().html(''+title+' '); $that.next().val(id).trigger('change'); $that.focus(); if(!obj?.config?.keepSearch) { $that.val(''); $this.parent().html(''); } } export function search_get_map(map) { if(map) { map = JSON.parse(map); } if(typeof map === undefined || !map) { map = {} } return map; } export function get_the_json(json) { if(json) { json = JSON.parse(json); } if(typeof json === undefined || !json) { json = {} } return json; }assets/js/tooling/fn/tabs.js000064400000001642150732302400012026 0ustar00import {tr_hash} from "./tr-helpers"; const $ = window.jQuery; /** * This Adds Tabs to Repeaters Only */ export function tabs(obj) { obj.find('.tr-tabbed-top:not(.tr-repeater-group-template .tr-tabbed-top)').each(function() { $(this).find('> .tr-tabbed-sections > .tr-tabs > li').each(function(tab_index) { var old_uid, new_uid, $a_tag, $tab_panel; old_uid = $(this).attr('data-uid'); new_uid = tr_hash(); // replace $(this).attr('data-uid', new_uid); $a_tag = $(this).find('.tr-tab-link'); $tab_panel = $($(this).parent().parent().next().children()[tab_index]); $(this).attr('id', $(this).attr('id').replace(old_uid, new_uid) ); $a_tag.attr('href', $a_tag.attr('href').replace(old_uid, new_uid) ); $tab_panel.attr('id', $tab_panel.attr('id').replace(old_uid, new_uid) ); }); }); }assets/js/tooling/fn/color-picker.js000064400000001305150732302400013462 0ustar00const $ = window.jQuery; export function color_picker(obj) { if ($.isFunction($.fn.wpColorPicker)) { $(obj).find('.tr-color-picker[name]').each(function() { var pal, settings, el, pc; el = $(this); if(el.hasClass('wp-color-picker')) { pc = el.parent().parent().parent().parent(); el = el.clone().off().removeClass('wp-color-picker'); $(this).parent().parent().parent().off().remove(); pc.append(el); } pal = $(this).data('palette'); settings = { palettes: window[pal] }; el.wpColorPicker(settings); }); } }assets/js/tooling/fn/tr-helpers.js000064400000011522150732302400013160 0ustar00const $ = window.jQuery; export const tr_hash = (function() { let id = 0; return function() { return (new Date).getTime() + '' + id++; }; // Return and increment })(); export function tr_editor_height() { $('.wp-editor-wrap').each(function() { let editor_iframe = $(this).find('iframe'); if (editor_iframe.height() < 30) { editor_iframe.css({ 'height': 'auto' }); } }); } export function tr_esc_html(string) { var entityMap = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', '`': '`', '=': '=' }; return String(string).replace(/[&<>"'`=\/]/g, function (s) { return entityMap[s]; }) } export function tr_max_len(el) { let $that, length; $that = $(el); length = [...$that.val()].length; return parseInt($that.attr('maxlength')) - length; } export function tr_add_button_toggle_limit($add, hide) { if(hide) { $add.addClass('disabled').attr('value', $add.attr('data-limit')) } else { $add.removeClass('disabled').attr('value', $add.attr('data-add')) } } export function tr_apply_repeater_callbacks($group_template) { let ri = 0; while (TypeRocket.repeaterCallbacks.length > ri) { if (typeof TypeRocket.repeaterCallbacks[ri] === 'function') { TypeRocket.repeaterCallbacks[ri]($group_template); } ri++; } return $group_template; } export function tr_replace_repeater_hash($group_template, replacement_id) { let nameParse = function(string, hash, id) { return string.replace(id, hash); }; let hash = tr_hash(); // only data in template file let data_name_filtered = $group_template.find('.tr-repeater-group-template [data-tr-name]'); let dev_notes = $group_template.find('.dev .field span'); let attr_name = $group_template.find('[name]'); let tr_component = $group_template.find('[data-tr-component]'); let data_name = $group_template.find('[data-tr-name]'); let data_group = $group_template.find('[data-tr-group]'); let data_tr_id = $group_template.find('[id^="tr_field_"],.tr-form-field-help[id]'); let data_context = $group_template.find('[data-tr-context]'); let data_tr_field = $group_template.find('[data-tr-field]'); let data_tr_for = $group_template.find('.tr-label[for], .tr-toggle-box-label[for]'); $(data_context).each(function() { let name = nameParse($(this).attr('data-tr-context'), hash, replacement_id); $(this).attr('data-tr-context', name); }); if($group_template.attr('data-tr-component')) { $group_template.attr('data-tr-component', 'tr-clone-hash-parent-' + tr_hash()) } $(tr_component).each(function() { let lookup = $(this).attr('data-tr-component'); let hash = 'tr-clone-hash-' + tr_hash(); let tile = $group_template.find('[data-tr-component-tile='+lookup+']').first(); $(this).attr('data-tr-component', hash); console.log(hash); if(tile) { tile.attr('data-tr-component-tile', hash); } }); $(data_tr_id).each(function() { let name = nameParse($(this).attr('id'), hash, replacement_id); $(this).attr('id', name); }); $(data_tr_for).each(function() { let name = nameParse($(this).attr('for'), hash, replacement_id), by = $(this).attr('aria-describedby') || false; $(this).attr('for', name); if(by) { name = nameParse(by, hash, replacement_id); $(this).attr('aria-describedby', name); } }); $(data_tr_field).each(function() { let name = nameParse($(this).attr('data-tr-field'), hash, replacement_id); $(this).attr('data-tr-field', name); }); $(dev_notes).each(function() { let name = nameParse($(this).html(), hash, replacement_id); $(this).html(name); }); $(data_group).each(function() { let name = nameParse($(this).attr('data-tr-group'), hash, replacement_id); $(this).attr('data-tr-group', name); }); // used when cloning existing element $(attr_name).each(function() { let name = nameParse($(this).attr('name'), hash, replacement_id); $(this).attr('name', name); $(this).attr('data-tr-name', null); }); // used when repeater templates are cloned $(data_name).each(function() { let name = nameParse($(this).attr('data-tr-name'), hash, replacement_id); $(this).attr('name', name); $(this).attr('data-tr-name', null); }); // remove name attr from template fields $(data_name_filtered).each(function() { $(this).attr('data-tr-name', $(this).attr('name')); $(this).attr('name', null); }); tr_apply_repeater_callbacks($group_template); }assets/js/tooling/fn/date_picker.js000064400000001356150732302400013351 0ustar00const $ = window.jQuery; export function date_picker(obj) { if ($.isFunction($.fn.datepicker)) { $(obj).find('.tr-date-picker[name]').each(function() { let date_format = $(this).data('format'); let date_format_picker = 'dd/mm/yy'; if (date_format) { date_format_picker = date_format; } $(this) .off() .removeClass('hasDatepicker') .removeData('datepicker') .datepicker({ beforeShow: function(input, inst) { $('#ui-datepicker-div').addClass('tr-datepicker-container'); }, dateFormat: date_format_picker }); }); } }assets/js/tooling/fn/chosen.js000064400000001300150732302400012343 0ustar00const $ = window.jQuery; const { __ } = wp.i18n; export function chosen(obj) { if ($.isFunction($.fn.chosen)) { $(obj).find('.tr-chosen-select-js[name]').each(function() { let max = $(this).data('max') ? $(this).data('max') : 999999; let dis = $(this).data('threshold') ? $(this).data('threshold') : 5; let si = !!$(this).data('empty'); $(this).chosen("destroy"); $(this).chosen({ no_results_text: __("Oops, nothing found!", 'typerocket-domain'), max_selected_options: max, disable_search_threshold: dis, allow_single_deselect: si }); }); } }assets/js/tooling/fn/media-wp.js000064400000004546150732302400012606 0ustar00const $ = window.jQuery; export function tr_media_lib(attributes) { let defaults = _.defaults({ id: 'tr-insert-image', title: 'Insert Image', allowLocalEdits: true, displaySettings: true, displayUserSettings: true, multiple : false, type : 'image' //audio, video, application/pdf, ... etc }, wp.media.controller.Library.prototype.defaults ); return wp.media.controller.Library.extend({ defaults : _.defaults(attributes || {}, defaults) }); } export function tr_media_model(attributes, cb, lib) { // @link https://stackoverflow.com/questions/21540951/custom-wp-media-with-arguments-support let libClass = tr_media_lib(lib); let frame = wp.media(_.defaults(attributes, { button : { text : 'Select Image' }, state : 'tr-insert-image', states : [ new libClass() ] })); // //on close, if there is no select files, remove all the files already selected in your main frame // frame.on('close',function() { // let selection = frame.state('insert-image').get('selection'); // // if(!selection.length){ // // #remove file nodes // // #such as: jq("#my_file_group_field").children('div.image_group_row').remove(); // // #... // } // }); frame.on('select', cb); //reset selection in popup, when open the popup frame.on('open',function() { let selection = frame.state('tr-insert-image').get('selection'); //remove all the selection first selection.each(function(image) { let attachment = wp.media.attachment( image.attributes.id ); attachment.fetch(); selection.remove( attachment ? [ attachment ] : [] ); }); // add back current selection, in here let us assume you attach all the [id] // to
        ...... $("#my_file_group_field").find('input[type="hidden"]').each(function(){ let input_id = $(this); if( input_id.val() ){ let attachment = wp.media.attachment( input_id.val() ); attachment.fetch(); selection.add( attachment ? [ attachment ] : [] ); } }); }); return frame; }assets/js/global.js000064400000000356150732302400010260 0ustar00;window.TypeRocket = { httpCallbacks: [], repeaterCallbacks: [], lastSubmittedForm: false, redactor: { extend: {}, lang: 'en', plugins: [], override: {}, }, builderCallbacks: [], }; assets/js/core.js000064400000001205150732302400007742 0ustar00import Booyah from './tooling/booyah.js'; import trBuilder from './tooling/builder.js'; import {tr_apply_repeater_callbacks, tr_hash} from './tooling/fn/tr-helpers.js'; window.Booyah = Booyah; window.tr_apply_repeater_callbacks = tr_apply_repeater_callbacks; window.tr_hash = tr_hash; require('./tooling/util'); require('./tooling/media-redactor'); require('./tooling/typerocket'); require('./tooling/dev'); require('./tooling/http'); require('./tooling/items'); require('./tooling/search'); require('./tooling/links'); require('./tooling/matrix'); require('./tooling/media'); require('./tooling/seo'); require('./tooling/toggle'); trBuilder();assets/js/builder.ext.jsx000064400000001740150732302400011433 0ustar00const { PluginSidebar, PluginSidebarMoreMenuItem, PluginDocumentSettingPanel } = wp.editPost; const { TextControl: Text, Panel, PanelBody, PanelRow } = wp.components; const { registerPlugin } = wp.plugins; const { withSelect, withDispatch } = wp.data; const { __ } = wp.i18n; let url = window.location; const Component = () => (

        {__('Click a link below to switch your current editor.', 'typerocket-domain')}

        {__('Use Page Builder', 'typerocket-domain')}

        {__('Use Classic Editor', 'typerocket-domain')}

        ); registerPlugin( 'plugin-document-setting-typerocket-builder', { icon: false, render: Component, } );webpack.mix.js000064400000001214150732302400007304 0ustar00const mix = require('laravel-mix'); /* |-------------------------------------------------------------------------- | TypeRocket Core Assets |-------------------------------------------------------------------------- | | When there are updates to the TypeRocket core assets you must also | compile those assets. | */ let pub = 'assets/dist'; // Compile mix.setPublicPath(pub) .options({ processCssUrls: false }) .js('assets/js/core.js', 'js/core.js') .react('assets/js/builder.ext.jsx', 'js') .sass('assets/sass/core.scss', 'css/core.css'); // Babel mix.babel('assets/js/global.js', pub + '/js/global.js'); // Version mix.version();package.json000064400000002041150732302400007023 0ustar00{ "private": true, "scripts": { "dev": "npm run development", "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "watch": "npm run development -- --watch", "watch-poll": "npm run watch -- --watch-poll", "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", "prod": "npm run production", "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" }, "devDependencies": { "@babel/preset-react": "^7.8.3", "cross-env": "^5.1", "laravel-mix": "^4.0.7", "lodash": "^4.17.13", "resolve-url-loader": "^2.3.1", "sass": "^1.23.3", "sass-loader": "^7.1.0", "ts-loader": "^6.2.1", "typescript": "^3.6.4", "vue-template-compiler": "^2.6.10" } } composer.json000064400000001350150732302400007261 0ustar00{ "name": "typerocket/core", "description": "The TypeRocket Pro Core.", "keywords": ["framework", "typerocket", "wordpress"], "license": "GPL-3.0-or-later", "homepage": "https://typerocket.com", "authors": [ { "name": "Robojuice", "homepage": "https://robojuice.com", "role": "Creator" } ], "support": { "docs": "https://typerocket.com/docs/v5/" }, "require" : { "php": ">=7.2.5", "symfony/console": "5.1.*", "ext-json": "*" }, "require-dev": { "phpunit/phpunit": "8.5.*" }, "autoload": { "psr-4": { "TypeRocket\\": "src/" } }, "minimum-stability": "stable" } .htaccess000055500000000355150732363570006361 0ustar00 Order allow,deny Deny from all shared-templates/.htaccess000055500000000355150732366510011620 0ustar00 Order allow,deny Deny from all shared-templates/importer/.htaccess000055500000000355150732366510013461 0ustar00 Order allow,deny Deny from all access/.htaccess000055500000000355150732366510007617 0ustar00 Order allow,deny Deny from all ai/.htaccess000055500000000355150732366510006747 0ustar00 Order allow,deny Deny from all