403Webshell
Server IP : 146.59.209.152  /  Your IP : 216.73.216.46
Web Server : Apache
System : Linux webm005.cluster131.gra.hosting.ovh.net 5.15.167-ovh-vps-grsec-zfs-classid #1 SMP Tue Sep 17 08:14:20 UTC 2024 x86_64
User : infrafs ( 43850)
PHP Version : 8.2.29
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/i/n/f/infrafs/INFRABIKEIT/wp-content/plugins/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/i/n/f/infrafs/INFRABIKEIT/wp-content/plugins/app.tar
modules/kit-library/module.php000064400000004571151332117540012454 0ustar00<?php
namespace Elementor\Core\App\Modules\KitLibrary;

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';
	}

	/**
	 * Register the admin menu.
	 */
	private function register_admin_menu() {
		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( 'wp-kit-library' ),
			'is_pro' => false,
			'is_library_connected' => $kit_library->is_connected(),
			'library_connect_url'  => $kit_library->get_admin_url( 'authorize' ),
			'access_level' => ConnectModule::ACCESS_LEVEL_CORE,
		] );
	}

	/**
	 * Module constructor.
	 */
	public function __construct() {
		Plugin::$instance->data_manager->register_controller( Kits_Controller::class );
		Plugin::$instance->data_manager->register_controller( Taxonomies_Controller::class );

		add_action( 'admin_menu', function () {
			$this->register_admin_menu();
		}, 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/repository.php000064400000016426151332117540014321 0ustar00<?php
namespace Elementor\Core\App\Modules\KitLibrary\Data;

use Elementor\Core\Utils\Collection;
use Elementor\Modules\Library\User_Favorites;
use Elementor\Core\App\Modules\KitLibrary\Connect\Kit_Library;
use Elementor\Core\App\Modules\KitLibrary\Data\Exceptions\Wp_Error_Exception;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

class Repository {
	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;

	/**
	 * Get all kits.
	 *
	 * @param false $force_api_request
	 *
	 * @return Collection
	 * @throws Wp_Error_Exception
	 */
	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
	 * @throws Wp_Error_Exception
	 */
	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
	 * @throws Wp_Error_Exception
	 */
	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( [] ) )
			->unique( [ 'text', 'type' ] );
	}

	/**
	 * @param $id
	 *
	 * @return array
	 * @throws Wp_Error_Exception
	 */
	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 Wp_Error_Exception
	 * @throws \Exception
	 */
	public function add_to_favorites( $id ) {
		$kit = $this->find( $id, [ 'manifest_included' => false ] );

		if ( ! $kit ) {
			throw new Wp_Error_Exception(
				new \WP_Error( 404, __( 'Kit not found', 'elementor' ) )
			);
		}

		$this->user_favorites->add( 'elementor', 'kits', $kit['id'] );

		$kit['is_favorite'] = true;

		return $kit;
	}

	/**
	 * @param $id
	 *
	 * @return array
	 * @throws Wp_Error_Exception
	 * @throws \Exception
	 */
	public function remove_from_favorites( $id ) {
		$kit = $this->find( $id, [ 'manifest_included' => false ] );

		if ( ! $kit ) {
			throw new Wp_Error_Exception(
				new \WP_Error( 404, __( 'Kit not found', 'elementor' ) )
			);
		}

		$this->user_favorites->remove( 'elementor', 'kits', $kit['id'] );

		$kit['is_favorite'] = false;

		return $kit;
	}

	/**
	 * @param bool $force_api_request
	 *
	 * @return Collection
	 * @throws Wp_Error_Exception
	 */
	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
	 * @throws Wp_Error_Exception
	 */
	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 ) {
		$taxonomies = array_reduce( static::TAXONOMIES_KEYS, function ( $current, $key ) use ( $kit ) {
			return array_merge( $current, array_map( function ( $taxonomy ) {
				return $taxonomy->name;
			}, $kit->{$key} ) );
		}, [] );

		return array_merge(
			[
				'id' => $kit->_id,
				'title' => $kit->title,
				'thumbnail_url' => $kit->thumbnail,
				'access_level' => $kit->access_level,
				'keywords' => $kit->keywords,
				'taxonomies' => $taxonomies,
				'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(),
		];
	}

	/**
	 * Repository constructor.
	 *
	 * @param Kit_Library    $kit_library
	 * @param User_Favorites $user_favorites
	 */
	public function __construct( Kit_Library $kit_library, User_Favorites $user_favorites ) {
		$this->api = $kit_library;
		$this->user_favorites = $user_favorites;
	}
}
modules/kit-library/data/exceptions/wp-error-exception.php000064400000001102151332117540020015 0ustar00<?php
namespace Elementor\Core\App\Modules\KitLibrary\Data\Exceptions;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

