PluginProbe
Elementor Website Builder – more than just a page builder / 3.22.1
Elementor Website Builder – more than just a page builder v3.22.1
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
elementor / includes / compatibility.php

compatibility.php in Elementor Website Builder – more than just a page builder 3.22.1, at includes/compatibility.php

376 lines 10.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor;
3
4 use Elementor\Core\Base\Document;
5 use Elementor\Core\DocumentTypes\PageBase;
6 use Elementor\TemplateLibrary\Source_Local;
7 use Elementor\Utils;
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit; // Exit if accessed directly.
11 }
12
13 /**
14 * Elementor compatibility.
15 *
16 * Elementor compatibility handler class is responsible for compatibility with
17 * external plugins. The class resolves different issues with non-compatible
18 * plugins.
19 *
20 * @since 1.0.0
21 */
22 class Compatibility {
23
24 /**
25 * Register actions.
26 *
27 * Run Elementor compatibility with external plugins using custom filters and
28 * actions.
29 *
30 * @since 1.0.0
31 * @access public
32 * @static
33 */
34 public static function register_actions() {
35 add_action( 'init', [ __CLASS__, 'init' ] );
36
37 self::polylang_compatibility();
38 self::yoast_duplicate_post();
39
40 if ( is_admin() || defined( 'WP_LOAD_IMPORTERS' ) ) {
41 add_filter( 'wp_import_post_meta', [ __CLASS__, 'on_wp_import_post_meta' ] );
42 add_filter( 'wxr_importer.pre_process.post_meta', [ __CLASS__, 'on_wxr_importer_pre_process_post_meta' ] );
43 }
44
45 add_action( 'elementor/maintenance_mode/mode_changed', [ __CLASS__, 'clear_3rd_party_cache' ] );
46 }
47
48 public static function clear_3rd_party_cache() {
49 // W3 Total Cache.
50 if ( function_exists( 'w3tc_flush_all' ) ) {
51 w3tc_flush_all();
52 }
53
54 // WP Fastest Cache.
55 if ( ! empty( $GLOBALS['wp_fastest_cache'] ) && method_exists( $GLOBALS['wp_fastest_cache'], 'deleteCache' ) ) {
56 $GLOBALS['wp_fastest_cache']->deleteCache();
57 }
58
59 // WP Super Cache
60 if ( function_exists( 'wp_cache_clean_cache' ) ) {
61 global $file_prefix;
62 wp_cache_clean_cache( $file_prefix, true );
63 }
64 }
65
66 /**
67 * Add new button to gutenberg.
68 *
69 * Insert new "Elementor" button to the gutenberg editor to create new post
70 * using Elementor page builder.
71 *
72 * @since 1.9.0
73 * @access public
74 * @static
75 */
76 public static function add_new_button_to_gutenberg() {
77 global $typenow;
78 if ( ! User::is_current_user_can_edit_post_type( $typenow ) ) {
79 return;
80 }
81
82 // Introduced in WP 5.0
83 if ( function_exists( 'use_block_editor_for_post' ) && ! use_block_editor_for_post( $typenow ) ) {
84 return;
85 }
86
87 // Deprecated/removed in Gutenberg plugin v5.3.0
88 if ( function_exists( 'gutenberg_can_edit_post_type' ) && ! gutenberg_can_edit_post_type( $typenow ) ) {
89 return;
90 }
91
92 ?>
93 <script type="text/javascript">
94 document.addEventListener( 'DOMContentLoaded', function() {
95 var dropdown = document.querySelector( '#split-page-title-action .dropdown' );
96
97 if ( ! dropdown ) {
98 return;
99 }
100
101 var url = '<?php echo esc_url( Plugin::$instance->documents->get_create_new_post_url( $typenow ) ); ?>';
102
103 dropdown.insertAdjacentHTML( 'afterbegin', '<a href="' + url + '">Elementor</a>' );
104 } );
105 </script>
106 <?php
107 }
108
109 /**
110 * Init.
111 *
112 * Initialize Elementor compatibility with external plugins.
113 *
114 * Fired by `init` action.
115 *
116 * @since 1.0.0
117 * @access public
118 * @static
119 */
120 public static function init() {
121 // Hotfix for NextGEN Gallery plugin.
122 if ( defined( 'NGG_PLUGIN_VERSION' ) ) {
123 add_filter( 'elementor/document/urls/edit', function( $edit_link ) {
124 return add_query_arg( 'display_gallery_iframe', '', $edit_link );
125 } );
126 }
127
128 // Exclude our Library from Yoast SEO plugin.
129 add_filter( 'wpseo_sitemaps_supported_post_types', [ __CLASS__, 'filter_library_post_type' ] );
130 add_filter( 'wpseo_accessible_post_types', [ __CLASS__, 'filter_library_post_type' ] );
131 add_filter( 'wpseo_sitemap_exclude_post_type', function( $retval, $post_type ) {
132 if ( Source_Local::CPT === $post_type ) {
133 $retval = true;
134 }
135
136 return $retval;
137 }, 10, 2 );
138
139 // Disable optimize files in Editor from Autoptimize plugin.
140 add_filter( 'autoptimize_filter_noptimize', function( $retval ) {
141 if ( Plugin::$instance->editor->is_edit_mode() ) {
142 $retval = true;
143 }
144
145 return $retval;
146 } );
147
148 // Add the description (content) tab for a new product, so it can be edited with Elementor.
149 add_filter( 'woocommerce_product_tabs', function( $tabs ) {
150 if ( ! isset( $tabs['description'] ) && Plugin::$instance->preview->is_preview_mode() ) {
151 $post = get_post();
152 if ( empty( $post->post_content ) ) {
153 $tabs['description'] = [
154 'title' => esc_html__( 'Description', 'elementor' ),
155 'priority' => 10,
156 'callback' => 'woocommerce_product_description_tab',
157 ];
158 }
159 }
160
161 return $tabs;
162 } );
163
164 // Fix WC session not defined in editor.
165 if ( class_exists( 'woocommerce' ) ) {
166 add_action( 'elementor/editor/before_enqueue_scripts', function() {
167 remove_action( 'woocommerce_shortcode_before_product_cat_loop', 'wc_print_notices' );
168 remove_action( 'woocommerce_before_shop_loop', 'wc_print_notices' );
169 remove_action( 'woocommerce_before_single_product', 'wc_print_notices' );
170 } );
171
172 add_filter( 'elementor/maintenance_mode/is_login_page', function( $value ) {
173
174 // Support Woocommerce Account Page.
175 if ( is_account_page() && ! is_user_logged_in() ) {
176 $value = true;
177 }
178 return $value;
179 } );
180 }
181
182 // Fix Jetpack Contact Form in Editor Mode.
183 if ( class_exists( 'Grunion_Editor_View' ) ) {
184 add_action( 'elementor/editor/before_enqueue_scripts', function() {
185 remove_action( 'media_buttons', 'grunion_media_button', 999 );
186 remove_action( 'admin_enqueue_scripts', 'grunion_enable_spam_recheck' );
187
188 remove_action( 'admin_notices', [ 'Grunion_Editor_View', 'handle_editor_view_js' ] );
189 remove_action( 'admin_head', [ 'Grunion_Editor_View', 'admin_head' ] );
190 } );
191 }
192
193 // Fix Popup Maker in Editor Mode.
194 if ( class_exists( 'PUM_Admin_Shortcode_UI' ) ) {
195 add_action( 'elementor/editor/before_enqueue_scripts', function() {
196 $pum_admin_instance = \PUM_Admin_Shortcode_UI::instance();
197
198 remove_action( 'print_media_templates', [ $pum_admin_instance, 'print_media_templates' ] );
199 remove_action( 'admin_print_footer_scripts', [ $pum_admin_instance, 'admin_print_footer_scripts' ], 100 );
200 remove_action( 'wp_ajax_pum_do_shortcode', [ $pum_admin_instance, 'wp_ajax_pum_do_shortcode' ] );
201
202 remove_action( 'admin_enqueue_scripts', [ $pum_admin_instance, 'admin_enqueue_scripts' ] );
203
204 remove_filter( 'pum_admin_var', [ $pum_admin_instance, 'pum_admin_var' ] );
205 } );
206 }
207
208 // Fix Preview URL for https://github.com/wpmudev/domain-mapping plugin
209 if ( class_exists( 'domain_map' ) ) {
210 add_filter( 'elementor/document/urls/preview', function( $preview_url ) {
211 if ( wp_parse_url( $preview_url, PHP_URL_HOST ) !== Utils::get_super_global_value( $_SERVER, 'HTTP_HOST' ) ) {
212 $preview_url = \domain_map::utils()->unswap_url( $preview_url );
213 $preview_url = add_query_arg( [
214 'dm' => \Domainmap_Module_Mapping::BYPASS,
215 ], $preview_url );
216 }
217
218 return $preview_url;
219 } );
220 }
221
222 // Gutenberg
223 if ( function_exists( 'gutenberg_init' ) ) {
224 add_action( 'admin_print_scripts-edit.php', [ __CLASS__, 'add_new_button_to_gutenberg' ], 11 );
225 }
226 }
227
228 public static function filter_library_post_type( $post_types ) {
229 unset( $post_types[ Source_Local::CPT ] );
230
231 return $post_types;
232 }
233
234 /**
235 * Polylang compatibility.
236 *
237 * Fix Polylang compatibility with Elementor.
238 *
239 * @since 2.0.0
240 * @access private
241 * @static
242 */
243 private static function polylang_compatibility() {
244 // Copy elementor data while polylang creates a translation copy
245 add_filter( 'pll_copy_post_metas', [ __CLASS__, 'save_polylang_meta' ], 10, 4 );
246 }
247
248 /**
249 * Save polylang meta.
250 *
251 * Copy elementor data while polylang creates a translation copy.
252 *
253 * Fired by `pll_copy_post_metas` filter.
254 *
255 * @since 1.6.0
256 * @access public
257 * @static
258 *
259 * @param array $keys List of custom fields names.
260 * @param bool $sync True if it is synchronization, false if it is a copy.
261 * @param int $from ID of the post from which we copy information.
262 * @param int $to ID of the post to which we paste information.
263 *
264 * @return array List of custom fields names.
265 */
266 public static function save_polylang_meta( $keys, $sync, $from, $to ) {
267 // Copy only for a new post.
268 if ( ! $sync ) {
269 Plugin::$instance->db->copy_elementor_meta( $from, $to );
270 }
271
272 return $keys;
273 }
274
275 private static function yoast_duplicate_post() {
276 add_filter( 'duplicate_post_excludelist_filter', function( $meta_excludelist ) {
277 $exclude_list = [
278 Document::TYPE_META_KEY,
279 '_elementor_page_assets',
280 '_elementor_controls_usage',
281 '_elementor_css',
282 '_elementor_screenshot',
283 ];
284
285 return array_merge( $meta_excludelist, $exclude_list );
286 } );
287
288 add_action( 'duplicate_post_post_copy', function( $new_post_id, $post ) {
289 $original_template_type = get_post_meta( $post->ID, Document::TYPE_META_KEY, true );
290 if ( ! empty( $original_template_type ) ) {
291 update_post_meta( $new_post_id, Document::TYPE_META_KEY, $original_template_type );
292 }
293 }, 10, 2 );
294 }
295
296 /**
297 * Process post meta before WP importer.
298 *
299 * Normalize Elementor post meta on import, We need the `wp_slash` in order
300 * to avoid the unslashing during the `add_post_meta`.
301 *
302 * Fired by `wp_import_post_meta` filter.
303 *
304 * @since 1.0.0
305 * @access public
306 * @static
307 *
308 * @param array $post_meta Post meta.
309 *
310 * @return array Updated post meta.
311 */
312 public static function on_wp_import_post_meta( $post_meta ) {
313 $is_wp_importer_before_0_7 = self::is_wp_importer_before_0_7();
314
315 if ( $is_wp_importer_before_0_7 ) {
316 foreach ( $post_meta as &$meta ) {
317 if ( '_elementor_data' === $meta['key'] ) {
318 $meta['value'] = wp_slash( $meta['value'] );
319 break;
320 }
321 }
322 }
323
324 return $post_meta;
325 }
326
327 /**
328 * Is WP Importer Before 0.7
329 *
330 * Checks if WP Importer is installed, and whether its version is older than 0.7.
331 *
332 * @return bool
333 */
334 public static function is_wp_importer_before_0_7() {
335 $wp_importer = get_plugins( '/wordpress-importer' );
336
337 if ( ! empty( $wp_importer ) ) {
338 $wp_importer_version = $wp_importer['wordpress-importer.php']['Version'];
339
340 if ( version_compare( $wp_importer_version, '0.7', '<' ) ) {
341 return true;
342 }
343 }
344
345 return false;
346 }
347
348 /**
349 * Process post meta before WXR importer.
350 *
351 * Normalize Elementor post meta on import with the new WP_importer, We need
352 * the `wp_slash` in order to avoid the unslashing during the `add_post_meta`.
353 *
354 * Fired by `wxr_importer.pre_process.post_meta` filter.
355 *
356 * @since 1.0.0
357 * @access public
358 * @static
359 *
360 * @param array $post_meta Post meta.
361 *
362 * @return array Updated post meta.
363 */
364 public static function on_wxr_importer_pre_process_post_meta( $post_meta ) {
365 $is_wp_importer_before_0_7 = self::is_wp_importer_before_0_7();
366
367 if ( $is_wp_importer_before_0_7 ) {
368 if ( '_elementor_data' === $post_meta['key'] ) {
369 $post_meta['value'] = wp_slash( $post_meta['value'] );
370 }
371 }
372
373 return $post_meta;
374 }
375 }
376