balmet.com

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

compatibility.php (11929B)


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