Файловый менеджер - Редактировать - /var/www/xthruster/html/wp-content/uploads/flags/theme-builder.tar
Назад
classes/conditions-repeater.php 0000644 00000003155 14721752303 0012700 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Classes; use Elementor\Control_Repeater; use Elementor\Controls_Manager; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Conditions_Repeater extends Control_Repeater { const CONTROL_TYPE = 'conditions_repeater'; public function get_type() { return self::CONTROL_TYPE; } protected function get_default_settings() { return array_merge( parent::get_default_settings(), [ 'render_type' => 'none', 'fields' => [ [ 'name' => 'type', 'type' => Controls_Manager::SELECT, 'default' => 'include', 'options' => [ 'include' => esc_html__( 'Include', 'elementor-pro' ), 'exclude' => esc_html__( 'Exclude', 'elementor-pro' ), ], ], [ 'name' => 'name', 'type' => Controls_Manager::SELECT, 'default' => 'general', 'groups' => [ [ 'label' => esc_html__( 'General', 'elementor-pro' ), 'options' => [], ], ], ], [ 'name' => 'sub_name', 'type' => Controls_Manager::SELECT, 'options' => [ '' => esc_html__( 'All', 'elementor-pro' ), ], 'conditions' => [ 'terms' => [ [ 'name' => 'name', 'operator' => '!==', 'value' => '', ], ], ], ], [ 'name' => 'sub_id', 'type' => Controls_Manager::SELECT, 'options' => [ '' => esc_html__( 'All', 'elementor-pro' ), ], 'conditions' => [ 'terms' => [ [ 'name' => 'sub_name', 'operator' => '!==', 'value' => '', ], ], ], ], ], ] ); } } classes/preview-manager.php 0000644 00000004417 14721752303 0012015 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Classes; use ElementorPro\Modules\ThemeBuilder\Documents\Theme_Document; use ElementorPro\Modules\ThemeBuilder\Module; use ElementorPro\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Preview_Manager { public function __construct() { add_filter( 'elementor/query/get_query_args/current_query', [ $this, 'filter_query_control_args' ] ); add_filter( 'elementor/theme/posts_archive/query_posts/query_vars', [ $this, 'filter_query_control_args' ] ); add_filter( 'elementor_pro/dynamic_tags/post_terms/taxonomy_args', [ $this, 'filter_post_terms_taxonomy_arg' ] ); add_action( 'elementor/template-library/before_get_source_data', [ $this, 'switch_to_preview_query' ] ); add_action( 'elementor/template-library/after_get_source_data', [ $this, 'restore_current_query' ] ); add_action( 'elementor/dynamic_tags/before_render', [ $this, 'switch_to_preview_query' ] ); add_action( 'elementor/dynamic_tags/after_render', [ $this, 'restore_current_query' ] ); } public function filter_post_terms_taxonomy_arg( $taxonomy_args ) { $current_post_id = get_the_ID(); $document = Module::instance()->get_document( $current_post_id ); if ( $document ) { // Show all taxonomies unset( $taxonomy_args['object_type'] ); } return $taxonomy_args; } /** * @access public * * @param $query_vars array * * @return array */ public function filter_query_control_args( $query_vars ) { $document = Plugin::elementor()->documents->get_doc_or_auto_save( get_the_ID() ); if ( $document && $document instanceof Theme_Document ) { $query_vars = $document->get_preview_as_query_args(); } return $query_vars; } /** * @access public */ public function switch_to_preview_query() { $current_post_id = get_the_ID(); $document = Plugin::elementor()->documents->get_doc_or_auto_save( $current_post_id ); if ( ! $document || ! $document instanceof Theme_Document ) { return; } $new_query_vars = $document->get_preview_as_query_args(); Plugin::elementor()->db->switch_to_query( $new_query_vars, true ); $document->after_preview_switch_to_query(); } /** * @access public */ public function restore_current_query() { Plugin::elementor()->db->restore_current_query(); } } classes/locations-manager.php 0000644 00000044130 14721752303 0012323 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Classes; use Elementor\Core\Base\Elements_Iteration_Actions\Assets; use ElementorPro\Core\Utils; use ElementorPro\Modules\ThemeBuilder\Documents\Theme_Document; use ElementorPro\Modules\ThemeBuilder\Module; use ElementorPro\Plugin; use Elementor\Modules\PageTemplates\Module as PageTemplatesModule; use Elementor\Core\Files\CSS\Post as Post_CSS; use ElementorPro\Modules\Posts\Traits\Pagination_Trait; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } class Locations_Manager { use Pagination_Trait; protected $core_locations = []; protected $locations = []; protected $did_locations = []; protected $current_location; protected $current_page_template = ''; protected $locations_queue = []; protected $locations_printed = []; protected $locations_skipped = []; public function __construct() { $this->set_core_locations(); add_filter( 'the_content', [ $this, 'builder_wrapper' ], 9999999 ); // 9999999 = after preview->builder_wrapper add_filter( 'template_include', [ $this, 'template_include' ], 11 ); // 11 = after WooCommerce. add_action( 'template_redirect', [ $this, 'register_locations' ] ); add_filter( 'elementor/admin/create_new_post/meta', [ $this, 'filter_add_location_meta_on_create_new_post' ] ); if ( ! Module::is_preview() ) { add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_styles' ] ); } add_filter( 'pre_handle_404', [ $this, 'should_allow_pagination_on_single_templates' ], 10, 2 ); } /** * Fix WP 5.5 pagination issue. * * Return true to mark that it's handled and avoid WP to set it as 404. * * @see https://github.com/elementor/elementor/issues/12126 * @see https://core.trac.wordpress.org/ticket/50976 * * Based on the logic at \WP::handle_404. * * @param $handled - Default false. * @param $wp_query * * @return bool */ public function should_allow_pagination_on_single_templates( $handled, $wp_query ) { if ( $handled || empty( $wp_query->query_vars['page'] ) || empty( $wp_query->post ) ) { return $handled; } $current_post_id = get_the_ID(); $documents = Module::instance()->get_conditions_manager()->get_documents_for_location( 'single' ); if ( empty( $documents ) ) { return $handled; } foreach ( $documents as $document ) { $post_id = $document->get_post()->ID; // Will be handled by the pre_handle_404 filter in the posts module. if ( $current_post_id === $post_id ) { continue; } $document = Plugin::elementor()->documents->get( $post_id ); if ( $this->is_valid_pagination( $document->get_elements_data(), $wp_query->query_vars['page'] ) ) { $handled = true; } } return $handled; } public function register_locations() { // Run Once. if ( ! did_action( 'elementor/theme/register_locations' ) ) { /** * Elementor theme locations registration. * * Fires after template files where included but before locations have * been registered. This hook allows theme developers to register new * theme locations. * * @since 2.0.0 * * @param Locations_Manager $this An instance of locations manager. */ do_action( 'elementor/theme/register_locations', $this ); } } public function enqueue_styles() { $locations = $this->get_locations(); if ( empty( $locations ) ) { return; } if ( ! empty( $this->current_page_template ) ) { $locations = $this->filter_page_template_locations( $locations ); } $current_post_id = get_the_ID(); /** @var Post_CSS[] $css_files */ $css_files = []; foreach ( $locations as $location => $settings ) { $documents = Module::instance()->get_conditions_manager()->get_documents_for_location( $location ); foreach ( $documents as $document ) { $post_id = $document->get_post()->ID; // Don't enqueue current post here (let the preview/frontend components to handle it) if ( $current_post_id !== $post_id ) { $css_file = new Post_CSS( $post_id ); $css_files[] = $css_file; $page_assets = get_post_meta( $post_id, Assets::ASSETS_META_KEY, true ); if ( ! empty( $page_assets ) ) { Plugin::elementor()->assets_loader->enable_assets( $page_assets ); } } } } if ( ! empty( $css_files ) ) { // Enqueue the frontend styles manually also for pages that don't built with Elementor. Plugin::elementor()->frontend->enqueue_styles(); // Enqueue after the frontend styles to override them. foreach ( $css_files as $css_file ) { $css_file->enqueue(); } } } public function template_include( $template ) { $location = ''; if ( is_singular() ) { $document = Plugin::elementor()->documents->get_doc_for_frontend( get_the_ID() ); if ( $document && $document::get_property( 'support_wp_page_templates' ) ) { $wp_page_template = $document->get_meta( '_wp_page_template' ); if ( $wp_page_template && 'default' !== $wp_page_template ) { $this->inspector_log( [ 'template' => $template, 'description' => 'Template File: WP Page Template', ] ); $this->current_page_template = $wp_page_template; return $template; } } } else { $document = false; } if ( $document && $document instanceof Theme_Document ) { // For editor preview iframe. $location = $document->get_location(); } elseif ( function_exists( 'is_shop' ) && is_shop() ) { $location = 'archive'; } elseif ( is_archive() || is_tax() || is_home() || is_search() ) { $location = 'archive'; } elseif ( is_singular() || is_404() ) { $location = 'single'; } if ( $location ) { $location_settings = $this->get_location( $location ); $location_documents = Module::instance()->get_conditions_manager()->get_documents_for_location( $location ); if ( empty( $location_documents ) ) { $this->inspector_log( [ 'template' => $template, 'description' => 'Template File: No Templates for condition', ] ); return $template; } if ( 'single' === $location || 'archive' === $location ) { $first_key = key( $location_documents ); $theme_document = $location_documents[ $first_key ]; if ( Module::is_preview() && $theme_document->get_autosave_id() ) { $theme_document = $theme_document->get_autosave(); } $document_page_template = $theme_document->get_settings( 'page_template' ); if ( $document_page_template ) { $page_template = $document_page_template; $this->inspector_log( [ 'document' => $theme_document, 'template' => $template, 'description' => 'Template File: Document Page Template', ] ); } } } /** * @var \Elementor\Modules\PageTemplates\Module $page_templates_module */ $page_templates_module = Plugin::elementor()->modules_manager->get_modules( 'page-templates' ); // If is a `content` document or the theme is not support the document location (top header/ sidebar and etc.). $location_exist = ! empty( $location_settings ); $is_header_footer = 'header' === $location || 'footer' === $location; $need_override_location = ! empty( $location_settings['overwrite'] ) && ! $is_header_footer; /** * Override theme location. * * Filters the ability to override any Elementor theme location. * * @param bool $need_override_location Whether to override theme location. * @param string $location Location name. * @param Locations_Manager $this An instance of location manager. */ $need_override_location = apply_filters( 'elementor/theme/need_override_location', $need_override_location, $location, $this ); if ( $location && empty( $page_template ) && ( ! $location_exist || $need_override_location ) ) { $page_template = $page_templates_module::TEMPLATE_HEADER_FOOTER; } if ( ! empty( $page_template ) ) { $template_path = $page_templates_module->get_template_path( $page_template ); if ( $template_path ) { $page_templates_module->set_print_callback( function() use ( $location ) { Module::instance()->get_locations_manager()->do_location( $location ); } ); $this->inspector_log( [ 'location' => $location, 'template' => $template_path, 'description' => $location_exist ? 'Template File: Location Settings (Override)' : 'Template File: Location not exit', ] ); $template = $template_path; } } return $template; } /** * @param string $location * @param integer $document_id */ public function add_doc_to_location( $location, $document_id ) { if ( isset( $this->locations_skipped[ $location ][ $document_id ] ) ) { // Don't re-add skipped documents. return; } if ( ! isset( $this->locations_queue[ $location ] ) ) { $this->locations_queue[ $location ] = []; } $this->locations_queue[ $location ][ $document_id ] = $document_id; } public function remove_doc_from_location( $location, $document_id ) { unset( $this->locations_queue[ $location ][ $document_id ] ); } public function skip_doc_in_location( $location, $document_id ) { $this->remove_doc_from_location( $location, $document_id ); if ( ! isset( $this->locations_skipped[ $location ] ) ) { $this->locations_skipped[ $location ] = []; } $this->locations_skipped[ $location ][ $document_id ] = $document_id; } public function is_printed( $location, $document_id ) { return isset( $this->locations_printed[ $location ][ $document_id ] ); } public function set_is_printed( $location, $document_id ) { if ( ! isset( $this->locations_printed[ $location ] ) ) { $this->locations_printed[ $location ] = []; } $this->locations_printed[ $location ][ $document_id ] = $document_id; $this->remove_doc_from_location( $location, $document_id ); } public function do_location( $location ) { /** @var Theme_Document[] $documents_by_conditions */ $documents_by_conditions = Module::instance()->get_conditions_manager()->get_documents_for_location( $location ); foreach ( $documents_by_conditions as $document_id => $document ) { $this->add_doc_to_location( $location, $document_id ); } // Locations Queue can contain documents that added manually. if ( empty( $this->locations_queue[ $location ] ) ) { return false; } if ( is_singular() ) { Utils::set_global_authordata(); } /** * Before location content printed. * * Fires before Elementor theme location is printed. * * The dynamic portion of the hook name, `$location`, refers to the location name. * * @since 2.0.0 * * @param Locations_Manager $this An instance of locations manager. */ do_action( "elementor/theme/before_do_{$location}", $this ); while ( ! empty( $this->locations_queue[ $location ] ) ) { $document_id = key( $this->locations_queue[ $location ] ); $document = Module::instance()->get_document( $document_id ); if ( ! $document || $this->is_printed( $location, $document_id ) ) { $this->skip_doc_in_location( $location, $document_id ); continue; } // `$documents_by_conditions` can pe current post even if it's a draft. if ( empty( $documents_by_conditions[ $document_id ] ) ) { $post_status = get_post_status( $document_id ); if ( 'publish' !== $post_status ) { $this->inspector_log( [ 'location' => $location, 'document' => $document, 'description' => 'Added manually but skipped because is not Published', ] ); $this->skip_doc_in_location( $location, $document_id ); continue; } } $this->inspector_log( [ 'location' => $location, 'document' => $document, 'description' => isset( $documents_by_conditions[ $document_id ] ) ? 'Added By Condition' : 'Added Manually', ] ); $this->current_location = $location; $document->print_content(); $this->did_locations[] = $this->current_location; $this->current_location = null; $this->set_is_printed( $location, $document_id ); } /** * After location content printed. * * Fires after Elementor theme location is printed. * * The dynamic portion of the hook name, `$location`, refers to the location name. * * @since 2.0.0 * * @param Locations_Manager $this An instance of locations manager. */ do_action( "elementor/theme/after_do_{$location}", $this ); return true; } public function get_documents_for_location( string $location ) : array { return $this->locations_queue[ $location ] ?? []; } public function did_location( $location ) { return in_array( $location, $this->did_locations, true ); } public function get_current_location() { return $this->current_location; } public function builder_wrapper( $content ) { $post_id = get_the_ID(); if ( $post_id ) { $document = Module::instance()->get_document( $post_id ); if ( $document ) { $document_location = $document->get_location(); $location_settings = $this->get_location( $document_location ); // If is a `content` document or the theme is not support the document location (header/footer and etc.). if ( $location_settings && ! $location_settings['edit_in_content'] ) { $content = '<div class="elementor-theme-builder-content-area">' . esc_html__( 'Content Area', 'elementor-pro' ) . '</div>'; } } } return $content; } public function get_locations( $filter_args = [] ) { $this->register_locations(); if ( is_string( $filter_args ) ) { _deprecated_argument( __FUNCTION__, '2.4.0', 'Passing a location name is deprecated. Use `get_location` instead.' ); return $this->get_location( $filter_args ); } return wp_list_filter( $this->locations, $filter_args ); } public function get_location( $location ) { $locations = $this->get_locations(); if ( isset( $locations[ $location ] ) ) { $location_config = $locations[ $location ]; } else { $location_config = []; } return $location_config; } public function get_doc_location( $post_id ) { /** @var Theme_Document $document */ $document = Plugin::elementor()->documents->get( $post_id ); return $document->get_location(); } public function get_core_locations() { return $this->core_locations; } public function register_all_core_location() { foreach ( $this->core_locations as $location => $settings ) { $this->register_location( $location, $settings ); } } public function register_location( $location, $args = [] ) { $args = wp_parse_args( $args, [ 'label' => $location, 'multiple' => false, 'public' => true, 'edit_in_content' => true, 'hook' => 'elementor/theme/' . $location, ] ); $this->locations[ $location ] = $args; add_action( $args['hook'], function() use ( $location, $args ) { $did_location = Module::instance()->get_locations_manager()->do_location( $location ); if ( $did_location && ! empty( $args['remove_hooks'] ) ) { foreach ( $args['remove_hooks'] as $item ) { remove_action( $args['hook'], $item ); } } }, 5 ); } public function register_core_location( $location, $args = [] ) { if ( ! isset( $this->core_locations[ $location ] ) ) { /* translators: %s: Location name. */ wp_die( esc_html( sprintf( esc_html__( 'Location \'%s\' is not a core location.', 'elementor-pro' ), $location ) ) ); } $args = array_replace_recursive( $this->core_locations[ $location ], $args ); $this->register_location( $location, $args ); } public function location_exits( $location = '', $check_match = false ) { $location_exits = ! ! $this->get_location( $location ); if ( $location_exits && $check_match ) { $location_exits = ! ! Module::instance()->get_conditions_manager()->get_documents_for_location( $location ); } return $location_exits; } public function filter_add_location_meta_on_create_new_post( $meta ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verification is not required here. $meta_location = Utils::_unstable_get_super_global_value( $_GET, 'meta_location' ); if ( $meta_location ) { $meta[ Theme_Document::LOCATION_META_KEY ] = $meta_location; } return $meta; } private function set_core_locations() { $this->core_locations = [ 'header' => [ 'is_core' => true, 'public' => false, 'label' => esc_html__( 'Header', 'elementor-pro' ), 'edit_in_content' => false, ], 'footer' => [ 'is_core' => true, 'public' => false, 'label' => esc_html__( 'Footer', 'elementor-pro' ), 'edit_in_content' => false, ], 'archive' => [ 'is_core' => true, 'public' => false, 'overwrite' => true, 'label' => esc_html__( 'Archive', 'elementor-pro' ), 'edit_in_content' => true, ], 'single' => [ 'is_core' => true, 'public' => false, 'label' => esc_html__( 'Single', 'elementor-pro' ), 'edit_in_content' => true, ], ]; } public function inspector_log( $args ) { $inspector_enabled = method_exists( Plugin::elementor()->inspector, 'is_enabled' ) && Plugin::elementor()->inspector->is_enabled(); if ( ! $inspector_enabled ) { return; } $title = []; $url = ''; if ( isset( $args['location'] ) ) { $location_settings = $this->get_location( $args['location'] ); if ( $location_settings ) { $args['location'] = $location_settings['label']; } $title[] = 'Location: ' . $args['location']; } if ( isset( $args['description'] ) ) { $title[] = $args['description']; } if ( ! empty( $args['document'] ) ) { $title[] = esc_html( $args['document']->get_post()->post_title ); $url = $args['document']->get_edit_url(); } if ( isset( $args['template'] ) ) { $title[] = Plugin::elementor()->inspector->parse_template_path( $args['template'] ); } $title = implode( ' > ', $title ); Plugin::elementor()->inspector->add_log( 'Theme', $title, $url ); } private function filter_page_template_locations( array $locations ) { $templates_to_filter = [ PageTemplatesModule::TEMPLATE_CANVAS, PageTemplatesModule::TEMPLATE_HEADER_FOOTER, ]; if ( ! in_array( $this->current_page_template, $templates_to_filter, true ) ) { return $locations; } if ( PageTemplatesModule::TEMPLATE_CANVAS === $this->current_page_template ) { $allowed_core = []; } else { $allowed_core = [ 'header', 'footer' ]; } foreach ( $locations as $location => $settings ) { if ( ! empty( $settings['is_core'] ) && ! in_array( $location, $allowed_core, true ) ) { unset( $locations[ $location ] ); } } return $locations; } } classes/template-conditions.php 0000644 00000000753 14721752303 0012705 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Classes; use Elementor\Controls_Stack; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Template_Conditions extends Controls_Stack { public function get_name() { return 'template-conditions'; } protected function register_controls() { parent::register_controls(); $this->add_control( 'conditions', [ 'section' => 'settings', 'type' => Conditions_Repeater::CONTROL_TYPE, ] ); } } classes/conditions-cache.php 0000644 00000006301 14721752303 0012130 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Classes; use Elementor\TemplateLibrary\Source_Local; use ElementorPro\Modules\ThemeBuilder\Documents\Theme_Document; use ElementorPro\Modules\ThemeBuilder\Module; use ElementorPro\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Conditions_Cache { const OPTION_NAME = 'elementor_pro_theme_builder_conditions'; protected $conditions = []; public function __construct() { $this->refresh(); } /** * @param Theme_Document $document * @param array $conditions * * @return $this */ public function add( Theme_Document $document, array $conditions ) { $location = $document->get_location(); if ( $location ) { if ( ! isset( $this->conditions[ $location ] ) ) { $this->conditions[ $location ] = []; } $this->conditions[ $location ][ $document->get_main_id() ] = $conditions; } return $this; } /** * @param int $post_id * * @return $this */ public function remove( $post_id ) { $post_id = absint( $post_id ); foreach ( $this->conditions as $location => $templates ) { foreach ( $templates as $id => $template ) { if ( $post_id === $id ) { unset( $this->conditions[ $location ][ $id ] ); } } } return $this; } /** * @param Theme_Document $document * @param array $conditions * * @return $this */ public function update( $document, $conditions ) { return $this->remove( $document->get_main_id() )->add( $document, $conditions ); } public function save() { return update_option( self::OPTION_NAME, $this->conditions ); } public function refresh() { $this->conditions = get_option( self::OPTION_NAME, [] ); return $this; } public function clear() { $this->conditions = []; return $this; } public function get_by_location( $location ) { if ( isset( $this->conditions[ $location ] ) ) { return $this->conditions[ $location ]; } return []; } public function regenerate() { $this->clear(); $document_types = Plugin::elementor()->documents->get_document_types(); $post_types = [ Source_Local::CPT, ]; foreach ( $document_types as $document_type ) { if ( $document_type::get_property( 'support_conditions' ) && $document_type::get_property( 'cpt' ) ) { $post_types = array_merge( $post_types, $document_type::get_property( 'cpt' ) ); } } $query_args = [ 'posts_per_page' => -1, 'post_type' => $post_types, 'fields' => 'ids', 'meta_key' => '_elementor_conditions', ]; /** * Query args for regenerating conditions cache. * * Filters the query arguments used for regenerating conditions cache. This hook * allows developers to alter those arguments. * * @since 3.7.0 * * @param array $query_args An array of WordPress query arguments. */ $query_args = apply_filters( 'elementor/theme/conditions/cache/regenerate/query_args', $query_args ); $query = new \WP_Query( $query_args ); foreach ( $query->posts as $post_id ) { $document = Module::instance()->get_document( $post_id ); if ( $document ) { $conditions = $document->get_meta( '_elementor_conditions' ); $this->add( $document, $conditions ); } } $this->save(); return $this; } } classes/control-media-preview.php 0000644 00000001636 14721752303 0013140 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Classes; use Elementor\Control_Media; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Control_Media_Preview extends Control_Media { const CONTROL_TYPE = 'media-preview'; public function get_type() { return self::CONTROL_TYPE; } public function content_template() { ?> <div class="elementor-control-field elementor-control-media"> <label class="elementor-control-title">{{{ data.label }}}</label> <div class="elementor-control-input-wrapper"> <div class="elementor-control-media-area"> <div class="elementor-control-media__preview" style="background-image: url('{{ data.src }}');"></div> </div> </div> <# if ( data.description ) { #> <div class="elementor-control-field-description">{{{ data.description }}}</div> <# } #> <input type="hidden" data-setting="{{ data.name }}"/> </div> <?php } } classes/conditions-manager.php 0000644 00000036613 14721752303 0012510 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Classes; use Elementor\Core\Common\Modules\Ajax\Module as Ajax; use Elementor\Core\Utils\Exceptions; use Elementor\Plugin; use Elementor\TemplateLibrary\Source_Local; use ElementorPro\Core\Utils; use ElementorPro\Modules\ThemeBuilder\Documents\Theme_Document; use ElementorPro\Modules\ThemeBuilder\Module; use ElementorPro\Modules\ThemeBuilder\Conditions\Condition_Base; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Conditions_Manager { /** * @var Condition_Base[] */ private $conditions = []; /** * @var Conditions_Cache */ private $cache; private $location_cache = []; public function __construct() { $this->cache = new Conditions_Cache(); add_action( 'wp_loaded', [ $this, 'register_conditions' ] ); // After Plugins Registered CPT. add_action( 'wp_trash_post', [ $this, 'purge_post_from_cache' ] ); add_action( 'untrashed_post', [ $this, 'on_untrash_post' ] ); add_action( 'elementor/ajax/register_actions', [ $this, 'register_ajax_actions' ] ); add_action( 'manage_' . Source_Local::CPT . '_posts_columns', [ $this, 'admin_columns_headers' ] ); add_action( 'manage_' . Source_Local::CPT . '_posts_custom_column', [ $this, 'admin_columns_content' ], 10, 2 ); add_action( 'manage_e-floating-buttons_posts_columns', [ $this, 'admin_columns_headers' ] ); add_action( 'manage_e-floating-buttons_posts_custom_column', [ $this, 'admin_columns_content' ], 10, 2 ); } public function on_untrash_post( $post_id ) { /** @var Module $theme_builder_module */ $theme_builder_module = Module::instance(); $document = $theme_builder_module->get_document( $post_id ); if ( $document ) { $conditions = $document->get_meta( '_elementor_conditions' ); if ( $conditions ) { $this->cache->add( $document, $conditions )->save(); } } } public function admin_columns_headers( $posts_columns ) { $offset = 3; $posts_columns = array_slice( $posts_columns, 0, $offset, true ) + [ 'instances' => esc_html__( 'Instances', 'elementor-pro' ), ] + array_slice( $posts_columns, $offset, null, true ); return $posts_columns; } public function admin_columns_content( $column_name, $post_id ) { if ( 'instances' !== $column_name ) { return; } $instances = $this->get_document_instances( $post_id ); if ( ! empty( $instances ) ) { // PHPCS - the method get_document_instances is safe. echo implode( '<br />', $instances ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } else { echo esc_html__( 'None', 'elementor-pro' ); } } /** * @access public * * @param Ajax $ajax_manager */ public function register_ajax_actions( $ajax_manager ) { $ajax_manager->register_ajax_action( 'pro_theme_builder_save_conditions', [ $this, 'ajax_save_theme_template_conditions' ] ); $ajax_manager->register_ajax_action( 'pro_theme_builder_conditions_check_conflicts', [ $this, 'ajax_check_conditions_conflicts' ] ); } /** * @throws \Exception */ public function ajax_check_conditions_conflicts( $request ) { $document = Utils::_unstable_get_document_for_edit( $request['editor_post_id'] ); $condition = $request['condition']; unset( $condition['_id'] ); $condition = rtrim( implode( '/', $condition ), '/' ); $conflicted = array_map( function ( $conflict ) { return sprintf( '<a href="%s" target="_blank">%s</a>', $conflict['edit_url'], $conflict['template_title'] ); }, $this->get_conditions_conflicts( $document->get_main_id(), $condition ) ); if ( empty( $conflicted ) ) { return ''; } return esc_html__( 'Elementor recognized that you have set this location for other templates: ', 'elementor-pro' ) . ' ' . implode( ', ', $conflicted ); } public function get_conditions_conflicts_by_location( $condition, $location, $ignore_post_id = null ) { /** @var Module $theme_builder_module */ $theme_builder_module = Module::instance(); $location_settings = $theme_builder_module->get_locations_manager()->get_location( $location ); if ( ! empty( $location_settings['multiple'] ) ) { return []; } $conditions_groups = $this->cache->get_by_location( $location ); $conflicted = []; if ( ! empty( $conditions_groups ) ) { foreach ( $conditions_groups as $template_id => $conditions ) { if ( ! get_post( $template_id ) ) { $this->purge_post_from_cache( $template_id ); } if ( $ignore_post_id === $template_id ) { continue; } if ( false !== array_search( $condition, $conditions, true ) ) { $template_title = esc_html( get_the_title( $template_id ) ); $document = $theme_builder_module->get_document( $template_id ); if ( ! $document instanceof Theme_Document ) { Plugin::$instance->logger->get_logger()->error( "Error fetching document in conditions manager. Template: $template_title" ); } $edit_url = isset( $document ) ? $document->get_edit_url() : ''; $conflicted[] = [ 'template_id' => $template_id, 'template_title' => $template_title, 'edit_url' => $edit_url, ]; } } } return $conflicted; } public function get_conditions_conflicts( $post_id, $condition ) { /** @var Module $theme_builder_module */ $theme_builder_module = Module::instance(); $document = $theme_builder_module->get_document( $post_id ); return $this->get_conditions_conflicts_by_location( $condition, $document->get_location(), $post_id ); } /** * @throws \Exception */ public function ajax_save_theme_template_conditions( $request ) { $document = Utils::_unstable_get_document_for_edit( $request['editor_post_id'] ); if ( ! isset( $request['conditions'] ) ) { $request['conditions'] = []; } $is_saved = $this->save_conditions( $document->get_main_id(), $request['conditions'] ); if ( ! $is_saved ) { throw new \Exception( 'Error while saving conditions.', Exceptions::INTERNAL_SERVER_ERROR ); } } private function register_condition( $id, $args = [] ) { if ( isset( $this->conditions[ $id ] ) ) { return; } $class_name = ucfirst( $id ); $class_name = '\\ElementorPro\\Modules\\ThemeBuilder\\Conditions\\' . $class_name; /** @var Condition_Base $condition */ $condition = new $class_name( $args ); $this->register_condition_instance( $condition ); foreach ( $condition->get_sub_conditions() as $key => $val ) { if ( is_numeric( $key ) ) { $id = $val; $args = []; } else { $id = $key; $args = $val; } $this->register_condition( $id, $args ); } } /** * @param Condition_Base $instance */ public function register_condition_instance( $instance ) { $this->conditions[ $instance->get_name() ] = $instance; } /** * @param $id * * @return Condition_Base|bool */ public function get_condition( $id ) { return isset( $this->conditions[ $id ] ) ? $this->conditions[ $id ] : false; } public function get_conditions_config() { $config = []; foreach ( $this->conditions as $condition ) { $config[ $condition->get_name() ] = $condition->get_config(); } return $config; } public function get_document_instances( $post_id ) { /** @var Module $theme_builder_module */ $theme_builder_module = Module::instance(); $document = $theme_builder_module->get_document( $post_id ); $summary = []; if ( ! $document ) { return $summary; } $document_conditions = $this->get_document_conditions( $document ); if ( ! empty( $document_conditions ) ) { foreach ( $document_conditions as $document_condition ) { if ( 'exclude' === $document_condition['type'] ) { continue; } $condition_name = ! empty( $document_condition['sub_name'] ) ? $document_condition['sub_name'] : $document_condition['name']; $condition = $this->get_condition( $condition_name ); if ( ! $condition ) { continue; } if ( ! empty( $document_condition['sub_id'] ) ) { $instance_label = $condition->get_label() . " #{$document_condition['sub_id']}"; } else { $instance_label = $condition->get_all_label(); } $summary[ $condition->get_name() ] = $instance_label; } } return $summary; } public function register_conditions() { $this->register_condition( 'general' ); /** * Elementor theme conditions registration. * * Fires when a new theme condition is registered. This hook allows developers * to register new theme conditions. * * @param Conditions_Manager $this An instance of conditions manager. */ do_action( 'elementor/theme/register_conditions', $this ); } public function save_conditions( $post_id, $conditions ) { $conditions_to_save = []; foreach ( $conditions as $condition ) { unset( $condition['_id'] ); $conditions_to_save[] = rtrim( implode( '/', $condition ), '/' ); } /** @var Module $theme_builder_module */ $theme_builder_module = Module::instance(); $document = $theme_builder_module->get_document( $post_id ); if ( ! $document ) { return false; } if ( empty( $conditions_to_save ) ) { $is_saved = $document->delete_meta( '_elementor_conditions' ); } else { $is_saved = $document->update_meta( '_elementor_conditions', $conditions_to_save ); } $this->cache->regenerate(); return $is_saved; } public function get_location_templates( $location ) { $conditions_priority = []; $conditions_groups = $this->cache->get_by_location( $location ); if ( empty( $conditions_groups ) ) { return $conditions_priority; } /** @var Module $theme_builder_module */ $theme_builder_module = Module::instance(); $location_manager = $theme_builder_module->get_locations_manager(); $excludes = []; foreach ( $conditions_groups as $theme_template_id => $conditions ) { /** * Template ID for theme location templates. * * Filters the template ID for theme location templates. * * @param int $theme_template_id Template ID. * @param string $location Theme location. */ $theme_template_id = apply_filters( 'elementor/theme/get_location_templates/template_id', $theme_template_id, $location ); foreach ( $conditions as $condition ) { $parsed_condition = $this->parse_condition( $condition ); $include = $parsed_condition['type']; $name = $parsed_condition['name']; $sub_name = $parsed_condition['sub_name']; $sub_id = $parsed_condition['sub_id']; $is_include = 'include' === $include; $condition_instance = $this->get_condition( $name ); if ( ! $condition_instance ) { continue; } $condition_pass = $condition_instance->check( [] ); $sub_condition_instance = null; if ( $condition_pass && $sub_name ) { $sub_condition_instance = $this->get_condition( $sub_name ); if ( ! $sub_condition_instance ) { continue; } $args = [ 'id' => apply_filters( 'elementor/theme/get_location_templates/condition_sub_id', $sub_id, $parsed_condition ), ]; $condition_pass = $sub_condition_instance->check( $args ); } if ( $condition_pass ) { $post_status = get_post_status( $theme_template_id ); if ( 'publish' !== $post_status ) { $location_manager->inspector_log( [ 'location' => $location, 'document' => $theme_builder_module->get_document( $theme_template_id ), 'description' => 'Skipped, is not Published', ] ); continue; } if ( $is_include ) { $conditions_priority[ $theme_template_id ] = $this->get_condition_priority( $condition_instance, $sub_condition_instance, $sub_id ); } else { $excludes[] = $theme_template_id; } } } // End foreach(). } // End foreach(). foreach ( $excludes as $exclude_id ) { unset( $conditions_priority[ $exclude_id ] ); } asort( $conditions_priority ); return $conditions_priority; } public function get_theme_templates_ids( $location ) { /** @var Module $theme_builder_module */ $theme_builder_module = Module::instance(); $location_manager = $theme_builder_module->get_locations_manager(); // In case the user want to preview any page with a theme_template_id, // like http://domain.com/any-post/?preview=1&theme_template_id=6453 $force_template_id = Utils::_unstable_get_super_global_value( $_GET, 'theme_template_id' ); if ( $force_template_id ) { $document = $theme_builder_module->get_document( $force_template_id ); // e.g. header / header if ( $document && $location === $document->get_location() ) { $location_manager->inspector_log( [ 'location' => $location, 'document' => $document, 'description' => 'Force Template by URL param', ] ); return [ $force_template_id => 1, ]; } } $current_post_id = get_the_ID(); $document = $theme_builder_module->get_document( $current_post_id ); if ( $document && $location === $document->get_location() ) { $location_manager->inspector_log( [ 'location' => $location, 'document' => $document, 'description' => 'Current Edited Template', ] ); return [ $current_post_id => 1, ]; } $templates = $this->get_location_templates( $location ); return $templates; } /** * @param Condition_Base $condition_instance * @param Condition_Base $sub_condition_instance * @param int $sub_id * * @return mixed * @throws \Exception */ private function get_condition_priority( $condition_instance, $sub_condition_instance, $sub_id ) { $priority = $condition_instance::get_priority(); if ( $sub_condition_instance ) { if ( $sub_condition_instance::get_priority() < $priority ) { $priority = $sub_condition_instance::get_priority(); } $priority -= 10; if ( $sub_id ) { $priority -= 10; } elseif ( 0 === count( $sub_condition_instance->get_sub_conditions() ) ) { // if no sub conditions - it's more specific. $priority -= 5; } } return $priority; } /** * @param Theme_Document $document * * @return array */ public function get_document_conditions( $document ) { $saved_conditions = $document->get_main_meta( '_elementor_conditions' ); $conditions = []; if ( is_array( $saved_conditions ) ) { foreach ( $saved_conditions as $condition ) { $conditions[] = $this->parse_condition( $condition ); } } return $conditions; } protected function parse_condition( $condition ) { list ( $type, $name, $sub_name, $sub_id ) = array_pad( explode( '/', $condition ), 4, '' ); return compact( 'type', 'name', 'sub_name', 'sub_id' ); } /** * @param $location * * @return Theme_Document[] */ public function get_documents_for_location( $location ) { if ( isset( $this->location_cache[ $location ] ) ) { return $this->location_cache[ $location ]; } $theme_templates_ids = $this->get_theme_templates_ids( $location ); /** @var Module $theme_builder_module */ $theme_builder_module = Module::instance(); $location_settings = $theme_builder_module->get_locations_manager()->get_location( $location ); $documents = []; foreach ( $theme_templates_ids as $theme_template_id => $priority ) { $document = $theme_builder_module->get_document( $theme_template_id ); if ( $document ) { $documents[ $theme_template_id ] = $document; } if ( empty( $location_settings['multiple'] ) ) { break; } } $this->location_cache[ $location ] = $documents; return $documents; } public function purge_post_from_cache( $post_id ) { return $this->cache->remove( $post_id )->save(); } public function get_cache() { return $this->cache; } public function clear_cache() { $this->cache->clear(); } public function clear_location_cache() { $this->location_cache = []; } } classes/templates-types-manager.php 0000644 00000003021 14721752303 0013462 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Classes; use ElementorPro\Modules\ThemeBuilder\Documents; use ElementorPro\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Templates_Types_Manager { private $docs_types = []; public function __construct() { add_action( 'elementor/documents/register', [ $this, 'register_documents' ] ); } public function get_types_config( $args = [] ) { $config = []; $document_types = Plugin::elementor()->documents->get_document_types( $args ); foreach ( $document_types as $type => $document_type ) { $properties = $document_type::get_properties(); if ( ( new $document_type() ) instanceof Documents\Theme_Document ) { $config[ $type ] = $properties; } } return $config; } public function register_documents() { $this->docs_types = [ 'section' => Documents\Section::get_class_full_name(), 'header' => Documents\Header::get_class_full_name(), 'footer' => Documents\Footer::get_class_full_name(), 'single' => Documents\Single::get_class_full_name(), 'single-post' => Documents\Single_Post::get_class_full_name(), 'single-page' => Documents\Single_Page::get_class_full_name(), 'archive' => Documents\Archive::get_class_full_name(), 'search-results' => Documents\Search_Results::get_class_full_name(), 'error-404' => Documents\Error_404::get_class_full_name(), ]; foreach ( $this->docs_types as $type => $class_name ) { Plugin::elementor()->documents->register_document_type( $type, $class_name ); } } } classes/theme-support.php 0000644 00000007076 14721752303 0011544 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Classes; use ElementorPro\Modules\ThemeBuilder\Module; use ElementorPro\Modules\ThemeBuilder\ThemeSupport\GeneratePress_Theme_Support; use ElementorPro\Modules\ThemeBuilder\ThemeSupport\Safe_Mode_Theme_Support; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Theme_Support { public function __construct() { add_action( 'init', [ $this, 'init' ] ); } public function init() { $theme = wp_get_theme(); switch ( $theme->get_template() ) { case 'generatepress': new GeneratePress_Theme_Support(); break; case 'elementor-safe': new Safe_Mode_Theme_Support(); break; } add_action( 'elementor/theme/register_locations', [ $this, 'after_register_locations' ], 99 ); } /** * @param Locations_Manager $location_manager */ public function after_register_locations( $location_manager ) { $core_locations = $location_manager->get_core_locations(); $overwrite_header_location = false; $overwrite_footer_location = false; foreach ( $core_locations as $location => $settings ) { if ( ! $location_manager->get_location( $location ) ) { if ( 'header' === $location ) { $overwrite_header_location = true; } elseif ( 'footer' === $location ) { $overwrite_footer_location = true; } $location_manager->register_core_location( $location, [ 'overwrite' => true, ] ); } } if ( $overwrite_header_location || $overwrite_footer_location ) { /** @var Module $theme_builder_module */ $theme_builder_module = Module::instance(); $conditions_manager = $theme_builder_module->get_conditions_manager(); $headers = $conditions_manager->get_documents_for_location( 'header' ); $footers = $conditions_manager->get_documents_for_location( 'footer' ); if ( ! empty( $headers ) || ! empty( $footers ) ) { add_action( 'get_header', [ $this, 'get_header' ] ); add_action( 'get_footer', [ $this, 'get_footer' ] ); add_filter( 'show_admin_bar', [ $this, 'filter_admin_bar_from_body_open' ] ); } } } public function get_header( $name ) { require __DIR__ . '/../views/theme-support-header.php'; $templates = []; $name = (string) $name; if ( '' !== $name ) { $templates[] = "header-{$name}.php"; } $templates[] = 'header.php'; // Avoid running wp_head hooks again remove_all_actions( 'wp_head' ); ob_start(); // It cause a `require_once` so, in the get_header it self it will not be required again. locate_template( $templates, true ); ob_get_clean(); } /** * Don't show admin bar on `wp_body_open` because the theme header HTML is ignored via `$this->get_header()`. * * @param bool $show_admin_bar * * @return bool */ public function filter_admin_bar_from_body_open( $show_admin_bar ) { global $wp_current_filter; // A flag to mark if $show_admin_bar is switched to false during this filter, // if so, it needed to switch back on the next filter (wp_footer). static $switched = false; if ( $show_admin_bar && in_array( 'wp_body_open', $wp_current_filter ) ) { $show_admin_bar = false; $switched = true; } elseif ( $switched ) { $show_admin_bar = true; } return $show_admin_bar; } public function get_footer( $name ) { require __DIR__ . '/../views/theme-support-footer.php'; $templates = []; $name = (string) $name; if ( '' !== $name ) { $templates[] = "footer-{$name}.php"; } $templates[] = 'footer.php'; ob_start(); // It cause a `require_once` so, in the get_header it self it will not be required again. locate_template( $templates, true ); ob_get_clean(); } } conditions/singular.php 0000644 00000002363 14721752303 0011262 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; use ElementorPro\Modules\ThemeBuilder\Module; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Singular extends Condition_Base { protected $sub_conditions = [ 'front_page', ]; public static function get_type() { return 'singular'; } public function get_name() { return 'singular'; } public static function get_priority() { return 60; } public function get_label() { return esc_html__( 'Singular', 'elementor-pro' ); } public function get_all_label() { return esc_html__( 'All Singular', 'elementor-pro' ); } public function register_sub_conditions() { $post_types = Module::get_public_post_types(); $post_types['attachment'] = get_post_type_object( 'attachment' )->label; foreach ( $post_types as $post_type => $label ) { $condition = new Post( [ 'post_type' => $post_type, ] ); $this->register_sub_condition( $condition ); } $this->sub_conditions[] = 'child_of'; $this->sub_conditions[] = 'any_child_of'; $this->sub_conditions[] = 'by_author'; // Last condition. $this->sub_conditions[] = 'not_found404'; } public function check( $args ) { return ( is_singular() && ! is_embed() ) || is_404(); } } conditions/by-author.php 0000644 00000001723 14721752303 0011347 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; use ElementorPro\Modules\QueryControl\Module as QueryModule; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class By_Author extends Condition_Base { public static function get_type() { return 'singular'; } public static function get_priority() { return 40; } public function get_name() { return 'by_author'; } public function get_label() { return esc_html__( 'By Author', 'elementor-pro' ); } public function check( $args = null ) { return is_singular() && get_post_field( 'post_author' ) === $args['id']; } protected function register_controls() { $this->add_control( 'author_id', [ 'section' => 'settings', 'type' => QueryModule::QUERY_CONTROL_ID, 'select2options' => [ 'dropdownCssClass' => 'elementor-conditions-select2-dropdown', ], 'autocomplete' => [ 'object' => QueryModule::QUERY_OBJECT_AUTHOR, ], ] ); } } conditions/any-child-of-term.php 0000644 00000001777 14721752303 0012665 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Any_Child_Of_Term extends Child_Of_Term { private $taxonomy; public function get_name() { return 'any_child_of_' . $this->taxonomy->name; } public function get_label() { /* translators: %s: Singular taxonomy label. */ return sprintf( esc_html__( 'Any Child %s Of', 'elementor-pro' ), $this->taxonomy->labels->singular_name ); } public function __construct( $data ) { parent::__construct( $data ); $this->taxonomy = $data['object']; } public function check( $args ) { $id = (int) $args['id']; /** * @var \WP_Term $current */ $current = get_queried_object(); if ( ! $this->is_term() || 0 === $current->parent ) { return false; } while ( $current->parent > 0 ) { if ( $id === $current->parent ) { return true; } $current = get_term_by( 'id', $current->parent, $current->taxonomy ); } return $id === $current->parent; } } conditions/any-child-of.php 0000644 00000001070 14721752303 0011702 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Any_Child_Of extends Child_Of { public function get_name() { return 'any_child_of'; } public function get_label() { return esc_html__( 'Any Child Of', 'elementor-pro' ); } public function check( $args ) { if ( ! is_singular() ) { return false; } $id = (int) $args['id']; $parents = get_post_ancestors( get_the_ID() ); return ( ( 0 === $id && ! empty( $parents ) ) || in_array( $id, $parents ) ); } } conditions/archive.php 0000644 00000002403 14721752303 0011052 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; use ElementorPro\Modules\ThemeBuilder\Module; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Archive extends Condition_Base { protected $sub_conditions = [ 'author', 'date', 'search', ]; public static function get_type() { return 'archive'; } public static function get_priority() { return 80; } public function get_name() { return 'archive'; } public function get_label() { return esc_html__( 'Archives', 'elementor-pro' ); } public function get_all_label() { return esc_html__( 'All Archives', 'elementor-pro' ); } public function register_sub_conditions() { $post_types = Module::get_public_post_types(); foreach ( $post_types as $post_type => $label ) { if ( ! get_post_type_archive_link( $post_type ) ) { continue; } $condition = new Post_Type_Archive( [ 'post_type' => $post_type, ] ); $this->register_sub_condition( $condition ); } } public function check( $args ) { $is_archive = is_archive() || is_home() || is_search(); // WooCommerce is handled by `woocommerce` module. if ( $is_archive && class_exists( 'woocommerce' ) && is_woocommerce() ) { $is_archive = false; } return $is_archive; } } conditions/in-taxonomy.php 0000644 00000002533 14721752303 0011717 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; use ElementorPro\Modules\QueryControl\Module as QueryModule; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class In_Taxonomy extends Condition_Base { /** * @var \WP_Taxonomy */ private $taxonomy; public static function get_type() { return 'singular'; } public static function get_priority() { return 40; } public function __construct( $data ) { parent::__construct(); $this->taxonomy = $data['object']; } public function get_name() { return 'in_' . $this->taxonomy->name; } public function get_label() { /* translators: %s: Taxonomy label. */ return sprintf( esc_html__( 'In %s', 'elementor-pro' ), $this->taxonomy->labels->singular_name ); } public function check( $args ) { return is_singular() && has_term( (int) $args['id'], $this->taxonomy->name ); } protected function register_controls() { $this->add_control( 'taxonomy', [ 'section' => 'settings', 'type' => QueryModule::QUERY_CONTROL_ID, 'select2options' => [ 'dropdownCssClass' => 'elementor-conditions-select2-dropdown', ], 'autocomplete' => [ 'object' => QueryModule::QUERY_OBJECT_TAX, 'display' => 'detailed', 'by_field' => 'term_id', 'query' => [ 'taxonomy' => $this->taxonomy->name, ], ], ] ); } } conditions/author.php 0000644 00000001651 14721752303 0010737 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; use ElementorPro\Modules\QueryControl\Module as QueryModule; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Author extends Condition_Base { public static function get_type() { return 'archive'; } public static function get_priority() { return 70; } public function get_name() { return 'author'; } public function get_label() { return esc_html__( 'Author Archive', 'elementor-pro' ); } public function check( $args = null ) { return is_author( $args['id'] ); } protected function register_controls() { $this->add_control( 'author_id', [ 'section' => 'settings', 'type' => QueryModule::QUERY_CONTROL_ID, 'select2options' => [ 'dropdownCssClass' => 'elementor-conditions-select2-dropdown', ], 'autocomplete' => [ 'object' => QueryModule::QUERY_OBJECT_AUTHOR, ], ] ); } } conditions/post-type-by-author.php 0000644 00000002342 14721752303 0013307 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; use ElementorPro\Modules\QueryControl\Module as QueryModule; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Post_Type_By_Author extends Condition_Base { private $post_type; public static function get_type() { return 'singular'; } public static function get_priority() { return 40; } public function __construct( $post_type ) { parent::__construct(); $this->post_type = $post_type; } public function get_name() { return $this->post_type->name . '_by_author'; } public function get_label() { /* translators: %s: Post type label. */ return sprintf( esc_html__( '%s By Author', 'elementor-pro' ), $this->post_type->label ); } public function check( $args = null ) { return is_singular( $this->post_type->name ) && get_post_field( 'post_author' ) === $args['id']; } protected function register_controls() { $this->add_control( 'author_id', [ 'section' => 'settings', 'type' => QueryModule::QUERY_CONTROL_ID, 'select2options' => [ 'dropdownCssClass' => 'elementor-conditions-select2-dropdown', ], 'autocomplete' => [ 'object' => QueryModule::QUERY_OBJECT_AUTHOR, ], ] ); } } conditions/child-of.php 0000644 00000002414 14721752303 0011120 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; use ElementorPro\Modules\QueryControl\Module as QueryModule; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Child_Of extends Condition_Base { public static function get_type() { return 'singular'; } public static function get_priority() { return 40; } public function get_name() { return 'child_of'; } public function get_label() { return esc_html__( 'Direct Child Of', 'elementor-pro' ); } public function check( $args ) { if ( ! is_singular() ) { return false; } $id = (int) $args['id']; $parent_id = wp_get_post_parent_id( get_the_ID() ); return ( ( 0 === $id && 0 < $parent_id ) || ( $parent_id === $id ) ); } protected function register_controls() { $hierarchical_post_types = get_post_types( [ 'hierarchical' => true, 'public' => true, ] ); $this->add_control( 'parent_id', [ 'section' => 'settings', 'type' => QueryModule::QUERY_CONTROL_ID, 'select2options' => [ 'dropdownCssClass' => 'elementor-conditions-select2-dropdown', ], 'autocomplete' => [ 'object' => QueryModule::QUERY_OBJECT_POST, 'query' => [ 'post_type' => array_keys( $hierarchical_post_types ), ], ], ] ); } } conditions/not-found404.php 0000644 00000000767 14721752303 0011605 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Not_Found404 extends Condition_Base { public static function get_type() { return 'singular'; } public static function get_priority() { return 20; } public function get_name() { return 'not_found404'; } public function get_label() { return esc_html__( '404 Page', 'elementor-pro' ); } public function check( $args ) { return is_404(); } } conditions/in-sub-term.php 0000644 00000001556 14721752303 0011603 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class In_Sub_Term extends In_Taxonomy { /** * @var \WP_Taxonomy */ private $taxonomy; public function __construct( $data ) { parent::__construct( $data ); $this->taxonomy = $data['object']; } public function get_name() { return 'in_' . $this->taxonomy->name . '_children'; } public function get_label() { /* translators: %s: Taxonomy label. */ return sprintf( esc_html__( 'In Child %s', 'elementor-pro' ), $this->taxonomy->labels->name ); } public function check( $args ) { $id = (int) $args['id']; if ( ! is_singular() || ! $id ) { return false; } $child_terms = get_term_children( $id, $this->taxonomy->name ); return ! empty( $child_terms ) && has_term( $child_terms, $this->taxonomy->name ); } } conditions/taxonomy.php 0000644 00000002443 14721752303 0011313 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; use ElementorPro\Modules\QueryControl\Module as QueryModule; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Taxonomy extends Condition_Base { private $taxonomy; public static function get_type() { return 'archive'; } public static function get_priority() { return 70; } public function __construct( $data ) { parent::__construct(); $this->taxonomy = $data['object']; } public function get_name() { return $this->taxonomy->name; } public function get_label() { return $this->taxonomy->label; } public function check( $args ) { $taxonomy = $this->get_name(); $id = (int) $args['id']; if ( 'category' === $taxonomy ) { return is_category( $id ); } if ( 'post_tag' === $taxonomy ) { return is_tag( $id ); } return is_tax( $taxonomy, $id ); } protected function register_controls() { $this->add_control( 'taxonomy', [ 'section' => 'settings', 'type' => QueryModule::QUERY_CONTROL_ID, 'options' => [ '' => esc_html__( 'All', 'elementor-pro' ), ], 'autocomplete' => [ 'object' => QueryModule::QUERY_OBJECT_TAX, 'by_field' => 'term_id', 'query' => [ 'taxonomy' => $this->taxonomy->name, ], ], ] ); } } conditions/general.php 0000644 00000001112 14721752303 0011042 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class General extends Condition_Base { protected $sub_conditions = [ 'archive', 'singular', ]; public static function get_type() { return 'general'; } public function get_name() { return 'general'; } public function get_label() { return esc_html__( 'General', 'elementor-pro' ); } public function get_all_label() { return esc_html__( 'Entire Site', 'elementor-pro' ); } public function check( $args ) { return true; } } conditions/condition-base.php 0000644 00000003040 14721752303 0012325 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; use Elementor\Controls_Stack; use Elementor\Core\Utils\Exceptions; use ElementorPro\Modules\ThemeBuilder\Module; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Condition_Base extends Controls_Stack { protected $sub_conditions = []; public static function get_priority() { return 100; } abstract public function get_label(); public function get_unique_name() { return 'condition_' . $this->get_name(); } public static function get_type() { throw new \Exception( 'Please overwrite the method.', Exceptions::INTERNAL_SERVER_ERROR ); } public function check( $args ) { return false; } public function get_sub_conditions() { return $this->sub_conditions; } public function get_all_label() { return $this->get_label(); } protected function get_initial_config() { $config = parent::get_initial_config(); $config['label'] = $this->get_label(); $config['sub_conditions'] = $this->get_sub_conditions(); $config['all_label'] = $this->get_all_label(); return $config; } public function register_sub_conditions() {} /** * @param self $condition */ public function register_sub_condition( $condition ) { $conditions_manager = Module::instance()->get_conditions_manager(); $conditions_manager->register_condition_instance( $condition ); $this->sub_conditions[] = $condition->get_name(); } public function __construct( array $data = [] ) { parent::__construct( $data ); $this->register_sub_conditions(); } } conditions/front-page.php 0000644 00000000774 14721752303 0011504 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Front_Page extends Condition_Base { public static function get_type() { return 'singular'; } public static function get_priority() { return 30; } public function get_name() { return 'front_page'; } public function get_label() { return esc_html__( 'Front Page', 'elementor-pro' ); } public function check( $args ) { return is_front_page(); } } conditions/post-type-archive.php 0000644 00000003421 14721752303 0013015 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Post_Type_Archive extends Condition_Base { private $post_type; private $post_taxonomies; public static function get_type() { return 'archive'; } public static function get_priority() { return 70; } public function __construct( $data ) { $this->post_type = get_post_type_object( $data['post_type'] ); $taxonomies = get_object_taxonomies( $data['post_type'], 'objects' ); $this->post_taxonomies = wp_filter_object_list( $taxonomies, [ 'public' => true, 'show_in_nav_menus' => true, ] ); parent::__construct(); } public function get_name() { return $this->post_type->name . '_archive'; } public function get_label() { /* translators: %s: Post type label. */ return sprintf( esc_html__( '%s Archive', 'elementor-pro' ), $this->post_type->label ); } public function get_all_label() { /* translators: %s: Post type label. */ return sprintf( esc_html__( '%s Archive', 'elementor-pro' ), $this->post_type->label ); } public function register_sub_conditions() { foreach ( $this->post_taxonomies as $slug => $object ) { $condition = new Taxonomy( [ 'object' => $object, ] ); $this->register_sub_condition( $condition ); if ( ! $object->hierarchical ) { continue; } $sub_conditions = [ 'Child_Of_Term', 'Any_Child_Of_Term', ]; foreach ( $sub_conditions as $class_name ) { $full_class_name = __NAMESPACE__ . '\\' . $class_name; $this->register_sub_condition( new $full_class_name( [ 'object' => $object ] ) ); } } } public function check( $args ) { return is_post_type_archive( $this->post_type->name ) || ( 'post' === $this->post_type->name && is_home() ); } } conditions/search.php 0000644 00000000763 14721752303 0010705 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Search extends Condition_Base { public static function get_type() { return 'archive'; } public static function get_priority() { return 70; } public function get_name() { return 'search'; } public function get_label() { return esc_html__( 'Search Results', 'elementor-pro' ); } public function check( $args ) { return is_search(); } } conditions/date.php 0000644 00000000753 14721752303 0010354 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Date extends Condition_Base { public static function get_type() { return 'archive'; } public static function get_priority() { return 70; } public function get_name() { return 'date'; } public function get_label() { return esc_html__( 'Date Archive', 'elementor-pro' ); } public function check( $args ) { return is_date(); } } conditions/child-of-term.php 0000644 00000001653 14721752303 0012071 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Child_Of_Term extends Taxonomy { private $taxonomy; public function get_name() { return 'child_of_' . $this->taxonomy->name; } public function get_label() { /* translators: %s: Singular taxonomy label. */ return sprintf( esc_html__( 'Direct Child %s Of', 'elementor-pro' ), $this->taxonomy->labels->singular_name ); } public function __construct( $data ) { parent::__construct( $data ); $this->taxonomy = $data['object']; } public function is_term() { $taxonomy = $this->taxonomy->name; $current = get_queried_object(); return ( $current && isset( $current->taxonomy ) && $taxonomy === $current->taxonomy ); } public function check( $args ) { $id = (int) $args['id']; $current = get_queried_object(); return $this->is_term() && $id === $current->parent; } } conditions/post.php 0000644 00000004104 14721752303 0010416 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Conditions; use ElementorPro\Modules\QueryControl\Module as QueryModule; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Post extends Condition_Base { private $post_type; private $post_taxonomies; public static function get_type() { return 'singular'; } public static function get_priority() { return 40; } public function __construct( $data ) { $this->post_type = get_post_type_object( $data['post_type'] ); $taxonomies = get_object_taxonomies( $data['post_type'], 'objects' ); $this->post_taxonomies = wp_filter_object_list( $taxonomies, [ 'public' => true, 'show_in_nav_menus' => true, ] ); parent::__construct(); } public function get_name() { return $this->post_type->name; } public function get_label() { return $this->post_type->labels->singular_name; } public function get_all_label() { return $this->post_type->label; } public function check( $args ) { if ( isset( $args['id'] ) ) { $id = (int) $args['id']; if ( $id ) { return is_singular() && get_queried_object_id() === $id; } } return is_singular( $this->post_type->name ); } public function register_sub_conditions() { foreach ( $this->post_taxonomies as $slug => $object ) { $in_taxonomy = new In_Taxonomy( [ 'object' => $object, ] ); $this->register_sub_condition( $in_taxonomy ); if ( $object->hierarchical ) { $in_sub_term = new In_Sub_Term( [ 'object' => $object, ] ); $this->register_sub_condition( $in_sub_term ); } } $by_author = new Post_Type_By_Author( $this->post_type ); $this->register_sub_condition( $by_author ); } protected function register_controls() { $this->add_control( 'post_id', [ 'section' => 'settings', 'type' => QueryModule::QUERY_CONTROL_ID, 'select2options' => [ 'dropdownCssClass' => 'elementor-conditions-select2-dropdown', ], 'autocomplete' => [ 'object' => QueryModule::QUERY_OBJECT_POST, 'query' => [ 'post_type' => $this->get_name(), ], ], ] ); } } views/panel-template.php 0000644 00000010351 14721752303 0011326 0 ustar 00 <?php if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } // TODO: Remove after moving to Route API ?> <script type="text/template" id="tmpl-elementor-publish"> <# if ( screens.length > 1 ) { #> <div id="elementor-publish__tabs" class="elementor-templates-modal__sidebar"> <# screens.forEach( function( screen ) { #> <div class="elementor-publish__tab" data-screen="{{ screen.name }}"> <div class="elementor-publish__tab__image"> <img src="{{ screen.image }}" loading="lazy"> </div> <div class="elementor-publish__tab__content"> <div class="elementor-publish__tab__title">{{{ screen.title }}}</div> <div class="elementor-publish__tab__description">{{{ screen.description }}}</div> </div> </div> <# } ); #> </div> <# } #> <div id="elementor-publish__screen" class="elementor-templates-modal__content"></div> </script> <script type="text/template" id="tmpl-elementor-component-publish"> <# if ( Object.keys( tabs ).length > 1 ) { #> <div id="elementor-publish__tabs" class="elementor-templates-modal__sidebar"> <# jQuery.each( tabs, ( tab, args ) => { #> <div class="elementor-component-tab elementor-publish__tab" data-tab="{{ tab }}"> <div class="elementor-publish__tab__image"> <img src="{{ args.image }}" loading="lazy"> </div> <div class="elementor-publish__tab__content"> <div class="elementor-publish__tab__title">{{{ args.title }}}</div> <div class="elementor-publish__tab__description">{{{ args.description }}}</div> </div> </div> <# } ); #> </div> <# } #> <div id="elementor-publish__screen" class="elementor-templates-modal__content"></div> </script> <script type="text/template" id="tmpl-elementor-theme-builder-conditions-view"> <div class="elementor-template-library-blank-icon"> <img src="<?php echo ELEMENTOR_PRO_MODULES_URL; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>theme-builder/assets/images/conditions-tab.svg" loading="lazy"> </div> <div class="elementor-template-library-blank-title"> {{ sprintf( '<?php echo esc_html__( 'Where Do You Want to Display Your %s?', 'elementor-pro' ); ?>', elementor.config.document.post_type_title ) }} </div> <div class="elementor-template-library-blank-message"> {{ sprintf( '<?php echo esc_html__( 'Set the conditions that determine where your %s is used throughout your site.', 'elementor-pro' ); ?>', elementor.config.document.post_type_title ) }} <br /> <?php echo esc_html__( "For example, choose 'Entire Site' to display the template across your site.", 'elementor-pro' ); ?> </div> <div id="elementor-theme-builder-conditions"> <div id="elementor-theme-builder-conditions-controls"></div> </div> </script> <script type="text/template" id="tmpl-elementor-theme-builder-conditions-repeater-row"> <div class="elementor-theme-builder-conditions-repeater-row-controls"></div> <div class="elementor-repeater-row-tool elementor-repeater-tool-remove"> <i class="eicon-close" aria-hidden="true"></i> <span class="elementor-screen-only"><?php esc_html_e( 'Remove this item', 'elementor-pro' ); ?></span> </div> </script> <script type="text/template" id="tmpl-elementor-theme-builder-button-preview"> <i class="eicon-preview-medium tooltip-target" aria-hidden="true" data-tooltip="<?php esc_attr_e( 'Preview Changes', 'elementor-pro' ); ?>"></i> <span class="elementor-screen-only"> <?php esc_attr_e( 'Preview Changes', 'elementor-pro' ); ?> </span> <div class="elementor-panel-footer-sub-menu-wrapper"> <div class="elementor-panel-footer-sub-menu"> <div onclick="$e.run( 'theme-builder-publish/preview-settings' );" id="elementor-panel-footer-theme-builder-button-preview-settings" class="elementor-panel-footer-sub-menu-item"> <i class="eicon-wrench" aria-hidden="true"></i> <span class="elementor-title"><?php esc_html_e( 'Settings', 'elementor-pro' ); ?></span> </div> <div onclick="$e.run( 'editor/documents/preview', { id: elementor.documents.getCurrent().id, force: true } );" id="elementor-panel-footer-theme-builder-button-open-preview" class="elementor-panel-footer-sub-menu-item"> <i class="eicon-editor-external-link" aria-hidden="true"></i> <span class="elementor-title"><?php esc_html_e( 'Preview', 'elementor-pro' ); ?></span> </div> </div> </div> </script> views/theme-support-header.php 0000644 00000001547 14721752303 0012467 0 ustar 00 <?php use ElementorPro\Modules\ThemeBuilder\Module; use Elementor\Utils; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } $location_manager = Module::instance()->get_locations_manager(); ?> <!DOCTYPE html> <html <?php language_attributes(); ?>> <head> <meta charset="<?php bloginfo( 'charset' ); ?>"> <?php // PHPCS - not a user input. echo Utils::get_meta_viewport( 'theme-builder' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> <?php if ( ! current_theme_supports( 'title-tag' ) ) : ?> <title> <?php // PHPCS - already escaped by WordPress. echo wp_get_document_title(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> </title> <?php endif; ?> <?php wp_head(); ?> </head> <body <?php body_class(); ?>> <?php wp_body_open(); $location_manager->do_location( 'header' ); ?> views/theme-support-footer.php 0000644 00000000425 14721752303 0012527 0 ustar 00 <?php use ElementorPro\Modules\ThemeBuilder\Module; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } $location_manager = Module::instance()->get_locations_manager(); $location_manager->do_location( 'footer' ); ?> <?php wp_footer(); ?> </body> </html> views/comments-template.php 0000644 00000002476 14721752303 0012065 0 ustar 00 <?php if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } /** @var \ElementorPro\Modules\ThemeBuilder\Skins\Post_Comments_Skin_Classic $skin */ $skin = $GLOBALS['post_comment_skin_classic']; if ( post_password_required() ) { ?> <p class="nocomments"><?php esc_html_e( 'This post is password protected. Enter the password to view comments.', 'elementor-pro' ); ?></p> <?php return; } ?> <?php $comment_count = get_comment_count(); if ( $comment_count ) : ?> <h3 id="comments"> <?php echo esc_html( $skin->get_instance_value( 'title' ) ); ?> </h3> <div class="navigation"> <div class="alignleft"><?php previous_comments_link(); ?></div> <div class="alignright"><?php next_comments_link(); ?></div> </div> <ol class="commentlist"> <?php wp_list_comments( [ 'callback' => [ $skin, 'comment_callback' ], ] ); ?> </ol> <div class="navigation"> <div class="alignleft"><?php previous_comments_link(); ?></div> <div class="alignright"><?php next_comments_link(); ?></div> </div> <?php else : ?> <?php if ( comments_open() ) : ?> <p class="nocomments"><?php echo esc_html( $skin->get_instance_value( 'title' ) ); ?></p> <?php else : ?> <!-- If comments are closed. --> <p class="nocomments"><?php esc_html_e( 'Comments are closed.', 'elementor-pro' ); ?></p> <?php endif; endif; module.php 0000644 00000034736 14721752303 0006563 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder; use Elementor\Controls_Manager; use Elementor\Core\Admin\Admin_Notices; use Elementor\Core\Admin\Menu\Admin_Menu_Manager; use Elementor\Core\Admin\Menu\Main as MainMenu; use Elementor\Core\App\App; use Elementor\Core\Base\Document; use Elementor\TemplateLibrary\Source_Local; use ElementorPro\Base\Module_Base; use ElementorPro\Core\Utils; use ElementorPro\Modules\ThemeBuilder\AdminMenuItems\Theme_Builder_Menu_Item; use ElementorPro\Modules\ThemeBuilder\Classes; use ElementorPro\Modules\ThemeBuilder\Documents\Single; use ElementorPro\Modules\ThemeBuilder\Documents\Theme_Document; use ElementorPro\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Module extends Module_Base { const ADMIN_LIBRARY_TAB_GROUP = 'theme'; const ADMIN_MENU_PRIORITY = 15; public static function is_preview() { return Plugin::elementor()->preview->is_preview_mode() || is_preview(); } public static function get_public_post_types( $args = [] ) { $post_types = Utils::get_public_post_types( $args ); // Product form WooCommerce are handled separately. if ( class_exists( 'woocommerce' ) ) { unset( $post_types['product'] ); } return $post_types; } public function get_name() { return 'theme-builder'; } public function get_widgets() { $widgets = [ 'Site_Logo', 'Site_Title', 'Page_Title', 'Post_Title', 'Post_Excerpt', 'Post_Content', 'Post_Featured_Image', 'Archive_Title', ]; if ( class_exists( '\ElementorPro\Modules\Posts\Widgets\Posts' ) ) { $widgets[] = 'Archive_Posts'; } return $widgets; } /** * @return Classes\Conditions_Manager */ public function get_conditions_manager() { return $this->get_component( 'conditions' ); } /** * @return Classes\Locations_Manager */ public function get_locations_manager() { return $this->get_component( 'locations' ); } /** * @return Classes\Preview_Manager */ public function get_preview_manager() { return $this->get_component( 'preview' ); } /** * @return Classes\Templates_Types_Manager */ public function get_types_manager() { return $this->get_component( 'templates_types' ); } /** * @param $post_id * * @return Theme_Document */ public function get_document( $post_id ) { $document = null; try { $document = Plugin::elementor()->documents->get( $post_id ); } catch ( \Exception $e ) { // Do nothing. unset( $e ); } if ( ! empty( $document ) && ! $document instanceof Theme_Document ) { $document = null; } return $document; } public function document_config( $config, $post_id ) { $document = $this->get_document( $post_id ); if ( ! $document ) { return $config; } $types_manager = $this->get_types_manager(); $conditions_manager = $this->get_conditions_manager(); $template_type = $this->get_template_type( $post_id ); $config = array_replace_recursive( $config, [ 'theme_builder' => [ 'types' => $types_manager->get_types_config(), 'conditions' => $conditions_manager->get_conditions_config(), 'template_conditions' => ( new Classes\Template_Conditions() )->get_config(), 'is_theme_template' => $this->is_theme_template( $post_id ), 'settings' => [ 'template_type' => $template_type, 'location' => $document->get_location(), 'conditions' => $conditions_manager->get_document_conditions( $document ), ], ], ] ); return $config; } public function register_controls( Controls_Manager $controls_manager ) { $controls_manager->register( new Classes\Conditions_Repeater() ); $controls_manager->register( new Classes\Control_Media_Preview() ); } public function create_new_dialog_types( $types ) { /** * @var Theme_Document[] $document_types */ foreach ( $types as $type => $label ) { $document_type = Plugin::elementor()->documents->get_document_type( $type ); $instance = new $document_type(); if ( $instance instanceof Theme_Document && 'section' !== $type ) { $types[ $type ] .= $instance->get_location_label(); } if ( Single::class === $document_type ) { unset( $types[ $type ] ); } } return $types; } public function print_location_field() { $locations = $this->get_locations_manager()->get_locations( [ 'public' => true, ] ); if ( empty( $locations ) ) { return; } ?> <div id="elementor-new-template__form__location__wrapper" class="elementor-form-field"> <label for="elementor-new-template__form__location" class="elementor-form-field__label"> <?php echo esc_html__( 'Select a Location', 'elementor-pro' ); ?> </label> <div class="elementor-form-field__select__wrapper"> <select id="elementor-new-template__form__location" class="elementor-form-field__select" name="meta_location"> <option value=""> <?php echo esc_html__( 'Select...', 'elementor-pro' ); ?> </option> <?php foreach ( $locations as $location => $settings ) { echo sprintf( '<option value="%1$s">%2$s</option>', esc_html( $location ), esc_html( $settings['label'] ) ); } ?> </select> </div> </div> <?php } public function print_post_type_field() { $post_types = self::get_public_post_types( [ 'exclude_from_search' => false, ] ); if ( empty( $post_types ) ) { return; } ?> <div id="elementor-new-template__form__post-type__wrapper" class="elementor-form-field"> <label for="elementor-new-template__form__post-type" class="elementor-form-field__label"> <?php echo esc_html__( 'Select Post Type', 'elementor-pro' ); ?> </label> <div class="elementor-form-field__select__wrapper"> <select id="elementor-new-template__form__post-type" class="elementor-form-field__select" name="<?php echo Single::REMOTE_CATEGORY_META_KEY; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>" > <option value=""> <?php echo esc_html__( 'Select', 'elementor-pro' ); ?>... </option> <?php foreach ( $post_types as $post_type => $label ) { $doc_type = Plugin::elementor()->documents->get_document_type( $post_type ); $doc_class = new $doc_type(); $is_base_page = $doc_class instanceof \Elementor\Core\DocumentTypes\PageBase; if ( $is_base_page ) { $post_type_object = get_post_type_object( $post_type ); echo sprintf( '<option value="%1$s">%2$s</option>', esc_html( $post_type ), esc_html( $post_type_object->labels->singular_name ) ); } } // 404. echo sprintf( '<option value="%1$s">%2$s</option>', 'not_found404', esc_html__( '404 Page', 'elementor-pro' ) ); ?> </select> </div> </div> <?php } public function admin_head() { $current_screen = get_current_screen(); if ( $current_screen && in_array( $current_screen->id, [ 'elementor_library', 'edit-elementor_library' ] ) ) { // For column type (Supported/Unsupported) & for `print_location_field`. $this->get_locations_manager()->register_locations(); } } /** * An hack to hide the app menu on before render without remove the app page from system. * * @param $menu * * @return mixed */ public function hide_admin_app_submenu( $menu ) { remove_submenu_page( Source_Local::ADMIN_MENU_SLUG, App::PAGE_ID ); return $menu; } public function admin_columns_content( $column_name, $post_id ) { if ( 'elementor_library_type' === $column_name ) { /** @var Document $document */ $document = Plugin::elementor()->documents->get( $post_id ); if ( $document instanceof Theme_Document ) { $location_label = $document->get_location_label(); if ( $location_label ) { echo ' - ' . esc_html( $location_label ); } } } } public function get_template_type( $post_id ) { return Source_local::get_template_type( $post_id ); } public function is_theme_template( $post_id ) { $document = Plugin::elementor()->documents->get( $post_id ); return $document instanceof Theme_Document; } public function on_elementor_editor_init() { Plugin::elementor()->common->add_template( __DIR__ . '/views/panel-template.php' ); } public function add_finder_items( array $categories ) { $categories['create']['items']['theme-template'] = [ 'title' => esc_html__( 'Add New Theme Template', 'elementor-pro' ), 'icon' => 'plus-circle-o', 'url' => $this->get_admin_templates_url() . '#add_new', 'keywords' => [ 'template', 'theme', 'new', 'create' ], ]; return $categories; } /** * Add New item to admin menu. * * @since 3.6.0 * @access private */ private function register_admin_menu( MainMenu $menu ) { $menu->add_submenu( [ 'menu_title' => esc_html__( 'Theme Builder', 'elementor-pro' ), 'menu_slug' => Plugin::elementor()->app->get_settings( 'menu_url' ), 'index' => 30, ] ); } /** * Add New item to admin menu. * * Fired by `admin_menu` action. * * @since 3.6.0 * @access private */ private function register_admin_menu_legacy( Admin_Menu_Manager $admin_menu ) { $admin_menu->register( $this->get_admin_templates_url( true ), new Theme_Builder_Menu_Item() ); } public function print_new_theme_builder_promotion( $views ) { /** @var Source_Local $source */ $source = Plugin::elementor()->templates_manager->get_source( 'local' ); $current_tab_group = $source->get_current_tab_group(); if ( self::ADMIN_LIBRARY_TAB_GROUP === $current_tab_group ) { /** * @var Admin_Notices $admin_notices */ $admin_notices = Plugin::elementor()->admin->get_component( 'admin-notices' ); $admin_notices->print_admin_notice( [ 'title' => esc_html__( 'Meet the New Theme Builder: More Intuitive and Visual Than Ever', 'elementor-pro' ), 'description' => esc_html__( 'With the new Theme Builder you can visually manage every part of your site intuitively, making the task of designing a complete website that much easier', 'elementor-pro' ), 'button' => [ 'text' => esc_html__( 'Try it Now', 'elementor-pro' ), 'class' => 'elementor-button e-accent', 'url' => Plugin::elementor()->app->get_settings( 'menu_url' ), ], ] ); } return $views; } private function get_admin_templates_url( $relative = false ) { $base_url = Source_Local::ADMIN_MENU_SLUG; if ( ! $relative ) { $base_url = admin_url( $base_url ); } return add_query_arg( 'tabs_group', self::ADMIN_LIBRARY_TAB_GROUP, $base_url ); } /** * Get the conflicts between the active templates' conditions and new templates. * * @since 3.8.0 * * @param array $templates * @return array */ public function get_conditions_conflicts( array $templates ) : array { $conflicts = []; foreach ( $templates as $template_id => $template ) { if ( empty( $template['conditions'] ) ) { continue; } foreach ( $template['conditions'] as $condition ) { $condition = rtrim( implode( '/', $condition ), '/' ); $condition_conflicts = $this->get_conditions_manager()->get_conditions_conflicts_by_location( $condition, $template['location'] ); if ( $condition_conflicts ) { $conflicts[ $template_id ] = $condition_conflicts; } } } return $conflicts; } /** * TODO: BC - remove in 3.11.0|4.1.0 * Add conflicts to import result. * * @since 3.7.0 * * @param array $result * @return array */ private function add_conflicts_to_import_result( array $result ) { $manifest_data = $result['manifest']; if ( empty( $manifest_data['templates'] ) ) { return $result; } $result['conflicts'] = $this->get_conditions_conflicts( $manifest_data['templates'] ); return $result; } /** * Add attributes to the document wrapper element. * * @param array $attributes - The document's wrapper element attributes. * @param Document $document * * @return array */ public function add_document_attributes( array $attributes, Document $document ): array { $attributes['data-elementor-post-type'] = $document->get_post()->post_type; return $attributes; } public function __construct() { parent::__construct(); require __DIR__ . '/api.php'; $this->add_component( 'theme_support', new Classes\Theme_Support() ); $this->add_component( 'conditions', new Classes\Conditions_Manager() ); $this->add_component( 'templates_types', new Classes\Templates_Types_Manager() ); $this->add_component( 'preview', new Classes\Preview_Manager() ); $this->add_component( 'locations', new Classes\Locations_Manager() ); add_action( 'elementor/controls/register', [ $this, 'register_controls' ] ); // Editor add_action( 'elementor/editor/init', [ $this, 'on_elementor_editor_init' ] ); add_filter( 'elementor/document/config', [ $this, 'document_config' ], 10, 2 ); add_filter( 'elementor/document/wrapper_attributes', [ $this, 'add_document_attributes' ], 10, 2 ); // Admin add_action( 'admin_head', [ $this, 'admin_head' ] ); add_filter( 'add_menu_classes', [ $this, 'hide_admin_app_submenu' ], 9 /* Before core submenu fixes */ ); add_action( 'manage_' . Source_Local::CPT . '_posts_custom_column', [ $this, 'admin_columns_content' ], 10, 2 ); add_action( 'elementor/template-library/create_new_dialog_fields', [ $this, 'print_location_field' ] ); add_action( 'elementor/template-library/create_new_dialog_fields', [ $this, 'print_post_type_field' ] ); if ( Plugin::elementor()->experiments->is_feature_active( 'admin_menu_rearrangement' ) ) { add_action( 'elementor/admin/menu_registered/elementor', function( MainMenu $menu ) { $this->register_admin_menu( $menu ); } ); } else { add_action( 'elementor/admin/menu/register', function ( Admin_Menu_Manager $admin_menu ) { $this->register_admin_menu_legacy( $admin_menu ); }, static::ADMIN_MENU_PRIORITY /* After "Popups" */ ); // TODO: BC - Remove after `Admin_Menu_Manager` will be the standard. add_action( 'admin_menu', function () { if ( did_action( 'elementor/admin/menu/register' ) ) { return; } add_submenu_page( Source_Local::ADMIN_MENU_SLUG, '', esc_html__( 'Theme Builder', 'elementor-pro' ), 'publish_posts', $this->get_admin_templates_url( true ) ); }, 22 /* After core promotion menu */ ); } add_filter( 'elementor/template-library/create_new_dialog_types', [ $this, 'create_new_dialog_types' ] ); add_filter( 'views_edit-' . Source_Local::CPT, [ $this, 'print_new_theme_builder_promotion' ], 9 ); // Moved into the IE module \ElementorPro\Core\App\Modules\ImportExport\Module::add_actions // TODO: remove in 3.10.0 add_filter( 'elementor/import/stage_1/result', function ( array $result ) { return $this->add_conflicts_to_import_result( $result ); }); // Common add_filter( 'elementor/finder/categories', [ $this, 'add_finder_items' ] ); } } api.php 0000644 00000001263 14721752303 0006034 0 ustar 00 <?php use ElementorPro\Modules\ThemeBuilder\Module as Theme_Builder_Module; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } function elementor_theme_do_location( $location ) { /** @var Theme_Builder_Module $theme_builder_module */ $theme_builder_module = Theme_Builder_Module::instance(); return $theme_builder_module->get_locations_manager()->do_location( $location ); } function elementor_location_exits( $location, $check_match = false ) { /** @var Theme_Builder_Module $theme_builder_module */ $theme_builder_module = Theme_Builder_Module::instance(); return $theme_builder_module->get_locations_manager()->location_exits( $location, $check_match ); } widgets/archive-posts.php 0000644 00000007565 14721752303 0011533 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Widgets; use Elementor\Controls_Manager; use Elementor\Core\Kits\Documents\Tabs\Global_Colors; use Elementor\Core\Kits\Documents\Tabs\Global_Typography; use Elementor\Group_Control_Typography; use ElementorPro\Modules\Posts\Widgets\Posts_Base; use ElementorPro\Modules\ThemeBuilder\Skins; use ElementorPro\Modules\QueryControl\Module as Query_Control; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * Class Posts */ class Archive_Posts extends Posts_Base { public function get_name() { return 'archive-posts'; } public function get_title() { return esc_html__( 'Archive Posts', 'elementor-pro' ); } public function get_icon() { return 'eicon-archive-posts'; } public function get_categories() { return [ 'theme-elements-archive' ]; } public function get_keywords() { return [ 'posts', 'cpt', 'archive', 'loop', 'query', 'cards', 'custom post type' ]; } public function get_inline_css_depends() { return [ 'posts' ]; } /** * Get style dependencies. * * Retrieve the list of style dependencies the widget requires. * * @since 3.24.0 * @access public * * @return array Widget style dependencies. */ public function get_style_depends(): array { return [ 'widget-posts' ]; } protected function register_skins() { $this->add_skin( new Skins\Posts_Archive_Skin_Classic( $this ) ); $this->add_skin( new Skins\Posts_Archive_Skin_Cards( $this ) ); $this->add_skin( new Skins\Posts_Archive_Skin_Full_Content( $this ) ); } protected function register_controls() { parent::register_controls(); $this->register_pagination_section_controls(); $this->register_advanced_section_controls(); $this->update_control( 'pagination_type', [ 'default' => 'numbers', ] ); } public function register_advanced_section_controls() { $this->start_controls_section( 'section_advanced', [ 'label' => esc_html__( 'Advanced', 'elementor-pro' ), ] ); $this->add_control( 'nothing_found_message', [ 'label' => esc_html__( 'Nothing Found Message', 'elementor-pro' ), 'type' => Controls_Manager::TEXTAREA, 'default' => esc_html__( 'It seems we can\'t find what you\'re looking for.', 'elementor-pro' ), 'dynamic' => [ 'active' => true, ], ] ); $this->end_controls_section(); $this->start_controls_section( 'section_nothing_found_style', [ 'tab' => Controls_Manager::TAB_STYLE, 'label' => esc_html__( 'Nothing Found Message', 'elementor-pro' ), 'condition' => [ 'nothing_found_message!' => '', ], ] ); $this->add_control( 'nothing_found_color', [ 'label' => esc_html__( 'Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'global' => [ 'default' => Global_Colors::COLOR_TEXT, ], 'selectors' => [ '{{WRAPPER}} .elementor-posts-nothing-found' => 'color: {{VALUE}};', ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'nothing_found_typography', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_TEXT, ], 'selector' => '{{WRAPPER}} .elementor-posts-nothing-found', ] ); $this->end_controls_section(); } public function query_posts() { global $wp_query; $query_vars = $wp_query->query_vars; /** * Posts archive query vars. * * Filters the post query variables when the theme loads the posts archive page. * * @since 2.0.0 * * @param array $query_vars The query variables for the `WP_Query`. */ $query_vars = apply_filters( 'elementor/theme/posts_archive/query_posts/query_vars', $query_vars ); if ( $query_vars !== $wp_query->query_vars ) { $this->query = new \WP_Query( $query_vars ); // SQL_CALC_FOUND_ROWS is used. } else { $this->query = $wp_query; } Query_Control::add_to_avoid_list( wp_list_pluck( $this->query->posts, 'ID' ) ); } } widgets/post-featured-image.php 0000644 00000002476 14721752303 0012602 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Widgets; use Elementor\Widget_Image; use ElementorPro\Base\Base_Widget_Trait; use ElementorPro\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Post_Featured_Image extends Widget_Image { use Base_Widget_Trait; public function get_name() { // `theme` prefix is to avoid conflicts with a dynamic-tag with same name. return 'theme-post-featured-image'; } public function get_title() { return esc_html__( 'Featured Image', 'elementor-pro' ); } public function get_icon() { return 'eicon-featured-image'; } public function get_categories() { return [ 'theme-elements-single' ]; } public function get_keywords() { return [ 'image', 'featured', 'thumbnail' ]; } public function get_inline_css_depends() { return [ [ 'name' => 'image', 'is_core_dependency' => true, ], ]; } protected function register_controls() { parent::register_controls(); $this->update_control( 'image', [ 'dynamic' => [ 'default' => Plugin::elementor()->dynamic_tags->tag_data_to_tag_text( null, 'post-featured-image' ), ], ], [ 'recursive' => true, ] ); } protected function get_html_wrapper_class() { return parent::get_html_wrapper_class() . ' elementor-widget-' . parent::get_name(); } } widgets/title-widget-base.php 0000644 00000002473 14721752303 0012247 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Widgets; use Elementor\Widget_Heading; use Elementor\Plugin; use ElementorPro\Base\Base_Widget_Trait; use ElementorPro\Plugin as ProPlugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } abstract class Title_Widget_Base extends Widget_Heading { use Base_Widget_Trait; abstract protected function get_dynamic_tag_name(); protected function should_show_page_title() { $current_doc = Plugin::instance()->documents->get( get_the_ID() ); if ( $current_doc && 'yes' === $current_doc->get_settings( 'hide_title' ) ) { return false; } return true; } protected function register_controls() { parent::register_controls(); $dynamic_tag_name = $this->get_dynamic_tag_name(); $this->update_control( 'title', [ 'dynamic' => [ 'default' => ProPlugin::elementor()->dynamic_tags->tag_data_to_tag_text( null, $dynamic_tag_name ), ], ], [ 'recursive' => true, ] ); $this->update_control( 'header_size', [ 'default' => 'h1', ] ); } protected function get_html_wrapper_class() { return parent::get_html_wrapper_class() . ' elementor-page-title elementor-widget-' . parent::get_name(); } public function render() { if ( $this->should_show_page_title() ) { return parent::render(); } } } widgets/post-excerpt.php 0000644 00000005701 14721752303 0011367 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Widgets; use Elementor\Controls_Manager; use Elementor\Core\Kits\Documents\Tabs\Global_Colors; use Elementor\Core\Kits\Documents\Tabs\Global_Typography; use Elementor\Group_Control_Typography; use ElementorPro\Base\Base_Widget; use ElementorPro\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Post_Excerpt extends Base_Widget { public function get_name() { // `theme` prefix is to avoid conflicts with a dynamic-tag with same name. return 'theme-post-excerpt'; } public function get_title() { return esc_html__( 'Post Excerpt', 'elementor-pro' ); } public function get_icon() { return 'eicon-post-excerpt'; } public function get_categories() { return [ 'theme-elements-single' ]; } public function get_keywords() { return [ 'post', 'excerpt', 'description' ]; } protected function register_controls() { $this->start_controls_section( 'section_content', [ 'label' => esc_html__( 'Content', 'elementor-pro' ), ] ); $this->add_control( 'excerpt', [ 'type' => Controls_Manager::TEXT, 'label_block' => true, 'dynamic' => [ 'active' => true, 'default' => Plugin::elementor()->dynamic_tags->tag_data_to_tag_text( null, 'post-excerpt' ), ], ] ); $this->end_controls_section(); $this->start_controls_section( 'section_style', [ 'label' => esc_html__( 'Style', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_responsive_control( 'align', [ 'label' => esc_html__( 'Alignment', 'elementor-pro' ), 'type' => Controls_Manager::CHOOSE, 'options' => [ 'left' => [ 'title' => esc_html__( 'Left', 'elementor-pro' ), 'icon' => 'eicon-text-align-left', ], 'center' => [ 'title' => esc_html__( 'Center', 'elementor-pro' ), 'icon' => 'eicon-text-align-center', ], 'right' => [ 'title' => esc_html__( 'Right', 'elementor-pro' ), 'icon' => 'eicon-text-align-right', ], 'justify' => [ 'title' => esc_html__( 'Justified', 'elementor-pro' ), 'icon' => 'eicon-text-align-justify', ], ], 'selectors' => [ '{{WRAPPER}} .elementor-widget-container' => 'text-align: {{VALUE}};', ], ] ); $this->add_control( 'title_color', [ 'label' => esc_html__( 'Text Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'global' => [ 'default' => Global_Colors::COLOR_TEXT, ], 'selectors' => [ '{{WRAPPER}} .elementor-widget-container' => 'color: {{VALUE}};', ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'typography', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_TEXT, ], 'selector' => '{{WRAPPER}} .elementor-widget-container', ] ); $this->end_controls_section(); } protected function render() { $this->print_unescaped_setting( 'excerpt' ); } } widgets/site-title.php 0000644 00000004041 14721752303 0011011 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Widgets; use Elementor\Controls_Manager; use Elementor\Widget_Heading; use ElementorPro\Base\Base_Widget_Trait; use ElementorPro\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Site_Title extends Widget_Heading { use Base_Widget_Trait; public function get_name() { // `theme` prefix is to avoid conflicts with a dynamic-tag with same name. return 'theme-site-title'; } public function get_title() { return esc_html__( 'Site Title', 'elementor-pro' ); } public function get_icon() { return 'eicon-site-title'; } public function get_categories() { return [ 'theme-elements' ]; } public function get_keywords() { return [ 'site', 'title', 'name' ]; } public function get_inline_css_depends() { return [ [ 'name' => 'heading', 'is_core_dependency' => true, ], ]; } protected function register_controls() { parent::register_controls(); $this->update_control( 'title', [ 'dynamic' => [ 'default' => Plugin::elementor()->dynamic_tags->tag_data_to_tag_text( null, 'site-title' ), ], ], [ 'recursive' => true, ] ); $this->update_control( 'link', [ 'dynamic' => [ 'default' => Plugin::elementor()->dynamic_tags->tag_data_to_tag_text( null, 'site-url' ), ], ], [ 'recursive' => true, ] ); $this->add_control( 'site_identity_notice', [ 'type' => Controls_Manager::ALERT, 'alert_type' => 'info', 'content' => sprintf( /* translators: 1: Link opening tag, 2: Link closing tag. */ esc_html__( 'To edit the title of your site, go to %1$sSite Identity%2$s.', 'elementor-pro' ), '<a href="#" onclick="elementorPro.modules.themeBuilder.openSiteIdentity( event )" >', '</a>' ), ], [ 'position' => [ 'of' => 'title', 'type' => 'control', 'at' => 'before', ], ] ); } protected function get_html_wrapper_class() { return parent::get_html_wrapper_class() . ' elementor-widget-' . parent::get_name(); } } widgets/page-title.php 0000644 00000001475 14721752303 0010771 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Widgets; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Page_Title extends Title_Widget_Base { protected function get_dynamic_tag_name() { return 'page-title'; } public function get_name() { // `theme` prefix is to avoid conflicts with a dynamic-tag with same name. return 'theme-page-title'; } public function get_inline_css_depends() { return [ [ 'name' => 'heading', 'is_core_dependency' => true, ], ]; } public function get_title() { return esc_html__( 'Page Title', 'elementor-pro' ); } public function get_icon() { return 'eicon-archive-title'; } public function get_categories() { return [ 'theme-elements' ]; } public function get_keywords() { return [ 'title', 'heading', 'page' ]; } } widgets/archive-title.php 0000644 00000001524 14721752303 0011471 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Widgets; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Archive_Title extends Title_Widget_Base { protected function get_dynamic_tag_name() { return 'archive-title'; } public function get_name() { // `theme` prefix is to avoid conflicts with a dynamic-tag with same name. return 'theme-archive-title'; } public function get_title() { return esc_html__( 'Archive Title', 'elementor-pro' ); } public function get_icon() { return 'eicon-archive-title'; } public function get_categories() { return [ 'theme-elements-archive' ]; } public function get_keywords() { return [ 'title', 'heading', 'archive' ]; } public function get_inline_css_depends() { return [ [ 'name' => 'heading', 'is_core_dependency' => true, ], ]; } } widgets/post-title.php 0000644 00000001667 14721752303 0011045 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Widgets; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Post_Title extends Title_Widget_Base { public function get_name() { // `theme` prefix is to avoid conflicts with a dynamic-tag with same name. return 'theme-post-title'; } public function get_title() { return esc_html__( 'Post Title', 'elementor-pro' ); } public function get_icon() { return 'eicon-post-title'; } public function get_categories() { return [ 'theme-elements-single' ]; } public function get_keywords() { return [ 'title', 'heading', 'post' ]; } protected function get_dynamic_tag_name() { return 'post-title'; } public function get_common_args() { return [ '_css_classes' => [ 'default' => 'entry-title', ], ]; } public function get_inline_css_depends() { return [ [ 'name' => 'heading', 'is_core_dependency' => true, ], ]; } } widgets/post-content.php 0000644 00000005267 14721752303 0011376 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Widgets; use Elementor\Controls_Manager; use Elementor\Core\Kits\Documents\Tabs\Global_Colors; use Elementor\Core\Kits\Documents\Tabs\Global_Typography; use Elementor\Group_Control_Typography; use ElementorPro\Base\Base_Widget; use ElementorPro\Modules\Posts\Skins\Skin_Content_Base; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Post_Content extends Base_Widget { use Skin_Content_Base; public function get_name() { // `theme` prefix is to avoid conflicts with a dynamic-tag with same name. return 'theme-post-content'; } public function get_title() { return esc_html__( 'Post Content', 'elementor-pro' ); } public function get_icon() { return 'eicon-post-content'; } public function get_categories() { return [ 'theme-elements-single' ]; } public function get_keywords() { return [ 'content', 'post' ]; } public function show_in_panel() { // By default don't show. return false; } protected function register_controls() { $this->start_controls_section( 'section_style', [ 'label' => esc_html__( 'Style', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_responsive_control( 'align', [ 'label' => esc_html__( 'Alignment', 'elementor-pro' ), 'type' => Controls_Manager::CHOOSE, 'options' => [ 'left' => [ 'title' => esc_html__( 'Left', 'elementor-pro' ), 'icon' => 'eicon-text-align-left', ], 'center' => [ 'title' => esc_html__( 'Center', 'elementor-pro' ), 'icon' => 'eicon-text-align-center', ], 'right' => [ 'title' => esc_html__( 'Right', 'elementor-pro' ), 'icon' => 'eicon-text-align-right', ], 'justify' => [ 'title' => esc_html__( 'Justified', 'elementor-pro' ), 'icon' => 'eicon-text-align-justify', ], ], 'selectors' => [ '{{WRAPPER}}' => 'text-align: {{VALUE}};', ], ] ); $this->add_control( 'text_color', [ 'label' => esc_html__( 'Text Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'default' => '', 'selectors' => [ '{{WRAPPER}}' => 'color: {{VALUE}};', ], 'global' => [ 'default' => Global_Colors::COLOR_TEXT, ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'typography', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_TEXT, ], ] ); $this->end_controls_section(); } protected function render() { // Post CSS should not be printed here because it overrides the already existing post CSS. $this->render_post_content( false, false ); } public function render_plain_content() {} } widgets/site-logo.php 0000644 00000012563 14721752303 0010640 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Widgets; use Elementor\Controls_Manager; use Elementor\Group_Control_Image_Size; use Elementor\Utils; use Elementor\Widget_Image; use ElementorPro\Base\Base_Widget_Trait; use ElementorPro\Modules\ThemeBuilder\Classes\Control_Media_Preview; use ElementorPro\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Site_Logo extends Widget_Image { use Base_Widget_Trait; public function get_name() { // `theme` prefix is to avoid conflicts with a dynamic-tag with same name. return 'theme-site-logo'; } public function get_title() { return esc_html__( 'Site Logo', 'elementor-pro' ); } public function get_icon() { return 'eicon-site-logo'; } public function get_categories() { return [ 'theme-elements' ]; } public function get_keywords() { return [ 'site', 'logo', 'branding' ]; } public function get_inline_css_depends() { return [ [ 'name' => 'image', 'is_core_dependency' => true, ], ]; } protected function register_controls() { parent::register_controls(); $this->update_control( 'section_image', [ 'label' => esc_html__( 'Site Logo', 'elementor-pro' ), ] ); $this->update_control( 'image', [ 'label' => esc_html__( 'Site Logo', 'elementor-pro' ), 'type' => Control_Media_Preview::CONTROL_TYPE, 'src' => $this->get_site_logo(), 'dynamic' => [ 'default' => Plugin::elementor()->dynamic_tags->tag_data_to_tag_text( null, 'site-logo' ), ], ], [ 'recursive' => true, ] ); $this->update_control( 'image_size', [ 'separator' => 'before', 'default' => 'full', ] ); $this->update_control( 'link_to', [ 'options' => [ 'none' => esc_html__( 'None', 'elementor-pro' ), 'site_url' => esc_html__( 'Site URL', 'elementor-pro' ), 'custom' => esc_html__( 'Custom URL', 'elementor-pro' ), 'file' => esc_html__( 'Media File', 'elementor-pro' ), ], 'default' => 'site_url', ], [ 'recursive' => true, ] ); $this->update_control( 'caption_source', [ 'options' => [ 'none' => esc_html__( 'None', 'elementor-pro' ), 'attachment' => esc_html__( 'Attachment Caption', 'elementor-pro' ), ], ] ); $this->remove_control( 'caption' ); $this->add_control( 'change_logo_cta', [ 'type' => Controls_Manager::BUTTON, 'label_block' => true, 'show_label' => false, 'button_type' => 'default elementor-button-center', 'text' => esc_html__( 'Change Site Logo', 'elementor-pro' ), 'event' => 'elementorProSiteLogo:change', ], [ 'position' => [ 'of' => 'image', 'type' => 'control', 'at' => 'after', ], ] ); } /** * TODO: Remove this method when Elementor Core 3.11.0 is required. * Duplicate of render() method from Elementor\Widget_Image class, so it will use the get_link_url() method. * * @return void */ protected function render() { $settings = $this->get_settings_for_display(); if ( empty( $settings['image']['url'] ) ) { return; } $has_caption = $this->has_caption( $settings ); $link = $this->get_link_url( $settings ); if ( $link ) { $this->add_link_attributes( 'link', $link ); if ( Plugin::elementor()->editor->is_edit_mode() ) { $this->add_render_attribute( 'link', 'class', 'elementor-clickable' ); } if ( 'file' === $settings['link_to'] ) { $this->add_lightbox_data_attributes( 'link', $settings['image']['id'], $settings['open_lightbox'] ); } } ?> <?php if ( $has_caption ) : ?> <figure class="wp-caption"> <?php endif; ?> <?php if ( $link ) : ?> <a <?php $this->print_render_attribute_string( 'link' ); ?>> <?php endif; ?> <?php Group_Control_Image_Size::print_attachment_image_html( $settings ); ?> <?php if ( $link ) : ?> </a> <?php endif; ?> <?php if ( $has_caption ) : ?> <figcaption class="widget-image-caption wp-caption-text"><?php echo wp_kses_post( $this->get_caption( $settings ) ); ?></figcaption> <?php endif; ?> <?php if ( $has_caption ) : ?> </figure> <?php endif; ?> <?php } protected function get_html_wrapper_class() { return parent::get_html_wrapper_class() . ' elementor-widget-' . parent::get_name(); } protected function get_link_url( $settings ) { switch ( $settings['link_to'] ) { case 'none': return false; case 'custom': return ( ! empty( $settings['link']['url'] ) ) ? $settings['link'] : false; case 'site_url': return [ 'url' => Plugin::elementor()->dynamic_tags->get_tag_data_content( null, 'site-url' ) ?? '' ]; default: return [ 'url' => $settings['image']['url'] ]; } } // TODO: Remove this method when removing the render() method. private function has_caption( $settings ) { return ( ! empty( $settings['caption_source'] ) && 'none' !== $settings['caption_source'] ); } // TODO: Remove this method when removing the render() method. private function get_caption( $settings ) { $caption = ''; if ( ! empty( $settings['caption_source'] ) && 'attachment' === $settings['caption_source'] ) { $caption = wp_get_attachment_caption( $settings['image']['id'] ); } return $caption; } // Get the site logo from the dynamic tag private function get_site_logo(): string { $site_logo = Plugin::elementor()->dynamic_tags->get_tag_data_content( null, 'site-logo' ); return $site_logo['url'] ?? Utils::get_placeholder_image_src(); } } admin-menu-items/theme-builder-menu-item.php 0000644 00000001205 14721752303 0015054 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\AdminMenuItems; use Elementor\Core\Admin\Menu\Interfaces\Admin_Menu_Item; use Elementor\TemplateLibrary\Source_Local; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } class Theme_Builder_Menu_Item implements Admin_Menu_Item { public function get_capability() { return 'publish_posts'; } public function get_label() { return esc_html__( 'Theme Builder', 'elementor-pro' ); } public function get_parent_slug() { return Source_Local::ADMIN_MENU_SLUG; } public function is_visible() { return true; } public function get_position() { return null; } } skins/posts-archive-skin-cards.php 0000644 00000002064 14721752303 0013235 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Skins; use ElementorPro\Modules\Posts\Skins\Skin_Cards; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Posts_Archive_Skin_Cards extends Skin_Cards { use Posts_Archive_Skin_Base; protected function _register_controls_actions() { add_action( 'elementor/element/archive-posts/section_layout/before_section_end', [ $this, 'register_controls' ] ); add_action( 'elementor/element/archive-posts/section_layout/after_section_end', [ $this, 'register_style_sections' ] ); add_action( 'elementor/element/archive-posts/archive_cards_section_design_image/before_section_end', [ $this, 'register_additional_design_image_controls' ] ); } public function get_id() { return 'archive_cards'; } public function get_title() { return esc_html__( 'Cards', 'elementor-pro' ); } public function get_container_class() { // Use parent class and parent css. return 'elementor-posts--skin-cards'; } /* Remove `posts_per_page` control */ protected function register_post_count_control() {} } skins/posts-archive-skin-classic.php 0000644 00000001637 14721752303 0013567 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Skins; use ElementorPro\Modules\Posts\Skins\Skin_Classic; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Posts_Archive_Skin_Classic extends Skin_Classic { use Posts_Archive_Skin_Base; protected function _register_controls_actions() { add_action( 'elementor/element/archive-posts/section_layout/before_section_end', [ $this, 'register_controls' ] ); add_action( 'elementor/element/archive-posts/section_layout/after_section_end', [ $this, 'register_style_sections' ] ); } public function get_id() { return 'archive_classic'; } public function get_title() { return esc_html__( 'Classic', 'elementor-pro' ); } public function get_container_class() { // Use parent class and parent css. return 'elementor-posts--skin-classic'; } /* Remove `posts_per_page` control */ protected function register_post_count_control() {} } skins/posts-archive-skin-full-content.php 0000644 00000001012 14721752303 0014543 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Skins; use ElementorPro\Modules\Posts\Skins\Skin_Full_Content; use ElementorPro\Modules\Posts\Skins\Skin_Content_Base; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Posts_Archive_Skin_Full_Content extends Skin_Full_Content { use Skin_Content_Base; use Posts_Archive_Skin_Base; public function get_id() { return 'archive_full_content'; } /* Remove `posts_per_page` control */ protected function register_post_count_control() {} } skins/posts-archive-skin-base.php 0000644 00000002726 14721752303 0013060 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Skins; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } trait Posts_Archive_Skin_Base { public function render() { $this->parent->query_posts(); $wp_query = $this->parent->get_query(); if ( ! $wp_query->found_posts ) { $this->render_loop_header(); $should_escape = true; /** * Should escape 'nothing found' message. * * Filters the ability for escaping HTML tags on archive pages that return no * result. * * By default Elementor removes HTML tags from the 'nothing found' message added * by the user, for security reasons. This hook allows developers to change this * behaviour. By setting this to `false`, Elementor will increase flexibility * and allow the user to add HTML tags to the message. * * @param bool $should_escape Whether to escape 'nothing found' message. */ $should_escape = apply_filters( 'elementor_pro/theme_builder/archive/escape_nothing_found_message', $should_escape ); $message = $this->parent->get_settings_for_display( 'nothing_found_message' ); if ( $should_escape ) { $message = esc_html( $message ); } ?> <div class="elementor-posts-nothing-found"> <?php // PHPCS - escaped before if should escape echo $message; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> </div> <?php $this->render_loop_footer(); return; } parent::render(); } } skins/post-comments-skin-classic.php 0000644 00000030675 14721752303 0013614 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Skins; use Elementor\Skin_Base; use Elementor\Controls_Manager; use Elementor\Group_Control_Border; use Elementor\Group_Control_Typography; use Elementor\Scheme_Color; use Elementor\Scheme_Typography; use Elementor\Utils; use ElementorPro\Modules\ThemeBuilder\Module; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Post_Comments_Skin_Classic extends Skin_Base { public function get_id() { return 'skin-classic'; } public function get_title() { return 'Skin Classic'; } protected function _register_controls_actions() { add_action( 'elementor/element/post-comments/section_content/after_section_end', [ $this, 'register_controls' ] ); } public function register_controls() { $this->start_controls_section( 'section_title', [ 'label' => esc_html__( 'Title', 'elementor-pro' ), ] ); $this->add_control( 'title', [ 'label' => esc_html__( 'Title', 'elementor-pro' ), 'default' => '[field id="comment-count"]', 'label_block' => true, 'dynamic' => [ 'types' => [ 'text', ], 'apply_on' => 'value', 'allow_free_text' => true, 'allow_multiple' => true, ], ] ); $this->end_controls_section(); $this->start_controls_section( 'section_content', [ 'label' => esc_html__( 'Content', 'elementor-pro' ), ] ); $this->add_control( 'show_gravatar', [ 'label' => esc_html__( 'Gravatar', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'default' => 'yes', 'label_off' => esc_html__( 'Hide', 'elementor-pro' ), 'label_on' => esc_html__( 'Show', 'elementor-pro' ), ] ); $this->end_controls_section(); $this->start_controls_section( 'section_style', [ 'label' => esc_html__( 'Comments', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_control( 'row_gap', [ 'label' => esc_html__( 'Rows Gap', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'default' => [ 'size' => 10, ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-comment' => 'margin-bottom: {{SIZE}}{{UNIT}};', ], ] ); $this->add_control( 'row_background_color', [ 'label' => esc_html__( 'Background Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'default' => '#ffffff', 'selectors' => [ '{{WRAPPER}} .elementor-comment' => 'background-color: {{VALUE}};', ], 'separator' => 'before', ] ); $this->add_control( 'row_border_color', [ 'label' => esc_html__( 'Border Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-comment' => 'border-color: {{VALUE}};', ], 'separator' => 'before', ] ); $this->add_control( 'row_border_width', [ 'label' => esc_html__( 'Border Width', 'elementor-pro' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ], 'placeholder' => '1', 'selectors' => [ '{{WRAPPER}} .elementor-comment' => 'border-width: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', ], ] ); $this->add_control( 'row_border_radius', [ 'label' => esc_html__( 'Border Radius', 'elementor-pro' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ], 'selectors' => [ '{{WRAPPER}} .elementor-comment' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', ], ] ); $this->end_controls_section(); $this->start_controls_section( 'section_meta_style', [ 'label' => esc_html__( 'Meta', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_control( 'meta_spacing', [ 'label' => esc_html__( 'Spacing', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'default' => [ 'size' => 0, ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-comment .comment-meta' => 'padding-bottom: {{SIZE}}{{UNIT}};', ], ] ); $this->add_control( 'meta_color', [ 'label' => esc_html__( 'Text Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-comment .comment-meta' => 'color: {{VALUE}};', ], 'global' => [ 'default' => Global_Colors::COLOR_TEXT, ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'meta_typography', 'selector' => '{{WRAPPER}} .elementor-comment .comment-meta', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_TEXT, ], ] ); $this->end_controls_section(); $this->start_controls_section( 'section_content_style', [ 'label' => esc_html__( 'Content', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_control( 'content_text_color', [ 'label' => esc_html__( 'Text Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-comment .comment-content' => 'color: {{VALUE}};', ], 'global' => [ 'default' => Global_Colors::COLOR_TEXT, ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'content__typography', 'selector' => '{{WRAPPER}} .elementor-comment .comment-content', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_TEXT, ], ] ); $this->end_controls_section(); $this->start_controls_section( 'section_reply_button_style', [ 'label' => esc_html__( 'Reply Button', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->start_controls_tabs( 'tabs_reply_button_style' ); $this->start_controls_tab( 'tab_reply_button_normal', [ 'label' => esc_html__( 'Normal', 'elementor-pro' ), ] ); $this->add_control( 'reply_button_text_color', [ 'label' => esc_html__( 'Text Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'default' => '', 'selectors' => [ '{{WRAPPER}} .elementor-comment .comment-reply-link' => 'color: {{VALUE}};', ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'reply_button_typography', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_ACCENT, ], 'selector' => '{{WRAPPER}} .elementor-comment .comment-reply-link', ] ); $this->add_control( 'reply_button_background_color', [ 'label' => esc_html__( 'Background Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'global' => [ 'default' => Global_Colors::COLOR_ACCENT, ], 'selectors' => [ '{{WRAPPER}} .elementor-comment .comment-reply-link' => 'background-color: {{VALUE}};', ], ] ); $this->add_group_control( Group_Control_Border::get_type(), [ 'name' => 'reply_button_border', 'label' => esc_html__( 'Border', 'elementor-pro' ), 'placeholder' => '1px', 'default' => '1px', 'selector' => '{{WRAPPER}} .elementor-comment .comment-reply-link', ] ); $this->add_control( 'reply_button_border_radius', [ 'label' => esc_html__( 'Border Radius', 'elementor-pro' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ], 'selectors' => [ '{{WRAPPER}} .elementor-comment .comment-reply-link' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', ], ] ); $this->add_control( 'reply_button_text_padding', [ 'label' => esc_html__( 'Text Padding', 'elementor-pro' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ], 'selectors' => [ '{{WRAPPER}} .elementor-comment .comment-reply-link' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', ], ] ); $this->end_controls_tab(); $this->start_controls_tab( 'tab_reply_button_hover', [ 'label' => esc_html__( 'Hover', 'elementor-pro' ), ] ); $this->add_control( 'button_hover_color', [ 'label' => esc_html__( 'Text Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-comment .comment-reply-link:hover' => 'color: {{VALUE}};', ], ] ); $this->add_control( 'reply_button_background_hover_color', [ 'label' => esc_html__( 'Background Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-comment .comment-reply-link:hover' => 'background-color: {{VALUE}};', ], ] ); $this->add_control( 'reply_button_hover_border_color', [ 'label' => esc_html__( 'Border Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-comment .comment-reply-link:hover' => 'border-color: {{VALUE}};', ], 'condition' => [ $this->get_control_id( 'reply_button_border_border!' ) => '', ], ] ); $this->add_control( 'reply_button_hover_animation', [ 'label' => esc_html__( 'Animation', 'elementor-pro' ), 'type' => Controls_Manager::HOVER_ANIMATION, ] ); $this->end_controls_tab(); $this->end_controls_tabs(); $this->end_controls_section(); } public function render() { Module::instance()->get_preview_manager()->switch_to_preview_query(); // Hack to remove template comment form $comments_template_callback = function() { return __DIR__ . '/../views/comments-template.php'; }; add_filter( 'comments_template', $comments_template_callback ); // The `comments_template` doesn't has an API to pass current widget instance, so make it global $GLOBALS['post_comment_skin_classic'] = $this; comments_template(); remove_filter( 'comments_template', $comments_template_callback ); unset( $GLOBALS['post_comment_skin_classic'] ); Module::instance()->get_preview_manager()->restore_current_query(); } public function comment_callback( $comment, $args, $depth ) { $tag = ( 'div' === $args['style'] ) ? 'div' : 'li'; $class = 'elementor-comment'; if ( ! empty( $args['has_children'] ) ) { $class .= ' parent'; } ?> <<?php Utils::print_validated_html_tag( $tag ); ?> id="comment-<?php comment_ID(); ?>" <?php comment_class( $class, $comment ); ?>> <article id="div-comment-<?php comment_ID(); ?>" class="comment-body"> <div class="comment-meta"> <div class="comment-author vcard"> <?php if ( 0 < $args['avatar_size'] ) { echo get_avatar( $comment, $args['avatar_size'] ); } ?> <?php printf( /* translators: 1: Comment author link, 2: Span open tag, 3: Span closing tag. */ esc_html__( '%1$s %2$ssays:%3$s', 'elementor-pro' ), sprintf( '<b class="fn">%s</b>', get_comment_author_link( $comment ) ), '<span class="says">', '</span>' ); ?> </div><!-- .comment-author --> <div class="comment-metadata"> <a href="<?php echo esc_url( get_comment_link( $comment, $args ) ); ?>"> <time datetime="<?php comment_time( 'c' ); ?>"> <?php /* translators: 1: Comment date, 2: Comment time. */ wp_kses_post( sprintf( esc_html__( '%1$s at %2$s', 'elementor-pro' ), get_comment_date( '', $comment ), get_comment_time() ) ); ?> </time> </a> <?php edit_comment_link( esc_html__( 'Edit', 'elementor-pro' ), '<span class="edit-link">', '</span>' ); ?> </div><!-- .comment-metadata --> <?php if ( '0' == $comment->comment_approved ) : ?> <p class="comment-awaiting-moderation"><?php esc_html_e( 'Your comment is awaiting moderation.', 'elementor-pro' ); ?></p> <?php endif; ?> </div><!-- .comment-meta --> <div class="comment-content"> <?php comment_text(); ?> </div><!-- .comment-content --> <?php comment_reply_link( array_merge( $args, [ 'add_below' => 'div-comment', 'depth' => $depth, 'max_depth' => $args['max_depth'], 'before' => '<div class="reply">', 'after' => '</div>', ] ) ); ?> </article><!-- .comment-body --> </<?php Utils::print_validated_html_tag( $tag ); ?>> <?php } } documents/header-footer-base.php 0000644 00000002756 14721752303 0012730 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; use Elementor\Controls_Manager; use Elementor\Core\DocumentTypes\Post; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Header_Footer_Base extends Theme_Section_Document { public function get_css_wrapper_selector() { return '.elementor-' . $this->get_main_id(); } protected static function get_editor_panel_categories() { // Move to top as active. $categories = [ 'theme-elements' => [ 'title' => esc_html__( 'Site', 'elementor-pro' ), 'active' => true, ], ]; return $categories + parent::get_editor_panel_categories(); } protected function register_controls() { parent::register_controls(); Post::register_style_controls( $this ); $this->update_control( 'section_page_style', [ 'label' => esc_html__( 'Style', 'elementor-pro' ), ] ); $this->start_injection( [ 'of' => 'margin', ] ); $this->add_control( 'hidden_header_footer_style_control', [ 'type' => Controls_Manager::HIDDEN, 'default' => 'hidden_control', 'selectors' => [ '.elementor-theme-builder-content-area' => 'height: 400px;', '.elementor-location-header:before, .elementor-location-footer:before' => 'content: ""; display: table; clear: both;', ], ] ); $this->end_injection(); } protected function get_remote_library_config() { $config = parent::get_remote_library_config(); $config['category'] = $this->get_name(); return $config; } } documents/archive.php 0000644 00000006425 14721752303 0010712 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; use ElementorPro\Modules\ThemeBuilder\Module; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Archive extends Archive_Single_Base { public static function get_properties() { $properties = parent::get_properties(); $properties['location'] = 'archive'; $properties['condition_type'] = 'archive'; return $properties; } public static function get_type() { return 'archive'; } public static function get_title() { return esc_html__( 'Archive', 'elementor-pro' ); } public static function get_plural_title() { return esc_html__( 'Archives', 'elementor-pro' ); } protected static function get_site_editor_icon() { return 'eicon-archive'; } protected static function get_site_editor_tooltip_data() { return [ 'title' => esc_html__( 'What is an Archive Template?', 'elementor-pro' ), 'content' => esc_html__( 'An archive template allows you to easily design the layout and style of archive pages - those pages that show a list of posts (e.g. a blog’s list of recent posts), which may be filtered by terms such as authors, categories, tags, search results, etc.', 'elementor-pro' ), 'tip' => esc_html__( 'If you’d like a different style for a specific category, it’s easy to create a separate archive template whose condition is to only display when users are viewing that category’s list of posts.', 'elementor-pro' ), 'docs' => 'https://go.elementor.com/app-theme-builder-archive', 'video_url' => 'https://www.youtube.com/embed/wxElpEh9bfA', ]; } protected static function get_editor_panel_categories() { $categories = [ 'theme-elements-archive' => [ 'title' => esc_html__( 'Archive', 'elementor-pro' ), ], ]; return $categories + parent::get_editor_panel_categories(); } public static function get_preview_as_default() { return 'archive/recent_posts'; } public static function get_preview_as_options() { $post_type_archives = []; $taxonomies = []; $post_types = Module::get_public_post_types(); foreach ( $post_types as $post_type => $label ) { $post_type_object = get_post_type_object( $post_type ); if ( $post_type_object->has_archive ) { /* translators: %s: Post type label. */ $post_type_archives[ 'post_type_archive/' . $post_type ] = sprintf( esc_html__( '%s Archive', 'elementor-pro' ), $post_type_object->label ); } $post_type_taxonomies = get_object_taxonomies( $post_type, 'objects' ); $post_type_taxonomies = wp_filter_object_list( $post_type_taxonomies, [ 'public' => true, 'show_in_nav_menus' => true, ] ); foreach ( $post_type_taxonomies as $slug => $object ) { /* translators: %s: Taxonomy label. */ $taxonomies[ 'taxonomy/' . $slug ] = sprintf( esc_html__( '%s Archive', 'elementor-pro' ), $object->label ); } } $options = [ 'archive/recent_posts' => esc_html__( 'Recent Posts', 'elementor-pro' ), 'archive/date' => esc_html__( 'Date Archive', 'elementor-pro' ), 'archive/author' => esc_html__( 'Author Archive', 'elementor-pro' ), 'search' => esc_html__( 'Search Results', 'elementor-pro' ), ]; $options += $taxonomies + $post_type_archives; return [ 'archive' => [ 'label' => esc_html__( 'Archive', 'elementor-pro' ), 'options' => $options, ], ]; } } documents/footer.php 0000644 00000002364 14721752303 0010565 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Footer extends Header_Footer_Base { public static function get_properties() { $properties = parent::get_properties(); $properties['location'] = 'footer'; return $properties; } public static function get_type() { return 'footer'; } public static function get_title() { return esc_html__( 'Footer', 'elementor-pro' ); } public static function get_plural_title() { return esc_html__( 'Footers', 'elementor-pro' ); } protected static function get_site_editor_icon() { return 'eicon-footer'; } protected static function get_site_editor_tooltip_data() { return [ 'title' => esc_html__( 'What is a Footer Template?', 'elementor-pro' ), 'content' => esc_html__( 'The footer template allows you to easily design and edit custom WordPress footers without the limits of your theme’s footer design constraints', 'elementor-pro' ), 'tip' => esc_html__( 'You can create multiple footers, and assign each to different areas of your site.', 'elementor-pro' ), 'docs' => 'https://go.elementor.com/app-theme-builder-footer', 'video_url' => 'https://www.youtube.com/embed/xa8DoR4tQrY', ]; } } documents/theme-page-document.php 0000644 00000006706 14721752303 0013123 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; use Elementor\Controls_Manager; use Elementor\Core\DocumentTypes\Post; use Elementor\Modules\PageTemplates\Module as PageTemplatesModule; use Elementor\TemplateLibrary\Source_Local; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Theme_Page_Document extends Theme_Document { /** * Document sub type meta key. */ const REMOTE_CATEGORY_META_KEY = '_elementor_template_sub_type'; public function get_css_wrapper_selector() { return 'body.elementor-page-' . $this->get_main_id(); } public static function get_properties() { $properties = parent::get_properties(); $properties['support_wp_page_templates'] = true; return $properties; } protected function register_controls() { parent::register_controls(); $this->start_injection( [ 'of' => 'post_status', 'fallback' => [ 'of' => 'post_title', ], ] ); $this->add_control( 'page_template', [ 'label' => esc_html__( 'Page Layout', 'elementor-pro' ), 'type' => Controls_Manager::SELECT, 'options' => [ '' => esc_html__( 'Default', 'elementor-pro' ), PageTemplatesModule::TEMPLATE_CANVAS => esc_html__( 'Elementor Canvas', 'elementor-pro' ), PageTemplatesModule::TEMPLATE_HEADER_FOOTER => esc_html__( 'Elementor Full Width', 'elementor-pro' ), ], ] ); $this->add_control( 'page_template_default_description', [ 'type' => Controls_Manager::RAW_HTML, 'raw' => esc_html__( 'Default Page Template from your theme', 'elementor-pro' ), 'content_classes' => 'elementor-descriptor', 'condition' => [ 'page_template' => 'default', ], ] ); $this->add_control( 'page_template_canvas_description', [ 'type' => Controls_Manager::RAW_HTML, 'raw' => esc_html__( 'No header, no footer, just Elementor', 'elementor-pro' ), 'content_classes' => 'elementor-descriptor', 'condition' => [ 'page_template' => PageTemplatesModule::TEMPLATE_CANVAS, ], ] ); $this->add_control( 'page_template_header_footer_description', [ 'type' => Controls_Manager::RAW_HTML, 'raw' => esc_html__( 'This template includes the header, full-width content and footer', 'elementor-pro' ), 'content_classes' => 'elementor-descriptor', 'condition' => [ 'page_template' => PageTemplatesModule::TEMPLATE_HEADER_FOOTER, ], ] ); $this->end_injection(); Post::register_style_controls( $this ); } /** * Add body classes. * * Add the body classes for the `style` controls selector. * * @param $body_classes * * @return array */ public function filter_body_classes( $body_classes ) { // Indicator for edit/preview an `archive` document, so it's a `single` elementor_library post - but need a behavior like an archive. $is_archive_template = 'archive' === Source_Local::get_template_type( get_the_ID() ); $add_body_class = false; if ( $this instanceof Archive && ( is_archive() || is_search() || is_home() || $is_archive_template ) ) { $add_body_class = true; } elseif ( $this instanceof Single_Base && ( is_singular() || is_404() ) && ! $is_archive_template ) { $add_body_class = true; } if ( $add_body_class ) { $body_classes[] = 'elementor-page-' . $this->get_main_id(); } return $body_classes; } public function __construct( array $data = [] ) { if ( $data ) { add_filter( 'body_class', [ $this, 'filter_body_classes' ] ); } parent::__construct( $data ); } } documents/header.php 0000644 00000002456 14721752303 0010521 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Header extends Header_Footer_Base { public static function get_properties() { $properties = parent::get_properties(); $properties['location'] = 'header'; $properties['support_lazyload'] = false; return $properties; } public static function get_type() { return 'header'; } public static function get_title() { return esc_html__( 'Header', 'elementor-pro' ); } public static function get_plural_title() { return esc_html__( 'Headers', 'elementor-pro' ); } protected static function get_site_editor_icon() { return 'eicon-header'; } protected static function get_site_editor_tooltip_data() { return [ 'title' => esc_html__( 'What is a Header Template?', 'elementor-pro' ), 'content' => esc_html__( 'The header template allows you to easily design and edit custom WordPress headers so you are no longer constrained by your theme’s header design limitations.', 'elementor-pro' ), 'tip' => esc_html__( 'You can create multiple headers, and assign each to different areas of your site.', 'elementor-pro' ), 'docs' => 'https://go.elementor.com/app-theme-builder-header', 'video_url' => 'https://www.youtube.com/embed/HHy5RK6W-6I', ]; } } documents/single-base.php 0000644 00000012301 14721752303 0011450 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; use Elementor\DB; use ElementorPro\Modules\FloatingButtons\Documents\Floating_Buttons; use ElementorPro\Modules\ThemeBuilder\Module; use ElementorPro\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Single_Base extends Archive_Single_Base { public static function get_properties() { $properties = parent::get_properties(); $properties['location'] = 'single'; $properties['condition_type'] = 'singular'; return $properties; } public static function get_title() { return esc_html__( 'Single', 'elementor-pro' ); } public static function get_plural_title() { return esc_html__( 'Singles', 'elementor-pro' ); } public static function get_editor_panel_config() { $config = parent::get_editor_panel_config(); $config['widgets_settings']['theme-post-content'] = [ 'show_in_panel' => true, ]; return $config; } protected static function get_editor_panel_categories() { $categories = [ 'theme-elements-single' => [ 'title' => esc_html__( 'Single', 'elementor-pro' ), ], ]; return $categories + parent::get_editor_panel_categories(); } public function before_get_content() { parent::before_get_content(); // For `loop_start` hook. if ( have_posts() ) { the_post(); } } public function after_get_content() { wp_reset_postdata(); parent::after_get_content(); } public function get_container_attributes() { $attributes = parent::get_container_attributes(); if ( is_singular() /* Not 404 */ ) { $post_classes = get_post_class( '', get_the_ID() ); $attributes['class'] .= ' ' . implode( ' ', $post_classes ); } return $attributes; } public function print_content() { $requested_post_id = get_the_ID(); if ( $requested_post_id !== $this->post->ID ) { $requested_document = Module::instance()->get_document( $requested_post_id ); if ( $requested_document instanceof Floating_Buttons ) { $requested_document->print_content(); parent::print_content(); return; } /** * if current requested document is theme-document & it's not a content type ( like header/footer/sidebar ) * show a placeholder instead of content. */ if ( $requested_document && ! $requested_document instanceof Section && $requested_document->get_location() !== $this->get_location() ) { echo '<div class="elementor-theme-builder-content-area">' . esc_html__( 'Content Area', 'elementor-pro' ) . '</div>'; return; } } parent::print_content(); } protected function register_controls() { parent::register_controls(); $post_type = $this->get_main_meta( self::REMOTE_CATEGORY_META_KEY ); $latest_posts = get_posts( [ 'posts_per_page' => 1, 'post_type' => $post_type, ] ); if ( ! empty( $latest_posts ) ) { $this->update_control( 'preview_type', [ 'default' => 'single/' . $post_type, ] ); $this->update_control( 'preview_id', [ 'default' => $latest_posts[0]->ID, ] ); } } public static function get_preview_as_options() { $post_types = Module::get_public_post_types(); $post_types['attachment'] = get_post_type_object( 'attachment' )->label; $post_types_options = []; foreach ( $post_types as $post_type => $label ) { $post_types_options[ 'single/' . $post_type ] = get_post_type_object( $post_type )->labels->singular_name; } return [ 'single' => [ 'label' => esc_html__( 'Single', 'elementor-pro' ), 'options' => $post_types_options, ], 'page/404' => esc_html__( '404', 'elementor-pro' ), ]; } public function get_depended_widget() { return Plugin::elementor()->widgets_manager->get_widget_types( 'theme-post-content' ); } public function get_elements_data( $status = DB::STATUS_PUBLISH ) { $data = parent::get_elements_data(); if ( Plugin::elementor()->preview->is_preview_mode() && self::get_property( 'location' ) === Module::instance()->get_locations_manager()->get_current_location() ) { $has_the_content = false; $depended_widget = $this->get_depended_widget(); Plugin::elementor()->db->iterate_data( $data, function( $element ) use ( &$has_the_content, $depended_widget ) { if ( isset( $element['widgetType'] ) && $depended_widget->get_name() === $element['widgetType'] ) { $has_the_content = true; } } ); if ( ! $has_the_content ) { add_action( 'wp_footer', [ $this, 'preview_error_handler' ] ); } } return $data; } public function preview_error_handler() { $depended_widget_title = $this->get_depended_widget()->get_title(); wp_localize_script( 'elementor-frontend', 'elementorPreviewErrorArgs', [ /* translators: %s: Widget name. */ 'headerMessage' => sprintf( esc_html__( 'The %s Widget was not found in your template.', 'elementor-pro' ), $depended_widget_title ), /* translators: 1: Widget name, 2: Template name. */ 'message' => sprintf( esc_html__( 'You must include the %1$s Widget in your template (%2$s), in order for Elementor to work on this page.', 'elementor-pro' ), $depended_widget_title, '<strong>' . static::get_title() . '</strong>' ), 'strings' => [ 'confirm' => esc_html__( 'Edit Template', 'elementor-pro' ), ], 'confirmURL' => $this->get_edit_url(), ] ); } } documents/theme-document.php 0000644 00000042507 14721752303 0012210 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; use Elementor\Controls_Manager; use Elementor\App\Modules\ImportExport\Module as Import_Export_Module; use Elementor\Modules\Library\Documents\Library_Document; use Elementor\TemplateLibrary\Source_Local; use Elementor\Utils; use ElementorPro\Core\Behaviors\Feature_Lock; use ElementorPro\Modules\QueryControl\Module as QueryModule; use ElementorPro\Modules\ThemeBuilder\Module; use ElementorPro\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Theme_Document extends Library_Document { const LOCATION_META_KEY = '_elementor_location'; public static function get_properties() { $properties = parent::get_properties(); $properties['admin_tab_group'] = Module::ADMIN_LIBRARY_TAB_GROUP; $properties['support_kit'] = true; $properties['support_site_editor'] = true; $properties['support_conditions'] = true; return $properties; } protected static function get_site_editor_route() { return '/site-editor/templates/' . static::get_type(); } protected static function get_site_editor_icon() { return 'eicon eicon-custom'; } protected static function get_site_editor_layout() { return 'grid'; } protected static function get_site_editor_thumbnail_url() { return ELEMENTOR_ASSETS_URL . 'images/app/site-editor/' . static::get_type() . '.svg'; } public static function get_site_editor_config() { return [ 'type' => static::get_type(), 'icon' => static::get_site_editor_icon(), 'title' => static::get_title(), 'page_title' => static::get_title(), 'page_layout' => static::get_site_editor_layout(), // Todo: Remove. Core plugin should use `urls.route`. 'url' => static::get_site_editor_route(), 'urls' => [ 'route' => static::get_site_editor_route(), 'create' => static::get_create_url(), 'thumbnail' => static::get_site_editor_thumbnail_url(), ], 'tooltip_data' => static::get_site_editor_tooltip_data(), 'show_instances' => true, ]; } public static function get_editor_panel_config() { $panel_config = parent::get_editor_panel_config(); $document_config = static::get_properties(); if ( true === $document_config['support_site_editor'] ) { $panel_config['messages']['publish_notification'] = esc_html__( 'Congrats! Your Site Part is Live', 'elementor-pro' ); } return $panel_config; } protected function get_have_a_look_url() { $document_config = static::get_properties(); if ( true === $document_config['support_site_editor'] ) { return ''; } return parent::get_have_a_look_url(); } public static function get_create_url() { $base_create_url = Plugin::elementor()->documents->get_create_new_post_url( Source_Local::CPT ); return add_query_arg( [ 'template_type' => static::get_type() ], $base_create_url ); } protected static function get_site_editor_tooltip_data() { return [ 'title' => '', 'content' => '', 'tip' => '', 'video_url' => '', ]; } public function get_name() { return static::get_type(); } public static function get_lock_behavior_v2() { return new Feature_Lock( [ 'type' => static::get_type(), ] ); } public function get_location_label() { $location = $this->get_location(); $locations_settings = Module::instance()->get_locations_manager()->get_location( $location ); $label = ''; $is_section_doc_type = 'section' === $this->get_name(); if ( $location ) { if ( $is_section_doc_type ) { $label .= isset( $locations_settings['label'] ) ? $locations_settings['label'] : $location; } } $supported = true; if ( $is_section_doc_type ) { if ( $location && ! $locations_settings ) { $supported = false; } } elseif ( ! $location || ! $locations_settings ) { $supported = false; } if ( ! $supported ) { $label .= ' (' . esc_html__( 'Unsupported', 'elementor-pro' ) . ')'; } return $label; } public function before_get_content() { $preview_manager = Module::instance()->get_preview_manager(); $preview_manager->switch_to_preview_query(); } public function after_get_content() { $preview_manager = Module::instance()->get_preview_manager(); $preview_manager->restore_current_query(); } public function get_content( $with_css = false ) { $this->before_get_content(); $content = parent::get_content( $with_css ); $this->after_get_content(); return $content; } public function print_content() { $plugin = Plugin::elementor(); if ( $plugin->preview->is_preview_mode( $this->get_main_id() ) ) { // PHPCS - the method builder_wrapper is safe. echo $plugin->preview->builder_wrapper( '' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } else { // PHPCS - the method get_content is safe. echo $this->get_content(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } public static function get_preview_as_default() { return ''; } public static function get_preview_as_options() { return []; } public function get_container_attributes() { $attributes = parent::get_container_attributes(); $location = Module::instance()->get_locations_manager()->get_current_location(); if ( $location ) { $attributes['class'] .= ' elementor-location-' . $location; } return $attributes; } /** * @static * @since 2.0.0 * @access public * * @return string */ public function get_edit_url() { $url = parent::get_edit_url(); if ( isset( $_GET['action'] ) && 'elementor_new_post' === $_GET['action'] ) { $url .= '#library'; } return $url; } public function get_export_summary() { $summary = parent::get_export_summary(); $summary['location'] = $this->get_location(); $theme_builder = Plugin::instance()->modules_manager->get_modules( 'theme-builder' ); $conditions = $theme_builder->get_conditions_manager()->get_document_conditions( $this ); foreach ( $conditions as $condition ) { if ( 'include' === $condition['type'] && ! $condition['sub_id'] ) { $summary['conditions'][] = $condition; break; } } return $summary; } public function import( array $data ) { parent::import( $data ); /** @var Module $theme_builder */ $theme_builder = Plugin::instance()->modules_manager->get_modules( 'theme-builder' ); $conditions = isset( $data['import_settings']['conditions'] ) ? $data['import_settings']['conditions'] : []; if ( ! empty( $conditions ) ) { $condition = $conditions[0]; $condition = rtrim( implode( '/', $condition ), '/' ); $conflicts = $theme_builder->get_conditions_manager()->get_conditions_conflicts_by_location( $condition, $this->get_location() ); if ( $conflicts ) { /** @var Import_Export_Module $import_export_module */ $import_export_module = Plugin::elementor()->app->get_component( 'import-export' ); $override_conditions = $import_export_module->import->get_settings( 'overrideConditions' ); if ( ! $override_conditions || ! in_array( $data['id'], $override_conditions, true ) ) { return; } foreach ( $conflicts as $template ) { /** @var Theme_Document $template_document */ $template_document = Plugin::elementor()->documents->get( $template['template_id'] ); $template_conditions = $theme_builder->get_conditions_manager()->get_document_conditions( $template_document ); foreach ( $template_conditions as $index => $template_condition ) { if ( in_array( $template_condition, $conditions, true ) ) { unset( $template_conditions[ $index ] ); } } $theme_builder->get_conditions_manager()->save_conditions( $template_document->get_main_id(), $template_conditions ); } } } $theme_builder->get_conditions_manager()->save_conditions( $this->get_main_id(), $conditions ); } protected function register_controls() { parent::register_controls(); $this->start_controls_section( 'preview_settings', [ 'label' => esc_html__( 'Preview Settings', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_SETTINGS, ] ); $this->add_control( 'preview_type', [ 'label' => esc_html__( 'Preview Dynamic Content as', 'elementor-pro' ), 'label_block' => true, 'type' => Controls_Manager::SELECT, 'default' => $this::get_preview_as_default(), 'groups' => $this::get_preview_as_options(), 'export' => false, ] ); $this->add_control( 'preview_id', [ 'type' => QueryModule::QUERY_CONTROL_ID, 'label_block' => true, 'autocomplete' => [ 'object' => QueryModule::QUERY_OBJECT_JS, ], 'export' => false, 'condition' => [ 'preview_type!' => [ '', 'search', ], ], ] ); $this->add_control( 'preview_search_term', [ 'label' => esc_html__( 'Search Term', 'elementor-pro' ), 'export' => false, 'condition' => [ 'preview_type' => 'search', ], ] ); $this->add_control( 'apply_preview', [ 'type' => Controls_Manager::BUTTON, 'label' => esc_html__( 'Apply & Preview', 'elementor-pro' ), 'label_block' => true, 'show_label' => false, 'text' => esc_html__( 'Apply & Preview', 'elementor-pro' ), 'event' => 'elementorThemeBuilder:ApplyPreview', ] ); $this->end_controls_section(); $this->inject_html_tag_control(); } /** * @since 2.9.0 * * If the implementing document uses optional wrapper HTML tags, this method injects the control to choose the tag */ private function inject_html_tag_control() { $wrapper_tags = $this->get_wrapper_tags(); // Only proceed if the implementing document has optional wrapper HTML tags to replace 'div' if ( ! $wrapper_tags ) { return; } // Add 'div' to the beginning of the list of wrapper tags array_unshift( $wrapper_tags, 'div' ); /** * Inject the control that sets the HTML tag for the header/footer wrapper element */ $this->start_injection( [ 'of' => 'post_status', 'fallback' => [ 'of' => 'post_title', ], ] ); $this->add_control( 'content_wrapper_html_tag', [ 'label' => esc_html__( 'HTML Tag', 'elementor-pro' ), 'type' => Controls_Manager::SELECT, 'default' => 'div', 'options' => array_combine( $wrapper_tags, $wrapper_tags ), ] ); $this->end_injection(); } /** * @param null $elements_data * @since 2.9.0 * @access public * * Overwrite method from document.php to check for user-selected tags to use as the document wrapper element */ public function print_elements_with_wrapper( $elements_data = null ) { // Check if the implementing document has optional wrapper tags $has_wrapper_tags = $this->get_wrapper_tags(); $settings = $this->get_settings_for_display(); $wrapper_tag = 'div'; // Only proceed if the inheriting document has optional wrapper HTML tags to replace 'div' if ( $has_wrapper_tags ) { $wrapper_tag = Utils::validate_html_tag( $settings['content_wrapper_html_tag'] ); } if ( ! $elements_data ) { $elements_data = $this->get_elements_data(); } ?> <<?php Utils::print_validated_html_tag( $wrapper_tag ); ?> <?php Utils::print_html_attributes( $this->get_container_attributes() ); ?>> <?php $this->print_elements( $elements_data ); ?> </<?php Utils::print_validated_html_tag( $wrapper_tag ); ?>> <?php } public function get_wrapper_tags() { // 'div' is added later, no need to include it in this list return [ 'main', 'article', 'header', 'footer', 'section', 'aside', 'nav', ]; } public function get_elements_raw_data( $data = null, $with_html_content = false ) { $preview_manager = Module::instance()->get_preview_manager(); $preview_manager->switch_to_preview_query(); $editor_data = parent::get_elements_raw_data( $data, $with_html_content ); $preview_manager->restore_current_query(); return $editor_data; } public function render_element( $data ) { $preview_manager = Module::instance()->get_preview_manager(); $preview_manager->switch_to_preview_query(); $render_html = parent::render_element( $data ); $preview_manager->restore_current_query(); return $render_html; } public function get_wp_preview_url() { // Ajax request from editor. // PHPCS - the method is safe - just retrieving a value. if ( ! empty( $_POST['initial_document_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing return parent::get_wp_preview_url(); } $preview_id = (int) $this->get_settings( 'preview_id' ); $post_id = $this->get_main_id(); list( $preview_category, $preview_object_type ) = array_pad( explode( '/', $this->get_settings( 'preview_type' ) ), 2, '' ); $home_url = trailingslashit( home_url() ); switch ( $preview_category ) { case 'archive': switch ( $preview_object_type ) { case 'author': if ( empty( $preview_id ) ) { $preview_id = get_current_user_id(); } $preview_url = get_author_posts_url( $preview_id ); break; case 'date': $preview_url = add_query_arg( 'year', gmdate( 'Y' ), $home_url ); break; } break; case 'search': $preview_url = add_query_arg( 's', $this->get_settings( 'preview_search_term' ), $home_url ); break; case 'taxonomy': $term = get_term( $preview_id ); if ( $term && ! is_wp_error( $term ) ) { $preview_url = get_term_link( $preview_id ); } break; case 'page': switch ( $preview_object_type ) { case 'home': $preview_url = get_post_type_archive_link( 'post' ); break; case 'front': $preview_url = $home_url; break; case '404': $preview_url = add_query_arg( 'p', '-1', $home_url ); break; } break; case 'post_type_archive': $post_type = $preview_object_type; if ( post_type_exists( $post_type ) ) { $preview_url = get_post_type_archive_link( $post_type ); } break; case 'single': $post = get_post( $preview_id ); if ( $post ) { $preview_url = get_permalink( $post ); } break; } // End switch(). if ( empty( $preview_url ) ) { $preview_url = $this->get_permalink(); } $query_args = [ 'preview' => true, 'preview_nonce' => wp_create_nonce( 'post_preview_' . $post_id ), 'theme_template_id' => $post_id, ]; $preview_url = set_url_scheme( add_query_arg( $query_args, $preview_url ) ); /** * Document "WordPress preview" URL. * * Filters the WordPress preview URL. * * @since 2.0.0 * * @param string $preview_url Document preview URL. * @param Theme_Document $this An instance of the theme document. */ $preview_url = apply_filters( 'elementor/document/wp_preview_url', $preview_url, $this ); return $preview_url; } public function get_preview_as_query_args() { $preview_id = (int) $this->get_settings( 'preview_id' ); list( $preview_category, $preview_object_type ) = array_pad( explode( '/', $this->get_settings( 'preview_type' ) ), 2, '' ); switch ( $preview_category ) { case 'archive': switch ( $preview_object_type ) { case 'author': if ( empty( $preview_id ) ) { $preview_id = get_current_user_id(); } $query_args = [ 'author' => $preview_id, ]; break; case 'date': $query_args = [ 'year' => gmdate( 'Y' ), ]; break; case 'recent_posts': $query_args = [ 'post_type' => 'post', ]; break; } break; case 'search': $query_args = [ 's' => $this->get_settings( 'preview_search_term' ), ]; break; case 'taxonomy': case 'post_taxonomy': case 'product_taxonomy': $term = $this->get_taxonomy_term( $preview_id, $preview_object_type ); if ( $term && ! is_wp_error( $term ) ) { $query_args = [ 'tax_query' => [ [ 'taxonomy' => $term->taxonomy, 'terms' => [ $term->term_id ], 'field' => 'id', ], ], ]; } break; case 'page': switch ( $preview_object_type ) { case 'home': $query_args = []; break; case 'front': $query_args = [ 'p' => get_option( 'page_on_front' ), 'post_type' => 'page', ]; break; case '404': $query_args = [ 'p' => -1, ]; break; } break; case 'post_type_archive': $post_type = $preview_object_type; if ( post_type_exists( $post_type ) ) { $query_args = [ 'post_type' => $post_type, ]; } break; case 'single': $query_args = [ 'post_type' => $preview_object_type, 'p' => $preview_id, ]; break; } // End switch(). if ( empty( $query_args ) ) { $query_args = [ 'p' => $this->get_main_id(), 'post_type' => $this->get_main_post()->post_type, ]; } return $query_args; } public function after_preview_switch_to_query() { global $wp_query; if ( 'archive/recent_posts' === $this->get_settings( 'preview_type' ) ) { $wp_query->is_archive = true; } } public function get_location() { $value = self::get_property( 'location' ); if ( ! $value ) { $value = $this->get_main_meta( self::LOCATION_META_KEY ); } return $value; } public function get_initial_config() { $config = parent::get_initial_config(); $config['support_site_editor'] = static::get_property( 'support_site_editor' ); return $config; } /** * @param $preview_id * @param $preview_object_type * @return \WP_Error|\WP_Term|null */ private function get_taxonomy_term( $preview_id, $preview_object_type ) { if ( ! empty( $preview_id ) ) { return get_term( $preview_id ); } $terms = get_terms( [ 'taxonomy' => $preview_object_type, ] ); return reset( $terms ); } } documents/single-post.php 0000644 00000002446 14721752303 0011534 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Single_Post extends Single_Base { public static function get_type() { return 'single-post'; } public static function get_title() { return esc_html__( 'Single Post', 'elementor-pro' ); } public static function get_plural_title() { return esc_html__( 'Single Posts', 'elementor-pro' ); } protected static function get_site_editor_icon() { return 'eicon-single-post'; } protected static function get_site_editor_tooltip_data() { return [ 'title' => esc_html__( 'What is a Single Post Template?', 'elementor-pro' ), 'content' => esc_html__( 'A single post template allows you to easily design the layout and style of posts, ensuring a design consistency throughout all your blog posts, for example.', 'elementor-pro' ), 'tip' => esc_html__( 'You can create multiple single post templates, and assign each to a different category.', 'elementor-pro' ), 'docs' => 'https://go.elementor.com/app-theme-builder-post', 'video_url' => 'https://www.youtube.com/embed/8Fk-Edu7DL0', ]; } protected function get_remote_library_config() { $config = parent::get_remote_library_config(); $config['category'] = 'single post'; return $config; } } documents/single-page.php 0000644 00000002537 14721752303 0011464 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Single_Page extends Single_Base { public static function get_type() { return 'single-page'; } public static function get_sub_type() { return 'page'; } public static function get_title() { return esc_html__( 'Single Page', 'elementor-pro' ); } public static function get_plural_title() { return esc_html__( 'Single Pages', 'elementor-pro' ); } protected static function get_site_editor_icon() { return 'eicon-single-page'; } protected static function get_site_editor_tooltip_data() { return [ 'title' => esc_html__( 'What is a Single Page Template?', 'elementor-pro' ), 'content' => esc_html__( 'A single page template allows you to easily create the layout and style of pages, ensuring design consistency across all the pages of your site.', 'elementor-pro' ), 'tip' => esc_html__( 'You can create multiple single page templates, and assign each to different areas of your site.', 'elementor-pro' ), 'docs' => 'https://go.elementor.com/app-theme-builder-page', 'video_url' => 'https://www.youtube.com/embed/_y5eZ60lVoY', ]; } protected function get_remote_library_config() { $config = parent::get_remote_library_config(); $config['category'] = 'single page'; return $config; } } documents/search-results.php 0000644 00000003427 14721752303 0012234 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Search_Results extends Archive { public function get_name() { return 'search-results'; } public static function get_type() { return 'search-results'; } public static function get_sub_type() { return 'search'; } public static function get_title() { return esc_html__( 'Search Results', 'elementor-pro' ); } public static function get_plural_title() { return esc_html__( 'Search Results', 'elementor-pro' ); } protected static function get_site_editor_icon() { return 'eicon-search-results'; } protected static function get_site_editor_tooltip_data() { return [ 'title' => esc_html__( 'What is a Search Results Template?', 'elementor-pro' ), 'content' => esc_html__( 'You can easily control the layout and design of the Search Results page with the Search Results template, which is simply a special archive template just for displaying search results.', 'elementor-pro' ), 'tip' => esc_html__( 'You can customize the message if there are no results for the search term.', 'elementor-pro' ), 'docs' => 'https://go.elementor.com/app-theme-builder-search-results', 'video_url' => 'https://www.youtube.com/embed/KKkIU_L5sDo', ]; } public static function get_preview_as_default() { return 'search'; } public static function get_preview_as_options() { $options = [ 'search' => esc_html__( 'Search Results', 'elementor-pro' ), ]; return [ 'archive' => [ 'label' => esc_html__( 'Archive', 'elementor-pro' ), 'options' => $options, ], ]; } protected function get_remote_library_config() { $config = parent::get_remote_library_config(); $config['category'] = 'archive'; return $config; } } documents/archive-single-base.php 0000644 00000002737 14721752303 0013103 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; use ElementorPro\Core\Utils; use ElementorPro\Modules\ThemeBuilder\Module as ThemeBuilderModule; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Archive_Single_Base extends Theme_Page_Document { /** * Document sub type meta key. */ const REMOTE_CATEGORY_META_KEY = '_elementor_template_sub_type'; public static function get_sub_type() { return ''; } public static function get_create_url() { $create_url = parent::get_create_url(); $sub_type = static::get_sub_type(); if ( $sub_type ) { $create_url = add_query_arg( static::REMOTE_CATEGORY_META_KEY, static::get_sub_type(), $create_url ); } return $create_url; } /** * @access public */ public function save_template_type() { parent::save_template_type(); $this->save_sub_type_condition(); } private function save_sub_type_condition() { $conditions_manager = ThemeBuilderModule::instance()->get_conditions_manager(); $sub_type = Utils::_unstable_get_super_global_value( $_REQUEST, self::REMOTE_CATEGORY_META_KEY ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( ! empty( $sub_type ) && $conditions_manager->get_condition( $sub_type ) ) { $this->update_meta( self::REMOTE_CATEGORY_META_KEY, $sub_type ); $conditions_manager->save_conditions( $this->post->ID, [ [ 'include', $this->get_property( 'condition_type' ), $sub_type, ], ] ); } } } documents/single.php 0000644 00000002023 14721752303 0010540 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Single extends Single_Base { public static function get_type() { return 'single'; } public static function get_title() { return esc_html__( 'Single', 'elementor-pro' ); } public static function get_plural_title() { return esc_html__( 'Singles', 'elementor-pro' ); } protected function get_remote_library_config() { $config = parent::get_remote_library_config(); // Fallback for old multipurpose `single` documents. $category = $this->get_meta( self::REMOTE_CATEGORY_META_KEY ); if ( $category ) { if ( 'not_found404' === $category ) { $category = '404 page'; } else { $category = 'single ' . $category; } $config['category'] = $category; } else { $config['category'] = 'single post'; } return $config; } protected static function get_site_editor_thumbnail_url() { return ELEMENTOR_ASSETS_URL . 'images/app/site-editor/single-post.svg'; } } documents/section.php 0000644 00000004763 14721752303 0010740 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; use Elementor\Controls_Manager; use ElementorPro\Modules\ThemeBuilder\Module; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Section extends Theme_Section_Document { public function get_name() { return 'section'; } public static function get_type() { return 'section'; } public static function get_title() { return esc_html__( 'Section', 'elementor-pro' ); } public static function get_plural_title() { return esc_html__( 'Sections', 'elementor-pro' ); } public static function get_properties() { $properties = parent::get_properties(); $properties['admin_tab_group'] = 'library'; $properties['support_site_editor'] = false; return $properties; } protected function register_controls() { parent::register_controls(); Module::instance()->get_locations_manager()->register_locations(); $locations = Module::instance()->get_locations_manager()->get_locations( [ 'public' => true, ] ); if ( empty( $locations ) ) { return; } $this->start_controls_section( 'location_settings', [ 'label' => esc_html__( 'Location Settings', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_SETTINGS, ] ); $options = [ '' => esc_html__( 'Select', 'elementor-pro' ), ]; foreach ( $locations as $location => $settings ) { $options[ $location ] = $settings['label']; } $this->add_control( 'location', [ 'label' => esc_html__( 'Location', 'elementor-pro' ), 'label_block' => true, 'type' => Controls_Manager::SELECT, 'default' => $this->get_location(), 'save_default' => true, 'options' => $options, ] ); $this->add_control( 'apply_location', [ 'type' => Controls_Manager::BUTTON, 'label' => '', 'text' => esc_html__( 'Apply', 'elementor-pro' ), 'event' => 'elementorThemeBuilder:ApplyPreview', ] ); $this->end_controls_section(); } public function get_export_data() { $data = parent::get_export_data(); $data['location'] = $this->get_location(); return $data; } public function save_settings( $settings ) { if ( isset( $settings['location'] ) ) { if ( empty( $settings['location'] ) ) { $this->delete_main_meta( '_elementor_location' ); } else { $this->update_main_meta( '_elementor_location', $settings['location'] ); unset( $settings['location'] ); } Module::instance()->get_conditions_manager()->get_cache()->regenerate(); } parent::save_settings( $settings ); } } documents/error-404.php 0000644 00000003062 14721752303 0010721 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Error_404 extends Single_Base { public static function get_type() { return 'error-404'; } public static function get_sub_type() { return 'not_found404'; } public static function get_title() { return esc_html__( 'Error 404', 'elementor-pro' ); } public static function get_plural_title() { return esc_html__( 'Error 404', 'elementor-pro' ); } protected static function get_site_editor_icon() { return 'eicon-error-404'; } protected static function get_site_editor_tooltip_data() { return [ 'title' => esc_html__( 'What is a 404 Page Template?', 'elementor-pro' ), 'content' => esc_html__( 'A 404 page template allows you to easily design the layout and style of the page that is displayed when a visitor arrives at a page that does not exist.', 'elementor-pro' ), 'tip' => esc_html__( 'Keep your site\'s visitors happy when they get lost by displaying your recent posts, a search bar, or any information that might help the user find what they were looking for.', 'elementor-pro' ), 'docs' => 'https://go.elementor.com/app-theme-builder-error-404', 'video_url' => 'https://www.youtube.com/embed/ACCNp9tBMQg', ]; } public static function get_preview_as_options() { return [ 'page/404' => esc_html__( '404', 'elementor-pro' ), ]; } protected function get_remote_library_config() { $config = parent::get_remote_library_config(); $config['category'] = '404 page'; return $config; } } documents/theme-section-document.php 0000644 00000001550 14721752303 0013643 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\Documents; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Theme_Section_Document extends Theme_Document { public static function get_properties() { $properties = parent::get_properties(); $properties['condition_type'] = 'general'; return $properties; } protected static function get_site_editor_layout() { return 'strip'; } public static function get_preview_as_default() { return ''; } public static function get_preview_as_options() { return array_merge( [ '' => esc_html__( 'Select...', 'elementor-pro' ), ], Archive::get_preview_as_options(), Single::get_preview_as_options() ); } protected function get_remote_library_config() { $config = parent::get_remote_library_config(); $config['category'] = ''; return $config; } } theme-support/generate-press-theme-support.php 0000644 00000003513 14721752303 0015635 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\ThemeSupport; use Elementor\TemplateLibrary\Source_Local; use ElementorPro\Modules\ThemeBuilder\Classes\Locations_Manager; use ElementorPro\Modules\ThemeBuilder\Module; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class GeneratePress_Theme_Support { /** * @param Locations_Manager $manager */ public function register_locations( $manager ) { $manager->register_core_location( 'header' ); $manager->register_core_location( 'footer' ); } public function metabox_capability( $capability ) { if ( Source_Local::CPT === get_post_type() ) { $capability = 'do_not_allow'; } return $capability; } public function do_header() { $did_location = Module::instance()->get_locations_manager()->do_location( 'header' ); if ( $did_location ) { remove_action( 'generate_header', 'generate_construct_header' ); remove_action( 'generate_after_header', 'generate_add_navigation_after_header', 5 ); } } public function do_footer() { $did_location = Module::instance()->get_locations_manager()->do_location( 'footer' ); if ( $did_location ) { remove_action( 'generate_footer', 'generate_construct_footer' ); remove_action( 'generate_footer', 'generate_construct_footer_widgets', 5 ); } } public function body_classes( $classes ) { if ( in_array( 'elementor-template-full-width', $classes ) ) { $classes[] = 'full-width-content'; } return $classes; } public function __construct() { add_action( 'elementor/theme/register_locations', [ $this, 'register_locations' ] ); add_filter( 'generate_metabox_capability', [ $this, 'metabox_capability' ] ); add_action( 'generate_header', [ $this, 'do_header' ], 0 ); add_action( 'generate_footer', [ $this, 'do_footer' ], 0 ); add_filter( 'body_class', [ $this, 'body_classes' ], 11 ); } } theme-support/safe-mode-theme-support.php 0000644 00000001604 14721752303 0014550 0 ustar 00 <?php namespace ElementorPro\Modules\ThemeBuilder\ThemeSupport; use ElementorPro\Modules\ThemeBuilder\Classes\Locations_Manager; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Safe_Mode_Theme_Support { /** * @param Locations_Manager $manager */ public function register_locations( $manager ) { $manager->register_core_location( 'header' ); $manager->register_core_location( 'footer' ); } public function do_header() { elementor_theme_do_location( 'header' ); } public function do_footer() { elementor_theme_do_location( 'footer' ); } public function __construct() { add_action( 'elementor/theme/register_locations', [ $this, 'register_locations' ] ); add_action( 'elementor/page_templates/canvas/before_content', [ $this, 'do_header' ], 0 ); add_action( 'elementor/page_templates/canvas/after_content', [ $this, 'do_footer' ], 0 ); } } assets/images/conditions-tab.svg 0000644 00000002716 14721752303 0012763 0 ustar 00 <svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M18.9473 11.2421H30.3157" stroke="#E879F9" stroke-width="1.64211"/> <mask id="path-2-inside-1_1909_232654" fill="white"> <rect x="17.6836" y="8.8421" width="13.8947" height="11.3684" rx="1.26316"/> </mask> <rect x="17.6836" y="8.8421" width="13.8947" height="11.3684" rx="1.26316" stroke="#9DA5AE" stroke-width="3.28421" mask="url(#path-2-inside-1_1909_232654)"/> <path d="M8.8418 31.4526H20.2102" stroke="#E879F9" stroke-width="1.64211"/> <mask id="path-4-inside-2_1909_232654" fill="white"> <rect x="7.57812" y="29.0526" width="13.8947" height="11.3684" rx="1.26316"/> </mask> <rect x="7.57812" y="29.0526" width="13.8947" height="11.3684" rx="1.26316" stroke="#9DA5AE" stroke-width="3.28421" mask="url(#path-4-inside-2_1909_232654)"/> <path d="M29.0527 31.4526H40.4212" stroke="#E879F9" stroke-width="1.64211"/> <mask id="path-6-inside-3_1909_232654" fill="white"> <rect x="27.7891" y="29.0526" width="13.8947" height="11.3684" rx="1.26316"/> </mask> <rect x="27.7891" y="29.0526" width="13.8947" height="11.3684" rx="1.26316" stroke="#9DA5AE" stroke-width="3.28421" mask="url(#path-6-inside-3_1909_232654)"/> <path d="M14.5254 30.3158V25.8948C14.5254 25.1971 15.0909 24.6316 15.7885 24.6316H33.4728C34.1704 24.6316 34.7359 25.1971 34.7359 25.8947V30.3158" stroke="#9DA5AE" stroke-width="1.64211"/> <path d="M24.6316 18.9474V24" stroke="#9DA5AE" stroke-width="1.64211"/> </svg>
| ver. 1.4 |
Github
|
.
| PHP 7.4.3-4ubuntu2.24 | Генерация страницы: 0.01 |
proxy
|
phpinfo
|
Настройка