PluginProbe
Elementor Website Builder – more than just a page builder / 3.13.3
Elementor Website Builder – more than just a page builder v3.13.3
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 +31 -201 4.3.0-beta13.13.3 View file →
@@ -3,11 +3,10 @@
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\Config_Providers\Config_Provider_Factory;
8 +use Elementor\Core\Experiments\Manager as Experiments_Manager;
10 9 use Elementor\Core\Settings\Manager as SettingsManager;
11 10 use Elementor\Plugin;
12 11 use Elementor\TemplateLibrary\Source_Local;
13 12 use Elementor\Utils;
@@ -31,8 +30,10 @@
31 30 * User capability required to access Elementor editor.
32 31 */
33 32 const EDITING_CAPABILITY = 'edit_posts';
34 33
34 + const EDITOR_V2_EXPERIMENT_NAME = 'editor_v2';
35 +
35 36 /**
36 37 * Post ID.
37 38 *
38 39 * Holds the ID of the current post being edited.
@@ -81,11 +82,11 @@
81 82 *
82 83 * @since 1.0.0
83 84 * @access public
84 85 *
85 - * @param bool $to_die Optional. Whether to die at the end. Default is `true`.
86 + * @param bool $die Optional. Whether to die at the end. Default is `true`.
86 87 */
87 - public function init( $to_die = true ) {
88 + public function init( $die = true ) {
88 89 if ( empty( $_REQUEST['post'] ) ) {
89 90 return;
90 91 }
91 92
@@ -117,10 +118,8 @@
117 118
118 119 // Send MIME Type header like WP admin-header.
119 120 @header( 'Content-Type: ' . get_option( 'html_type' ) . '; charset=' . get_option( 'blog_charset' ) );
120 121
121 - self::send_document_isolation_policy_header();
122 -
123 122 add_filter( 'show_admin_bar', '__return_false' );
124 123
125 124 // Remove all WordPress actions
126 125 remove_all_actions( 'wp_head' );
@@ -162,9 +161,9 @@
162 161
163 162 $this->get_loader()->print_root_template();
164 163
165 164 // From the action it's an empty string, from tests its `false`
166 - if ( false !== $to_die ) {
165 + if ( false !== $die ) {
167 166 die;
168 167 }
169 168 }
170 169
@@ -212,67 +211,8 @@
212 211 die;
213 212 }
214 213
215 214 /**
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 215 * Whether the edit mode is active.
276 216 *
277 217 * Used to determine whether we are in the edit mode.
278 218 *
@@ -413,9 +353,11 @@
413 353
414 354 // Tweak for WP Admin menu icons
415 355 wp_print_styles( 'editor-buttons' );
416 356
357 + $this->get_loader()->print_client_settings();
417 358 $this->get_loader()->enqueue_scripts();
359 + $this->get_loader()->load_scripts_translations();
418 360
419 361 Plugin::$instance->controls_manager->enqueue_control_scripts();
420 362
421 363 /**
@@ -548,8 +490,10 @@
548 490 $plugin->controls_manager->render_controls();
549 491 $plugin->widgets_manager->render_widgets_content();
550 492 $plugin->elements_manager->render_elements_content();
551 493
494 + $plugin->schemes_manager->print_schemes_templates();
495 +
552 496 $plugin->dynamic_tags->print_templates();
553 497
554 498 $this->get_loader()->register_additional_templates();
555 499
@@ -596,92 +540,16 @@
596 540
597 541 add_action( 'admin_action_elementor', [ $this, 'init' ] );
598 542 add_action( 'template_redirect', [ $this, 'redirect_to_new_url' ] );
599 543
544 + $this->register_editor_v2_experiment();
545 +
600 546 // Handle autocomplete feature for URL control.
601 547 add_filter( 'wp_link_query_args', [ $this, 'filter_wp_link_query_args' ] );
602 548 add_filter( 'wp_link_query', [ $this, 'filter_wp_link_query' ] );
603 -
604 - add_filter( 'replace_editor', [ $this, 'filter_replace_editor' ], 10, 2 );
605 549 }
606 550
607 551 /**
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 552 * @since 2.2.0
685 553 * @access public
686 554 */
687 555 public function filter_wp_link_query_args( $query ) {
@@ -724,22 +592,10 @@
724 592 * @return Editor_Loader
725 593 */
726 594 private function get_loader() {
727 595 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 - );
740 -
741 - $this->loader->init();
596 + $this->loader = new Editor_Loader( Config_Provider_Factory::create() );
597 + $this->loader->register_hooks();
742 598 }
743 599
744 600 return $this->loader;
745 601 }
@@ -744,51 +600,25 @@
744 600 return $this->loader;
745 601 }
746 602
747 603 /**
748 - * Get elements presets.
604 + * Adding Editor V2 experiment.
749 605 *
750 - * @return array
751 - */
752 - public function get_elements_presets() {
753 - $element_types = Plugin::$instance->elements_manager->get_element_types();
754 - $presets = [];
755 -
756 - foreach ( $element_types as $el_type => $element ) {
757 - $this->check_element_for_presets( $element, $el_type, $presets );
758 - }
759 -
760 - return $presets;
761 - }
762 -
763 - /**
764 606 * @return void
607 + * @throws \Exception
765 608 */
766 - private function check_element_for_presets( $element, $el_type, &$presets ) {
767 - $element_presets = $element->get_panel_presets();
768 -
769 - if ( empty( $element_presets ) ) {
770 - return;
771 - }
772 -
773 - foreach ( $element_presets as $key => $preset ) {
774 - $this->maybe_add_preset( $el_type, $preset, $key, $presets );
775 - }
776 - }
777 -
778 - /**
779 - * @return void
780 - */
781 - private function maybe_add_preset( $el_type, $preset, $key, &$presets ) {
782 - if ( $this->is_valid_preset( $el_type, $preset ) ) {
783 - $presets[ $key ] = $preset;
784 - }
785 - }
786 -
787 - /**
788 - * @return boolean
789 - */
790 - private function is_valid_preset( $el_type, $preset ) {
791 - return isset( $preset['replacements']['custom']['originalWidget'] )
792 - && $el_type === $preset['replacements']['custom']['originalWidget'];
609 + private function register_editor_v2_experiment() {
610 + Plugin::$instance->experiments->add_feature( [
611 + 'name' => static::EDITOR_V2_EXPERIMENT_NAME,
612 + 'title' => esc_html__( 'Editor Top Bar', 'elementor' ),
613 + 'description' => sprintf(
614 + esc_html__(
615 + '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. %s',
616 + 'elementor'
617 + ),
618 + '<a href="https://go.elementor.com/wp-dash-elementor-top-bar/" target="_blank">' . esc_html__( 'Learn more', 'elementor' ) . '</a>'
619 + ),
620 + 'default' => Experiments_Manager::STATE_INACTIVE,
621 + 'status' => Experiments_Manager::RELEASE_STATUS_ALPHA,
622 + ] );
793 623 }
794 624 }