balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

editor.php (24928B)


      1 <?php
      2 namespace Elementor\Core\Editor;
      3 
      4 use Elementor\Api;
      5 use Elementor\Core\Breakpoints\Breakpoint;
      6 use Elementor\Core\Breakpoints\Manager as Breakpoints_Manager;
      7 use Elementor\Core\Common\Modules\Ajax\Module;
      8 use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
      9 use Elementor\Core\Debug\Loading_Inspection_Manager;
     10 use Elementor\Core\Files\Assets\Files_Upload_Handler;
     11 use Elementor\Core\Schemes\Manager as Schemes_Manager;
     12 use Elementor\Core\Settings\Manager as SettingsManager;
     13 use Elementor\Icons_Manager;
     14 use Elementor\Plugin;
     15 use Elementor\Settings;
     16 use Elementor\Shapes;
     17 use Elementor\TemplateLibrary\Source_Local;
     18 use Elementor\Tools;
     19 use Elementor\User;
     20 use Elementor\Utils;
     21 use Elementor\Core\Editor\Data;
     22 
     23 if ( ! defined( 'ABSPATH' ) ) {
     24 	exit; // Exit if accessed directly.
     25 }
     26 
     27 /**
     28  * Elementor editor.
     29  *
     30  * Elementor editor handler class is responsible for initializing Elementor
     31  * editor and register all the actions needed to display the editor.
     32  *
     33  * @since 1.0.0
     34  */
     35 class Editor {
     36 
     37 	/**
     38 	 * The nonce key for Elementor editor.
     39 	 * @deprecated 2.3.0
     40 	 */
     41 	const EDITING_NONCE_KEY = 'elementor-editing';
     42 
     43 	/**
     44 	 * User capability required to access Elementor editor.
     45 	 */
     46 	const EDITING_CAPABILITY = 'edit_posts';
     47 
     48 	/**
     49 	 * Post ID.
     50 	 *
     51 	 * Holds the ID of the current post being edited.
     52 	 *
     53 	 * @since 1.0.0
     54 	 * @access private
     55 	 *
     56 	 * @var int Post ID.
     57 	 */
     58 	private $post_id;
     59 
     60 	/**
     61 	 * Whether the edit mode is active.
     62 	 *
     63 	 * Used to determine whether we are in edit mode.
     64 	 *
     65 	 * @since 1.0.0
     66 	 * @access private
     67 	 *
     68 	 * @var bool Whether the edit mode is active.
     69 	 */
     70 	private $is_edit_mode;
     71 
     72 	/**
     73 	 * @var Notice_Bar
     74 	 */
     75 	public $notice_bar;
     76 
     77 	/**
     78 	 * Init.
     79 	 *
     80 	 * Initialize Elementor editor. Registers all needed actions to run Elementor,
     81 	 * removes conflicting actions etc.
     82 	 *
     83 	 * Fired by `admin_action_elementor` action.
     84 	 *
     85 	 * @since 1.0.0
     86 	 * @access public
     87 	 *
     88 	 * @param bool $die Optional. Whether to die at the end. Default is `true`.
     89 	 */
     90 	public function init( $die = true ) {
     91 		if ( empty( $_REQUEST['post'] ) ) {
     92 			return;
     93 		}
     94 
     95 		$this->set_post_id( absint( $_REQUEST['post'] ) );
     96 
     97 		if ( ! $this->is_edit_mode( $this->post_id ) ) {
     98 			return;
     99 		}
    100 
    101 		// BC: From 2.9.0, the editor shouldn't handle the global post / current document.
    102 		// Use requested id and not the global in order to avoid conflicts with plugins that changes the global post.
    103 		query_posts( [
    104 			'p' => $this->post_id,
    105 			'post_type' => get_post_type( $this->post_id ),
    106 		] );
    107 
    108 		Plugin::$instance->db->switch_to_post( $this->post_id );
    109 
    110 		$document = Plugin::$instance->documents->get( $this->post_id );
    111 
    112 		Plugin::$instance->documents->switch_to_document( $document );
    113 
    114 		// Change mode to Builder
    115 		$document->set_is_built_with_elementor( true );
    116 
    117 		// End BC.
    118 
    119 		Loading_Inspection_Manager::instance()->register_inspections();
    120 
    121 		// Send MIME Type header like WP admin-header.
    122 		@header( 'Content-Type: ' . get_option( 'html_type' ) . '; charset=' . get_option( 'blog_charset' ) );
    123 
    124 		add_filter( 'show_admin_bar', '__return_false' );
    125 
    126 		// Remove all WordPress actions
    127 		remove_all_actions( 'wp_head' );
    128 		remove_all_actions( 'wp_print_styles' );
    129 		remove_all_actions( 'wp_print_head_scripts' );
    130 		remove_all_actions( 'wp_footer' );
    131 
    132 		// Handle `wp_head`
    133 		add_action( 'wp_head', 'wp_enqueue_scripts', 1 );
    134 		add_action( 'wp_head', 'wp_print_styles', 8 );
    135 		add_action( 'wp_head', 'wp_print_head_scripts', 9 );
    136 		add_action( 'wp_head', 'wp_site_icon' );
    137 		add_action( 'wp_head', [ $this, 'editor_head_trigger' ], 30 );
    138 
    139 		// Handle `wp_footer`
    140 		add_action( 'wp_footer', 'wp_print_footer_scripts', 20 );
    141 		add_action( 'wp_footer', 'wp_auth_check_html', 30 );
    142 		add_action( 'wp_footer', [ $this, 'wp_footer' ] );
    143 
    144 		// Handle `wp_enqueue_scripts`
    145 		remove_all_actions( 'wp_enqueue_scripts' );
    146 
    147 		// Also remove all scripts hooked into after_wp_tiny_mce.
    148 		remove_all_actions( 'after_wp_tiny_mce' );
    149 
    150 		add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ], 999999 );
    151 		add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_styles' ], 999999 );
    152 
    153 		// Setup default heartbeat options
    154 		add_filter( 'heartbeat_settings', function( $settings ) {
    155 			$settings['interval'] = 15;
    156 			return $settings;
    157 		} );
    158 
    159 		// Tell to WP Cache plugins do not cache this request.
    160 		Utils::do_not_cache();
    161 
    162 		do_action( 'elementor/editor/init' );
    163 
    164 		$this->print_editor_template();
    165 
    166 		// From the action it's an empty string, from tests its `false`
    167 		if ( false !== $die ) {
    168 			die;
    169 		}
    170 	}
    171 
    172 	/**
    173 	 * Retrieve post ID.
    174 	 *
    175 	 * Get the ID of the current post.
    176 	 *
    177 	 * @since 1.8.0
    178 	 * @access public
    179 	 *
    180 	 * @return int Post ID.
    181 	 */
    182 	public function get_post_id() {
    183 		return $this->post_id;
    184 	}
    185 
    186 	/**
    187 	 * Redirect to new URL.
    188 	 *
    189 	 * Used as a fallback function for the old URL structure of Elementor page
    190 	 * edit URL.
    191 	 *
    192 	 * Fired by `template_redirect` action.
    193 	 *
    194 	 * @since 1.6.0
    195 	 * @access public
    196 	 */
    197 	public function redirect_to_new_url() {
    198 		if ( ! isset( $_GET['elementor'] ) ) {
    199 			return;
    200 		}
    201 
    202 		$document = Plugin::$instance->documents->get( get_the_ID() );
    203 
    204 		if ( ! $document ) {
    205 			wp_die( esc_html__( 'Document not found.', 'elementor' ) );
    206 		}
    207 
    208 		if ( ! $document->is_editable_by_current_user() || ! $document->is_built_with_elementor() ) {
    209 			return;
    210 		}
    211 
    212 		wp_safe_redirect( $document->get_edit_url() );
    213 		die;
    214 	}
    215 
    216 	/**
    217 	 * Whether the edit mode is active.
    218 	 *
    219 	 * Used to determine whether we are in the edit mode.
    220 	 *
    221 	 * @since 1.0.0
    222 	 * @access public
    223 	 *
    224 	 * @param int $post_id Optional. Post ID. Default is `null`, the current
    225 	 *                     post ID.
    226 	 *
    227 	 * @return bool Whether the edit mode is active.
    228 	 */
    229 	public function is_edit_mode( $post_id = null ) {
    230 		if ( null !== $this->is_edit_mode ) {
    231 			return $this->is_edit_mode;
    232 		}
    233 
    234 		if ( empty( $post_id ) ) {
    235 			$post_id = $this->post_id;
    236 		}
    237 
    238 		$document = Plugin::$instance->documents->get( $post_id );
    239 
    240 		if ( ! $document || ! $document->is_editable_by_current_user() ) {
    241 			return false;
    242 		}
    243 
    244 		/** @var Module ajax */
    245 		$ajax_data = Plugin::$instance->common->get_component( 'ajax' )->get_current_action_data();
    246 
    247 		if ( ! empty( $ajax_data ) && 'get_document_config' === $ajax_data['action'] ) {
    248 			return true;
    249 		}
    250 
    251 		// Ajax request as Editor mode
    252 		$actions = [
    253 			'elementor',
    254 
    255 			// Templates
    256 			'elementor_get_templates',
    257 			'elementor_save_template',
    258 			'elementor_get_template',
    259 			'elementor_delete_template',
    260 			'elementor_import_template',
    261 			'elementor_library_direct_actions',
    262 		];
    263 
    264 		if ( isset( $_REQUEST['action'] ) && in_array( $_REQUEST['action'], $actions ) ) {
    265 			return true;
    266 		}
    267 
    268 		return false;
    269 	}
    270 
    271 	/**
    272 	 * Lock post.
    273 	 *
    274 	 * Mark the post as currently being edited by the current user.
    275 	 *
    276 	 * @since 1.0.0
    277 	 * @access public
    278 	 *
    279 	 * @param int $post_id The ID of the post being edited.
    280 	 */
    281 	public function lock_post( $post_id ) {
    282 		if ( ! function_exists( 'wp_set_post_lock' ) ) {
    283 			require_once ABSPATH . 'wp-admin/includes/post.php';
    284 		}
    285 
    286 		wp_set_post_lock( $post_id );
    287 	}
    288 
    289 	/**
    290 	 * Get locked user.
    291 	 *
    292 	 * Check what user is currently editing the post.
    293 	 *
    294 	 * @since 1.0.0
    295 	 * @access public
    296 	 *
    297 	 * @param int $post_id The ID of the post being edited.
    298 	 *
    299 	 * @return \WP_User|false User information or false if the post is not locked.
    300 	 */
    301 	public function get_locked_user( $post_id ) {
    302 		if ( ! function_exists( 'wp_check_post_lock' ) ) {
    303 			require_once ABSPATH . 'wp-admin/includes/post.php';
    304 		}
    305 
    306 		$locked_user = wp_check_post_lock( $post_id );
    307 		if ( ! $locked_user ) {
    308 			return false;
    309 		}
    310 
    311 		return get_user_by( 'id', $locked_user );
    312 	}
    313 
    314 	/**
    315 	 * Print Editor Template.
    316 	 *
    317 	 * Include the wrapper template of the editor.
    318 	 *
    319 	 * @since 2.2.0
    320 	 * @access public
    321 	 */
    322 	public function print_editor_template() {
    323 		include ELEMENTOR_PATH . 'includes/editor-templates/editor-wrapper.php';
    324 	}
    325 
    326 	/**
    327 	 * Enqueue scripts.
    328 	 *
    329 	 * Registers all the editor scripts and enqueues them.
    330 	 *
    331 	 * @since 1.0.0
    332 	 * @access public
    333 	 */
    334 	public function enqueue_scripts() {
    335 		remove_action( 'wp_enqueue_scripts', [ $this, __FUNCTION__ ], 999999 );
    336 
    337 		global $wp_styles, $wp_scripts;
    338 
    339 		$plugin = Plugin::$instance;
    340 
    341 		// Reset global variable
    342 		$wp_styles = new \WP_Styles(); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
    343 		$wp_scripts = new \WP_Scripts(); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
    344 
    345 		$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || defined( 'ELEMENTOR_TESTS' ) && ELEMENTOR_TESTS ) ? '' : '.min';
    346 
    347 		wp_register_script(
    348 			'elementor-editor-modules',
    349 			ELEMENTOR_ASSETS_URL . 'js/editor-modules' . $suffix . '.js',
    350 			[
    351 				'elementor-common-modules',
    352 			],
    353 			ELEMENTOR_VERSION,
    354 			true
    355 		);
    356 
    357 		wp_register_script(
    358 			'elementor-editor-document',
    359 			ELEMENTOR_ASSETS_URL . 'js/editor-document' . $suffix . '.js',
    360 			[
    361 				'elementor-common-modules',
    362 			],
    363 			ELEMENTOR_VERSION,
    364 			true
    365 		);
    366 		// Hack for waypoint with editor mode.
    367 		wp_register_script(
    368 			'elementor-waypoints',
    369 			ELEMENTOR_ASSETS_URL . 'lib/waypoints/waypoints-for-editor.js',
    370 			[
    371 				'jquery',
    372 			],
    373 			'4.0.2',
    374 			true
    375 		);
    376 
    377 		wp_register_script(
    378 			'perfect-scrollbar',
    379 			ELEMENTOR_ASSETS_URL . 'lib/perfect-scrollbar/js/perfect-scrollbar' . $suffix . '.js',
    380 			[],
    381 			'1.4.0',
    382 			true
    383 		);
    384 
    385 		wp_register_script(
    386 			'jquery-easing',
    387 			ELEMENTOR_ASSETS_URL . 'lib/jquery-easing/jquery-easing' . $suffix . '.js',
    388 			[
    389 				'jquery',
    390 			],
    391 			'1.3.2',
    392 			true
    393 		);
    394 
    395 		wp_register_script(
    396 			'nprogress',
    397 			ELEMENTOR_ASSETS_URL . 'lib/nprogress/nprogress' . $suffix . '.js',
    398 			[],
    399 			'0.2.0',
    400 			true
    401 		);
    402 
    403 		wp_register_script(
    404 			'tipsy',
    405 			ELEMENTOR_ASSETS_URL . 'lib/tipsy/tipsy' . $suffix . '.js',
    406 			[
    407 				'jquery',
    408 			],
    409 			'1.0.0',
    410 			true
    411 		);
    412 
    413 		wp_register_script(
    414 			'jquery-elementor-select2',
    415 			ELEMENTOR_ASSETS_URL . 'lib/e-select2/js/e-select2.full' . $suffix . '.js',
    416 			[
    417 				'jquery',
    418 			],
    419 			'4.0.6-rc.1',
    420 			true
    421 		);
    422 
    423 		wp_register_script(
    424 			'flatpickr',
    425 			ELEMENTOR_ASSETS_URL . 'lib/flatpickr/flatpickr' . $suffix . '.js',
    426 			[
    427 				'jquery',
    428 			],
    429 			'1.12.0',
    430 			true
    431 		);
    432 
    433 		wp_register_script(
    434 			'ace',
    435 			'https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.5/ace.js',
    436 			[],
    437 			'1.2.5',
    438 			true
    439 		);
    440 
    441 		wp_register_script(
    442 			'ace-language-tools',
    443 			'https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.5/ext-language_tools.js',
    444 			[
    445 				'ace',
    446 			],
    447 			'1.2.5',
    448 			true
    449 		);
    450 
    451 		wp_register_script(
    452 			'jquery-hover-intent',
    453 			ELEMENTOR_ASSETS_URL . 'lib/jquery-hover-intent/jquery-hover-intent' . $suffix . '.js',
    454 			[],
    455 			'1.0.0',
    456 			true
    457 		);
    458 
    459 		wp_register_script(
    460 			'nouislider',
    461 			ELEMENTOR_ASSETS_URL . 'lib/nouislider/nouislider' . $suffix . '.js',
    462 			[],
    463 			'13.0.0',
    464 			true
    465 		);
    466 
    467 		wp_register_script(
    468 			'pickr',
    469 			ELEMENTOR_ASSETS_URL . 'lib/pickr/pickr.min.js',
    470 			[],
    471 			'1.5.0',
    472 			true
    473 		);
    474 
    475 		wp_register_script(
    476 			'elementor-editor',
    477 			ELEMENTOR_ASSETS_URL . 'js/editor' . $suffix . '.js',
    478 			[
    479 				'elementor-common',
    480 				'elementor-editor-modules',
    481 				'elementor-editor-document',
    482 				'wp-auth-check',
    483 				'jquery-ui-sortable',
    484 				'jquery-ui-resizable',
    485 				'perfect-scrollbar',
    486 				'nprogress',
    487 				'tipsy',
    488 				'imagesloaded',
    489 				'heartbeat',
    490 				'jquery-elementor-select2',
    491 				'flatpickr',
    492 				'ace',
    493 				'ace-language-tools',
    494 				'jquery-hover-intent',
    495 				'nouislider',
    496 				'pickr',
    497 				'react',
    498 				'react-dom',
    499 			],
    500 			ELEMENTOR_VERSION,
    501 			true
    502 		);
    503 
    504 		/**
    505 		 * Before editor enqueue scripts.
    506 		 *
    507 		 * Fires before Elementor editor scripts are enqueued.
    508 		 *
    509 		 * @since 1.0.0
    510 		 */
    511 		do_action( 'elementor/editor/before_enqueue_scripts' );
    512 
    513 		// Tweak for WP Admin menu icons
    514 		wp_print_styles( 'editor-buttons' );
    515 
    516 		$settings = SettingsManager::get_settings_managers_config();
    517 		// Moved to document since 2.9.0.
    518 		unset( $settings['page'] );
    519 
    520 		$document = Plugin::$instance->documents->get_doc_or_auto_save( $this->post_id );
    521 		$kits_manager = Plugin::$instance->kits_manager;
    522 
    523 		$page_title_selector = $kits_manager->get_current_settings( 'page_title_selector' );
    524 
    525 		$page_title_selector .= ', .elementor-page-title .elementor-heading-title';
    526 
    527 		$config = [
    528 			'initial_document' => $document->get_config(),
    529 			'version' => ELEMENTOR_VERSION,
    530 			'home_url' => home_url(),
    531 			'admin_settings_url' => admin_url( 'admin.php?page=' . Settings::PAGE_ID ),
    532 			'admin_tools_url' => admin_url( 'admin.php?page=' . Tools::PAGE_ID ),
    533 			'autosave_interval' => AUTOSAVE_INTERVAL,
    534 			'tabs' => $plugin->controls_manager->get_tabs(),
    535 			'controls' => $plugin->controls_manager->get_controls_data(),
    536 			'elements' => $plugin->elements_manager->get_element_types_config(),
    537 			'schemes' => [
    538 				'items' => $plugin->schemes_manager->get_registered_schemes_data(),
    539 				'enabled_schemes' => Schemes_Manager::get_enabled_schemes(),
    540 			],
    541 			'globals' => [
    542 				'defaults_enabled' => [
    543 					'colors' => $kits_manager->is_custom_colors_enabled(),
    544 					'typography' => $kits_manager->is_custom_typography_enabled(),
    545 				],
    546 			],
    547 			'icons' => [
    548 				'libraries' => Icons_Manager::get_icon_manager_tabs_config(),
    549 				'goProURL' => Utils::get_pro_link( 'https://elementor.com/pro/?utm_source=icon-library&utm_campaign=gopro&utm_medium=wp-dash' ),
    550 			],
    551 			'filesUpload' => [
    552 				'unfilteredFiles' => Files_Upload_Handler::is_enabled(),
    553 			],
    554 			'fa4_to_fa5_mapping_url' => ELEMENTOR_ASSETS_URL . 'lib/font-awesome/migration/mapping.js',
    555 			'default_schemes' => $plugin->schemes_manager->get_schemes_defaults(),
    556 			'settings' => $settings,
    557 			'system_schemes' => $plugin->schemes_manager->get_system_schemes(),
    558 			'wp_editor' => $this->get_wp_editor_config(),
    559 			'settings_page_link' => Settings::get_url(),
    560 			'tools_page_link' => Tools::get_url(),
    561 			'elementor_site' => 'https://go.elementor.com/about-elementor/',
    562 			'docs_elementor_site' => 'https://go.elementor.com/docs/',
    563 			'help_the_content_url' => 'https://go.elementor.com/the-content-missing/',
    564 			'help_flexbox_bc_url' => 'https://go.elementor.com/flexbox-layout-bc/',
    565 			'elementPromotionURL' => 'https://go.elementor.com/go-pro-%s',
    566 			'dynamicPromotionURL' => 'https://go.elementor.com/go-pro-dynamic-tag',
    567 			'additional_shapes' => Shapes::get_additional_shapes_for_config(),
    568 			'user' => [
    569 				'restrictions' => $plugin->role_manager->get_user_restrictions_array(),
    570 				'is_administrator' => current_user_can( 'manage_options' ),
    571 				'introduction' => User::get_introduction_meta(),
    572 			],
    573 			'preview' => [
    574 				'help_preview_error_url' => 'https://go.elementor.com/preview-not-loaded/',
    575 				'help_preview_http_error_url' => 'https://go.elementor.com/preview-not-loaded/#permissions',
    576 				'help_preview_http_error_500_url' => 'https://go.elementor.com/500-error/',
    577 				'debug_data' => Loading_Inspection_Manager::instance()->run_inspections(),
    578 			],
    579 			'locale' => get_locale(),
    580 			'rich_editing_enabled' => filter_var( get_user_meta( get_current_user_id(), 'rich_editing', true ), FILTER_VALIDATE_BOOLEAN ),
    581 			'page_title_selector' => $page_title_selector,
    582 			'tinymceHasCustomConfig' => class_exists( 'Tinymce_Advanced' ) || class_exists( 'Advanced_Editor_Tools' ),
    583 			'inlineEditing' => Plugin::$instance->widgets_manager->get_inline_editing_config(),
    584 			'dynamicTags' => Plugin::$instance->dynamic_tags->get_config(),
    585 			'ui' => [
    586 				'darkModeStylesheetURL' => ELEMENTOR_ASSETS_URL . 'css/editor-dark-mode' . $suffix . '.css',
    587 				'defaultGenericFonts' => $kits_manager->get_current_settings( 'default_generic_fonts' ),
    588 			],
    589 			// Empty array for BC to avoid errors.
    590 			'i18n' => [],
    591 			// 'responsive' contains the custom breakpoints config introduced in Elementor v3.2.0
    592 			'responsive' => [
    593 				'breakpoints' => Plugin::$instance->breakpoints->get_breakpoints_config(),
    594 				'icons_map' => Plugin::$instance->breakpoints->get_responsive_icons_classes_map(),
    595 			],
    596 		];
    597 
    598 		if ( ! Utils::has_pro() && current_user_can( 'manage_options' ) ) {
    599 			$config['promotionWidgets'] = Api::get_promotion_widgets();
    600 		}
    601 
    602 		$this->bc_move_document_filters();
    603 
    604 		/**
    605 		 * Localize editor settings.
    606 		 *
    607 		 * Filters the editor localized settings.
    608 		 *
    609 		 * @since 1.0.0
    610 		 *
    611 		 * @param array $config  Editor configuration.
    612 		 * @param int   $post_id The ID of the current post being edited.
    613 		 */
    614 		$config = apply_filters( 'elementor/editor/localize_settings', $config );
    615 
    616 		Utils::print_js_config( 'elementor-editor', 'ElementorConfig', $config );
    617 
    618 		wp_enqueue_script( 'elementor-editor' );
    619 
    620 		wp_set_script_translations( 'elementor-editor', 'elementor' );
    621 
    622 		$plugin->controls_manager->enqueue_control_scripts();
    623 
    624 		/**
    625 		 * After editor enqueue scripts.
    626 		 *
    627 		 * Fires after Elementor editor scripts are enqueued.
    628 		 *
    629 		 * @since 1.0.0
    630 		 */
    631 		do_action( 'elementor/editor/after_enqueue_scripts' );
    632 	}
    633 
    634 	/**
    635 	 * Enqueue styles.
    636 	 *
    637 	 * Registers all the editor styles and enqueues them.
    638 	 *
    639 	 * @since 1.0.0
    640 	 * @access public
    641 	 */
    642 	public function enqueue_styles() {
    643 		/**
    644 		 * Before editor enqueue styles.
    645 		 *
    646 		 * Fires before Elementor editor styles are enqueued.
    647 		 *
    648 		 * @since 1.0.0
    649 		 */
    650 		do_action( 'elementor/editor/before_enqueue_styles' );
    651 
    652 		$suffix = Utils::is_script_debug() ? '' : '.min';
    653 
    654 		$direction_suffix = is_rtl() ? '-rtl' : '';
    655 
    656 		wp_register_style(
    657 			'font-awesome',
    658 			ELEMENTOR_ASSETS_URL . 'lib/font-awesome/css/font-awesome' . $suffix . '.css',
    659 			[],
    660 			'4.7.0'
    661 		);
    662 
    663 		wp_register_style(
    664 			'elementor-select2',
    665 			ELEMENTOR_ASSETS_URL . 'lib/e-select2/css/e-select2' . $suffix . '.css',
    666 			[],
    667 			'4.0.6-rc.1'
    668 		);
    669 
    670 		wp_register_style(
    671 			'google-font-roboto',
    672 			'https://fonts.googleapis.com/css?family=Roboto:300,400,500,700',
    673 			[],
    674 			ELEMENTOR_VERSION
    675 		);
    676 
    677 		wp_register_style(
    678 			'flatpickr',
    679 			ELEMENTOR_ASSETS_URL . 'lib/flatpickr/flatpickr' . $suffix . '.css',
    680 			[],
    681 			'1.12.0'
    682 		);
    683 
    684 		wp_register_style(
    685 			'pickr',
    686 			ELEMENTOR_ASSETS_URL . 'lib/pickr/themes/monolith.min.css',
    687 			[],
    688 			'1.5.0'
    689 		);
    690 
    691 		wp_register_style(
    692 			'elementor-editor',
    693 			ELEMENTOR_ASSETS_URL . 'css/editor' . $direction_suffix . $suffix . '.css',
    694 			[
    695 				'elementor-common',
    696 				'elementor-select2',
    697 				'elementor-icons',
    698 				'wp-auth-check',
    699 				'google-font-roboto',
    700 				'flatpickr',
    701 				'pickr',
    702 			],
    703 			ELEMENTOR_VERSION
    704 		);
    705 
    706 		wp_enqueue_style( 'elementor-editor' );
    707 
    708 		$ui_theme = SettingsManager::get_settings_managers( 'editorPreferences' )->get_model()->get_settings( 'ui_theme' );
    709 
    710 		if ( 'light' !== $ui_theme ) {
    711 			$ui_theme_media_queries = 'all';
    712 
    713 			if ( 'auto' === $ui_theme ) {
    714 				$ui_theme_media_queries = '(prefers-color-scheme: dark)';
    715 			}
    716 
    717 			wp_enqueue_style(
    718 				'elementor-editor-dark-mode',
    719 				ELEMENTOR_ASSETS_URL . 'css/editor-dark-mode' . $suffix . '.css',
    720 				[
    721 					'elementor-editor',
    722 				],
    723 				ELEMENTOR_VERSION,
    724 				$ui_theme_media_queries
    725 			);
    726 		}
    727 
    728 		$breakpoints = Plugin::$instance->breakpoints->get_breakpoints();
    729 
    730 		// The two breakpoints under 'tablet' need to be checked for values.
    731 		if ( $breakpoints[ Breakpoints_Manager::BREAKPOINT_KEY_MOBILE ]->is_custom() || $breakpoints[ Breakpoints_Manager::BREAKPOINT_KEY_MOBILE_EXTRA ]->is_enabled() ) {
    732 			wp_add_inline_style(
    733 				'elementor-editor',
    734 				'.elementor-device-tablet #elementor-preview-responsive-wrapper { width: ' . Plugin::$instance->breakpoints->get_device_min_breakpoint( Breakpoints_Manager::BREAKPOINT_KEY_TABLET ) . 'px; }'
    735 			);
    736 		}
    737 
    738 		/**
    739 		 * After editor enqueue styles.
    740 		 *
    741 		 * Fires after Elementor editor styles are enqueued.
    742 		 *
    743 		 * @since 1.0.0
    744 		 */
    745 		do_action( 'elementor/editor/after_enqueue_styles' );
    746 	}
    747 
    748 	/**
    749 	 * Get WordPress editor config.
    750 	 *
    751 	 * Config the default WordPress editor with custom settings for Elementor use.
    752 	 *
    753 	 * @since 1.9.0
    754 	 * @access private
    755 	 */
    756 	private function get_wp_editor_config() {
    757 		// Remove all TinyMCE plugins.
    758 		remove_all_filters( 'mce_buttons', 10 );
    759 		remove_all_filters( 'mce_external_plugins', 10 );
    760 
    761 		if ( ! class_exists( '\_WP_Editors', false ) ) {
    762 			require ABSPATH . WPINC . '/class-wp-editor.php';
    763 		}
    764 
    765 		// WordPress 4.8 and higher
    766 		if ( method_exists( '\_WP_Editors', 'print_tinymce_scripts' ) ) {
    767 			\_WP_Editors::print_default_editor_scripts();
    768 			\_WP_Editors::print_tinymce_scripts();
    769 		}
    770 		ob_start();
    771 
    772 		wp_editor(
    773 			'%%EDITORCONTENT%%',
    774 			'elementorwpeditor',
    775 			[
    776 				'editor_class' => 'elementor-wp-editor',
    777 				'editor_height' => 250,
    778 				'drag_drop_upload' => true,
    779 			]
    780 		);
    781 
    782 		$config = ob_get_clean();
    783 
    784 		// Don't call \_WP_Editors methods again
    785 		remove_action( 'admin_print_footer_scripts', [ '_WP_Editors', 'editor_js' ], 50 );
    786 		remove_action( 'admin_print_footer_scripts', [ '_WP_Editors', 'print_default_editor_scripts' ], 45 );
    787 
    788 		\_WP_Editors::editor_js();
    789 
    790 		return $config;
    791 	}
    792 
    793 	/**
    794 	 * Editor head trigger.
    795 	 *
    796 	 * Fires the 'elementor/editor/wp_head' action in the head tag in Elementor
    797 	 * editor.
    798 	 *
    799 	 * @since 1.0.0
    800 	 * @access public
    801 	 */
    802 	public function editor_head_trigger() {
    803 		/**
    804 		 * Elementor editor head.
    805 		 *
    806 		 * Fires on Elementor editor head tag.
    807 		 *
    808 		 * Used to prints scripts or any other data in the head tag.
    809 		 *
    810 		 * @since 1.0.0
    811 		 */
    812 		do_action( 'elementor/editor/wp_head' );
    813 	}
    814 
    815 	/**
    816 	 * WP footer.
    817 	 *
    818 	 * Prints Elementor editor with all the editor templates, and render controls,
    819 	 * widgets and content elements.
    820 	 *
    821 	 * Fired by `wp_footer` action.
    822 	 *
    823 	 * @since 1.0.0
    824 	 * @access public
    825 	 */
    826 	public function wp_footer() {
    827 		$plugin = Plugin::$instance;
    828 
    829 		$plugin->controls_manager->render_controls();
    830 		$plugin->widgets_manager->render_widgets_content();
    831 		$plugin->elements_manager->render_elements_content();
    832 
    833 		$plugin->schemes_manager->print_schemes_templates();
    834 
    835 		$plugin->dynamic_tags->print_templates();
    836 
    837 		$this->init_editor_templates();
    838 
    839 		/**
    840 		 * Elementor editor footer.
    841 		 *
    842 		 * Fires on Elementor editor before closing the body tag.
    843 		 *
    844 		 * Used to prints scripts or any other HTML before closing the body tag.
    845 		 *
    846 		 * @since 1.0.0
    847 		 */
    848 		do_action( 'elementor/editor/footer' );
    849 	}
    850 
    851 	/**
    852 	 * Set edit mode.
    853 	 *
    854 	 * Used to update the edit mode.
    855 	 *
    856 	 * @since 1.0.0
    857 	 * @access public
    858 	 *
    859 	 * @param bool $edit_mode Whether the edit mode is active.
    860 	 */
    861 	public function set_edit_mode( $edit_mode ) {
    862 		$this->is_edit_mode = $edit_mode;
    863 	}
    864 
    865 	/**
    866 	 * Editor constructor.
    867 	 *
    868 	 * Initializing Elementor editor and redirect from old URL structure of
    869 	 * Elementor editor.
    870 	 *
    871 	 * @since 1.0.0
    872 	 * @access public
    873 	 */
    874 	public function __construct() {
    875 		Plugin::$instance->data_manager->register_controller( Data\Globals\Controller::class );
    876 
    877 		$this->notice_bar = new Notice_Bar();
    878 
    879 		add_action( 'admin_action_elementor', [ $this, 'init' ] );
    880 		add_action( 'template_redirect', [ $this, 'redirect_to_new_url' ] );
    881 
    882 		// Handle autocomplete feature for URL control.
    883 		add_filter( 'wp_link_query_args', [ $this, 'filter_wp_link_query_args' ] );
    884 		add_filter( 'wp_link_query', [ $this, 'filter_wp_link_query' ] );
    885 	}
    886 
    887 	/**
    888 	 * @since 2.2.0
    889 	 * @access public
    890 	 */
    891 	public function filter_wp_link_query_args( $query ) {
    892 		$library_cpt_key = array_search( Source_Local::CPT, $query['post_type'], true );
    893 		if ( false !== $library_cpt_key ) {
    894 			unset( $query['post_type'][ $library_cpt_key ] );
    895 		}
    896 
    897 		return $query;
    898 	}
    899 
    900 	/**
    901 	 * @since 2.2.0
    902 	 * @access public
    903 	 */
    904 	public function filter_wp_link_query( $results ) {
    905 
    906 		// PHPCS - The user data is not used.
    907 		if ( isset( $_POST['editor'] ) && 'elementor' === $_POST['editor'] ) {  // phpcs:ignore WordPress.Security.NonceVerification.Missing
    908 			$post_type_object = get_post_type_object( 'post' );
    909 			$post_label = $post_type_object->labels->singular_name;
    910 
    911 			foreach ( $results as & $result ) {
    912 				if ( 'post' === get_post_type( $result['ID'] ) ) {
    913 					$result['info'] = $post_label;
    914 				}
    915 			}
    916 		}
    917 
    918 		return $results;
    919 	}
    920 
    921 	/**
    922 	 * Init editor templates.
    923 	 *
    924 	 * Initialize default elementor templates used in the editor panel.
    925 	 *
    926 	 * @since 1.7.0
    927 	 * @access private
    928 	 */
    929 	private function init_editor_templates() {
    930 		$template_names = [
    931 			'global',
    932 			'panel',
    933 			'panel-elements',
    934 			'repeater',
    935 			'templates',
    936 			'navigator',
    937 			'hotkeys',
    938 			'responsive-bar',
    939 		];
    940 
    941 		foreach ( $template_names as $template_name ) {
    942 			Plugin::$instance->common->add_template( ELEMENTOR_PATH . "includes/editor-templates/$template_name.php" );
    943 		}
    944 	}
    945 
    946 	private function bc_move_document_filters() {
    947 		global $wp_filter;
    948 
    949 		$old_tag = 'elementor/editor/localize_settings';
    950 		$new_tag = 'elementor/document/config';
    951 
    952 		if ( ! has_filter( $old_tag ) ) {
    953 			return;
    954 		}
    955 
    956 		foreach ( $wp_filter[ $old_tag ] as $priority => $filters ) {
    957 			foreach ( $filters as $filter_id => $filter_args ) {
    958 				if ( 2 === $filter_args['accepted_args'] ) {
    959 					remove_filter( $old_tag, $filter_id, $priority );
    960 
    961 					add_filter( $new_tag, $filter_args['function'], $priority, 2 );
    962 
    963 					// TODO: Hard deprecation
    964 					// _deprecated_hook( '`' . $old_tag . ` is no longer using post_id', '2.9.0', $new_tag' );
    965 				}
    966 			}
    967 		}
    968 	}
    969 
    970 	public function set_post_id( $post_id ) {
    971 		$this->post_id = $post_id;
    972 	}
    973 }