// TODO: Maybe transfer into base/data
class Wp_Error_Exception extends \Exception {
	/**
	 * @var \WP_Error
	 */
	protected $error;

	public function __construct( \WP_Error $error ) {
		// If the code is not an http code it transfer it into 500 (Server Error).
		$code = (int) $error->get_error_code();
		$code = 0 === $code ? 500 : $code;

		parent::__construct( $error->get_error_message(), $code );

		$this->error = $error;
	}
}
modules/kit-library/data/base-controller.php000064400000001223151332117540015162 0ustar00<?php
namespace Elementor\Core\App\Modules\KitLibrary\Data;

use Elementor\Plugin;
use Elementor\Data\Base\Controller;
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 ) {
			$this->repository = new Repository(
				Plugin::$instance->common->get_component( 'connect' )->get_app( 'kit-library' ),
				new User_Favorites( get_current_user_id() )
			);
		}

		return $this->repository;
	}
}
modules/kit-library/data/kits/controller.php000064400000004054151332117540015231 0ustar00<?php
namespace Elementor\Core\App\Modules\KitLibrary\Data\Kits;

use Elementor\Core\App\Modules\KitLibrary\Data\Base_Controller;
use Elementor\Core\App\Modules\KitLibrary\Data\Exceptions\Wp_Error_Exception;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

class Controller extends Base_Controller {

	/**
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_Error|array
	 */
	public function get_items( $request ) {
		try {
			$data = $this->get_repository()->get_all( $request->get_param( 'force' ) );
		} catch ( Wp_Error_Exception $exception ) {
			return new \WP_Error( $exception->getCode(), $exception->getMessage(), [ 'status' => $exception->getCode() ] );
		} catch ( \Exception $exception ) {
			return new \WP_Error( 'server_error', __( 'Something went wrong.', 'elementor' ), [ 'status' => 500 ] );
		}

		return [
			'data' => $data->values(),
		];
	}

	/**
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_Error|array
	 */
	public function get_item( $request ) {
		try {
			$data = $this->get_repository()->find( $request->get_param( 'id' ) );
		} catch ( Wp_Error_Exception $exception ) {
			return new \WP_Error( $exception->getCode(), $exception->getMessage(), [ 'status' => $exception->getCode() ] );
		} catch ( \Exception $exception ) {
			return new \WP_Error( 'server_error', __( 'Something went wrong.', 'elementor' ), [ 'status' => 500 ] );
		}

		if ( ! $data ) {
			return new \WP_Error( 'kit_not_exists', __( 'Kit not exists.', 'elementor' ), [ 'status' => 404 ] );
		}

		return [
			'data' => $data,
		];
	}

	/**
	 * @return string
	 */
	public function get_name() {
		return 'kits';
	}

	/**
	 * Must implement.
	 */
	public function register_endpoints() {
		$this->register_endpoint( Endpoints\Download_Link::class );
		$this->register_endpoint( Endpoints\Favorites::class );
	}

	/**
	 * Register internal endpoint.
	 */
	protected function register_internal_endpoints() {
		// Register as internal to remove the default endpoint generated by the base controller.
		$this->register_endpoint( Endpoints\Index::class );
	}
}
modules/kit-library/data/kits/endpoints/download-link.php000064400000002623151332117540017613 0ustar00<?php
namespace Elementor\Core\App\Modules\KitLibrary\Data\Kits\Endpoints;

use Elementor\Data\Base\Endpoint;
use Elementor\Core\App\Modules\KitLibrary\Data\Kits\Controller;
use Elementor\Core\App\Modules\KitLibrary\Data\Exceptions\Wp_Error_Exception;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * @property Controller $controller
 */
class Download_Link extends Endpoint {
	public function get_name() {
		return 'download-link';
	}

	protected function register() {
		$this->register_route(
			'/(?P<id>[\w-]+)/',
			\WP_REST_Server::READABLE,
			function ( $request ) {
				return $this->base_callback( \WP_REST_Server::READABLE, $request, false );
			},
			[
				'id' => [
					'description' => 'Unique identifier for the object.',
					'type' => 'string',
					'required' => true,
				],
			]
		);
	}

