as3cf->filter_local->filter_post( json_encode( $config['initial_document']['elements'], JSON_UNESCAPED_SLASHES ) ), true ); // Avoid replacing content if the filtering failed if ( false !== $filtered ) { $config['initial_document']['elements'] = $filtered; } return $config; } /** * Replace local URLs in settings that Elementor renders in HTML for some attributes, i.e json structs for * the section background slideshow * * @param Element_Base $element * * @handles elementor/frontend/before_render */ public function frontend_before_render( $element ) { $element->set_settings( json_decode( $this->as3cf->filter_local->filter_post( json_encode( $element->get_settings(), JSON_UNESCAPED_SLASHES ) ), true ) ); } /** * Handle Elementor's call to update_metadata() for _elementor_data when saving * a post or page. Rewrites remote URLs to local. * * @param bool $check * @param int $object_id * @param string $meta_key * @param mixed $meta_value * @param mixed $prev_value * * @handles update_post_metadata * * @return bool */ public function update_post_metadata( $check, $object_id, $meta_key, $meta_value, $prev_value ) { if ( '_elementor_css' === $meta_key ) { $this->rewrite_css( $object_id, $meta_value ); return $check; } if ( '_elementor_data' !== $meta_key ) { return $check; } // We expect the meta value to be a JSON formatted string from Elementor. Exit early if it's not. if ( ! is_string( $meta_value ) || ! AS3CF_Utils::is_json( $meta_value ) ) { return $check; } // We're calling update_metadata recursively and need to make sure // we never nest deeper than one level. if ( 0 === $this->recursion_level ) { $this->recursion_level++; // We get here from an update_metadata() call that has already done some string sanitizing // including wp_unslash(), but the original json from Elementor still needs slashes // removed for our filters to work. // Note: wp_unslash can't be used because it also unescapes any embedded HTML. $json = str_replace( '\/', '/', $meta_value ); $json = $this->as3cf->filter_provider->filter_post( $json ); $meta_value = wp_slash( str_replace( '/', '\/', $json ) ); update_metadata( 'post', $object_id, '_elementor_data', $meta_value, $prev_value ); // Reset recursion level and let update_metadata we already handled saving the meta $this->recursion_level = 0; return true; } return $check; } /** * Rewrites local URLs in generated CSS files * * @param int $object_id * @param array $meta_value */ private function rewrite_css( $object_id, $meta_value ) { if ( 'file' === $meta_value['status'] ) { $elementor_css = new Post( $object_id ); $file = Post::get_base_uploads_dir() . Post::DEFAULT_FILES_DIR . $elementor_css->get_file_name(); if ( file_exists( $file ) ) { $old_content = file_get_contents( $file ); if ( ! empty( $old_content ) ) { file_put_contents( $file, $this->as3cf->filter_local->filter_post( $old_content ) ); } } } } /** * Some widgets, specifically any standard WordPress widgets, make ajax requests back to the server * before the edited section gets rendered in the Elementor editor. When they do, Elementor picks up * properties directly from the saved post meta. * * @param array $instance * @param array $new_instance * * @handles widget_update_callback * * @return mixed */ public function widget_update_callback( $instance, $new_instance ) { return json_decode( $this->as3cf->filter_local->filter_post( json_encode( $instance, JSON_UNESCAPED_SLASHES ) ), true ); } /** * Clears the Elementor cache * * @handles Multiple as3cf_*_completed and as3cf_*_cancelled actions */ public function clear_elementor_css_cache() { if ( class_exists( '\Elementor\Plugin' ) ) { Plugin::instance()->files_manager->clear_cache(); } } /** * Rewrite URLs in Elementor frontend inline CSS before it's rendered/printed by WordPress * * @implements wp_print_styles */ public function wp_print_styles() { $wp_styles = wp_styles(); if ( empty( $wp_styles->registered['elementor-frontend']->extra['after'] ) ) { return; } foreach ( $wp_styles->registered['elementor-frontend']->extra['after'] as &$extra_css ) { $filtered_css = $this->as3cf->filter_local->filter_post( $extra_css ); if ( ! empty( $filtered_css ) ) { $extra_css = $filtered_css; } } } }