m( [ 'content' => $data['content'], 'title' => $data['title'], 'type' => $data['type'], 'page_settings' => $data['page_settings'], ] ); if ( is_wp_error( $template_id ) ) { return $template_id; } return $this->get_item( $template_id ); } /** * Prepare template to export. * * Retrieve the relevant template data and return them as an array. * * @since 1.6.0 * @access private * * @param int $template_id The template ID. * * @return \WP_Error|array Exported template data. */ private function prepare_template_export( $template_id ) { $document = Plugin::$instance->documents->get( $template_id ); $template_data = $document->get_export_data(); if ( empty( $template_data['content'] ) ) { return new \WP_Error( 'empty_template', 'The template is empty' ); } $content = apply_filters( 'elementor/template_library/sources/local/export/elements', $template_data['content'] ); $export_data = [ 'content' => $content, 'page_settings' => $template_data['settings'], 'version' => DB::DB_VERSION, 'title' => $document->get_main_post()->post_title, 'type' => self::get_template_type( $template_id ), ]; $this->attach_global_styles_to_data( $export_data, $content, $template_id ); return [ 'name' => 'elementor-' . $template_id . '-' . gmdate( 'Y-m-d' ) . '.json', 'content' => wp_json_encode( $export_data ), ]; } /** * Get template label by type. * * Retrieve the template label for any given template type. * * @since 2.0.0 * @access private * * @param string $template_type Template type. * * @return string Template label. */ private function get_template_label_by_type( $template_type ) { $document_types = Plugin::instance()->documents->get_document_types(); if ( isset( $document_types[ $template_type ] ) ) { $template_label = call_user_func( [ $document_types[ $template_type ], 'get_title' ] ); } else { $template_label = ucwords( str_replace( [ '_', '-' ], ' ', $template_type ) ); } /** * Template label by template type. * * Filters the template label by template type in the template library . * * @since 2.0.0 * * @param string $template_label Template label. * @param string $template_type Template type. */ $template_label = apply_filters( 'elementor/template-library/get_template_label_by_type', $template_label, $template_type ); return $template_label; } private function get_template_labels_by_type( $template_type ) { $labels = [ 'singular' => '', 'plural' => '', ]; if ( ! $template_type ) { return $labels; } $document_types = Plugin::instance()->documents->get_document_types(); if ( isset( $document_types[ $template_type ] ) ) { $doc_type = $document_types[ $template_type ]; $labels['singular'] = call_user_func( [ $doc_type, 'get_title' ] ); $labels['plural'] = call_user_func( [ $doc_type, 'get_plural_title' ] ); } else { $labels['singular'] = $this->get_template_label_by_type( $template_type ); } if ( ! $labels['plural'] ) { $labels['plural'] = $labels['singular']; } return $labels; } private function get_current_template_labels() { $labels = [ 'singular' => '', 'plural' => '', ]; $template_type = Utils::get_super_global_value( $_GET, self::TAXONOMY_TYPE_SLUG ); if ( $template_type ) { return $this->get_template_labels_by_type( $template_type ); } $current_tabs_group = $this->get_current_tab_group(); if ( $current_tabs_group ) { $doc_types = Plugin::$instance->documents->get_document_types( [ 'admin_tab_group' => $current_tabs_group, ], 'and' ); if ( 1 === count( $doc_types ) ) { $doc_type = reset( $doc_types ); $labels['singular'] = call_user_func( [ $doc_type, 'get_title' ] ); $labels['plural'] = call_user_func( [ $doc_type, 'get_plural_title' ] ); } } if ( ! $labels['plural'] ) { $labels['plural'] = $labels['singular']; } return $labels; } /** * Filter template types in admin query. * * Update the template types in the main admin query. * * Fired by `parse_query` action. * * @since 2.4.0 * @access public * * @param \WP_Query $query The `WP_Query` instance. */ public function admin_query_filter_types( \WP_Query $query ) { if ( ! $this->is_current_screen() || ! empty( $query->query_vars['meta_key'] ) ) { return; } $current_tabs_group = $this->get_current_tab_group(); if ( isset( $query->query_vars[ self::TAXONOMY_CATEGORY_SLUG ] ) && '-1' === $query->query_vars[ self::TAXONOMY_CATEGORY_SLUG ] ) { unset( $query->query_vars[ self::TAXONOMY_CATEGORY_SLUG ] ); } if ( empty( $current_tabs_group ) ) { return; } $doc_types = Plugin::$instance->documents->get_document_types( [ 'admin_tab_group' => $current_tabs_group, ] ); $query->query_vars['meta_key'] = Document::TYPE_META_KEY; $query->query_vars['meta_value'] = array_keys( $doc_types ); } /** * Add template library actions. * * Register filters and actions for the template library. * * @since 2.0.0 * @access private */ private function add_actions() { if ( is_admin() ) { add_action( 'admin_init', [ $this, 'redirect_categories_page_to_saved_templates_page' ] ); add_action( 'elementor/editor-one/menu/register', function ( Menu_Data_Provider $menu_data_provider ) { $this->register_editor_one_menu( $menu_data_provider ); } ); add_action( 'elementor/editor-one/menu/excluded_level4_slugs', function ( array $excluded_slugs ): array { $excluded_slugs[] = 'edit.php?post_type=elementor_library#add_new'; $excluded_slugs[] = 'edit-tags.php?taxonomy=elementor_library_category&post_type=elementor_library'; return $excluded_slugs; } ); add_filter( 'elementor/editor-one/menu/elementor_post_types', function ( array $elementor_post_types ): array { $elementor_post_types[ self::CPT ] = []; return $elementor_post_types; } ); add_filter( 'elementor/editor-one/admin-edit-post-types', function ( array $post_types ): array { $post_types[] = self::CPT; return $post_types; } ); add_filter( 'admin_title', [ $this, 'admin_title' ], 10, 2 ); add_action( 'all_admin_notices', [ $this, 'replace_admin_heading' ] ); add_filter( 'post_row_actions', [ $this, 'post_row_actions' ], 10, 2 ); add_action( 'admin_footer', [ $this, 'admin_import_template_form' ] ); add_action( 'save_post', [ $this, 'on_save_post' ], 10, 2 ); add_filter( 'display_post_states', [ $this, 'remove_elementor_post_state_from_library' ], 11, 2 ); add_action( 'parse_query', [ $this, 'admin_query_filter_types' ] ); // Template filter by category. add_action( 'restrict_manage_posts', [ $this, 'add_filter_by_category' ] ); // Template type column. add_action( 'manage_' . self::CPT . '_posts_columns', [ $this, 'admin_columns_headers' ] ); add_action( 'manage_' . self::CPT . '_posts_custom_column', [ $this, 'admin_columns_content' ], 10, 2 ); // Template library bulk actions. add_filter( 'bulk_actions-edit-elementor_library', [ $this, 'admin_add_bulk_export_action' ] ); add_filter( 'handle_bulk_actions-edit-elementor_library', [ $this, 'admin_export_multiple_templates' ], 10, 3 ); // Print template library tabs. add_filter( 'views_edit-' . self::CPT, [ $this, 'admin_print_tabs' ] ); // Show blank state. add_action( 'manage_posts_extra_tablenav', [ $this, 'maybe_render_blank_state' ] ); } add_action( 'elementor/document/after_save', [ $this, 'on_template_update' ], 10, 2 ); add_action( 'template_redirect', [ $this, 'block_template_frontend' ] ); // Remove elementor library templates from WP Sitemap add_filter( 'wp_sitemaps_post_types', function( $post_types ) { return $this->remove_elementor_cpt_from_sitemap( $post_types ); } ); } public function on_template_update( \Elementor\Core\Base\Document $document, array $data ) { if ( ! empty( $data['post_title'] ) ) { wp_update_post( [ 'ID' => $document->get_main_id(), 'post_title' => $data['post_title'], ] ); } } /** * @since 2.0.6 * @access public */ public function admin_columns_content( $column_name, $post_id ) { if ( 'elementor_library_type' === $column_name ) { /** @var Document $document */ $document = Plugin::$instance->documents->get( $post_id ); if ( $document && $document instanceof Library_Document ) { $document->print_admin_column_type(); } } } /** * @since 2.0.6 * @access public */ public function admin_columns_headers( $posts_columns ) { // Replace original column that bind to the taxonomy - with another column. unset( $posts_columns['taxonomy-elementor_library_type'] ); $offset = 2; $posts_columns = array_slice( $posts_columns, 0, $offset, true ) + [ 'elementor_library_type' => esc_html__( 'Type', 'elementor' ), ] + array_slice( $posts_columns, $offset, null, true ); return $posts_columns; } public function get_current_tab_group() { $current_tabs_group = Utils::get_super_global_value( $_GET, 'tabs_group' ) ?? ''; $type_slug = Utils::get_super_global_value( $_GET, self::TAXONOMY_TYPE_SLUG ); if ( $type_slug ) { $doc_type = Plugin::$instance->documents->get_document_type( $type_slug, '' ); if ( $doc_type ) { $current_tabs_group = $doc_type::get_property( 'admin_tab_group' ); } } return $current_tabs_group; } private function get_library_title() { $title = ''; if ( $this->is_current_screen() ) { $current_tab_group = $this->get_current_tab_group(); if ( $current_tab_group ) { $titles = [ 'library' => esc_html__( 'Saved Templates', 'elementor' ), 'theme' => esc_html__( 'Theme Builder', 'elementor' ), 'popup' => esc_html__( 'Popups', 'elementor' ), ]; if ( ! empty( $titles[ $current_tab_group ] ) ) { $title = $titles[ $current_tab_group ]; } } } return $title; } private function is_current_screen() { global $pagenow, $typenow; return 'edit.php' === $pagenow && self::CPT === $typenow; } /** * @param array $post_types * * @return array */ private function remove_elementor_cpt_from_sitemap( array $post_types ) { unset( $post_types[ self::CPT ] ); return $post_types; } private function avoid_rest_access_for_non_admins(): void { add_filter( 'rest_pre_dispatch', function ( $value, \WP_REST_Server $server, \WP_REST_Request $request ) { if ( strpos( $request->get_route(), self::CPT ) !== false ) { if ( ! current_user_can( 'manage_options' ) ) { return new \WP_Error( 'rest_forbidden', esc_html__( 'Sorry, you are not allowed to do that.', 'elementor' ), [ 'status' => rest_authorization_required_code() ] ); } } return $value; }, 10, 3 ); } public function save_bulk_items( array $args = [] ) { $items = []; foreach ( $args as $item ) { $items[] = $this->save_item( [ 'content' => $item['content'], 'title' => $item['title'], 'type' => $item['type'], 'page_settings' => $item['page_settings'], ] ); } return $items; } /** * Template library local source constructor. * * Initializing the template library local source base by registering custom * template data and running custom actions. * * @since 1.0.0 * @access public */ public function __construct() { parent::__construct(); $this->add_actions(); } public function format_args_for_bulk_action( $args ) { $bulk_args = []; foreach ( $args['from_template_id'] as $from_template_id ) { if ( ! $this->is_allowed_to_read_template( [ 'template_id' => $from_template_id, ] ) ) { continue; } $document = Plugin::$instance->documents->get( $from_template_id ); if ( ! $document ) { continue; } $page = SettingsManager::get_settings_managers( 'page' )->get_model( $from_template_id ); $bulk_args[] = array_merge( $args, [ 'title' => $document->get_post()->post_title, 'type' => $document::get_type(), 'content' => $document->get_elements_data(), 'page_settings' => $page->get_data( 'settings' ), ] ); } return $bulk_args; } public function format_args_for_single_action( $args ) { if ( ! $this->is_allowed_to_read_template( [ 'template_id' => $args['from_template_id'], ] ) ) { return new \WP_Error( 'template_error', esc_html__( 'You do not have permission to access this template.', 'elementor' ) ); } $document = Plugin::$instance->documents->get( $args['from_template_id'] ); if ( ! $document ) { return new \WP_Error( 'template_error', 'Document not found.' ); } $args['content'] = $document->get_elements_data(); $page = SettingsManager::get_settings_managers( 'page' )->get_model( $args['from_template_id'] ); $args['page_settings'] = $page->get_data( 'settings' ); return $args; } public function is_allowed_to_read_template( array $args ): bool { if ( null === $this->wordpress_adapter ) { $this->set_wordpress_adapter( new WordPress_Adapter() ); } $post_id = intval( $args['template_id'] ); $post_status = $this->wordpress_adapter->get_post_status( $post_id ); if ( 'publish' === $post_status && ! post_password_required( $post_id ) ) { return true; } $can_read_template = $this->wordpress_adapter->current_user_can( 'edit_post', $post_id ); return apply_filters( 'elementor/template-library/is_allowed_to_read_template', $can_read_template, $args ); } public function set_wordpress_adapter( Wordpress_Adapter_Interface $wordpress_adapter ) { $this->wordpress_adapter = $wordpress_adapter; } public function set_elementor_adapter( Elementor_Adapter_Interface $elementor_adapter ): void { $this->elementor_adapter = $elementor_adapter; } }