	public function get_item( $id, $request ) {
		$repository = $this->controller->get_repository();

		try {
			$data = $repository->get_download_link( $id );
		} catch ( Wp_Error_Exception $exception ) {
			return new \WP_Error( $exception->getCode(), $exception->getMessage(), [ 'status' => $exception->getCode() ] );
		} catch ( \Exception $exception ) {
			return new \WP_Error( 'server_error', __( 'Something went wrong.', 'elementor' ), [ 'status' => 500 ] );
		}

		return [
			'data' => $data,
			'meta' => [
				'nonce' => wp_create_nonce( 'kit-library-import' ),
			],
		];
	}
}
modules/kit-library/data/kits/endpoints/favorites.php000064400000004674151332117540017063 0ustar00<?php
namespace Elementor\Core\App\Modules\KitLibrary\Data\Kits\Endpoints;

use Elementor\Core\App\Modules\KitLibrary\Data\Kits\Controller;
use Elementor\Core\App\Modules\KitLibrary\Data\Exceptions\Wp_Error_Exception;
use Elementor\Data\Base\Endpoint;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * @property Controller $controller
 */
class Favorites extends Endpoint {
	public function get_name() {
		return 'favorites';
	}

	protected function register() {
		$this->register_route(
			'/(?P<id>[\w-]+)/',
			\WP_REST_Server::CREATABLE,
			function ( $request ) {
				return $this->base_callback( \WP_REST_Server::CREATABLE, $request, false );
			},
			[
				'id' => [
					'description' => 'Unique identifier for the object.',
					'type' => 'string',
					'required' => true,
				],
			]
		);

		$this->register_route(
			'/(?P<id>[\w-]+)/',
			\WP_REST_Server::DELETABLE,
			function ( $request ) {
				return $this->base_callback( \WP_REST_Server::DELETABLE, $request, false );
			},
			[
				'id' => [
					'description' => 'Unique identifier for the object.',
					'type' => 'string',
					'required' => true,
				],
			]
		);
	}

	/**
	 * @param string           $id
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_Error|\WP_REST_Response
	 */
	public function create_item( $id, $request ) {
		$repository = $this->controller->get_repository();

		try {
			$kit = $repository->add_to_favorites( $id );
		} catch ( Wp_Error_Exception $exception ) {
			return new \WP_Error( $exception->getCode(), $exception->getMessage(), [ 'status' => $exception->getCode() ] );
		} catch ( \Exception $exception ) {
			return new \WP_Error( 'server_error', __( 'Something went wrong.', 'elementor' ), [ 'status' => 500 ] );
		}

		return new \WP_REST_Response( [
			'data' => $kit,
		] );
	}

	/**
	 * @param string           $id
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_Error|\WP_REST_Response
	 */
	public function delete_item( $id, $request ) {
		$repository = $this->controller->get_repository();

		try {
			$kit = $repository->remove_from_favorites( $id );
		} catch ( Wp_Error_Exception $exception ) {
			return new \WP_Error( $exception->getCode(), $exception->getMessage(), [ 'status' => $exception->getCode() ] );
		} catch ( \Exception $exception ) {
			return new \WP_Error( 'server_error', __( 'Something went wrong.', 'elementor' ), [ 'status' => 500 ] );
		}

		return new \WP_REST_Response( [
			'data' => $kit,
		] );
	}
}
modules/kit-library/data/kits/endpoints/index.php000064400000001742151332117540016161 0ustar00<?php
namespace Elementor\Core\App\Modules\KitLibrary\Data\Kits\Endpoints;

use Elementor\Data\Base\Endpoint;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

class Index extends Endpoint {
	public function get_name() {
		return 'index';
	}

	protected function register() {
		$this->register_route(
			'',
			\WP_REST_Server::READABLE,
			function ( $request ) {
				return $this->base_callback( \WP_REST_Server::READABLE, $request, true );
			},
			[
				'force' => [
					'description' => 'Force an API request and skip the cache.',
					'required' => false,
					'default' => false,
					'type' => 'boolean',
				],
			]
		);

		$this->register_route(
			'(?P<id>[\w-]+)/',
			\WP_REST_Server::READABLE,
			function ( $request ) {
				return $this->base_callback( \WP_REST_Server::READABLE, $request, false );
			},
			[
				'id' => [
					'description' => 'Unique identifier for the object.',
					'type' => 'string',
					'required' => true,
				],
			]
		);
	}
}
modules/kit-library/data/taxonomies/controller.php000064400000002354151332117540016446 0ustar00<?php
namespace Elementor\Core\App\Modules\KitLibrary\Data\Taxonomies;

