PATH:
home
/
lab2454c
/
foreclass.com
/
wp-content
/
plugins
/
search-replace-for-elementor
/
inc
/
editor
<?php /** * Elementor search and replace. * * @package ELEMSNR * @copyright Copyright (c) 2023, Developry Ltd. * @license https://www.gnu.org/licenses/gpl-2.0.html GNU Public License * @since 1.0 */ namespace ELEMSNR; ! defined( ABSPATH ) || exit; // Exit if accessed directly. if ( ! class_exists( 'Elementor_Search_Replace' ) ) { class Elementor_Search_Replace { /** * Set a size limit for a single Elementor data page. */ public $data_size_limit; /** * Calculate the runtime for the search and replace script. */ public $runtime; public function __construct() { $this->data_size_limit = 50; } public function init() { add_action( 'wp_loaded', array( $this, 'on_loaded' ) ); } public function on_loaded() { add_action( 'wp_ajax_elemsnr_highlight_search', array( $this, 'elemsnr_highlight_search' ) ); add_action( 'wp_ajax_elemsnr_unhighlight_search', array( $this, 'elemsnr_unhighlight_search' ) ); add_action( 'wp_ajax_elemsnr_replace_search', array( $this, 'elemsnr_replace_search' ) ); add_action( 'wp_ajax_elemsnr_replace_html_regex', array( $this, 'elemsnr_replace_html_regex' ) ); } /** * Highlight all the searched/found terms. */ public function elemsnr_highlight_search() { $current_post_id = sanitize_text_field( $_REQUEST['current_post_id'] ); $search_phrase = trim( sanitize_text_field( $_REQUEST['search_phrase'] ) ); $replace_with_phrase = trim( sanitize_text_field( $_REQUEST['replace_with_phrase'] ) ); $is_highlighted = filter_var( sanitize_text_field( $_REQUEST['is_highlighted'] ), FILTER_VALIDATE_BOOLEAN ); $is_text_only = filter_var( sanitize_text_field( $_REQUEST['is_text_only'] ), FILTER_VALIDATE_BOOLEAN ); $current_post_data = get_post_meta( $current_post_id, '_elementor_data', true ); $elementor_data = json_decode( $current_post_data, true ); $elementor_data_size = round( mb_strlen( $current_post_data, '8bit' ) / 1024, 2 ); $this->is_nonce_token_valid(); $this->is_user_cap(); $this->is_post_id( $current_post_id ); $this->is_elementor_data( $elementor_data ); $this->is_data_size_limit( $elementor_data_size ); if ( strlen( $search_phrase ) < 3 ) { $this->print_output_message( 0, __( 'Minimum 3 characters for your search value.', 'search-replace-for-elementor' ) ); } $settings = array( 'search_phrase' => $search_phrase, 'replace_with_phrase' => $replace_with_phrase, 'highlight' => $is_highlighted, 'is_text_only' => $is_text_only, 'is_case_sensitive' => false, 'is_links' => false, 'is_images' => false, 'count' => false, 'regex' => false, ); // Clean up all the custom tags from _elementor_data. $elementor_data_clean = $this->clean_custom_tags( $elementor_data, $settings ); $this->update_postmeta( $current_post_id, $elementor_data_clean ); // Count search phrase occurrences. $search_occurrences = $this->count_search_occurrences( $elementor_data_clean, $settings ); if ( 0 === $search_occurrences ) { $search_phrase = stripslashes( $search_phrase ); $this->print_output_message( 0, /* translators: %1$s is replaced with search phrase */ __( 'No results found for %1$s!', 'search-replace-for-elementor' ), array( '<strong>' . $search_phrase . '</strong>' ) ); } $elementor_data_highlight = $this->add_custom_tags( $elementor_data_clean, $settings, $is_links, $is_images ); $this->update_postmeta( $current_post_id, $elementor_data_highlight ); $search_phrase = stripslashes( $search_phrase ); $this->print_output_message( 1, /* translators: %1$s is replaced with search occurances */ /* translators: %2$s is replaced with search phrase */ __( '%1$s result(s) found for %2$s!', 'search-replace-for-elementor' ), array( '<strong>' . $search_occurrences . '</strong>', '<strong>' . $search_phrase . '</strong>', ) ); } /** * UnHighlight and clear all the searched/found terms. */ public function elemsnr_unhighlight_search() { $current_post_id = sanitize_text_field( $_REQUEST['current_post_id'] ); $search_phrase = trim( sanitize_text_field( $_REQUEST['search_phrase'] ) ); $replace_with_phrase = trim( sanitize_text_field( $_REQUEST['replace_with_phrase'] ) ); $is_highlighted = filter_var( sanitize_text_field( $_REQUEST['is_highlighted'] ), FILTER_VALIDATE_BOOLEAN ); $is_text_only = filter_var( sanitize_text_field( $_REQUEST['is_text_only'] ), FILTER_VALIDATE_BOOLEAN ); $current_post_data = get_post_meta( $current_post_id, '_elementor_data', true ); $elementor_data = json_decode( $current_post_data, true ); $elementor_data_size = round( mb_strlen( $current_post_data, '8bit' ) / 1024, 2 ); $this->is_nonce_token_valid(); $this->is_user_cap(); $this->is_post_id( $current_post_id ); $this->is_elementor_data( $elementor_data ); $this->is_data_size_limit( $elementor_data_size ); $settings = array( 'search_phrase' => $search_phrase, 'replace_with_phrase' => $replace_with_phrase, 'highlight' => $is_highlighted, 'is_text_only' => $is_text_only, 'is_case_sensitive' => false, 'is_links' => false, 'is_images' => false, 'count' => false, 'regex' => false, ); // Clean up all the custom tags from _elementor_data. $elementor_data_clean = $this->clean_custom_tags( $elementor_data, $settings ); $this->update_postmeta( $current_post_id, $elementor_data_clean ); $this->print_output_message( 1, __( 'All custom tags were removed successfully!', 'search-replace-for-elementor' ) ); } /** * Replace the searched and found terms. */ public function elemsnr_replace_search() { $current_post_id = sanitize_text_field( $_REQUEST['current_post_id'] ); $search_phrase = trim( sanitize_text_field( $_REQUEST['search_phrase'] ) ); $replace_with_phrase = trim( sanitize_text_field( $_REQUEST['replace_with_phrase'] ) ); $is_highlighted = filter_var( sanitize_text_field( $_REQUEST['is_highlighted'] ), FILTER_VALIDATE_BOOLEAN ); $is_text_only = filter_var( sanitize_text_field( $_REQUEST['is_text_only'] ), FILTER_VALIDATE_BOOLEAN ); $current_post_data = get_post_meta( $current_post_id, '_elementor_data', true ); $elementor_data = json_decode( $current_post_data, true ); $elementor_data_size = round( mb_strlen( $current_post_data, '8bit' ) / 1024, 2 ); $this->is_nonce_token_valid(); $this->is_user_cap(); $this->is_post_id( $current_post_id ); $this->is_elementor_data( $elementor_data ); $this->is_data_size_limit( $elementor_data_size ); if ( strlen( $search_phrase ) < 3 ) { $this->print_output_message( 0, __( 'Minimum 3 characters for your search value.', 'search-replace-for-elementor' ) ); } if ( strlen( $replace_with_phrase ) < 3 ) { $this->print_output_message( 0, __( 'Minimum 3 characters for your replace with value.', 'search-replace-for-elementor' ) ); } if ( $is_links && ( ! filter_var( $search_phrase, FILTER_VALIDATE_URL ) || ! filter_var( $replace_with_phrase, FILTER_VALIDATE_URL ) ) ) { $this->print_output_message( 0, __( 'You have entered an invalid URL(s) (e.g. https://example.com/).', 'search-replace-for-elementor' ) ); } $settings = array( 'search_phrase' => $search_phrase, 'replace_with_phrase' => $replace_with_phrase, 'highlight' => $is_highlighted, 'is_text_only' => $is_text_only, 'is_case_sensitive' => false, 'is_links' => false, 'is_images' => false, 'count' => false, 'regex' => false, ); // Count search phrase occurrences. $search_occurrences = $this->count_search_occurrences( $elementor_data, $settings ); $elementor_data_new = $this->do_search_and_replace( $elementor_data, $settings, $is_links, $is_images ); $this->update_postmeta( $current_post_id, $elementor_data_new ); $search_phrase = stripslashes( $search_phrase ); $replace_with_phrase = stripslashes( $replace_with_phrase ); $this->print_output_message( 1, /* translators: %1$s is replaced with search phrase */ /* translators: %2$s is replaced with replace phrase */ /* translators: %3$s is replaced with search occurances */ /* translators: %4$s is replaced with link to undo */ __( '%1$s was replaced with %2$s %3$s time(s). %4$s', 'search-replace-for-elementor' ), array( "<strong id=\"elemsnr-undo-search-phrase\">{$search_phrase}</strong>", "<strong id=\"elemsnr-undo-replace-with-phrase\">{$replace_with_phrase}</strong>", '<strong>' . $search_occurrences . '</strong>', '<a href="#" name="elemsnr-undo-button">Undo</a>', ) ); } /** * Run HTML regular expression search and replace. */ public function elemsnr_replace_html_regex() { $current_post_id = sanitize_text_field( $_REQUEST['current_post_id'] ); $search_phrase = trim( $_REQUEST['search_phrase'] ); // TODO: We don't use sanitize_text_field(); becuase HTML is used in regexp. $replace_with_phrase = trim( $_REQUEST['replace_with_phrase'] ); $current_post_data = get_post_meta( $current_post_id, '_elementor_data', true ); $elementor_data = json_decode( $current_post_data, true ); $elementor_data_size = round( mb_strlen( $current_post_data, '8bit' ) / 1024, 2 ); $this->is_nonce_token_valid(); $this->is_user_cap(); $this->is_post_id( $current_post_id ); $this->is_elementor_data( $elementor_data ); $this->is_data_size_limit( $elementor_data_size ); if ( strlen( $search_phrase ) < 3 || strlen( $replace_with_phrase ) < 3 ) { $this->print_output_message( 0, __( 'Please enter search and replace with field values.', 'search-replace-for-elementor' ) ); } $settings = array( 'search_phrase' => $search_phrase, 'replace_with_phrase' => $replace_with_phrase, 'highlight' => false, 'is_text_only' => false, 'is_case_sensitive' => false, 'is_links' => false, 'is_images' => false, 'count' => false, 'regex' => true, ); $elementor_data_new = $this->search_and_replace( $elementor_data, array_merge( $settings, array( 'search_phrase' => $search_phrase, 'replace_with_phrase' => $replace_with_phrase, ), ) ); $this->update_postmeta( $current_post_id, $elementor_data_new ); $this->update_regex_limit(); $search_phrase = htmlentities( $search_phrase ); $replace_with_phrase = htmlentities( $replace_with_phrase ); $this->print_output_message( 1, /* translators: %1$s is replaced with RegEx/search phrase */ /* translators: %2$s is replaced with HTML/replace phrase */ __( 'Regex %1$s was used and replaced with %2$s.', 'search-replace-for-elementor' ), array( "<strong id=\"elemsnr-undo-search-phrase\">{$search_phrase}</strong>", "<strong id=\"elemsnr-undo-replace-with-phrase\">{$replace_with_phrase}</strong>", ) ); } /** * Update Elementor _elementor_data postmeta. */ public function update_postmeta( $post_id, $elementor_data ) { if ( empty( $elementor_data ) ) { return; } // https://developer.wordpress.org/reference/functions/update_post_meta/#workaround update_metadata( 'post', $post_id, '_elementor_data', wp_slash( json_encode( $elementor_data, JSON_UNESCAPED_UNICODE ) ) ); } /** * Return a response message in JSON format and exit. */ public function print_output_message( $stauts, $error_message, $values_arr = array(), $runtime = '' ) { if ( $this->runtime > 0 ) { $runtime = " (<em>executed in {$this->runtime}sec</em>)"; } echo json_encode( array( array( 'status' => $stauts, 'message' => vsprintf( wp_kses( "{$error_message} {$runtime}", json_decode( ELEMSNR_PLUGIN_ALLOWED_HTML_ARR ) ), $values_arr ), // sprintf( // /* translators: %1$s is replaced with "Search Count" */ // /* translators: %2$s is replaced with "Search Text" */ // wp_kses( __( '%1$s results found for <strong>%2$s</strong>!', 'search-replace-for-elementor' ), json_decode( ELEMSNR_PLUGIN_ALLOWED_HTML_ARR ) ), // $search_text_count, // $search_input_text // ) ), ), ); exit; } /** * Check if multiple array keys exist in an array. */ function array_keys_exist( $array, $keys ) { $check = false; if ( ! is_array( $keys ) ) { $keys = func_get_args(); array_shift( $keys ); } foreach ( $keys as $key ) { if ( isset( $array[$key] ) || array_key_exists( $key, $array ) ) { $check = true; } } return $check; } /** * Iterate the array recursively and update the matched key/value with user input. */ public function search_and_replace( $elementor_data, $settings ) { // Elementor data MUST be an array, not NULL or string. if ( ! is_array( $elementor_data ) ) { return false; } $iterator = new Elementor_Data_Formatter( new \RecursiveArrayIterator( $elementor_data ), $settings ); $start = microtime( true ); $iterator_data_new = array(); $iterator_data_counter = 0; // Get the Elementor iterator all new values in temp array. foreach ( $iterator as $key => $value ) { foreach( $iterator->keys as $id => $keyword ) { if ( $keyword === $key ) { $iterator_data_new[] = $value; } } } // Update the original elementor data with the iterator. foreach ( $iterator as $key => $iterator_data ) { if ( is_array( $iterator_data ) && $this->array_keys_exist( $iterator_data, $iterator->keys ) ) { foreach ( $iterator_data as $keyword => $value ) { if ( in_array( $keyword, $iterator->keys ) ) { $replacement_value = stripslashes( $iterator_data_new[ $iterator_data_counter ] ); $iterator_data[ $keyword ] = $replacement_value; $current_depth = $iterator->getDepth(); // Go back up from current depth to recreate the original array. for ( $sub_depth = $current_depth; $sub_depth >= 0; $sub_depth-- ) { $sub_iterator = $iterator->getSubIterator( $sub_depth ); if ( $sub_depth === $current_depth ) { $sub_iterator->offsetSet( $sub_iterator->key(), $iterator_data ); } else { $sub_iterator->offsetSet( $sub_iterator->key(), $iterator->getSubIterator( $sub_depth + 1 )->getArrayCopy() ); } } $iterator_data_counter++; } } } } // Return number of occurances if we only need the count. if ( true === $settings['count'] && $settings['search_phrase'] ) { return $iterator->count_occurrences; } // This is the original elementor data updated with custom values. $elementor_data = $iterator->getArrayCopy(); $this->runtime = round( microtime( true ) - $start, 2 ); return $elementor_data; } /** * Clean up the custom <elsnr-highlight> tags. */ public function clean_custom_tags( $elementor_data, $settings ) { return $this->search_and_replace( $elementor_data, array_merge( $settings, array( 'search_phrase' => array( '<elsnr-highlight>', '</elsnr-highlight>' ), 'replace_with_phrase' => '', ), ) ); } /** * Add custom tags to highlight search phrases found. */ public function add_custom_tags( $elementor_data, $settings, $is_links, $is_images ) { if ( $is_links || $is_images ) { } else { $replace_with_phrase = "<elsnr-highlight>{$settings['search_phrase']}</elsnr-highlight>"; } return $this->search_and_replace( $elementor_data, array_merge( $settings, array( 'replace_with_phrase' => $replace_with_phrase ), ) ); } /** * Count all occurrences for the search phrase. */ public function count_search_occurrences( $elementor_data, $settings ) { return $this->search_and_replace( $elementor_data, array_merge( $settings, array( 'count' => true ), ) ); } /** * Do the actual search and replace with highlighted custom tags. */ public function do_search_and_replace( $elementor_data, $settings, $is_links, $is_images ) { if ( $is_links || $is_images ) { } else { // Need to work with I'm, you're, "Quote" etc. use stripslashes(). $search_phrase = stripslashes( $settings['search_phrase'] ); $replace_with_phrase = stripslashes( $settings['replace_with_phrase'] ); $search_phrase = "<elsnr-highlight>{$search_phrase}</elsnr-highlight>"; } return $this->search_and_replace( $elementor_data, array_merge( $settings, array( 'search_phrase' => $search_phrase, 'replace_with_phrase' => $replace_with_phrase, ), ) ); } /** * Display error if user access is not sufficient. */ public function is_user_cap() { if ( ! current_user_can( 'administrator' ) ) { $this->print_output_message( 0, __( 'Access denied! Current user does not have the capabilities to access this function.', 'search-replace-for-elementor' ) ); } } /** * Display error if post id is empty. */ public function is_post_id( $current_post_id ) { if ( ! $current_post_id ) { $this->print_output_message( 0, /* translators: %1$s is replaced with link to support email */ __( 'Post ID not found! Contact the plugin author @ %1$s.', 'search-replace-for-elementor' ), array( '<a href="mailto:support@' . ELEMSNR_PLUGIN_DOMAIN . '">support@' . ELEMSNR_PLUGIN_DOMAIN . '</a>' ) ); } } /** * Display error if data size limit is exceeded. */ public function is_data_size_limit( $elementor_data_size ) { if ( $elementor_data_size > $this->data_size_limit ) { $this->print_output_message( 0, /* translators: %1$s is replaced with data limit */ /* translators: %2$s is replaced with link to options page */ __( 'Elementor page/post data exceeds the set limit of %1$skb! Update data limit on the %2$s page to increase the set limit.', 'search-replace-for-elementor' ), array( '<em>' . $this->data_size_limit . '</em>', '<a href="' . esc_url( admin_url( 'admin.php?page=' . ELEMSNR_OPTIONS_PAGE ) ) . '">' . __( 'Options', 'search-replace-for-elementor' ) . '</a>', ) ); } } /** * Display error if elementor data is empty. */ public function is_elementor_data( $elementor_data ) { if ( empty( $elementor_data ) ) { $this->print_output_message( 0, /* translators: %1$s is replaced with link to support email */ __( 'Elementor data is empty! Add some content to this page or contact us @ %1$s.', 'search-replace-for-elementor' ), array( '<a href="mailto:support@' . ELEMSNR_PLUGIN_DOMAIN . '">support@' . ELEMSNR_PLUGIN_DOMAIN . '</a>' ) ); } } /** * Display error if ajax nonce token is invalid. */ public function is_nonce_token_valid() { if ( ! check_ajax_referer( 'elemsnr-ajax-nonce', 'security', false ) ) { $this->print_output_message( 0, /* translators: %1$s is replaced with link to support email */ __( 'Invalid security token sent! Contact us @ %1$s.', 'search-replace-for-elementor' ), array( '<a href="mailto:support@' . ELEMSNR_PLUGIN_DOMAIN . '">support@' . ELEMSNR_PLUGIN_DOMAIN . '</a>' ) ); } } /** * Use transients to manage number of HTML Regexp request per hour. */ public function update_regex_limit() { if ( false === get_option( 'elemsnr_replace_html_regex' ) || false === get_transient( 'elemsnr_replace_html_regex' ) ) { set_transient( 'elemsnr_replace_html_regex', 10, 12 * HOUR_IN_SECONDS ); update_option( 'elemsnr_replace_html_regex', get_transient( 'elemsnr_replace_html_regex' ) ); } else { update_option( 'elemsnr_replace_html_regex', get_option( 'elemsnr_replace_html_regex' ) - 1 ); } } } $elemsnr = new Elementor_Search_Replace(); $elemsnr->init(); }
[+]
..
[-] class-elementor-data-formatter.php
[edit]
[-] class-elementor-search-replace.php
[edit]