modules/onboarding/module.php 0000644 00000032136 15237752276 0012361 0 ustar 00 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 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( '%s', 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' ),
'
',
$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' ) . '
';
$info_text .= sprintf( '%2$s', $editor_page_link . '#e:run:panel/global/open&e:route:panel/history/revisions', esc_html__( 'Open Site Settings > History > Revisions.', 'elementor' ) );
?>
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 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 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 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 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 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 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 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 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 iterator, $this, $post_type );
}
return $sub_directories;
}
}
modules/import-export/directories/post-type.php 0000644 00000006402 15237752276 0016060 0 ustar 00 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 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 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 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 [ '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 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 importer = $importer;
}
}
modules/import-export/compatibility/kit-library.php 0000644 00000001432 15237752276 0016700 0 ustar 00 add_submenu( [
'page_title' => __( 'Kit Library', 'elementor' ),
'menu_title' => '',
'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 '[\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 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 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 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 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 [
'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 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 '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 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 get_elementor_ui_theme_preference() ? 'eps-theme-dark' : '';
?>
>