File manager - Edit - /home/quizenacom/public_html/app.tar
Back
modules/onboarding/module.php 0000644 00000032136 15237752276 0012361 0 ustar 00 <?php namespace Elementor\Core\App\Modules\Onboarding; use Automatic_Upgrader_Skin; use Elementor\Core\Base\Module as BaseModule; use Elementor\Core\Common\Modules\Ajax\Module as Ajax; use Elementor\Core\Common\Modules\Connect\Apps\Library; use Elementor\Core\Files\Uploads_Manager; use Elementor\Plugin; use Elementor\Tracker; use Plugin_Upgrader; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * Onboarding Module * * Responsible for initializing Elementor App functionality * * @since 3.6.0 */ class Module extends BaseModule { const VERSION = '1.0.0'; const ONBOARDING_OPTION = 'elementor_onboarded'; /** * Get name. * * @since 3.6.0 * @access public * * @return string */ public function get_name() { return 'onboarding'; } /** * Set Onboarding Settings * * Creates an array of module settings that is localized into the JS App config. * * @since 3.6.0 */ private function set_onboarding_settings() { if ( ! Plugin::$instance->common ) { return; } // Get the published pages and posts $pages_and_posts = new \WP_Query( [ 'post_type' => [ 'page', 'post' ], 'post_status' => 'publish', 'update_post_meta_cache' => false, 'update_post_term_cache' => false, 'no_found_rows' => true, ] ); $custom_site_logo_id = get_theme_mod( 'custom_logo' ); $custom_logo_src = wp_get_attachment_image_src( $custom_site_logo_id, 'full' ); $site_name = get_option( 'blogname', '' ); $hello_theme = wp_get_theme( 'hello-elementor' ); $hello_theme_errors = is_object( $hello_theme->errors() ) ? $hello_theme->errors()->errors : []; /** @var Library $library */ $library = Plugin::$instance->common->get_component( 'connect' )->get_app( 'library' ); Plugin::$instance->app->set_settings( 'onboarding', [ 'eventPlacement' => 'Onboarding wizard', 'onboardingAlreadyRan' => get_option( self::ONBOARDING_OPTION ), 'onboardingVersion' => self::VERSION, 'isLibraryConnected' => $library->is_connected(), // Used to check if the Hello Elementor theme is installed but not activated. 'helloInstalled' => empty( $hello_theme_errors['theme_not_found'] ), 'helloActivated' => 'hello-elementor' === get_option( 'template' ), // The "Use Hello theme on my site" checkbox should be checked by default only if this condition is met. 'helloOptOut' => count( $pages_and_posts->posts ) < 5, 'siteName' => esc_html( $site_name ), 'isUnfilteredFilesEnabled' => Uploads_Manager::are_unfiltered_uploads_enabled(), 'urls' => [ 'kitLibrary' => Plugin::$instance->app->get_base_url() . '#/kit-library?order[direction]=desc&order[by]=featuredIndex', 'createNewPage' => Plugin::$instance->documents->get_create_new_post_url(), 'connect' => $library->get_admin_url( 'authorize', [ 'utm_source' => 'onboarding-wizard', 'utm_campaign' => 'connect-account', 'utm_medium' => 'wp-dash', 'utm_term' => self::VERSION, 'source' => 'generic', ] ), 'signUp' => $library->get_admin_url( 'authorize', [ 'utm_source' => 'onboarding-wizard', 'utm_campaign' => 'connect-account', 'utm_medium' => 'wp-dash', 'utm_term' => self::VERSION, 'source' => 'generic', 'screen_hint' => 'signup', ] ), 'uploadPro' => Plugin::$instance->app->get_base_url() . '#/onboarding/uploadAndInstallPro?mode=popup', ], 'siteLogo' => [ 'id' => $custom_site_logo_id, 'url' => $custom_logo_src ? $custom_logo_src[0] : '', ], 'utms' => [ 'connectTopBar' => '&utm_content=top-bar', 'connectCta' => '&utm_content=cta-button', 'connectCtaLink' => '&utm_content=cta-link', 'downloadPro' => '?utm_source=onboarding-wizard&utm_campaign=my-account-subscriptions&utm_medium=wp-dash&utm_content=import-pro-plugin&utm_term=' . self::VERSION, ], 'nonce' => wp_create_nonce( 'onboarding' ), ] ); } /** * Get Permission Error Response * * Returns the response that is returned when the user's capabilities are not sufficient for performing an action. * * @since 3.6.4 * * @return array */ private function get_permission_error_response() { return [ 'status' => 'error', 'payload' => [ 'error_message' => __( 'you are not allowed to perform this action', 'elementor' ), ], ]; } /** * Maybe Update Site Logo * * If a new name is provided, it will be updated as the Site Name. * * @since 3.6.0 * * @return array */ private function maybe_update_site_name() { $problem_error = [ 'status' => 'error', 'payload' => [ 'error_message' => 'There was a problem setting your site name', ], ]; // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( empty( $_POST['data'] ) ) { return $problem_error; } // phpcs:ignore WordPress.Security.NonceVerification.Missing $data = json_decode( stripslashes( $_POST['data'] ), true ); if ( ! isset( $data['siteName'] ) ) { return $problem_error; } /** * Onboarding Site Name * * Filters the new site name passed by the user to update in Elementor's onboarding process. * Elementor runs `esc_html()` on the Site Name passed by the user for security reasons. If a user wants to * include special characters in their site name, they can use this filter to override it. * * @since 3.6.0 * * @param string Escaped new site name */ $new_site_name = apply_filters( 'elementor/onboarding/site-name', $data['siteName'] ); // The site name is sanitized in `update_options()` update_option( 'blogname', $new_site_name ); return [ 'status' => 'success', 'payload' => [ 'siteNameUpdated' => true, ], ]; } /** * Maybe Update Site Logo * * If an image attachment ID is provided, it will be updated as the Site Logo Theme Mod. * * @since 3.6.0 * * @return array */ private function maybe_update_site_logo() { if ( ! current_user_can( 'edit_theme_options' ) ) { return $this->get_permission_error_response(); } $data_error = [ 'status' => 'error', 'payload' => [ 'error_message' => esc_html__( 'There was a problem setting your site logo', 'elementor' ), ], ]; // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( empty( $_POST['data'] ) ) { return $data_error; } // phpcs:ignore WordPress.Security.NonceVerification.Missing $data = json_decode( stripslashes( $_POST['data'] ), true ); // If there is no attachment ID passed or it is not a valid ID, exit here. if ( empty( $data['attachmentId'] ) ) { return $data_error; } $absint_attachment_id = absint( $data['attachmentId'] ); if ( 0 === $absint_attachment_id ) { return $data_error; } $attachment_url = wp_get_attachment_url( $data['attachmentId'] ); // Check if the attachment exists. If it does not, exit here. if ( ! $attachment_url ) { return $data_error; } set_theme_mod( 'custom_logo', $absint_attachment_id ); return [ 'status' => 'success', 'payload' => [ 'siteLogoUpdated' => true, ], ]; } /** * Maybe Upload Logo Image * * If an image file upload is provided, and it passes validation, it will be uploaded to the site's Media Library. * * @since 3.6.0 * * @return array */ private function maybe_upload_logo_image() { $error_message = __( 'There was a problem uploading your file', 'elementor' ); // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( empty( $_FILES['fileToUpload'] ) || ! is_array( $_FILES['fileToUpload'] ) ) { return [ 'status' => 'error', 'payload' => [ 'error_message' => $error_message, ], ]; } // If the user has allowed it, set the Request's state as an "Elementor Upload" request, in order to add // support for non-standard file uploads. if ( 'image/svg+xml' === $_FILES['fileToUpload']['type'] ) { if ( Uploads_Manager::are_unfiltered_uploads_enabled() ) { Plugin::$instance->uploads_manager->set_elementor_upload_state( true ); } else { wp_send_json_error( 'To upload SVG files, you must allow uploading unfiltered files.' ); } } // If the image is an SVG file, sanitation is performed during the import (upload) process. $image_attachment = Plugin::$instance->templates_manager->get_import_images_instance()->import( $_FILES['fileToUpload'] ); if ( 'image/svg+xml' === $_FILES['fileToUpload']['type'] && Uploads_Manager::are_unfiltered_uploads_enabled() ) { // Reset Upload state. Plugin::$instance->uploads_manager->set_elementor_upload_state( false ); } if ( $image_attachment && ! is_wp_error( $image_attachment ) ) { $result = [ 'status' => 'success', 'payload' => [ 'imageAttachment' => $image_attachment, ], ]; } else { $result = [ 'status' => 'error', 'payload' => [ 'error_message' => $error_message, ], ]; } return $result; } /** * Activate Hello Theme * * @since 3.6.0 * * @return array */ private function maybe_activate_hello_theme() { if ( ! current_user_can( 'switch_themes' ) ) { return $this->get_permission_error_response(); } switch_theme( 'hello-elementor' ); return [ 'status' => 'success', 'payload' => [ 'helloThemeActivated' => true, ], ]; } /** * Upload and Install Elementor Pro * * @since 3.6.0 * * @return array */ private function upload_and_install_pro() { if ( ! current_user_can( 'install_plugins' ) || ! current_user_can( 'activate_plugins' ) ) { return $this->get_permission_error_response(); } $error_message = __( 'There was a problem uploading your file', 'elementor' ); // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( empty( $_FILES['fileToUpload'] ) || ! is_array( $_FILES['fileToUpload'] ) ) { return [ 'status' => 'error', 'payload' => [ 'error_message' => $error_message, ], ]; } $result = []; if ( ! class_exists( 'Automatic_Upgrader_Skin' ) ) { require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; } $skin = new Automatic_Upgrader_Skin(); $upgrader = new Plugin_Upgrader( $skin ); $upload_result = $upgrader->install( $_FILES['fileToUpload']['tmp_name'], [ 'overwrite_package' => false ] ); if ( ! $upload_result || is_wp_error( $upload_result ) ) { $result = [ 'status' => 'error', 'payload' => [ 'error_message' => $error_message, ], ]; } else { $activated = activate_plugin( WP_PLUGIN_DIR . '/elementor-pro/elementor-pro.php', false, false, true ); if ( ! is_wp_error( $activated ) ) { $result = [ 'status' => 'success', 'payload' => [ 'elementorProInstalled' => true, ], ]; } else { $result = [ 'status' => 'error', 'payload' => [ 'error_message' => $error_message, 'elementorProInstalled' => false, ], ]; } } return $result; } private function maybe_update_onboarding_db_option() { $db_option = get_option( self::ONBOARDING_OPTION ); if ( ! $db_option ) { update_option( self::ONBOARDING_OPTION, true ); } return [ 'status' => 'success', 'payload' => 'onboarding DB', ]; } /** * Maybe Handle Ajax * * This method checks if there are any AJAX actions being * @since 3.6.0 * * @return array|null */ private function maybe_handle_ajax() { $result = []; // phpcs:ignore WordPress.Security.NonceVerification.Missing switch ( $_POST['action'] ) { case 'elementor_update_site_name': // If no value is passed for any reason, no need ot update the site name. $result = $this->maybe_update_site_name(); break; case 'elementor_update_site_logo': $result = $this->maybe_update_site_logo(); break; case 'elementor_upload_site_logo': $result = $this->maybe_upload_logo_image(); break; case 'elementor_activate_hello_theme': $result = $this->maybe_activate_hello_theme(); break; case 'elementor_upload_and_install_pro': $result = $this->upload_and_install_pro(); break; case 'elementor_update_onboarding_option': $result = $this->maybe_update_onboarding_db_option(); } if ( ! empty( $result ) ) { if ( 'success' === $result['status'] ) { wp_send_json_success( $result['payload'] ); } else { wp_send_json_error( $result['payload'] ); } } } public function __construct() { add_action( 'elementor/init', function() { // Only load when viewing the onboarding app. if ( Plugin::$instance->app->is_current() ) { $this->set_onboarding_settings(); // Needed for installing the Hello Elementor theme. wp_enqueue_script( 'updates' ); // Needed for uploading Logo from WP Media Library. wp_enqueue_media(); Plugin::$instance->app->set_settings( 'disable_dark_theme', true ); } }, 12 ); // Needed for uploading Logo from WP Media Library. The 'admin_menu' hook is used because it runs before // 'admin_init', and the App triggers printing footer scripts on 'admin_init' at priority 0. add_action( 'admin_menu', function() { add_action( 'wp_print_footer_scripts', 'wp_print_media_templates' ); } ); add_action( 'admin_init', function() { if ( wp_doing_ajax() && isset( $_POST['action'] ) && isset( $_POST['_nonce'] ) && wp_verify_nonce( $_POST['_nonce'], Ajax::NONCE_KEY ) && current_user_can( 'manage_options' ) ) { $this->maybe_handle_ajax(); } } ); } } modules/import-export/module.php 0000644 00000034366 15237752276 0013077 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport; use Elementor\Core\App\Modules\ImportExport\Directories\WP_Content; use Elementor\Core\App\Modules\ImportExport\Directories\WP_Post_Type; use Elementor\Modules\LandingPages\Module as Landing_Pages_Module; use Elementor\Core\Base\Document; use Elementor\Core\Base\Module as BaseModule; use Elementor\Core\Common\Modules\Ajax\Module as Ajax; use Elementor\Core\Files\Uploads_Manager; use Elementor\Plugin; use Elementor\TemplateLibrary\Source_Local; use Elementor\Tools; use Elementor\Utils; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * Import Export Module * * Responsible for initializing Elementor App functionality */ class Module extends BaseModule { const FORMAT_VERSION = '1.0'; const EXPORT_TRIGGER_KEY = 'elementor_export_kit'; const IMPORT_TRIGGER_KEY = 'elementor_import_kit'; const MANIFEST_ERROR_KEY = 'manifest-error'; const PERMISSIONS_ERROR_KEY = 'plugin-installation-permissions-error'; /** * @var Export */ public $export; /** * @var Import */ public $import; /** * Get name. * * @access public * * @return string */ public function get_name() { return 'import-export'; } public function get_init_settings() { if ( ! Plugin::$instance->app->is_current() ) { return []; } return $this->get_config_data(); } public function get_summary_titles() { $summary_titles = []; $document_types = Plugin::$instance->documents->get_document_types(); foreach ( $document_types as $name => $document_type ) { $summary_titles['templates'][ $name ] = [ 'single' => $document_type::get_title(), 'plural' => $document_type::get_plural_title(), ]; } $post_types = get_post_types_by_support( 'elementor' ); $post_types[] = 'nav_menu_item'; foreach ( $post_types as $post_type ) { if ( Source_Local::CPT === $post_type ) { continue; } $post_type_object = get_post_type_object( $post_type ); $summary_titles['content'][ $post_type ] = [ 'single' => $post_type_object->labels->singular_name, 'plural' => $post_type_object->label, ]; } $custom_post_types = $this->get_registered_cpt_names(); if ( ! empty( $custom_post_types ) ) { foreach ( $custom_post_types as $custom_post_type ) { $custom_post_types_object = get_post_type_object( $custom_post_type ); //cpt data appears in two arrays: //1. content object: in order to show the export summary when completed in getLabel function $summary_titles['content'][ $custom_post_type ] = [ 'single' => $custom_post_types_object->labels->singular_name, 'plural' => $custom_post_types_object->label, ]; //2. customPostTypes object: in order to actually export the data $summary_titles['content']['customPostTypes'][ $custom_post_type ] = [ 'single' => $custom_post_types_object->labels->singular_name, 'plural' => $custom_post_types_object->label, ]; } } $active_kit = Plugin::$instance->kits_manager->get_active_kit(); foreach ( $active_kit->get_tabs() as $key => $tab ) { $summary_titles['site-settings'][ $key ] = $tab->get_title(); } return $summary_titles; } /** * Retrieve custom post type names. * * @since 3.6.0 * @access public * * @return array custom post type names. */ public function get_registered_cpt_names() { $post_types = get_post_types( [ 'public' => true, 'can_export' => true, ] ); unset( $post_types['attachment'], $post_types['page'], $post_types['post'], $post_types[ Landing_Pages_Module::CPT ], $post_types[ Source_Local::CPT ] ); $custom_post_types = []; foreach ( $post_types as $post_type ) { array_push( $custom_post_types, $post_type ); } return $custom_post_types; } private function import_stage_1() { // PHPCS - Already validated in caller function. if ( ! empty( $_POST['e_import_file'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( ! isset( $_POST['e_kit_library_nonce'] ) || ! wp_verify_nonce( $_POST['e_kit_library_nonce'], 'kit-library-import' ) ) { throw new \Error( esc_html__( 'Invalid kit library nonce', 'elementor' ) ); } $file_url = $_POST['e_import_file']; if ( ! filter_var( $file_url, FILTER_VALIDATE_URL ) || 0 !== strpos( $file_url, 'http' ) ) { throw new \Error( esc_html__( 'Invalid URL', 'elementor' ) ); } $remote_zip_request = wp_remote_get( $file_url ); if ( is_wp_error( $remote_zip_request ) ) { throw new \Error( $remote_zip_request->get_error_message() ); } if ( 200 !== $remote_zip_request['response']['code'] ) { throw new \Error( $remote_zip_request['response']['message'] ); } $file_name = Plugin::$instance->uploads_manager->create_temp_file( $remote_zip_request['body'], 'kit.zip' ); } else { // PHPCS - Already validated in caller function. $file_name = $_FILES['e_import_file']['tmp_name']; // phpcs:ignore WordPress.Security.NonceVerification.Missing } $extraction_result = Plugin::$instance->uploads_manager->extract_and_validate_zip( $file_name, [ 'json', 'xml' ] ); if ( ! empty( $file_url ) ) { Plugin::$instance->uploads_manager->remove_file_or_dir( dirname( $file_name ) ); } $session_dir = $extraction_result['extraction_directory']; $manifest_file_content = Utils::file_get_contents( $session_dir . 'manifest.json', true ); if ( ! $manifest_file_content ) { throw new \Error( self::MANIFEST_ERROR_KEY ); } $manifest_data = json_decode( $manifest_file_content, true ); // In case that the manifest content is not a valid JSON or empty. if ( ! $manifest_data ) { throw new \Error( self::MANIFEST_ERROR_KEY ); } if ( isset( $manifest_data['plugins'] ) && ! current_user_can( 'install_plugins' ) ) { throw new \Error( static::PERMISSIONS_ERROR_KEY ); } $manifest_data = $this->import->adapt_manifest_structure( $manifest_data ); $result = [ 'session' => $session_dir, 'manifest' => $manifest_data, ]; $result = apply_filters( 'elementor/import/stage_1/result', $result ); return $result; } private function import_stage_2( $settings_directory ) { set_time_limit( 0 ); $result = $this->import->run(); Plugin::$instance->uploads_manager->remove_file_or_dir( $settings_directory ); return $result; } private function on_admin_init() { if ( ! isset( $_POST['action'] ) || self::IMPORT_TRIGGER_KEY !== $_POST['action'] || ! wp_verify_nonce( $_POST['_nonce'], Ajax::NONCE_KEY ) ) { return; } $import_settings = json_decode( stripslashes( $_POST['data'] ), true ); // Set the Request's state as an Elementor upload request, in order to support unfiltered file uploads. Plugin::$instance->uploads_manager->set_elementor_upload_state( true ); try { $this->import = new Import( $import_settings ); if ( 1 === $import_settings['stage'] ) { $result = $this->import_stage_1(); } elseif ( 2 === $import_settings['stage'] ) { $result = $this->import_stage_2( $import_settings['session'] ); // Adding the most updated data of the summaryTitles, in case that the data was changed during the process by new installed plugins. $result['configData'] = $this->get_config_data(); } wp_send_json_success( $result ); } catch ( \Error $error ) { wp_send_json_error( $error->getMessage() ); } } private function on_init() { if ( ! isset( $_POST['action'] ) || self::EXPORT_TRIGGER_KEY !== $_POST['action'] || ! wp_verify_nonce( $_POST['_nonce'], Ajax::NONCE_KEY ) ) { return; } $export_settings = json_decode( stripslashes( $_POST['data'] ), true ); try { $this->export = new Export( self::merge_properties( [], $export_settings, [ 'include', 'kitInfo', 'plugins', 'selectedCustomPostTypes' ] ) ); $export_result = $this->export->run(); $file_name = $export_result['file_name']; $file = Utils::file_get_contents( $file_name ); Plugin::$instance->uploads_manager->remove_file_or_dir( dirname( $file_name ) ); wp_send_json_success( [ 'manifest' => $export_result['manifest'], 'file' => base64_encode( $file ), ] ); } catch ( \Error $error ) { wp_send_json_error( $error->getMessage() ); } } private function render_import_export_tab_content() { $intro_text_link = sprintf( '<a href="https://go.elementor.com/wp-dash-import-export-general/" target="_blank">%s</a>', esc_html__( 'Learn more', 'elementor' ) ); $intro_text = sprintf( /* translators: 1: New line break, 2: Learn More link. */ __( 'Design sites faster with a template kit that contains some or all components of a complete site, like templates, content & site settings.%1$sYou can import a kit and apply it to your site, or export the elements from this site to be used anywhere else. %2$s', 'elementor' ), '<br>', $intro_text_link ); $content_data = [ 'export' => [ 'title' => esc_html__( 'Export a Template Kit', 'elementor' ), 'button' => [ 'url' => Plugin::$instance->app->get_base_url() . '#/export', 'text' => esc_html__( 'Start Export', 'elementor' ), ], 'description' => esc_html__( 'Bundle your whole site - or just some of its elements - to be used for another website.', 'elementor' ), 'link' => [ 'url' => 'https://go.elementor.com/wp-dash-import-export-export-flow/', 'text' => esc_html__( 'Learn More', 'elementor' ), ], ], 'import' => [ 'title' => esc_html__( 'Import a Template Kit', 'elementor' ), 'button' => [ 'url' => Plugin::$instance->app->get_base_url() . '#/import', 'text' => esc_html__( 'Start Import', 'elementor' ), ], 'description' => esc_html__( 'Apply the design and settings of another site to this one.', 'elementor' ), 'link' => [ 'url' => 'https://go.elementor.com/wp-dash-import-export-import-flow/', 'text' => esc_html__( 'Learn More', 'elementor' ), ], ], ]; $home_page_editor_url = $this->get_elementor_editor_home_page_url(); $editor_page_link = $home_page_editor_url ? $home_page_editor_url : $this->get_recently_edited_elementor_editor_page_url(); $info_text = esc_html__( 'Even after you import and apply a Template Kit, you can undo it by restoring a previous version of your site.', 'elementor' ) . '<br>'; $info_text .= sprintf( '<a href="%1$s" target="_blank">%2$s</a>', $editor_page_link . '#e:run:panel/global/open&e:route:panel/history/revisions', esc_html__( 'Open Site Settings > History > Revisions.', 'elementor' ) ); ?> <div class="tab-import-export-kit__content"> <p class="tab-import-export-kit__info"><?php Utils::print_unescaped_internal_string( $intro_text ); ?></p> <div class="tab-import-export-kit__wrapper"> <?php foreach ( $content_data as $data ) { ?> <div class="tab-import-export-kit__container"> <div class="tab-import-export-kit__box"> <h2><?php Utils::print_unescaped_internal_string( $data['title'] ); ?></h2> <a href="<?php Utils::print_unescaped_internal_string( $data['button']['url'] ); ?>" class="elementor-button elementor-button-success"> <?php Utils::print_unescaped_internal_string( $data['button']['text'] ); ?> </a> </div> <p><?php Utils::print_unescaped_internal_string( $data['description'] ); ?></p> <a href="<?php Utils::print_unescaped_internal_string( $data['link']['url'] ); ?>" target="_blank"><?php Utils::print_unescaped_internal_string( $data['link']['text'] ); ?></a> </div> <?php } ?> </div> <p class="tab-import-export-kit__info"><?php Utils::print_unescaped_internal_string( $info_text ); ?></p> </div> <?php } private function get_elementor_editor_home_page_url() { if ( 'page' !== get_option( 'show_on_front' ) ) { return ''; } $frontpage_id = get_option( 'page_on_front' ); return $this->get_elementor_editor_page_url( $frontpage_id ); } private function get_elementor_home_page_url() { if ( 'page' !== get_option( 'show_on_front' ) ) { return ''; } $frontpage_id = get_option( 'page_on_front' ); return $this->get_elementor_page_url( $frontpage_id ); } private function get_recently_edited_elementor_page_url() { $query = Utils::get_recently_edited_posts_query( [ 'posts_per_page' => 1 ] ); if ( ! isset( $query->post ) ) { return ''; } return $this->get_elementor_page_url( $query->post->ID ); } private function get_recently_edited_elementor_editor_page_url() { $query = Utils::get_recently_edited_posts_query( [ 'posts_per_page' => 1 ] ); if ( ! isset( $query->post ) ) { return ''; } return $this->get_elementor_editor_page_url( $query->post->ID ); } private function get_elementor_document( $page_id ) { $document = Plugin::$instance->documents->get( $page_id ); if ( ! $document || ! $document->is_built_with_elementor() ) { return false; } return $document; } private function get_elementor_page_url( $page_id ) { $document = $this->get_elementor_document( $page_id ); return $document ? $document->get_preview_url() : ''; } private function get_elementor_editor_page_url( $page_id ) { $document = $this->get_elementor_document( $page_id ); return $document ? $document->get_edit_url() : ''; } private function get_config_data() { $export_nonce = wp_create_nonce( 'elementor_export' ); $export_url = add_query_arg( [ '_nonce' => $export_nonce ], Plugin::$instance->app->get_base_url() ); return [ 'exportURL' => $export_url, 'summaryTitles' => $this->get_summary_titles(), 'isUnfilteredFilesEnabled' => Uploads_Manager::are_unfiltered_uploads_enabled(), 'elementorHomePageUrl' => $this->get_elementor_home_page_url(), 'recentlyEditedElementorPageUrl' => $this->get_recently_edited_elementor_page_url(), ]; } public function register_settings_tab( Tools $tools ) { $tools->add_tab( 'import-export-kit', [ 'label' => esc_html__( 'Import / Export Kit', 'elementor' ), 'sections' => [ 'intro' => [ 'label' => esc_html__( 'Template Kits', 'elementor' ), 'callback' => function() { $this->render_import_export_tab_content(); }, 'fields' => [], ], ], ] ); } public function __construct() { add_action( 'init', function() { $this->on_init(); } ); add_action( 'admin_init', function() { $this->on_admin_init(); } ); $page_id = Tools::PAGE_ID; add_action( "elementor/admin/after_create_settings/{$page_id}", [ $this, 'register_settings_tab' ] ); if ( Utils::is_wp_cli() ) { \WP_CLI::add_command( 'elementor kit', WP_CLI::class ); } } } modules/import-export/import.php 0000644 00000007456 15237752276 0013124 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport; use Elementor\Core\App\Modules\ImportExport\Compatibility\Base_Adapter; use Elementor\Core\App\Modules\ImportExport\Compatibility\Envato; use Elementor\Core\App\Modules\ImportExport\Compatibility\Kit_Library; use Elementor\Core\App\Modules\ImportExport\Directories\Root; use Elementor\Plugin; use Elementor\Utils; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Import extends Iterator { /** * @var Base_Adapter[] */ private $adapters = []; private $documents_elements = []; final public function run() { $this->temp_dir = $this->get_settings( 'session' ); $manifest_data = $this->read_json_file( 'manifest' ); $manifest_data = $this->adapt_manifest_structure( $manifest_data ); $root_directory = new Root( $this ); add_filter( 'elementor/document/save/data', [ $this, 'prevent_saving_elements_on_post_creation' ], 10, 2 ); $imported_posts = $root_directory->run_import( $manifest_data ); remove_filter( 'elementor/document/save/data', [ $this, 'prevent_saving_elements_on_post_creation' ], 10 ); $map_old_new_post_ids = $this->map_old_new_post_ids( $imported_posts ); $this->save_elements_of_imported_posts( $map_old_new_post_ids ); $this->update_object_id_of_imported_menu_items( $map_old_new_post_ids ); return $imported_posts; } public function prevent_saving_elements_on_post_creation( $data, $document ) { if ( isset( $data['elements'] ) ) { $this->documents_elements[ $document->get_main_id() ] = $data['elements']; $data['elements'] = []; } return $data; } final public function read_json_file( $name ) { $name = $this->get_archive_file_full_path( $name . '.json' ); return json_decode( Utils::file_get_contents( $name, true ), true ); } final public function get_adapters() { return $this->adapters; } final public function adapt_manifest_structure( array $manifest_data ) { $this->init_adapters( $manifest_data ); foreach ( $this->adapters as $adapter ) { $manifest_data = $adapter->get_manifest_data( $manifest_data ); } return $manifest_data; } private function init_adapters( array $manifest_data ) { /** @var Base_Adapter[] $adapter_types */ $adapter_types = [ Envato::class, Kit_Library::class ]; foreach ( $adapter_types as $adapter_type ) { if ( $adapter_type::is_compatibility_needed( $manifest_data, $this->get_settings() ) ) { $this->adapters[] = new $adapter_type( $this ); } } } private function save_elements_of_imported_posts( $map_old_new_post_ids ) { foreach ( $this->documents_elements as $new_id => $document_elements ) { $document = Plugin::$instance->documents->get( $new_id ); $updated_elements = $document->on_import_replace_dynamic_content( $document_elements, $map_old_new_post_ids ); $document->save( [ 'elements' => $updated_elements ] ); } } private function update_object_id_of_imported_menu_items( $map_old_new_post_ids ) { foreach ( $map_old_new_post_ids as $new_post_id ) { if ( 'nav_menu_item' !== get_post_type( $new_post_id ) ) { continue; } $post_meta = get_post_meta( $new_post_id ); // Skip items that not related to posts. if ( 'post_type' !== $post_meta['_menu_item_type'][0] ) { continue; } $update_meta = update_post_meta( $new_post_id, '_menu_item_object_id', $map_old_new_post_ids[ $post_meta['_menu_item_object_id'][0] ] ); if ( ! $update_meta ) { wp_delete_post( $new_post_id ); } } } private function map_old_new_post_ids( $imported_posts ) { $map_old_new_post_ids = []; foreach ( $imported_posts as $imported_post ) { if ( isset( $imported_post['succeed'] ) ) { $map_old_new_post_ids += $imported_post['succeed']; } else { $map_old_new_post_ids += $this->map_old_new_post_ids( $imported_post ); } } return $map_old_new_post_ids; } } modules/import-export/directories/plugins.php 0000644 00000001032 15237752276 0015567 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Directories; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } if ( ! function_exists( 'get_plugins' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } class Plugins extends Base { protected function get_name() { return 'plugins'; } protected function export() { $included_plugins = $this->iterator->get_settings( 'plugins' ); return $included_plugins; } protected function import( array $import_settings ) { return null; } } modules/import-export/directories/wp-custom-post-type-title.php 0000644 00000001303 15237752276 0021126 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Directories; use Elementor\Core\App\Modules\ImportExport\Iterator; use Elementor\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class WP_Custom_Post_Type_Title extends Base { private $post_type; public function __construct( Iterator $iterator, Base $parent, $post_type ) { parent::__construct( $iterator, $parent ); $this->post_type = $post_type; } public function export() { $post_type_object = get_post_type_object( $this->post_type ); return [ 'name' => $post_type_object->name, 'label' => $post_type_object->label, ]; } protected function get_name() { return $this->post_type; } } modules/import-export/directories/wp-content.php 0000644 00000002503 15237752276 0016210 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Directories; use Elementor\Core\App\Modules\ImportExport\Iterator; use Elementor\Modules\LandingPages\Module as Landing_Pages_Module; use Elementor\TemplateLibrary\Source_Local; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class WP_Content extends Base { public $custom_post_types; public function __construct( Iterator $iterator, Base $parent, $custom_post_types ) { $this->custom_post_types = $custom_post_types; parent::__construct( $iterator, $parent ); } protected function get_name() { return 'wp-content'; } protected function get_default_sub_directories() { $post_types = get_post_types( [ 'public' => true, 'can_export' => true, ] ); if ( null !== $this->custom_post_types ) { foreach ( $post_types as $post_type ) { if ( ! in_array( $post_type, $this->custom_post_types ) ) { unset( $post_types[ $post_type ] ); } } } $native_post_types = [ 'page' => 'page', 'post' => 'post', 'nav_menu_item' => 'nav_menu_item', ]; $post_types_to_export = array_merge( $native_post_types, $post_types ); $sub_directories = []; foreach ( $post_types_to_export as $post_type ) { $sub_directories[] = new WP_Post_Type( $this->iterator, $this, $post_type ); } return $sub_directories; } } modules/import-export/directories/custom-post-type-title.php 0000644 00000002145 15237752276 0020507 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Directories; use Elementor\Core\App\Modules\ImportExport\Iterator; use Elementor\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * Adds CPT name and label values to manifest.json. * * @since 3.6.0 */ class Custom_Post_Type_Title extends Base { public $custom_post_types; public function __construct( Iterator $iterator, Base $parent, $custom_post_types ) { $this->custom_post_types = $custom_post_types; parent::__construct( $iterator, $parent ); } protected function get_name() { return 'custom-post-type-title'; } protected function get_default_sub_directories() { $post_types = get_post_types( [ 'public' => true, 'can_export' => true, ] ); foreach ( $post_types as $post_type ) { if ( ! in_array( $post_type, $this->custom_post_types ) ) { unset( $post_types[ $post_type ] ); } } $sub_directories = []; foreach ( $post_types as $post_type ) { $sub_directories[] = new WP_Custom_Post_Type_Title( $this->iterator, $this, $post_type ); } return $sub_directories; } } modules/import-export/directories/wp-post-type.php 0000644 00000002545 15237752276 0016510 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Directories; use Elementor\Core\App\Modules\ImportExport\Iterator; use Elementor\Core\Utils\ImportExport\WP_Exporter; use Elementor\Core\Utils\ImportExport\WP_Import; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class WP_Post_Type extends Base { private $post_type; protected function get_name() { return $this->post_type; } public function __construct( Iterator $iterator, Base $parent, $post_type ) { parent::__construct( $iterator, $parent ); $this->post_type = $post_type; } public function export() { $wp_exporter = new WP_Exporter( [ 'content' => $this->post_type, 'status' => 'publish', 'limit' => 20, 'meta_query' => [ [ 'key' => '_elementor_edit_mode', 'compare' => 'NOT EXISTS', ], ], 'include_post_featured_image_as_attachment' => true, // Will export 'featured_image' as attachment. ] ); $export_result = $wp_exporter->run(); $this->exporter->add_file( $this->post_type . '.xml', $export_result['xml'] ); return $export_result['ids']; } protected function import( array $import_settings ) { $wp_importer = new WP_Import( $this->importer->get_archive_file_full_path( $this->post_type . '.xml' ), [ 'fetch_attachments' => true, ] ); $result = $wp_importer->run(); return $result['summary']['posts']; } } modules/import-export/directories/base.php 0000644 00000005507 15237752276 0015033 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Directories; use Elementor\Core\App\Modules\ImportExport\Export; use Elementor\Core\App\Modules\ImportExport\Import; use Elementor\Core\App\Modules\ImportExport\Iterator; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Base { /** * @var Base[] */ private $sub_directories = []; /** * @var Base */ private $parent; /** * @var Iterator */ protected $iterator; /** * @var Export */ protected $exporter; /** * @var Import */ protected $importer; abstract protected function get_name(); public function __construct( Iterator $iterator, Base $parent = null ) { $this->iterator = $iterator; if ( $iterator instanceof Export ) { $this->exporter = $iterator; } else { $this->importer = $iterator; } $this->parent = $parent; $this->register_directories(); } final public function get_path() { $path = $this->get_name(); if ( $this->parent ) { $parent_name = $this->parent->get_name(); if ( $parent_name ) { $parent_name .= '/'; } $path = $parent_name . $path; } return $path; } final public function run_export() { $this->exporter->set_current_archive_path( $this->get_path() ); $manifest_data = $this->export(); foreach ( $this->sub_directories as $sub_directory ) { $manifest_data[ $sub_directory->get_name() ] = $sub_directory->run_export(); } return $manifest_data; } final public function run_import( array $settings ) { $this->importer->set_current_archive_path( $this->get_path() ); $meta_data = $this->import( $settings ); foreach ( $this->sub_directories as $sub_directory ) { $sub_directory_name = $sub_directory->get_name(); if ( ! isset( $settings[ $sub_directory_name ] ) ) { continue; } $meta_data[ $sub_directory_name ] = $sub_directory->run_import( $settings[ $sub_directory_name ] ); } return $meta_data; } /** * @return array */ protected function export() { return []; } /** * @param array $import_settings * @return array */ protected function import( array $import_settings ) { return []; } protected function get_default_sub_directories() { return []; } private function register_directories() { $sub_directories = $this->get_default_sub_directories(); $path = $this->get_path(); /** * Kit sub directories. * * Filters sub directories when importing/exporting kits. * * The dynamic portion of the hook name, `$path`, refers to the directory path. * * @param array $sub_directories A list of sub directories. * @param Elementor\Core\App\Modules\ImportExport\Directories\Base $this The base class instance. */ $sub_directories = apply_filters( "elementor/kit/import-export/directory/{$path}", $sub_directories, $this ); $this->sub_directories = $sub_directories; } } modules/import-export/directories/templates.php 0000644 00000004661 15237752276 0016117 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Directories; use Elementor\Core\Base\Document; use Elementor\Plugin; use Elementor\TemplateLibrary\Source_Local; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Templates extends Base { protected function get_name() { return 'templates'; } protected function export() { $template_types = array_values( Source_Local::get_template_types() ); $query_args = [ 'post_type' => Source_Local::CPT, 'post_status' => 'publish', 'posts_per_page' => -1, 'meta_query' => [ [ 'key' => Document::TYPE_META_KEY, 'value' => $template_types, ], ], ]; $templates_query = new \WP_Query( $query_args ); $manifest_data = []; foreach ( $templates_query->posts as $template_post ) { $template_id = $template_post->ID; $template_document = Plugin::$instance->documents->get( $template_id ); $template_export_data = $template_document->get_export_data(); $this->exporter->add_json_file( $template_id, $template_export_data ); $manifest_data[ $template_id ] = $template_document->get_export_summary(); } return $manifest_data; } protected function import( array $import_settings ) { $result = [ 'succeed' => [], 'failed' => [], ]; foreach ( $import_settings as $id => $template_settings ) { try { $import = $this->import_template( $id, $template_settings ); if ( is_wp_error( $import ) ) { $result['failed'][ $id ] = $import->get_error_message(); continue; } $result['succeed'][ $id ] = $import; } catch ( \Error $error ) { $result['failed'][ $id ] = $error->getMessage(); } } return $result; } private function import_template( $id, array $template_settings ) { $template_data = $this->importer->read_json_file( $id ); $doc_type = $template_settings['doc_type']; $new_document = Plugin::$instance->documents->create( $doc_type, [ 'post_title' => $template_settings['title'], 'post_type' => Source_Local::CPT, 'post_status' => 'publish', ] ); if ( is_wp_error( $new_document ) ) { return $new_document; } $template_data['import_settings'] = $template_settings; $template_data['id'] = $id; foreach ( $this->importer->get_adapters() as $adapter ) { $template_data = $adapter->get_template_data( $template_data, $template_settings ); } $new_document->import( $template_data ); return $new_document->get_main_id(); } } modules/import-export/directories/content.php 0000644 00000001170 15237752276 0015563 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Directories; use Elementor\TemplateLibrary\Source_Local; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Content extends Base { protected function get_name() { return 'content'; } protected function get_default_sub_directories() { $post_types = get_post_types_by_support( 'elementor' ); $sub_directories = []; foreach ( $post_types as $post_type ) { if ( Source_Local::CPT === $post_type ) { continue; } $sub_directories[] = new Post_Type( $this->iterator, $this, $post_type ); } return $sub_directories; } } modules/import-export/directories/post-type.php 0000644 00000006402 15237752276 0016060 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Directories; use Elementor\Core\App\Modules\ImportExport\Iterator; use Elementor\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Post_Type extends Base { private $post_type; private $show_page_on_front; private $page_on_front_id; public function __construct( Iterator $iterator, Base $parent, $post_type ) { parent::__construct( $iterator, $parent ); $this->post_type = $post_type; if ( 'page' === $post_type ) { $this->init_page_on_front_data(); } } public function export() { $query_args = [ 'post_type' => $this->post_type, 'post_status' => 'publish', 'posts_per_page' => -1, 'meta_query' => [ [ 'key' => '_elementor_data', 'compare' => 'EXISTS', ], [ 'key' => '_elementor_data', 'compare' => '!=', 'value' => '[]', ], ], ]; $query = new \WP_Query( $query_args ); $manifest_data = []; foreach ( $query->posts as $post ) { $document = Plugin::$instance->documents->get( $post->ID ); $post_manifest_data = [ 'title' => $post->post_title, 'excerpt' => $post->post_excerpt, 'doc_type' => $document->get_name(), 'thumbnail' => get_the_post_thumbnail_url( $post ), 'url' => get_permalink( $post ), ]; if ( $post->ID === $this->page_on_front_id ) { $post_manifest_data['show_on_front'] = true; } $manifest_data[ $post->ID ] = $post_manifest_data; $this->exporter->add_json_file( $post->ID, $document->get_export_data() ); } return $manifest_data; } public function import_post( $id, array $post_settings ) { $post_data = $this->importer->read_json_file( $id ); $post_attributes = [ 'post_title' => $post_settings['title'], 'post_type' => $this->post_type, 'post_status' => 'publish', ]; if ( ! empty( $post_settings['excerpt'] ) ) { $post_attributes['post_excerpt'] = $post_settings['excerpt']; } $new_document = Plugin::$instance->documents->create( $post_settings['doc_type'], $post_attributes ); if ( is_wp_error( $new_document ) ) { return $new_document; } $post_data['import_settings'] = $post_settings; $new_document->import( $post_data ); $new_id = $new_document->get_main_id(); if ( ! empty( $post_settings['show_on_front'] ) ) { update_option( 'page_on_front', $new_id ); if ( ! $this->show_page_on_front ) { update_option( 'show_on_front', 'page' ); } } return $new_id; } protected function get_name() { return $this->post_type; } protected function import( array $import_settings ) { $result = [ 'succeed' => [], 'failed' => [], ]; foreach ( $import_settings as $id => $post_settings ) { try { $import = $this->import_post( $id, $post_settings ); if ( is_wp_error( $import ) ) { $result['failed'][ $id ] = $import->get_error_message(); continue; } $result['succeed'][ $id ] = $import; } catch ( \Error $error ) { $result['failed'][ $id ] = $error->getMessage(); } } return $result; } private function init_page_on_front_data() { $this->show_page_on_front = 'page' === get_option( 'show_on_front' ); if ( $this->show_page_on_front && $this->exporter ) { $this->page_on_front_id = (int) get_option( 'page_on_front' ); } } } modules/import-export/directories/root.php 0000644 00000007030 15237752276 0015075 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Directories; use Elementor\Core\App\Modules\ImportExport\Module; use Elementor\Core\Settings\Page\Manager as PageManager; use Elementor\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Root extends Base { protected function get_name() { return ''; } protected function export() { $kit = Plugin::$instance->kits_manager->get_active_kit(); $exporter_settings = $this->exporter->get_settings(); $include = $exporter_settings['include']; $include_site_settings = in_array( 'settings', $include, true ); if ( $include_site_settings ) { $kit_data = $kit->get_export_data(); $excluded_kit_settings_keys = [ 'site_name', 'site_description', 'site_logo', 'site_favicon', ]; foreach ( $excluded_kit_settings_keys as $setting_key ) { unset( $kit_data['settings'][ $setting_key ] ); } $this->exporter->add_json_file( 'site-settings', $kit_data ); } $kit_post = $kit->get_post(); $manifest_data = [ 'name' => sanitize_title( $exporter_settings['kitInfo']['title'] ), 'title' => $exporter_settings['kitInfo']['title'], 'description' => $exporter_settings['kitInfo']['description'], 'author' => get_the_author_meta( 'display_name', $kit_post->post_author ), 'version' => Module::FORMAT_VERSION, 'elementor_version' => ELEMENTOR_VERSION, 'created' => gmdate( 'Y-m-d H:i:s' ), 'thumbnail' => get_the_post_thumbnail_url( $kit_post ), 'site' => get_site_url(), ]; if ( $include_site_settings ) { $kit_tabs = $kit->get_tabs(); unset( $kit_tabs['settings-site-identity'] ); $manifest_data['site-settings'] = array_keys( $kit_tabs ); } return $manifest_data; } protected function import( array $import_settings ) { $include = $this->importer->get_settings( 'include' ); if ( ! in_array( 'settings', $include, true ) ) { return; } $kit = Plugin::$instance->kits_manager->get_active_kit(); $old_settings = $kit->get_meta( PageManager::META_KEY ); if ( ! $old_settings ) { $old_settings = []; } $new_settings = $this->importer->read_json_file( 'site-settings' ); $new_settings = $new_settings['settings']; if ( ! empty( $old_settings['custom_colors'] ) ) { $new_settings['custom_colors'] = array_merge( $old_settings['custom_colors'], $new_settings['custom_colors'] ); } if ( ! empty( $old_settings['custom_typography'] ) ) { $new_settings['custom_typography'] = array_merge( $old_settings['custom_typography'], $new_settings['custom_typography'] ); } $new_settings = array_replace_recursive( $old_settings, $new_settings ); Plugin::$instance->kits_manager->create_new_kit( $import_settings['title'], $new_settings ); } protected function get_default_sub_directories() { $sub_directories = []; $include = $this->iterator->get_settings( 'include' ); if ( in_array( 'templates', $include, true ) ) { $sub_directories[] = new Templates( $this->iterator, $this ); } if ( in_array( 'content', $include, true ) ) { $custom_post_types = $this->iterator->get_settings( 'selectedCustomPostTypes' ); $sub_directories[] = new Content( $this->iterator, $this ); $sub_directories[] = new WP_Content( $this->iterator, $this, $custom_post_types ); if ( ! empty( $custom_post_types ) ) { $sub_directories[] = new Custom_Post_Type_Title( $this->iterator, $this, $custom_post_types ); } } if ( in_array( 'plugins', $include, true ) ) { $sub_directories[] = new Plugins( $this->iterator, $this ); } return $sub_directories; } } modules/import-export/export.php 0000644 00000003237 15237752276 0013124 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport; use Elementor\Core\App\Modules\ImportExport\Directories\Root; use Elementor\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Export extends Iterator { /** * @var \ZipArchive */ private $zip_archive; private $archive_file_name; final public function run() { ob_start(); $this->init_zip_archive(); $root_directory = new Root( $this ); $manifest_data = $root_directory->run_export(); /** * Manifest data from exported kit. * * Filters the manifest data of any exported kit. * * @param array $manifest_data Manifest data. * @param Export $this The export instance. */ $manifest_data = apply_filters( 'elementor/kit/export/manifest-data', $manifest_data, $this ); $this->set_current_archive_path( '' ); $this->add_json_file( 'manifest', $manifest_data ); $this->zip_archive->close(); return [ 'manifest' => $manifest_data, 'file_name' => $this->archive_file_name, ]; } public function add_json_file( $name, $content, $json_flags = null ) { $this->add_file( $name . '.json', wp_json_encode( $content, $json_flags ) ); } public function add_file( $file_name, $content ) { $this->zip_archive->addFromString( $this->get_archive_file_path( $file_name ), $content ); } private function init_zip_archive() { $zip_archive = new \ZipArchive(); $this->temp_dir = Plugin::$instance->uploads_manager->create_unique_dir(); $this->archive_file_name = $this->temp_dir . 'kit.zip'; $zip_archive->open( $this->archive_file_name, \ZipArchive::CREATE | \ZipArchive::OVERWRITE ); $this->zip_archive = $zip_archive; } } modules/import-export/iterator.php 0000644 00000002551 15237752276 0013432 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport; use Elementor\Core\Base\Base_Object; use Elementor\Modules\System_Info\Reporters\Server; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Iterator extends Base_Object { const ZIP_ARCHIVE_MODULE_NOT_INSTALLED_KEY = 'zip-archive-module-not-installed'; const NO_WRITE_PERMISSIONS_KEY = 'no-write-permissions'; protected $temp_dir; private $current_archive_path = ''; abstract public function run(); protected function get_archive_file_path( $file_name ) { return $this->get_current_archive_path() . $file_name; } public function get_archive_file_full_path( $file_name ) { return $this->temp_dir . $this->get_archive_file_path( $file_name ); } public function get_current_archive_path() { return $this->current_archive_path; } public function set_current_archive_path( $path ) { if ( $path ) { $path .= '/'; } $this->current_archive_path = $path; } public function __construct( array $settings ) { if ( ! class_exists( '\ZipArchive' ) ) { throw new \Error( self::ZIP_ARCHIVE_MODULE_NOT_INSTALLED_KEY ); } $server = new Server(); $server_write_permissions = $server->get_write_permissions(); if ( $server_write_permissions['warning'] ) { throw new \Error( self::NO_WRITE_PERMISSIONS_KEY ); } $this->set_settings( $settings ); } } modules/import-export/wp-cli.php 0000644 00000020505 15237752276 0012773 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport; use Elementor\Core\Utils\Collection; use Elementor\Core\Utils\Plugins_Manager; use Elementor\Plugin; use Elementor\Core\App\Modules\KitLibrary\Connect\Kit_Library; use Elementor\Utils; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Wp_Cli extends \WP_CLI_Command { /** * Export a Kit * * [--include] * Which type of content to include. Possible values are 'content', 'templates', 'site-settings'. * if this parameter won't be specified, All data types will be included. * * ## EXAMPLES * * 1. wp elementor kit export path/to/export-file-name.zip * - This will export all site data to the specified file name. * * 2. wp elementor kit export path/to/export-file-name.zip --include=kit-settings,content * - This will export only site settings and content. * * @param array $args * @param array $assoc_args */ public function export( $args, $assoc_args ) { if ( empty( $args[0] ) ) { \WP_CLI::error( 'Please specify a file name' ); } \WP_CLI::line( 'Kit export started.' ); $export_settings = [ 'include' => [ 'content', 'templates', 'settings' ], ]; foreach ( $assoc_args as $key => $value ) { $import_settings[ $key ] = explode( ',', $value ); } $export_settings = array_merge( $export_settings, $assoc_args ); try { $exporter = new Export( $export_settings ); $result = $exporter->run(); rename( $result['file_name'], $args[0] ); } catch ( \Error $error ) { \WP_CLI::error( $error->getMessage() ); } \WP_CLI::success( 'Kit exported successfully.' ); } /** * Import a Kit * * [--include] * Which type of content to include. Possible values are 'content', 'templates', 'site-settings'. * if this parameter won't be specified, All data types will be included. * * [--overrideConditions] * Templates ids to override conditions for. * * [--sourceType] * Which source type is used in the current session. Available values are 'local', 'remote', 'library'. * The default value is 'local' * * ## EXAMPLES * * 1. wp elementor kit import path/to/elementor-kit.zip * - This will import the whole kit file content. * * 2. wp elementor kit import path/to/elementor-kit.zip --include=site-settings,content * - This will import only site settings and content. * * 3. wp elementor kit import path/to/elementor-kit.zip --overrideConditions=3478,4520 * - This will import all content and will override conditions for the given template ids. * * 4. wp elementor kit import path/to/elementor-kit.zip --unfilteredFilesUpload=enable * - This will allow the import process to import unfiltered files. * * @param array $args * @param array $assoc_args */ public function import( array $args, array $assoc_args ) { if ( ! current_user_can( 'administrator' ) ) { \WP_CLI::error( 'You must run this command as an admin user' ); } if ( empty( $args[0] ) ) { \WP_CLI::error( 'Please specify a file to import' ); } \WP_CLI::line( 'Kit import started' ); \WP_CLI::line( 'Extracting zip archive...' ); $assoc_args = wp_parse_args( $assoc_args, [ 'sourceType' => 'local', ] ); $url = null; $file_path = $args[0]; if ( 'library' === $assoc_args['sourceType'] ) { $url = $this->get_url_from_library( $args[0] ); } elseif ( 'remote' === $assoc_args['sourceType'] ) { $url = $args[0]; } if ( 'enable' === $assoc_args['unfilteredFilesUpload'] ) { Plugin::$instance->uploads_manager->set_elementor_upload_state( true ); Plugin::$instance->uploads_manager->enable_unfiltered_files_upload(); } if ( $url ) { $file_path = $this->create_temp_file_from_url( $url ); } $extraction_result = Plugin::$instance->uploads_manager->extract_and_validate_zip( $file_path, [ 'json', 'xml' ] ); if ( is_wp_error( $extraction_result ) ) { \WP_CLI::error( $extraction_result->get_error_message() ); } $import_settings = [ 'include' => [ 'templates', 'content', 'settings' ], 'session' => $extraction_result['extraction_directory'], ]; foreach ( $assoc_args as $key => $value ) { $import_settings[ $key ] = explode( ',', $value ); } // Remove irrelevant settings from the $import_settings array $remove_irrelevant = [ 'sourceType', 'unfilteredFilesUpload' ]; $import_settings = array_diff_key( $import_settings, array_flip( $remove_irrelevant ) ); try { \WP_CLI::line( 'Importing data...' ); $import = new Import( $import_settings ); $manifest_data = $this->get_manifest_data( $import_settings['session'] ); $manifest_data = $import->adapt_manifest_structure( $manifest_data ); if ( isset( $manifest_data['plugins'] ) ) { $successfully_imported_plugins = $this->import_plugins( $manifest_data['plugins'] ); \WP_CLI::line( 'Ready to use plugins: ' . $successfully_imported_plugins ); } Plugin::$instance->app->get_component( 'import-export' )->import = $import; $import->run(); \WP_CLI::line( 'Removing temp files...' ); Plugin::$instance->uploads_manager->remove_file_or_dir( $import_settings['session'] ); // The file was created from remote or library request and it should be removed. if ( $url ) { Plugin::$instance->uploads_manager->remove_file_or_dir( dirname( $file_path ) ); } \WP_CLI::success( 'Kit imported successfully' ); } catch ( \Error $error ) { Plugin::$instance->uploads_manager->remove_file_or_dir( $import_settings['session'] ); \WP_CLI::error( $error->getMessage() ); } } /** * Helper to get kit url by the kit id * TODO: Maybe extract it. * * @param $kit_id * * @return string */ private function get_url_from_library( $kit_id ) { /** @var Kit_Library $app */ $app = Plugin::$instance->common->get_component( 'connect' )->get_app( 'kit-library' ); if ( ! $app ) { \WP_CLI::error( 'Kit library app not found' ); } $response = $app->download_link( $kit_id ); if ( is_wp_error( $response ) ) { \WP_CLI::error( "Library Response: {$response->get_error_message()}" ); } return $response->download_link; } /** * Helper to get kit zip file path by the kit url * TODO: Maybe extract it. * * @param $url * * @return string */ private function create_temp_file_from_url( $url ) { $response = wp_remote_get( $url ); if ( is_wp_error( $response ) ) { \WP_CLI::error( "Download file url: {$response->get_error_message()}" ); } if ( 200 !== $response['response']['code'] ) { \WP_CLI::error( "Download file url: {$response['response']['message']}" ); } return Plugin::$instance->uploads_manager->create_temp_file( $response['body'], 'kit.zip' ); } /** * Helper to get the manifest data from the 'manifest.json' file. * * @param string $extraction_directory * @return array */ private function get_manifest_data( $extraction_directory ) { $manifest_file_content = Utils::file_get_contents( $extraction_directory . 'manifest.json', true ); if ( ! $manifest_file_content ) { \WP_CLI::error( 'Manifest not found' ); } $manifest_data = json_decode( $manifest_file_content, true ); // In case that the manifest content is not a valid JSON or empty. if ( ! $manifest_data ) { \WP_CLI::error( 'Manifest content is not valid json' ); } return $manifest_data; } /** * Handle the import process of plugins. * * Returns a string contains the successfully installed and activated plugins. * * @param array $plugins * @return string */ private function import_plugins( $plugins ) { $plugins_collection = ( new Collection( $plugins ) ) ->map( function ( $item ) { if ( ! $this->ends_with( $item['plugin'], '.php' ) ) { $item['plugin'] .= '.php'; } return $item; } ); $slugs = $plugins_collection ->map( function ( $item ) { return $item['plugin']; } ) ->all(); $plugins_manager = new Plugins_Manager(); $install = $plugins_manager->install( $slugs ); $activate = $plugins_manager->activate( $install['succeeded'] ); $names = $plugins_collection ->filter( function ( $item ) use ( $activate ) { return in_array( $item['plugin'], $activate['succeeded'], true ); } ) ->map( function ( $item ) { return $item['name']; } ) ->implode( ', ' ); return $names; } private function ends_with( $haystack, $needle ) { return substr( $haystack, -strlen( $needle ) ) === $needle; } } modules/import-export/compatibility/envato.php 0000644 00000005076 15237752276 0015753 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Compatibility; use Elementor\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Envato extends Base_Adapter { public static function is_compatibility_needed( array $manifest_data, array $import_settings ) { return ! empty( $manifest_data['manifest_version'] ); } public function get_manifest_data( array $manifest_data ) { $templates = $manifest_data['templates']; $manifest_data['templates'] = []; foreach ( $templates as $template ) { // Envato store their global kit styles as a 'global.json' template file, this needs to be converted to 'site-settings.json' file if ( ! empty( $template['metadata']['template_type'] ) && 'global-styles' === $template['metadata']['template_type'] ) { $global_file_data = $this->importer->read_json_file( str_replace( '.json', '', $template['source'] ) ); $site_settings = [ 'settings' => $global_file_data['page_settings'] ]; $site_settings_file_destination = $this->importer->get_archive_file_full_path( 'site-settings.json' ); file_put_contents( $site_settings_file_destination, wp_json_encode( $site_settings ) ); // Getting the site-settings because Envato stores them in one of the posts. $kit = Plugin::$instance->kits_manager->get_active_kit(); $kit_tabs = $kit->get_tabs(); unset( $kit_tabs['settings-site-identity'] ); $manifest_data['site-settings'] = array_keys( $kit_tabs ); continue; } // Evanto uses "type" instead of "doc_type" $template['doc_type'] = $template['type']; // Evanto uses for "name" instead of "title" $template['title'] = $template['name']; // Envato specifying an exact path to the template rather than using its "ID" as an index. // This extracts the "file name" part out of our exact source list and we treat that as an ID. $file_name_without_extension = str_replace( '.json', '', basename( $template['source'] ) ); // Append the template to the global list: $manifest_data['templates'][ $file_name_without_extension ] = $template; } return $manifest_data; } public function get_template_data( array $template_data, array $template_settings ) { if ( ! empty( $template_data['metadata']['elementor_pro_conditions'] ) ) { foreach ( $template_data['metadata']['elementor_pro_conditions'] as $condition ) { list ( $type, $name, $sub_name, $sub_id ) = array_pad( explode( '/', $condition ), 4, '' ); $template_data['import_settings']['conditions'][] = compact( 'type', 'name', 'sub_name', 'sub_id' ); } } return $template_data; } } modules/import-export/compatibility/base-adapter.php 0000644 00000001317 15237752276 0017001 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Compatibility; use Elementor\Core\App\Modules\ImportExport\Import; use Elementor\Core\Base\Base_Object; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Base_Adapter extends Base_Object { protected $importer; public static function is_compatibility_needed( array $manifest_data, array $import_settings ) { return false; } public function get_manifest_data( array $manifest_data ) { return $manifest_data; } public function get_template_data( array $template_data, array $template_settings ) { return $template_data; } public function __construct( Import $importer ) { $this->importer = $importer; } } modules/import-export/compatibility/kit-library.php 0000644 00000001432 15237752276 0016700 0 ustar 00 <?php namespace Elementor\Core\App\Modules\ImportExport\Compatibility; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Kit_Library extends Base_Adapter { public static function is_compatibility_needed( array $manifest_data, array $import_settings ) { return ! empty( $import_settings['referrer'] ) && 'kit-library' === $import_settings['referrer']; } public function get_manifest_data( array $manifest_data ) { if ( ! empty( $manifest_data['content']['page'] ) ) { foreach ( $manifest_data['content']['page'] as & $page ) { $page['thumbnail'] = false; } } if ( ! empty( $manifest_data['templates'] ) ) { foreach ( $manifest_data['templates'] as & $template ) { $template['thumbnail'] = false; } } return $manifest_data; } } modules/kit-library/module.php 0000644 00000006313 15237752276 0012466 0 ustar 00 <?php namespace Elementor\Core\App\Modules\KitLibrary; use Elementor\Core\Admin\Menu\Main as MainMenu; use Elementor\Plugin; use Elementor\TemplateLibrary\Source_Local; use Elementor\Core\Base\Module as BaseModule; use Elementor\Core\App\Modules\KitLibrary\Connect\Kit_Library; use Elementor\Core\Common\Modules\Connect\Module as ConnectModule; use Elementor\Core\App\Modules\KitLibrary\Data\Kits\Controller as Kits_Controller; use Elementor\Core\App\Modules\KitLibrary\Data\Taxonomies\Controller as Taxonomies_Controller; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Module extends BaseModule { /** * Get name. * * @access public * * @return string */ public function get_name() { return 'kit-library'; } private function register_admin_menu( MainMenu $menu ) { $menu->add_submenu( [ 'page_title' => __( 'Kit Library', 'elementor' ), 'menu_title' => '<span id="e-admin-menu__kit-library">' . __( 'Kit Library', 'elementor' ) . '</span>', 'menu_slug' => Plugin::$instance->app->get_base_url() . '#/kit-library', 'index' => 40, ] ); } /** * Register the admin menu the old way. */ private function register_admin_menu_legacy() { add_submenu_page( Source_Local::ADMIN_MENU_SLUG, __( 'Kit Library', 'elementor' ), __( 'Kit Library', 'elementor' ), 'manage_options', Plugin::$instance->app->get_base_url() . '#/kit-library' ); } private function set_kit_library_settings() { if ( ! Plugin::$instance->common ) { return; } /** @var ConnectModule $connect */ $connect = Plugin::$instance->common->get_component( 'connect' ); /** @var Kit_Library $kit_library */ $kit_library = $connect->get_app( 'kit-library' ); Plugin::$instance->app->set_settings( 'kit-library', [ 'has_access_to_module' => current_user_can( 'administrator' ), 'subscription_plans' => $connect->get_subscription_plans( 'kit-library' ), 'is_pro' => false, 'is_library_connected' => $kit_library->is_connected(), 'library_connect_url' => $kit_library->get_admin_url( 'authorize', [ 'utm_source' => 'kit-library', 'utm_medium' => 'wp-dash', 'utm_campaign' => 'library-connect', 'utm_term' => '%%page%%', // Will be replaced in the frontend. ] ), 'access_level' => ConnectModule::ACCESS_LEVEL_CORE, ] ); } /** * Module constructor. */ public function __construct() { Plugin::$instance->data_manager_v2->register_controller( new Kits_Controller() ); Plugin::$instance->data_manager_v2->register_controller( new Taxonomies_Controller() ); if ( Plugin::$instance->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( 'admin_menu', function() { $this->register_admin_menu_legacy(); }, 50 /* after Elementor page */ ); } add_action( 'elementor/connect/apps/register', function ( ConnectModule $connect_module ) { $connect_module->register_app( 'kit-library', Kit_Library::get_class_name() ); } ); add_action( 'elementor/init', function () { $this->set_kit_library_settings(); }, 12 /** after the initiation of the connect kit library */ ); } } modules/kit-library/data/kits/endpoints/favorites.php 0000644 00000002044 15237752276 0017066 0 ustar 00 <?php namespace Elementor\Core\App\Modules\KitLibrary\Data\Kits\Endpoints; use Elementor\Core\App\Modules\KitLibrary\Data\Kits\Controller; use Elementor\Data\V2\Base\Endpoint; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } /** * @property Controller $controller */ class Favorites extends Endpoint { public function get_name() { return 'favorites'; } public function get_format() { return 'kits/favorites/{id}'; } protected function register() { $args = [ 'id_arg_type_regex' => '[\w]+', ]; $this->register_item_route( \WP_REST_Server::CREATABLE, $args ); $this->register_item_route( \WP_REST_Server::DELETABLE, $args ); } public function create_item( $id, $request ) { $repository = $this->controller->get_repository(); $kit = $repository->add_to_favorites( $id ); return [ 'data' => $kit, ]; } public function delete_item( $id, $request ) { $repository = $this->controller->get_repository(); $kit = $repository->remove_from_favorites( $id ); return [ 'data' => $kit, ]; } } modules/kit-library/data/kits/endpoints/download-link.php 0000644 00000001545 15237752276 0017633 0 ustar 00 <?php namespace Elementor\Core\App\Modules\KitLibrary\Data\Kits\Endpoints; use Elementor\Data\V2\Base\Endpoint; use Elementor\Core\App\Modules\KitLibrary\Data\Kits\Controller; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } /** * @property Controller $controller */ class Download_Link extends Endpoint { public function get_name() { return 'download-link'; } public function get_format() { return 'kits/download-link/{id}'; } protected function register() { $this->register_item_route( \WP_REST_Server::READABLE, [ 'id_arg_type_regex' => '[\w]+', ] ); } public function get_item( $id, $request ) { $repository = $this->controller->get_repository(); $data = $repository->get_download_link( $id ); return [ 'data' => $data, 'meta' => [ 'nonce' => wp_create_nonce( 'kit-library-import' ), ], ]; } } modules/kit-library/data/kits/controller.php 0000644 00000002766 15237752276 0015257 0 ustar 00 <?php namespace Elementor\Core\App\Modules\KitLibrary\Data\Kits; use Elementor\Core\App\Modules\KitLibrary\Data\Base_Controller; use Elementor\Data\V2\Base\Exceptions\Error_404; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } class Controller extends Base_Controller { public function get_name() { return 'kits'; } public function get_items( $request ) { $data = $this->get_repository()->get_all( $request->get_param( 'force' ) ); return [ 'data' => $data->values(), ]; } public function get_item( $request ) { $data = $this->get_repository()->find( $request->get_param( 'id' ) ); if ( ! $data ) { return new Error_404( __( 'Kit not exists.', 'elementor' ), 'kit_not_exists' ); } return [ 'data' => $data, ]; } public function get_collection_params() { return [ 'force' => [ 'description' => 'Force an API request and skip the cache.', 'required' => false, 'default' => false, 'type' => 'boolean', ], ]; } public function register_endpoints() { $this->index_endpoint->register_item_route( \WP_REST_Server::READABLE, [ 'id' => [ 'description' => 'Unique identifier for the object.', 'type' => 'string', 'required' => true, ], 'id_arg_type_regex' => '[\w]+', ] ); $this->register_endpoint( new Endpoints\Download_Link( $this ) ); $this->register_endpoint( new Endpoints\Favorites( $this ) ); } public function get_permission_callback( $request ) { return current_user_can( 'administrator' ); } } modules/kit-library/data/repository.php 0000644 00000017161 15237752276 0014334 0 ustar 00 <?php namespace Elementor\Core\App\Modules\KitLibrary\Data; use Elementor\Core\Utils\Collection; use Elementor\Data\V2\Base\Exceptions\Error_404; use Elementor\Data\V2\Base\Exceptions\WP_Error_Exception; use Elementor\Modules\Library\User_Favorites; use Elementor\Core\App\Modules\KitLibrary\Connect\Kit_Library; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } class Repository { /** * There is no label for subscription plan with access_level=0 + it should not * be translated. */ const SUBSCRIPTION_PLAN_FREE_TAG = 'Free'; const TAXONOMIES_KEYS = [ 'tags', 'categories', 'features', 'types' ]; const KITS_CACHE_KEY = 'elementor_remote_kits'; const KITS_TAXONOMIES_CACHE_KEY = 'elementor_remote_kits_taxonomies'; const KITS_CACHE_TTL_HOURS = 12; const KITS_TAXONOMIES_CACHE_TTL_HOURS = 12; /** * @var Kit_Library */ protected $api; /** * @var User_Favorites */ protected $user_favorites; /** * @var Collection */ protected $subscription_plans; /** * Get all kits. * * @param false $force_api_request * * @return Collection */ public function get_all( $force_api_request = false ) { return $this->get_kits_data( $force_api_request ) ->map( function ( $kit ) { return $this->transform_kit_api_response( $kit ); } ); } /** * Get specific kit. * * @param $id * @param array $options * * @return array|null */ public function find( $id, $options = [] ) { $options = wp_parse_args( $options, [ 'manifest_included' => true, ] ); $item = $this->get_kits_data() ->find( function ( $kit ) use ( $id ) { return $kit->_id === $id; } ); if ( ! $item ) { return null; } $manifest = null; if ( $options['manifest_included'] ) { $manifest = $this->api->get_manifest( $id ); if ( is_wp_error( $manifest ) ) { throw new WP_Error_Exception( $manifest ); } } return $this->transform_kit_api_response( $item, $manifest ); } /** * @param false $force_api_request * * @return Collection */ public function get_taxonomies( $force_api_request = false ) { return $this->get_taxonomies_data( $force_api_request ) ->only( static::TAXONOMIES_KEYS ) ->reduce( function ( Collection $carry, $taxonomies, $type ) { return $carry->merge( array_map( function ( $taxonomy ) use ( $type ) { return [ 'text' => $taxonomy->name, 'type' => $type, ]; }, $taxonomies ) ); }, new Collection( [] ) ) ->merge( $this->subscription_plans->map( function ( $label ) { return [ 'text' => $label ? $label : self::SUBSCRIPTION_PLAN_FREE_TAG, 'type' => 'subscription_plans', ]; } ) ) ->unique( [ 'text', 'type' ] ); } /** * @param $id * * @return array */ public function get_download_link( $id ) { $response = $this->api->download_link( $id ); if ( is_wp_error( $response ) ) { throw new WP_Error_Exception( $response ); } return [ 'download_link' => $response->download_link ]; } /** * @param $id * * @return array * @throws \Exception */ public function add_to_favorites( $id ) { $kit = $this->find( $id, [ 'manifest_included' => false ] ); if ( ! $kit ) { throw new Error_404( __( 'Kit not found', 'elementor' ), 'kit_not_found' ); } $this->user_favorites->add( 'elementor', 'kits', $kit['id'] ); $kit['is_favorite'] = true; return $kit; } /** * @param $id * * @return array * @throws \Exception */ public function remove_from_favorites( $id ) { $kit = $this->find( $id, [ 'manifest_included' => false ] ); if ( ! $kit ) { throw new Error_404( __( 'Kit not found', 'elementor' ), 'kit_not_found' ); } $this->user_favorites->remove( 'elementor', 'kits', $kit['id'] ); $kit['is_favorite'] = false; return $kit; } /** * @param bool $force_api_request * * @return Collection */ private function get_kits_data( $force_api_request = false ) { $data = get_transient( static::KITS_CACHE_KEY ); if ( ! $data || $force_api_request ) { $data = $this->api->get_all(); if ( is_wp_error( $data ) ) { throw new WP_Error_Exception( $data ); } set_transient( static::KITS_CACHE_KEY, $data, static::KITS_CACHE_TTL_HOURS * HOUR_IN_SECONDS ); } return new Collection( $data ); } /** * @param bool $force_api_request * * @return Collection */ private function get_taxonomies_data( $force_api_request = false ) { $data = get_transient( static::KITS_TAXONOMIES_CACHE_KEY ); if ( ! $data || $force_api_request ) { $data = $this->api->get_taxonomies(); if ( is_wp_error( $data ) ) { throw new WP_Error_Exception( $data ); } set_transient( static::KITS_TAXONOMIES_CACHE_KEY, $data, static::KITS_TAXONOMIES_CACHE_TTL_HOURS * HOUR_IN_SECONDS ); } return new Collection( (array) $data ); } /** * @param $kit * @param null $manifest * * @return array */ private function transform_kit_api_response( $kit, $manifest = null ) { $subscription_plan_tag = $this->subscription_plans->get( $kit->access_level ); $taxonomies = ( new Collection( (array) $kit ) ) ->only( static::TAXONOMIES_KEYS ) ->flatten() ->pluck( 'name' ) ->push( $subscription_plan_tag ? $subscription_plan_tag : self::SUBSCRIPTION_PLAN_FREE_TAG ); return array_merge( [ 'id' => $kit->_id, 'title' => $kit->title, 'thumbnail_url' => $kit->thumbnail, 'access_level' => $kit->access_level, 'keywords' => $kit->keywords, 'taxonomies' => $taxonomies->values(), 'is_favorite' => $this->user_favorites->exists( 'elementor', 'kits', $kit->_id ), // TODO: Remove all the isset when the API stable. 'trend_index' => isset( $kit->trend_index ) ? $kit->trend_index : 0, 'featured_index' => isset( $kit->featured_index ) ? $kit->featured_index : 0, 'popularity_index' => isset( $kit->popularity_index ) ? $kit->popularity_index : 0, 'created_at' => isset( $kit->created_at ) ? $kit->created_at : null, 'updated_at' => isset( $kit->updated_at ) ? $kit->updated_at : null, // ], $manifest ? $this->transform_manifest_api_response( $manifest ) : [] ); } /** * @param $manifest * * @return array */ private function transform_manifest_api_response( $manifest ) { $manifest_content = ( new Collection( (array) $manifest->content ) ) ->reduce( function ( $carry, $content, $type ) { $mapped_documents = array_map( function ( $document ) use ( $type ) { // TODO: Fix it! // Hack to override a bug when a document with type of 'wp-page' is declared as 'wp-post'. if ( 'page' === $type ) { $document->doc_type = 'wp-page'; } return $document; }, (array) $content ); return $carry + $mapped_documents; }, [] ); $content = ( new Collection( (array) $manifest->templates ) ) ->union( $manifest_content ) ->map( function ( $manifest_item, $key ) { return [ 'id' => isset( $manifest_item->id ) ? $manifest_item->id : $key, 'title' => $manifest_item->title, 'doc_type' => $manifest_item->doc_type, 'thumbnail_url' => $manifest_item->thumbnail, 'preview_url' => isset( $manifest_item->url ) ? $manifest_item->url : null, ]; } ); return [ 'description' => $manifest->description, 'preview_url' => isset( $manifest->site ) ? $manifest->site : '', 'documents' => $content->values(), ]; } /** * @param Kit_Library $kit_library * @param User_Favorites $user_favorites * @param Collection $subscription_plans */ public function __construct( Kit_Library $kit_library, User_Favorites $user_favorites, Collection $subscription_plans ) { $this->api = $kit_library; $this->user_favorites = $user_favorites; $this->subscription_plans = $subscription_plans; } } modules/kit-library/data/base-controller.php 0000644 00000001715 15237752276 0015206 0 ustar 00 <?php namespace Elementor\Core\App\Modules\KitLibrary\Data; use Elementor\Plugin; use Elementor\Data\V2\Base\Controller; use Elementor\Core\Utils\Collection; use Elementor\Modules\Library\User_Favorites; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } abstract class Base_Controller extends Controller { /** * @var Repository */ private $repository; /** * @return Repository */ public function get_repository() { if ( ! $this->repository ) { /** @var \Elementor\Core\Common\Modules\Connect\Module $connect */ $connect = Plugin::$instance->common->get_component( 'connect' ); $subscription_plans = ( new Collection( $connect->get_subscription_plans() ) ) ->map( function ( $value ) { return $value['label']; } ); $this->repository = new Repository( $connect->get_app( 'kit-library' ), new User_Favorites( get_current_user_id() ), $subscription_plans ); } return $this->repository; } } modules/kit-library/data/taxonomies/controller.php 0000644 00000001465 15237752276 0016466 0 ustar 00 <?php namespace Elementor\Core\App\Modules\KitLibrary\Data\Taxonomies; use Elementor\Core\App\Modules\KitLibrary\Data\Base_Controller; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } class Controller extends Base_Controller { public function get_name() { return 'kit-taxonomies'; } public function get_collection_params() { return [ 'force' => [ 'description' => 'Force an API request and skip the cache.', 'required' => false, 'default' => false, 'type' => 'boolean', ], ]; } public function get_items( $request ) { $data = $this->get_repository()->get_taxonomies( $request->get_param( 'force' ) ); return [ 'data' => $data->values(), ]; } public function get_permission_callback( $request ) { return current_user_can( 'administrator' ); } } modules/kit-library/connect/kit-library.php 0000644 00000002034 15237752276 0015057 0 ustar 00 <?php namespace Elementor\Core\App\Modules\KitLibrary\Connect; use Elementor\Core\Common\Modules\Connect\Apps\Library; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Kit_Library extends Library { const DEFAULT_BASE_ENDPOINT = 'https://my.elementor.com/api/v1/kits-library'; const FALLBACK_BASE_ENDPOINT = 'https://ms-8874.elementor.com/api/v1/kits-library'; public function get_title() { return __( 'Kit Library', 'elementor' ); } public function get_all() { return $this->http_request( 'GET', 'kits' ); } public function get_taxonomies() { return $this->http_request( 'GET', 'taxonomies' ); } public function get_manifest( $id ) { return $this->http_request( 'GET', "kits/{$id}/manifest" ); } public function download_link( $id ) { return $this->http_request( 'GET', "kits/{$id}/download-link" ); } protected function get_api_url() { return [ static::DEFAULT_BASE_ENDPOINT, static::FALLBACK_BASE_ENDPOINT, ]; } protected function init() { // Remove parent init actions. } } modules/site-editor/module.php 0000644 00000002061 15237752276 0012461 0 ustar 00 <?php namespace Elementor\Core\App\Modules\SiteEditor; use Elementor\Core\Base\Module as BaseModule; use Elementor\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * Site Editor Module * * Responsible for initializing Elementor App functionality */ class Module extends BaseModule { /** * Get name. * * @access public * * @return string */ public function get_name() { return 'site-editor'; } public function add_menu_in_admin_bar( $admin_bar_config ) { $admin_bar_config['elementor_edit_page']['children'][] = [ 'id' => 'elementor_app_site_editor', 'title' => esc_html__( 'Theme Builder', 'elementor' ), 'sub_title' => esc_html__( 'Site', 'elementor' ), 'href' => Plugin::$instance->app->get_settings( 'menu_url' ), 'class' => 'elementor-app-link', 'parent_class' => 'elementor-second-section', ]; return $admin_bar_config; } public function __construct() { add_filter( 'elementor/frontend/admin_bar/settings', [ $this, 'add_menu_in_admin_bar' ] ); // After kit (Site settings) } } app.php 0000644 00000014606 15237752276 0006064 0 ustar 00 <?php namespace Elementor\Core\App; use Elementor\Modules\WebCli\Module as WebCLIModule; use Elementor\Core\Base\App as BaseApp; use Elementor\Core\Settings\Manager as SettingsManager; use Elementor\Plugin; use Elementor\TemplateLibrary\Source_Local; use Elementor\Utils; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } class App extends BaseApp { const PAGE_ID = 'elementor-app'; /** * Get module name. * * Retrieve the module name. * * @since 3.0.0 * @access public * * @return string Module name. */ public function get_name() { return 'app'; } public function get_base_url() { return admin_url( 'admin.php?page=' . self::PAGE_ID . '&ver=' . ELEMENTOR_VERSION ); } public function register_admin_menu() { add_submenu_page( Source_Local::ADMIN_MENU_SLUG, esc_html__( 'Theme Builder', 'elementor' ), esc_html__( 'Theme Builder', 'elementor' ), 'manage_options', self::PAGE_ID ); } public function fix_submenu( $menu ) { global $submenu; if ( is_multisite() && is_network_admin() ) { return $menu; } // Non admin role / custom wp menu. if ( empty( $submenu[ Source_Local::ADMIN_MENU_SLUG ] ) ) { return $menu; } // Hack to add a link to sub menu. foreach ( $submenu[ Source_Local::ADMIN_MENU_SLUG ] as &$item ) { if ( self::PAGE_ID === $item[2] ) { $item[2] = $this->get_settings( 'menu_url' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited $item[4] = 'elementor-app-link'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited } } return $menu; } public function is_current() { return ( ! empty( $_GET['page'] ) && self::PAGE_ID === $_GET['page'] ); } public function admin_init() { do_action( 'elementor/app/init', $this ); $this->enqueue_assets(); // Setup default heartbeat options // TODO: Enable heartbeat. add_filter( 'heartbeat_settings', function( $settings ) { $settings['interval'] = 15; return $settings; } ); $this->render(); die; } protected function get_init_settings() { $referer = wp_get_referer(); return [ 'menu_url' => $this->get_base_url() . '#site-editor/promotion', 'assets_url' => ELEMENTOR_ASSETS_URL, 'return_url' => $referer ? $referer : admin_url(), 'hasPro' => Utils::has_pro(), 'admin_url' => admin_url(), 'login_url' => wp_login_url(), 'base_url' => $this->get_base_url(), ]; } private function render() { require __DIR__ . '/view.php'; } /** * Get Elementor UI theme preference. * * Retrieve the user UI theme preference as defined by editor preferences manager. * * @since 3.0.0 * @access private * * @return string Preferred UI theme. */ private function get_elementor_ui_theme_preference() { $editor_preferences = SettingsManager::get_settings_managers( 'editorPreferences' ); return $editor_preferences->get_model()->get_settings( 'ui_theme' ); } /** * Enqueue dark theme detection script. * * Enqueues an inline script that detects user-agent settings for dark mode and adds a complimentary class to the body tag. * * @since 3.0.0 * @access private */ private function enqueue_dark_theme_detection_script() { if ( 'auto' === $this->get_elementor_ui_theme_preference() ) { wp_add_inline_script( 'elementor-app', 'if ( window.matchMedia && window.matchMedia( `(prefers-color-scheme: dark)` ).matches ) { document.body.classList.add( `eps-theme-dark` ); }' ); } } private function enqueue_assets() { Plugin::$instance->init_common(); /** @var WebCLIModule $web_cli */ $web_cli = Plugin::$instance->modules_manager->get_modules( 'web-cli' ); $web_cli->register_scripts(); Plugin::$instance->common->register_scripts(); wp_register_style( 'select2', $this->get_css_assets_url( 'e-select2', 'assets/lib/e-select2/css/' ), [], '4.0.6-rc.1' ); wp_register_style( 'elementor-icons', $this->get_css_assets_url( 'elementor-icons', 'assets/lib/eicons/css/' ), [], '5.15.0' ); wp_register_style( 'elementor-common', $this->get_css_assets_url( 'common', null, 'default', true ), [], ELEMENTOR_VERSION ); wp_register_style( 'select2', ELEMENTOR_ASSETS_URL . 'lib/e-select2/css/e-select2.css', [], '4.0.6-rc.1' ); wp_enqueue_style( 'elementor-app', $this->get_css_assets_url( 'app', null, 'default', true ), [ 'select2', 'elementor-icons', 'elementor-common', 'select2', ], ELEMENTOR_VERSION ); wp_enqueue_script( 'elementor-app-packages', $this->get_js_assets_url( 'app-packages' ), [ 'wp-i18n', 'react', ], ELEMENTOR_VERSION, true ); wp_register_script( 'select2', $this->get_js_assets_url( 'e-select2.full', 'assets/lib/e-select2/js/' ), [ 'jquery', ], '4.0.6-rc.1', true ); wp_enqueue_script( 'elementor-app', $this->get_js_assets_url( 'app' ), [ 'wp-url', 'wp-i18n', 'react', 'react-dom', 'select2', ], ELEMENTOR_VERSION, true ); if ( ! $this->get_settings( 'disable_dark_theme' ) ) { $this->enqueue_dark_theme_detection_script(); } wp_set_script_translations( 'elementor-app-packages', 'elementor' ); wp_set_script_translations( 'elementor-app', 'elementor' ); $this->print_config(); } public function enqueue_app_loader() { wp_enqueue_script( 'elementor-app-loader', $this->get_js_assets_url( 'app-loader' ), [ 'elementor-common', ], ELEMENTOR_VERSION, true ); $this->print_config( 'elementor-app-loader' ); } public function __construct() { $this->add_component( 'site-editor', new Modules\SiteEditor\Module() ); if ( current_user_can( 'manage_options' ) && Plugin::$instance->experiments->is_feature_active( 'e_import_export' ) || Utils::is_wp_cli() ) { $this->add_component( 'import-export', new Modules\ImportExport\Module() ); // Kit library is depended on import-export $this->add_component( 'kit-library', new Modules\KitLibrary\Module() ); } $this->add_component( 'onboarding', new Modules\Onboarding\Module() ); add_action( 'admin_menu', [ $this, 'register_admin_menu' ], 21 /* after Elementor page */ ); // Happens after WP plugin page validation. add_filter( 'add_menu_classes', [ $this, 'fix_submenu' ] ); if ( $this->is_current() ) { add_action( 'admin_init', [ $this, 'admin_init' ], 0 ); } else { add_action( 'elementor/common/after_register_scripts', [ $this, 'enqueue_app_loader' ] ); } } } view.php 0000644 00000001331 15237752276 0006245 0 ustar 00 <?php namespace Elementor\Core\App; use Elementor\Utils; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } /** * @var App $this */ $theme_class = 'dark' === $this->get_elementor_ui_theme_preference() ? 'eps-theme-dark' : ''; ?> <!DOCTYPE html> <html <?php language_attributes(); ?>> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title><?php echo esc_html__( 'Elementor', 'elementor' ) . ' ... '; ?></title> <base target="_parent"> <?php wp_print_styles(); ?> </head> <body class="<?php Utils::print_unescaped_internal_string( $theme_class ); ?>"> <div id="e-app"></div> <?php wp_print_footer_scripts(); ?> </body> </html>
| ver. 1.4 |
Github
|
.
| PHP 7.3.33 | Generation time: 0.05 |
proxy
|
phpinfo
|
Settings