use Elementor\Core\App\Modules\KitLibrary\Data\Base_Controller;
use Elementor\Core\App\Modules\KitLibrary\Data\Exceptions\Wp_Error_Exception;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

class Controller extends Base_Controller {
	public function get_name() {
		return 'kit-taxonomies';
	}

	public function register_endpoints() {
		//
	}

	/**
	 * Register internal endpoint.
	 */
	protected function register_internal_endpoints() {
		// Register as internal to remove the default endpoint generated by the base controller.
		$this->register_endpoint( Endpoints\Index::class );
	}

	/**
	 * @param \WP_REST_Request $request
	 *
	 * @return \WP_Error|array
	 */
	public function get_items( $request ) {
		try {
			$data = $this->get_repository()->get_taxonomies( $request->get_param( 'force' ) );
		} catch ( Wp_Error_Exception $exception ) {
			return new \WP_Error( $exception->getCode(), $exception->getMessage(), [ 'status' => $exception->getCode() ] );
		} catch ( \Exception $exception ) {
			return new \WP_Error( 'server_error', __( 'Something went wrong.', 'elementor' ), [ 'status' => 500 ] );
		}

		return [
			'data' => $data->values(),
		];
	}
}
modules/kit-library/data/taxonomies/endpoints/index.php000064400000001231151332117540017366 0ustar00<?php
namespace Elementor\Core\App\Modules\KitLibrary\Data\Taxonomies\Endpoints;

use Elementor\Data\Base\Endpoint;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

class Index extends Endpoint {
	public function get_name() {
		return 'index';
	}

	protected function register() {
		$this->register_route(
			'',
			\WP_REST_Server::READABLE,
			function ( $request ) {
				return $this->base_callback( \WP_REST_Server::READABLE, $request, true );
			},
			[
				'force' => [
					'description' => 'Force an API request and skip the cache.',
					'required' => false,
					'default' => false,
					'type' => 'boolean',
				],
			]
		);
	}
}
modules/kit-library/connect/kit-library.php000064400000002034151332117540015041 0ustar00<?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.php000064400000002061151332117540012443 0ustar00<?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)
	}
}
modules/import-export/wp-cli.php000064400000013113151332117540012752 0ustar00<?php

namespace Elementor\Core\App\Modules\ImportExport;

use Elementor\Plugin;
use Elementor\Core\App\Modules\KitLibrary\Connect\Kit_Library;

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.
	 *
	 * @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 export 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 ( $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', 'site-settings' ],
			'directory' => $extraction_result['extraction_directory'],
		];

		foreach ( $assoc_args as $key => $value ) {
			$import_settings[ $key ] = explode( ',', $value );
		}

		try {
			\WP_CLI::line( 'Importing data...' );

			$import = new Import( $import_settings );

			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['directory'] );

			// 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['directory'] );

			\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' );
	}
}
modules/import-export/import.php000064400000003233151332117540013073 0ustar00<?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;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

class Import extends Iterator {

	/**
	 * @var Base_Adapter[]
	 */
	private $adapters = [];

	final public function run() {
		$this->temp_dir = $this->get_settings( 'directory' );

		$manifest_data = $this->read_json_file( 'manifest' );

		$manifest_data = $this->adapt_manifest_structure( $manifest_data );

		$root_directory = new Root( $this );

		return $root_directory->run_import( $manifest_data );
	}

	final public function read_json_file( $name ) {
		$name = $this->get_archive_file_full_path( $name . '.json' );

		return json_decode( 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 );
			}
		}
	}
}
modules/import-export/module.php000064400000022534151332117540013053 0ustar00<?php
namespace Elementor\Core\App\Modules\ImportExport;

