PluginProbe
Elementor Website Builder – more than just a page builder / 3.23.0-dev3
Elementor Website Builder – more than just a page builder v3.23.0-dev3
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
← All changes | core/editor/editor.php +37 -159 4.3.0-beta13.23.0-dev3 View file →
@@ -3,11 +3,11 @@
3 3
4 4 use Elementor\Core\Breakpoints\Manager as Breakpoints_Manager;
5 5 use Elementor\Core\Common\Modules\Ajax\Module;
6 6 use Elementor\Core\Debug\Loading_Inspection_Manager;
7 -use Elementor\Core\Editor\Loader\Editor_Loader;
8 -use Elementor\Core\Utils\Assets_Config_Provider;
9 -use Elementor\Core\Utils\Collection;
7 +use Elementor\Core\Editor\Loader\Editor_Loader_Factory;
8 +use Elementor\Core\Editor\Loader\Editor_Loader_Interface;
9 +use Elementor\Core\Experiments\Manager as Experiments_Manager;
10 10 use Elementor\Core\Settings\Manager as SettingsManager;
11 11 use Elementor\Plugin;
12 12 use Elementor\TemplateLibrary\Source_Local;
13 13 use Elementor\Utils;
@@ -31,8 +31,10 @@
31 31 * User capability required to access Elementor editor.
32 32 */
33 33 const EDITING_CAPABILITY = 'edit_posts';
34 34
35 + const EDITOR_V2_EXPERIMENT_NAME = 'editor_v2';
36 +
35 37 /**
36 38 * Post ID.
37 39 *
38 40 * Holds the ID of the current post being edited.
@@ -66,9 +68,9 @@
66 68 */
67 69 public $promotion;
68 70
69 71 /**
70 - * @var Editor_Loader
72 + * @var Editor_Loader_Interface
71 73 */
72 74 private $loader;
73 75
74 76 /**
@@ -81,11 +83,11 @@
81 83 *
82 84 * @since 1.0.0
83 85 * @access public
84 86 *
85 - * @param bool $to_die Optional. Whether to die at the end. Default is `true`.
87 + * @param bool $die Optional. Whether to die at the end. Default is `true`.
86 88 */
87 - public function init( $to_die = true ) {
89 + public function init( $die = true ) {
88 90 if ( empty( $_REQUEST['post'] ) ) {
89 91 return;
90 92 }
91 93
@@ -117,10 +119,8 @@
117 119
118 120 // Send MIME Type header like WP admin-header.
119 121 @header( 'Content-Type: ' . get_option( 'html_type' ) . '; charset=' . get_option( 'blog_charset' ) );
120 122
121 - self::send_document_isolation_policy_header();
122 -
123 123 add_filter( 'show_admin_bar', '__return_false' );
124 124
125 125 // Remove all WordPress actions
126 126 remove_all_actions( 'wp_head' );
@@ -162,9 +162,9 @@
162 162
163 163 $this->get_loader()->print_root_template();
164 164
165 165 // From the action it's an empty string, from tests its `false`
166 - if ( false !== $to_die ) {
166 + if ( false !== $die ) {
167 167 die;
168 168 }
169 169 }
170 170
@@ -212,67 +212,8 @@
212 212 die;
213 213 }
214 214
215 215 /**
216 - * Whether the current request targets the Elementor editor.
217 - *
218 - * Unlike `is_edit_mode()`, this is not affected by temporary `set_edit_mode()` overrides.
219 - *
220 - * @since 4.1.0
221 - * @access public
222 - *
223 - * @return bool Whether the current request targets the Elementor editor.
224 - */
225 - public function is_editor_request() {
226 - $common = Plugin::$instance->common;
227 -
228 - if ( $common ) {
229 - /** @var Module ajax */
230 - $ajax_data = $common->get_component( 'ajax' )->get_current_action_data();
231 -
232 - if ( ! empty( $ajax_data ) && 'get_document_config' === $ajax_data['action'] ) {
233 - return true;
234 - }
235 - }
236 -
237 - if ( $this->is_editor_admin_screen() ) {
238 - return true;
239 - }
240 -
241 - return $this->is_editor_ajax_request();
242 - }
243 -
244 - private function is_editor_admin_screen(): bool {
245 - if ( ! function_exists( 'get_current_screen' ) ) {
246 - return false;
247 - }
248 -
249 - $screen = get_current_screen();
250 -
251 - if ( ! $screen ) {
252 - return false;
253 - }
254 -
255 - return isset( $_GET['action'] ) && 'elementor' === $_GET['action'] && in_array( $screen->base, [ 'post', 'toplevel_page_elementor' ], true );
256 - }
257 -
258 - private function is_editor_ajax_request(): bool {
259 - $actions = apply_filters( 'elementor/editor/ajax_actions', [
260 - 'elementor',
261 -
262 - // Templates
263 - 'elementor_get_templates',
264 - 'elementor_save_template',
265 - 'elementor_get_template',
266 - 'elementor_delete_template',
267 - 'elementor_import_template',
268 - 'elementor_library_direct_actions',
269 - ] );
270 -
271 - return isset( $_REQUEST['action'] ) && in_array( $_REQUEST['action'], $actions, true );
272 - }
273 -
274 - /**
275 216 * Whether the edit mode is active.
276 217 *
277 218 * Used to determine whether we are in the edit mode.
278 219 *
@@ -596,92 +537,16 @@
596 537
597 538 add_action( 'admin_action_elementor', [ $this, 'init' ] );
598 539 add_action( 'template_redirect', [ $this, 'redirect_to_new_url' ] );
599 540
541 + $this->register_editor_v2_experiment();
542 +
600 543 // Handle autocomplete feature for URL control.
601 544 add_filter( 'wp_link_query_args', [ $this, 'filter_wp_link_query_args' ] );
602 545 add_filter( 'wp_link_query', [ $this, 'filter_wp_link_query' ] );
603 -
604 - add_filter( 'replace_editor', [ $this, 'filter_replace_editor' ], 10, 2 );
605 546 }
606 547
607 548 /**
608 - * Whether the Document-Isolation-Policy header should be sent on the
609 - * Elementor editor screen and the editor preview iframe.
610 - *
611 - * DIP places the document in its own agent cluster, which is the prerequisite
612 - * for cross-origin isolation features such as SharedArrayBuffer (required by
613 - * WordPress core's client-side media processing introduced in WP 7.1).
614 - *
615 - * Both the editor parent document and the preview iframe must send the same
616 - * DIP header so they join the same agent cluster and synchronous DOM access
617 - * between them (e.g. `iframe.contentWindow.elementorFrontend`) keeps working.
618 - *
619 - * The header is only honored by browsers on a secure context (HTTPS or
620 - * localhost) so the helper short-circuits on insecure origins to avoid
621 - * sending a header that the browser will ignore.
622 - *
623 - * @since 4.1.0
624 - *
625 - * @return bool
626 - */
627 - public static function should_use_document_isolation_policy() {
628 - if ( ! is_ssl() ) {
629 - $raw_host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : '';
630 - $host = strtolower( (string) strtok( $raw_host, ':' ) );
631 -
632 - if ( 'localhost' !== $host && ! str_ends_with( $host, '.localhost' ) ) {
633 - return false;
634 - }
635 - }
636 -
637 - /**
638 - * Filters whether Elementor sends the Document-Isolation-Policy header
639 - * on the editor screen and preview iframe.
640 - *
641 - * @since 4.1.0
642 - *
643 - * @param bool $enabled Whether DIP is enabled. Defaults to true on a secure context.
644 - */
645 - return (bool) apply_filters( 'elementor/editor/use_document_isolation_policy', true );
646 - }
647 -
648 - /**
649 - * Send the Document-Isolation-Policy header for the current response.
650 - *
651 - * Safe to call from both the Elementor editor screen handler and the
652 - * preview iframe handler. No-op when {@see self::should_use_document_isolation_policy()}
653 - * returns false.
654 - *
655 - * @since 4.1.0
656 - */
657 - public static function send_document_isolation_policy_header() {
658 - if ( ! self::should_use_document_isolation_policy() || headers_sent() ) {
659 - return;
660 - }
661 -
662 - header( 'Document-Isolation-Policy: isolate-and-credentialless' );
663 - }
664 -
665 - /**
666 - * Signals to WordPress that Elementor is replacing the block editor on its own editor page,
667 - * so that block-editor-specific behaviour (e.g. WP 7.0 COOP/COEP isolation headers) is not
668 - * applied when the Elementor editor is active.
669 - *
670 - * @param bool $replace Whether the editor is being replaced.
671 - * @param \WP_Post $post The post being edited.
672 - *
673 - * @return bool
674 - */
675 - public function filter_replace_editor( $replace, $post ) {
676 - if ( isset( $_REQUEST['action'] ) && 'elementor' === $_REQUEST['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
677 - return true;
678 - }
679 -
680 - return $replace;
681 - }
682 -
683 - /**
684 549 * @since 2.2.0
685 550 * @access public
686 551 */
687 552 public function filter_wp_link_query_args( $query ) {
@@ -720,29 +585,42 @@
720 585
721 586 /**
722 587 * Get loader.
723 588 *
724 - * @return Editor_Loader
589 + * @return Editor_Loader_Interface
725 590 */
726 591 private function get_loader() {
727 592 if ( ! $this->loader ) {
728 - $this->loader = new Editor_Loader(
729 - new Collection( [
730 - 'assets_url' => ELEMENTOR_ASSETS_URL,
731 - 'min_suffix' => ( Utils::is_script_debug() || Utils::is_elementor_tests() ) ? '' : '.min',
732 - 'direction_suffix' => is_rtl() ? '-rtl' : '',
733 - ] ),
734 - ( new Assets_Config_Provider() )->set_path_resolver(
735 - function ( $name ) {
736 - return ELEMENTOR_ASSETS_PATH . "js/packages/{$name}/{$name}.asset.php";
737 - }
738 - )
739 - );
593 + $this->loader = Editor_Loader_Factory::create();
740 594
741 595 $this->loader->init();
742 596 }
743 597
744 598 return $this->loader;
599 + }
600 +
601 + /**
602 + * Adding Editor V2 experiment.
603 + *
604 + * @return void
605 + * @throws \Exception
606 + */
607 + private function register_editor_v2_experiment() {
608 + Plugin::$instance->experiments->add_feature( [
609 + 'name' => static::EDITOR_V2_EXPERIMENT_NAME,
610 + 'title' => esc_html__( 'Editor Top Bar', 'elementor' ),
611 + 'description' => sprintf(
612 + '%1$s <a href="https://go.elementor.com/wp-dash-elementor-top-bar/" target="_blank">%2$s</a>',
613 + esc_html__( 'Get a sneak peek of the new Editor powered by React. The beautiful design and experimental layout of the Top bar are just some of the exciting tools on their way.', 'elementor' ),
614 + esc_html__( 'Learn more', 'elementor' )
615 + ),
616 + 'default' => Experiments_Manager::STATE_INACTIVE,
617 + 'release_status' => Experiments_Manager::RELEASE_STATUS_BETA,
618 + 'new_site' => [
619 + 'default_active' => true,
620 + 'minimum_installation_version' => '3.23.0',
621 + ],
622 + ] );
745 623 }
746 624
747 625 /**
748 626 * Get elements presets.