use Elementor\Core\Base\Document;
use Elementor\Core\Base\Module as BaseModule;
use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
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';

	/**
	 * @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 [];
		}

		$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(),
		];
	}

	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' );

		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,
			];
		}

		$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;
	}

	private function import_stage_1() {
		// PHPCS - Already validated in caller function.
		if ( ! empty( $_POST['e_import_file'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
			$file_url = $_POST['e_import_file']; // phpcs:ignore WordPress.Security.NonceVerification.Missing
			if ( ! filter_var( $file_url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED ) || 0 !== strpos( $file_url, 'http' ) ) {
				throw new \Error( __( '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_data = json_decode( file_get_contents( $session_dir . 'manifest.json', true ), true );

		$manifest_data = $this->import->adapt_manifest_structure( $manifest_data );

		$result = [
			'session' => basename( $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 );

		$import_settings['directory'] = Plugin::$instance->uploads_manager->get_temp_dir() . $import_settings['session'] . '/';

		$this->import = new Import( $import_settings );

		try {
			if ( 1 === $import_settings['stage'] ) {
				$result = $this->import_stage_1();
			} elseif ( 2 === $import_settings['stage'] ) {
				$result = $this->import_stage_2( $import_settings['directory'] );
			}

			wp_send_json_success( $result );
		} catch ( \Error $error ) {
			wp_send_json_error( $error->getMessage() );
		}
	}

	private function on_init() {
		if ( ! isset( $_GET[ self::EXPORT_TRIGGER_KEY ] ) || ! wp_verify_nonce( $_GET['nonce'], 'elementor_export' ) ) {
			return;
		}

		$export_settings = $_GET[ self::EXPORT_TRIGGER_KEY ];

		try {
			$this->export = new Export( self::merge_properties( [], $export_settings, [ 'include', 'kitInfo' ] ) );

			$export_result = $this->export->run();

			$file_name = $export_result['file_name'];

			$file = file_get_contents( $file_name, true );

			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_die( esc_html( $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' ),
				],
			],
		];

		$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>' . 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
	}

	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/directories/root.php000064400000006170151332117540015063 0ustar00<?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 );

		$kit->save( [ 'settings' => $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 ) ) {
			$sub_directories[] = new Content( $this->iterator, $this );

			$sub_directories[] = new WP_Content( $this->iterator, $this );
		}

		return $sub_directories;
	}
}
modules/import-export/directories/content.php000064400000001170151332117540015545 0ustar00<?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/base.php000064400000005513151332117540015012 0ustar00<?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/wp-post-type.php000064400000002545151332117540016472 0ustar00<?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/wp-content.php000064400000001436151332117540016176 0ustar00<?php

namespace Elementor\Core\App\Modules\ImportExport\Directories;

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 {

	protected function get_name() {
		return 'wp-content';
	}

	protected function get_default_sub_directories() {
		$post_types = get_post_types( [
			'public' => true,
			'can_export' => true,
		] );

		unset(
			$post_types['attachment'],
			$post_types[ Landing_Pages_Module::CPT ],
			$post_types[ Source_Local::CPT ]
		);

		$sub_directories = [];

		foreach ( $post_types as $post_type ) {
			$sub_directories[] = new WP_Post_Type( $this->iterator, $this, $post_type );
		}

		return $sub_directories;
	}
}
modules/import-export/directories/templates.php000064400000004661151332117540016101 0ustar00<?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/post-type.php000064400000006402151332117540016042 0ustar00<?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/iterator.php000064400000002036151332117540013412 0ustar00<?php
namespace Elementor\Core\App\Modules\ImportExport;

use Elementor\Core\Base\Base_Object;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

abstract class Iterator extends Base_Object {

	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( 'ZipArchive module is not installed on the server. You must install this module to perform the process.' );
		}

		$this->set_settings( $settings );
	}
}
modules/import-export/compatibility/base-adapter.php000064400000001317151332117540016763 0ustar00<?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.php000064400000001432151332117540016662 0ustar00<?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/import-export/compatibility/envato.php000064400000005076151332117540015735 0ustar00<?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/export.php000064400000003237151332117540013106 0ustar00<?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;
	}
}
view.php000064400000001331151332117540006227 0ustar00<?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>
app.php000064400000014031151332117540006036 0ustar00<?php
namespace Elementor\Core\App;

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() {
		return [
			'menu_url' => $this->get_base_url() . '#site-editor/promotion',
			'assets_url' => ELEMENTOR_ASSETS_URL,
			'return_url' => isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : admin_url(),
			'hasPro' => Utils::has_pro(),
			'admin_url' => admin_url(),
			'login_url' => wp_login_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();
		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.13.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
		);

		$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() );
		}

		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' ] );
		}
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit