Uname: Linux premium264.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
Software: LiteSpeed
PHP version: 8.3.22 [ PHP INFO ] PHP os: Linux
Server Ip: 69.57.162.13
Your Ip: 216.73.216.219
User: workvvfb (1129) | Group: workvvfb (1084)
Safe Mode: OFF
Disable Function:
NONE

name : index.php
<?php

namespace GT3\ThemesCore;

use GT3\ThemesCore\Customizer;
use GT3\ThemesCore\DashBoard;
use GT3\ThemesCore\Registration;
use RevSlider;
use RevSliderSliderImport;
use WP_Error;
use Elementor\Plugin as Elementor_plugin;
use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;

use GT3\ThemesCore\Import\Actions_Trait;
use GT3\ThemesCore\Import\Work_Trait;
use GT3\ThemesCore\Import\Plugins_Trait;
use GT3\ThemesCore\Import\Disable_Trait;
use GT3\ThemesCore\Import\Server_Side_Events_Trait;
use GT3\ThemesCore\Import\Process_Status_Trait;
use GT3\ThemesCore\Import\Reset_Trait;
use GT3\ThemesCore\Import\Rest_Actions_Trait;

final class Import extends \WP_Importer {
	use Actions_Trait;
	use Work_Trait;
	use Plugins_Trait;
	use Disable_Trait;
	use Server_Side_Events_Trait;
	use Process_Status_Trait;
	use Reset_Trait;
	use Rest_Actions_Trait;
	
	protected static $demo_url = 'https://gt3accounts.com/update/tgm.php';
	
	// information to import from JSON file
	protected $version;
	protected $authors     = array();
	protected $posts       = array();
	protected $terms       = array();
	protected $categories  = array();
	protected $tags        = array();
	protected $menu_items  = array();
	protected $attachments = array();
	public    $rev_sliders = array();
	protected $base_url    = '';
	
	// mappings from old information to new
	protected $processed_authors     = array();
	protected $author_mapping        = array();
	protected $processed_terms       = array();
	protected $processed_posts       = array();
	protected $post_orphans          = array();
	protected $processed_menu_items  = array();
	protected $menu_item_orphans     = array();
	protected $missing_menu_items    = array();
	protected $url_remap             = array();
	protected $featured_images       = array();
	protected $processed_attachments = array();
	protected $fetch_attachments     = true;
	protected $log                   = array();
	
	public $import_data = array();
	public $scheduled   = array();
	
	const STEP_IDLE            = -1;
	const STEP_INSTALL_PLUGINS = 2;
	const STEP_TERMS           = 3;
	const STEP_ATTACHMENTS     = 4;
	const STEP_POSTS           = 5;
	const STEP_MENUS           = 6;
	const STEP_FINISH          = 7;
	
	private $active        = false;
	private $current_step  = self::STEP_IDLE;
	private $current_index = 0;
	private $max_items     = array( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 );
	
	private $save_log          = false;
	private $save_log_external = true;
	
	const LIMIT_POSTS       = 10;
	const LIMIT_ATTACHMENTS = 5;
	
	private $cache_status = null;
	
	/** ----------------------------------------------------- */
	protected $elementor_active         = false;
	protected $elementor_media_controls = array();
	protected $theme                    = null;
	
	protected $path = '';
	protected $url  = '';
	
	protected $upload_dir = '';
	
	private static $nonce_key         = '_gt3_core_import_nonce';
	private        $_cache_option_key = '_gt3_core_import';
	
	private static $instance = null;
	/** ----------------------------------------------------- */
	
	/**
	 * New Import
	 */
	protected string $folder = '';
	/**  */
	
	/** @return self */
	public static function instance(){
		if(is_null(self::$instance)) {
			self::$instance = new self();
		}
		
		return self::$instance;
	}
	
	public function __construct(){
		$upload_dir              = wp_upload_dir();
		$this->folder            = trailingslashit($upload_dir['basedir']).'gt3/imports/';
		$this->path              = $this->folder;
		$this->theme_import_url  = get_template_directory_uri().'/core/demo-data/import/';
		$this->theme_import_path = get_template_directory().'/core/demo-data/import/';
		
		if (defined('DOING_AJAX') && DOING_AJAX) {
			ob_start();
		}
		
		$theme    = wp_get_theme();
		$is_child = $theme->get('Template');
		if(!empty($is_child)) {
			$theme = wp_get_theme($is_child);
		}
		$this->theme = $theme->get_stylesheet();
		
		if(!wp_mkdir_p($this->folder)) {
			return;
		}
		
		$this->folder = trailingslashit($this->folder.$this->theme);
		
		if(defined('DOING_AJAX')) {
			add_filter('wp_redirect', '__return_null');
		}
		$this->ajax_init();
		add_action('rest_api_init', array( $this, 'rest_init' ));
		
	}
	
	protected function remove_import_folder(){
		require_once ABSPATH.'wp-admin/includes/file.php';
		
		WP_Filesystem();
		$fs = new \WP_Filesystem_Direct(false);
		$fs->rmdir($this->folder, true);
	}
	
	protected function download_import(){
		require_once ABSPATH.'wp-admin/includes/file.php';
		
		$this->remove_import_folder();
		
		sleep(1);
		
		$url = self::$demo_url.'?'.base64_encode(json_encode(array(
				'a' => 'download_import',
				's' => $this->theme
			)));
		
		$file = $this->fetch_file($url);
		
		if(is_wp_error($file)) {
			//			$this->stop_streaming(array(
			//				"error"   => $file,
			//				'message' => __('Error downloading file.')
			//			));
		}
		
		try {
			$this->path   = stream_resolve_include_path($this->path);
			$unzip_status = unzip_file($file, $this->path);
			if(is_wp_error($unzip_status)) {
				//				$this->stop_streaming(array(
				//					"error"   => $unzip_status,
				//					'message' => __('Unzip error.'),
				//					'path'    => $this->path,
				//					'file'    => $file
				//				));
			}
			
			sleep(1);
		} finally {
			@unlink($file);
		}
		
	}
	
	public function ajax_handler(){
		$this->start_streaming();
		ob_start();
		$command = $this->get_param('command');
		//		$t = wp_create_nonce(self::$nonce_key);
		//		var_dump($t,wp_verify_nonce($t, self::$nonce_key));
		//
		//		die;
		if($command !== 'start_import') {
			check_ajax_referer(self::$nonce_key);
		}
		
		if(!current_user_can('administrator')) {
			die(0);
		}
		
		if($command && method_exists($this, sprintf('action_%s', $command))) {
			$this->get_elementor_media_controls_names();
			$this->disable_cache();
			call_user_func(array( $this, sprintf('action_%s', $command) ));
		} else {
			$this->stop_streaming(array(
				'error'     => true,
				'next_step' => false
			));
			die;
		}
		
		while(ob_get_level()) {
			ob_end_clean();
		}
		$this->stop_streaming(array(
			'error'     => false,
			'next_step' => true
		));
	}
	
	protected function get_param($name){
		return key_exists($name, $_REQUEST) ? $_REQUEST[$name] : null;
	}
	
	public function ajax_init(){
		add_action(sprintf('wp_ajax_%s', 'gt3_demo_action'), array( $this, 'ajax_handler' ));
	}
	
	
	public function rest_get_settings(){
		
		return rest_ensure_response(
			array_merge(
				array(
					'importLogo'  => get_template_directory_uri().'/core/demo-data/import/preview-import.jpg',
					'_ajax_nonce' => wp_create_nonce(self::$nonce_key),
					'plugins'     => apply_filters('gt3/tgmpa_plugins', []),
				)
			)
		);
	}
	
	
	protected function disable_cache(){
		$this->cache_status = wp_suspend_cache_addition();
		wp_suspend_cache_addition(true);
	}
	
	protected function get_meta_key($key, $post){
		$meta = array();
		if(is_array($post)) {
			$meta = key_exists('postmeta', $post) ? $post['postmeta'] : $post;
		}
		if(is_array($meta)) {
			foreach($meta as $_meta) {
				$_meta = array_merge(
					array(
						'meta_key'   => null,
						'meta_value' => null
					), is_array($_meta) ? $_meta : array()
				);
				
				if($_meta['meta_key'] === $key) {
					return $_meta['meta_value'];
				}
			}
		}
		
		return null;
	}
	
	
	public function process_rev_sliders(){
		if(class_exists('RevSlider')) {
			require_once RS_PLUGIN_PATH.'/admin/includes/template.class.php';
			require_once RS_PLUGIN_PATH.'/includes/cssparser.class.php';
			require_once RS_PLUGIN_PATH.'/admin/includes/plugin-update.class.php';
			require_once RS_PLUGIN_PATH.'/admin/includes/import.class.php';
			
			foreach($this->rev_sliders as $slug => $url) {
				$path = $this->fetch_file($url);
				
				if(is_wp_error($path)) {
					continue;
				}
				
				try {
					$i = new RevSliderSliderImport();
					$i->import_slider(true, $path);
				} finally {
					@unlink($path);
				}
			}
		}
	}
	
	public function allow_zip($t){
		if(!array_key_exists('zip', $t)) {
			$t['zip'] = 'application/zip';
		}
		
		return $t;
	}
	
	protected function fetch_file($url){
		$file_name = basename($url);
		add_filter('http_request_host_is_external', '__return_true');
		add_filter('upload_mimes', array( $this, 'allow_zip' ));
		return  download_url($url);
		
		// get placeholder file in the upload dir with a unique, sanitized filename
		$upload = wp_upload_bits($file_name, 0, '');
		
		// fetch the remote url and write it to the placeholder file
		$remote_response = wp_safe_remote_get(
			$url, array(
				'timeout'  => 300,
				'stream'   => true,
				'filename' => $upload['file'],
			)
		);
		remove_filter('upload_mimes', array( $this, 'allow_zip' ));
		
		$headers = wp_remote_retrieve_headers($remote_response);
		
		// request failed
		if(!$headers) {
			@unlink($upload['file']);
			
			return new WP_Error('import_file_error', __('Remote server did not respond', 'wordpress-importer'));
		}
		
		$remote_response_code = wp_remote_retrieve_response_code($remote_response);
		
		// make sure the fetch was successful
		if($remote_response_code != '200') {
			@unlink($upload['file']);
			
			return new WP_Error('import_file_error', sprintf(__('Remote server returned error response %1$d %2$s', 'wordpress-importer'), esc_html($remote_response_code), get_status_header_desc($remote_response_code)));
		}
		
		return $upload['file'];
	}
	
	protected function get_elementor_media_controls_names(){
		$this->elementor_active = class_exists('Elementor\Plugin');
		
		if(!$this->elementor_active) {
			return;
		}
		
		$this->elementor_media_controls = array_unique(
			apply_filters(
				'gt3/export/elementor/media_controls',
				array(
					\Elementor\Controls_Manager::MEDIA,
					\Elementor\Controls_Manager::GALLERY,
				)
			)
		);
	}
	
	/**
	 * Create new terms based on import information
	 *
	 * Doesn't create a term its slug already exists
	 */
	function process_terms(){
		$this->terms = apply_filters('wp_import_terms', $this->terms);
		
		if(empty($this->terms)) {
			return;
		}
		
		foreach($this->terms as $term) {
			
			if(!is_array($term)) {
				$term = array();
			}
			
			$term = array_merge(
				array(
					'id'   => 0,
					'type' => 'error',
				), $term
			);
			
			$this->process_term($term);
			
			$this->current_index++;
			$this->save_states();
			
		}
	}
	
	public function process_term($term){
		$term_id   = $term['id'];
		$term_slug = $term['type'];
		
		$term = $this->load_file('taxonomy', $term_id);
		if(is_wp_error($term)) {
			$this->log($term_id);
			$this->log($term->get_error_message());
			
			return;
		}
		
		// if the term already exists in the correct taxonomy leave it alone
		$term_id = term_exists($term['term_slug'], $term['term_taxonomy']);
		if($term_id) {
			if(is_array($term_id)) {
				$term_id = $term_id['term_id'];
			}
			if(isset($term['term_id'])) {
				$this->processed_terms[intval($term['term_id'])] = (int) $term_id;
			}
			
			return;
		}
		
		if(empty($term['term_parent'])) {
			$parent = 0;
		} else {
			$parent = term_exists($term['term_parent'], $term['term_taxonomy']);
			if(is_array($parent)) {
				$parent = $parent['term_id'];
			}
		}
		$term        = wp_slash($term);
		$description = isset($term['term_description']) ? $term['term_description'] : '';
		$termarr     = array( 'slug' => $term['term_slug'], 'description' => $description, 'parent' => intval($parent) );
		
		$id = wp_insert_term($term['term_name'], $term['term_taxonomy'], $termarr);
		if(!is_wp_error($id)) {
			if(isset($term['term_id'])) {
				$this->processed_terms[intval($term['term_id'])] = $id['term_id'];
			}
		} else {
			$this->log($term_id);
			$this->log(sprintf(__('Failed to import %s %s', 'wordpress-importer'), esc_html($term['term_taxonomy']), esc_html($term['term_name'])).' '.$id->get_error_message());
			
			return;
		}
		
		$this->process_termmeta($term, $id['term_id']);
	}
	
	/**
	 * Add metadata to imported term.
	 *
	 * @param array $term    Term data from WXR import.
	 * @param int   $term_id ID of the newly created term.
	 *
	 * @since 0.6.2
	 *
	 */
	protected function process_termmeta($term, $term_id){
		if(!isset($term['term_meta'])) {
			$term['term_meta'] = array();
		}
		
		/**
		 * Filters the metadata attached to an imported term.
		 *
		 * @param array $termmeta Array of term meta.
		 * @param int   $term_id  ID of the newly created term.
		 * @param array $term     Term data from the WXR import.
		 *
		 * @since 0.6.2
		 *
		 */
		$term['term_meta'] = apply_filters('wp_import_term_meta', $term['term_meta'], $term_id, $term);
		
		if(empty($term['term_meta'])) {
			return;
		}
		
		foreach($term['term_meta'] as $meta) {
			/**
			 * Filters the meta key for an imported piece of term meta.
			 *
			 * @param string $meta_key Meta key.
			 * @param int    $term_id  ID of the newly created term.
			 * @param array  $term     Term data from the WXR import.
			 *
			 * @since 0.6.2
			 *
			 */
			$key = apply_filters('import_term_meta_key', $meta['meta_key'], $term_id, $term);
			if(!$key) {
				continue;
			}
			
			// Export gets meta straight from the DB so could have a serialized string
			$value = maybe_unserialize($meta['meta_value']);
			
			//add_term_meta( $term_id, $key, $value );
			add_term_meta($term_id, wp_slash($key), $value);
			
			/**
			 * Fires after term meta is imported.
			 *
			 * @param int    $term_id ID of the newly created term.
			 * @param string $key     Meta key.
			 * @param mixed  $value   Meta value.
			 *
			 * @since 0.6.2
			 *
			 */
			do_action('import_term_meta', $term_id, $key, $value);
		}
	}
	
	function process_post($post){
		$post = apply_filters('wp_import_post_data_raw', $post);
		
		if(!post_type_exists($post['post_type'])) {
			$this->log(
				sprintf(
					__('Failed to import &#8220;%s&#8221;: Invalid post type %s', 'wordpress-importer'),
					esc_html($post['post_title']), esc_html($post['post_type'])
				)
			);
			$this->log($post);
			do_action('wp_import_post_exists', $post);
			
			return __LINE__;
		}
		
		if(isset($this->processed_posts[$post['post_id']]) && !empty($post['post_id'])) {
			return __LINE__;
		}
		
		if($post['status'] == 'auto-draft') {
			return __LINE__;
		}
		
		if('nav_menu_item' == $post['post_type']) {
			$this->process_menu_item($post);
			
			return __LINE__;
		}
		
		$empty_title = null;
		if(empty($post['post_title'])) {
			$empty_title        = $post['post_title'];
			$post['post_title'] = 'attachment-'.$post['post_id'];
		}
		
		$post_type_object = get_post_type_object($post['post_type']);
		
		$post_exists = post_exists($post['post_title'], '', $post['post_date']);
		
		/**
		 * Filter ID of the existing post corresponding to post currently importing.
		 *
		 * Return 0 to force the post to be imported. Filter the ID to be something else
		 * to override which existing post is mapped to the imported post.
		 *
		 * @param int   $post_exists Post ID, or 0 if post did not exist.
		 * @param array $post        The post array to be inserted.
		 *
		 * @see   post_exists()
		 * @since 0.6.2
		 *
		 */
		$post_exists = apply_filters('wp_import_existing_post', $post_exists, $post);
		
		if($post_exists && get_post_type($post_exists) == $post['post_type']) {
			$this->log(sprintf(__('%s &#8220;%s&#8221; already exists.', 'wordpress-importer'), $post_type_object->labels->singular_name, esc_html($post['post_title'])));
			$comment_post_ID                                 = $post_id = $post_exists;
			$this->processed_posts[intval($post['post_id'])] = intval($post_exists);
		} else {
			$post_parent = (int) $post['post_parent'];
			if($post_parent) {
				// if we already know the parent, map it to the new local ID
				if(isset($this->processed_posts[$post_parent])) {
					$post_parent = $this->processed_posts[$post_parent];
					// otherwise record the parent for later
				} else {
					$this->post_orphans[intval($post['post_id'])] = $post_parent;
					$post_parent                                  = 0;
				}
			}
			
			// map the post author
			$author = sanitize_user($post['post_author'], true);
			if(isset($this->author_mapping[$author])) {
				$author = $this->author_mapping[$author];
			} else {
				$author = (int) get_current_user_id();
			}
			
			$postdata = array(
				'import_id'      => $post['post_id'],
				'post_author'    => $author,
				'post_date'      => $post['post_date'],
				'post_date_gmt'  => $post['post_date_gmt'],
				'post_content'   => $this->fix_url($post['post_content']),
				'post_excerpt'   => $this->fix_url($post['post_excerpt']),
				'post_title'     => $post['post_title'],
				'post_status'    => $post['status'],
				'post_name'      => $post['post_name'],
				'comment_status' => $post['comment_status'],
				'ping_status'    => $post['ping_status'],
				'guid'           => $post['guid'],
				'post_parent'    => $post_parent,
				'menu_order'     => $post['menu_order'],
				'post_type'      => $post['post_type'],
				'post_password'  => $post['post_password']
			);
			
			$original_post_ID = $post['post_id'];
			$postdata         = apply_filters('wp_import_post_data_processed', $postdata, $post);
			
			$postdata = wp_slash($postdata);
			
			if('attachment' == $postdata['post_type']) {
				$remote_url = !empty($post['attachment_url']) ? $post['attachment_url'] : $post['guid'];
				
				// try to use _wp_attached file for upload folder placement to ensure the same location as the export site
				// e.g. location is 2003/05/image.jpg but the attachment post_date is 2010/09, see media_handle_upload()
				$postdata['upload_date'] = $post['post_date'];
				if(isset($post['postmeta'])) {
					foreach($post['postmeta'] as $meta) {
						if($meta['meta_key'] == '_wp_attached_file') {
							if(preg_match('%^[0-9]{4}/[0-9]{2}%', $meta['meta_value'], $matches)) {
								$postdata['upload_date'] = $matches[0];
							}
							break;
						}
					}
				}
				
				$comment_post_ID = $post_id = $this->process_attachment($postdata, $remote_url);
				
				$this->save_attachment_id($post_id, $postdata);
			} else {
				$comment_post_ID = $post_id = wp_insert_post($postdata, true);
				do_action('wp_import_insert_post', $post_id, $original_post_ID, $postdata, $post);
				$post = $this->fix_import_post($post, $postdata);
			}
			
			if(is_wp_error($post_id)) {
				$this->log(
					sprintf(
						__('Failed to import %s &#8220;%s&#8221; %s', 'wordpress-importer'),
						$post_type_object->labels->singular_name, esc_html($post['post_title']), __LINE__
					).' '.$post_id->get_error_message()
				);
				
				return __LINE__;
			}
			
			if($post['is_sticky'] == 1) {
				stick_post($post_id);
			}
		}
		
		// map pre-import ID to local ID
		$this->processed_posts[intval($post['post_id'])] = (int) $post_id;
		
		if(!is_null($empty_title)) {
			wp_update_post(
				array(
					'ID'         => $post_id,
					'post_title' => $empty_title,
				)
			);
		}
		
		if(!isset($post['terms'])) {
			$post['terms'] = array();
		}
		
		$post['terms'] = apply_filters('wp_import_post_terms', $post['terms'], $post_id, $post);
		
		// add categories, tags and other terms
		if(!empty($post['terms'])) {
			$terms_to_set = array();
			foreach($post['terms'] as $term) {
				if(!is_array($term)) {
					$term = $this->load_file('taxonomy', $term);
				}
				// back compat with WXR 1.0 map 'tag' to 'post_tag'
				$taxonomy    = $term['term_taxonomy'];
				$term_exists = term_exists($term['term_slug'], $taxonomy);
				$term_id     = is_array($term_exists) ? $term_exists['term_id'] : $term_exists;
				if(!$term_id) {
					$t = wp_insert_term($term['term_name'], $taxonomy, array( 'slug' => $term['term_slug'] ));
					if(!is_wp_error($t)) {
						$term_id = $t['term_id'];
						do_action('wp_import_insert_term', $t, $term, $post_id, $post);
					} else {
						$this->log(sprintf(__('Failed to import %s %s', 'wordpress-importer'), esc_html($taxonomy), esc_html($term['term_name'])).' '.$t->get_error_message());
						
						do_action('wp_import_insert_term_failed', $t, $term, $post_id, $post);
						continue;
					}
				}
				$terms_to_set[$taxonomy][] = intval($term_id);
			}
			
			foreach($terms_to_set as $tax => $ids) {
				$tt_ids = wp_set_post_terms($post_id, $ids, $tax);
				do_action('wp_import_set_post_terms', $tt_ids, $ids, $tax, $post_id, $post);
			}
			unset($post['terms'], $terms_to_set);
		}
		
		if(!isset($post['comments'])) {
			$post['comments'] = array();
		}
		
		$post['comments'] = apply_filters('wp_import_post_comments', $post['comments'], $post_id, $post);
		
		// add/update comments
		if(!empty($post['comments'])) {
			$num_comments      = 0;
			$inserted_comments = array();
			foreach($post['comments'] as $comment) {
				$comment_id                                       = $comment['comment_id'];
				$newcomments[$comment_id]['comment_post_ID']      = $comment_post_ID;
				$newcomments[$comment_id]['comment_author']       = $comment['comment_author'];
				$newcomments[$comment_id]['comment_author_email'] = $comment['comment_author_email'];
				$newcomments[$comment_id]['comment_author_IP']    = $comment['comment_author_IP'];
				$newcomments[$comment_id]['comment_author_url']   = $comment['comment_author_url'];
				$newcomments[$comment_id]['comment_date']         = $comment['comment_date'];
				$newcomments[$comment_id]['comment_date_gmt']     = $comment['comment_date_gmt'];
				$newcomments[$comment_id]['comment_content']      = $comment['comment_content'];
				$newcomments[$comment_id]['comment_approved']     = $comment['comment_approved'];
				$newcomments[$comment_id]['comment_type']         = $comment['comment_type'];
				$newcomments[$comment_id]['comment_parent']       = $comment['comment_parent'];
				$newcomments[$comment_id]['commentmeta']          = isset($comment['commentmeta']) ? $comment['commentmeta'] : array();
				if(isset($this->processed_authors[$comment['comment_user_id']])) {
					$newcomments[$comment_id]['user_id'] = $this->processed_authors[$comment['comment_user_id']];
				}
			}
			ksort($newcomments);
			
			foreach($newcomments as $key => $comment) {
				// if this is a new post we can skip the comment_exists() check
				if(!$post_exists || !comment_exists($comment['comment_author'], $comment['comment_date'])) {
					if(isset($inserted_comments[$comment['comment_parent']])) {
						$comment['comment_parent'] = $inserted_comments[$comment['comment_parent']];
					}
					$comment                 = wp_slash($comment);
					$comment                 = wp_filter_comment($comment);
					$inserted_comments[$key] = wp_insert_comment($comment);
					do_action('wp_import_insert_comment', $inserted_comments[$key], $comment, $comment_post_ID, $post);
					
					foreach($comment['commentmeta'] as $meta) {
						$value = maybe_unserialize($meta['meta_value']);
						//add_comment_meta( $inserted_comments[$key], $meta['key'], $value );
						add_comment_meta($inserted_comments[$key], wp_slash($meta['meta_key']), wp_slash($value));
					}
					
					$num_comments++;
				}
			}
			unset($newcomments, $inserted_comments, $post['comments']);
		}
		
		if(!isset($post['postmeta'])) {
			$post['postmeta'] = array();
		}
		
		$post['postmeta'] = apply_filters('wp_import_post_meta', $post['postmeta'], $post_id, $post);
		
		// add/update post meta
		if(!empty($post['postmeta'])) {
			foreach($post['postmeta'] as $meta) {
				if($meta['meta_key'] === '_elementor_css') {
					continue;
				}
				$key   = apply_filters('import_post_meta_key', $meta['meta_key'], $post_id, $post);
				$value = false;
				
				if('_edit_last' == $key) {
					if(isset($this->processed_authors[intval($meta['meta_value'])])) {
						$value = $this->processed_authors[intval($meta['meta_value'])];
					} else {
						$key = false;
					}
				}
				
				if($key) {
					// export gets meta straight from the DB so could have a serialized string
					if(!$value) {
						$value = maybe_unserialize($meta['meta_value']);
					}
					
					//add_post_meta( $post_id, $key, $value );
					$value = $this->fix_url($value);
					update_post_meta($post_id, wp_slash($key), wp_slash($value));
					do_action('import_post_meta', $post_id, $key, $value);
					
					// if the post has a featured image, take note of this in case of remap
					if('_thumbnail_id' == $key) {
						$this->featured_images[$post_id] = (int) $value;
					}
				}
			}
		}
		
		return true;
	}
	
	function _replace_url($data){
		$home     = get_home_url();
		$base_url = $this->import_data['base_url'];
		
		$uploads         = wp_upload_dir();
		$upload_url      = $this->import_data['upload_url'];
		$home_upload_url = $uploads['baseurl'];
		
		$data = str_replace($this->_slash($upload_url, 4), $this->_slash($home_upload_url, 4), $data);
		$data = str_replace($this->_slash($upload_url, 3), $this->_slash($home_upload_url, 3), $data);
		$data = str_replace($this->_slash($upload_url, 2), $this->_slash($home_upload_url, 2), $data);
		$data = str_replace($this->_slash($upload_url, 1), $this->_slash($home_upload_url, 1), $data);
		$data = str_replace($upload_url, $home_upload_url, $data);
		
		$data = str_replace($this->_slash($base_url, 4), $this->_slash($home, 4), $data);
		$data = str_replace($this->_slash($base_url, 3), $this->_slash($home, 3), $data);
		$data = str_replace($this->_slash($base_url, 2), $this->_slash($home, 2), $data);
		$data = str_replace($this->_slash($base_url, 1), $this->_slash($home, 1), $data);
		$data = str_replace($base_url, $home, $data);
		
		return $data;
	}
	
	function _slash($data, $count){
		$slash = str_repeat('\\', $count).'/';
		
		return str_replace('/', $slash, $data);
	}
	
	public function fix_url($value){
		if(is_array($value)) {
			array_walk_recursive($value, function(&$_value){
				$_value = $this->_replace_url($_value);
			});
		} else if(is_string($value)) {
			$value = $this->_replace_url($value);
		}
		
		return $value;
	}
	
	/**
	 * Create new posts based on import information
	 *
	 * Posts marked as having a parent which doesn't exist will become top level items.
	 * Doesn't create a new post if: the post type doesn't exist, the given post ID
	 * is already noted as imported or a post with the same title and date already exists.
	 * Note that new/updated terms, comments and meta are imported for the last of the above.
	 */
	function process_posts(){
		$i = 0;
		
		for(; $this->current_index < $this->get_max_index();) {
			
			$this->save_states();
			$post = array_slice($this->posts, $this->current_index, 1);
			if(count($post)) {
				$post = $post[0];
			}
			
			if(!is_array($post)) {
				$post = array();
			}
			
			$post = array_merge(
				array(
					'id'   => 0,
					'type' => 'error',
				), $post
			);
			
			$post_id   = $post['id'];
			$post_type = $post['type'];
			
			$post = $this->load_file('posts', $post_id);
			if(is_wp_error($post)) {
				$this->log($post_id);
				$this->log($post->get_error_message());
				continue;
			}
			
			$this->process_post($post);
			
			$this->current_index++;
			
			if(defined('REST_REQUEST') && REST_REQUEST) {
				$i++;
				if($i >= self::LIMIT_POSTS) {
					break;
				}
			}
			
		}
	}
	
	public function process_attachments(){
		$i = 0;
		
		for(; $this->current_index < $this->get_max_index();) {
			$this->save_states();
			$post = array_slice($this->attachments, $this->current_index, 1);
			if(count($post)) {
				$post = $post[0];
			}
			
			if(!is_array($post)) {
				$post = array();
			}
			
			$post = array_merge(
				array(
					'id'   => 0,
					'type' => 'error',
				), $post
			);
			
			$post_id   = $post['id'];
			$post_type = $post['type'];
			
			$post = $this->load_file('posts', $post_id);
			if(is_wp_error($post)) {
				$this->log($post_id);
				$this->log($post->get_error_message());
				continue;
			}
			
			$this->process_post($post);
			$this->current_index++;
			$this->save_states(false);
			
			if(defined('REST_REQUEST') && REST_REQUEST) {
				$i++;
				if($i > self::LIMIT_ATTACHMENTS) {
					break;
				}
			}
		}
	}
	
	public function process_menus(){
		$this->log($this->menu_items);
		foreach($this->menu_items as $post) {
			$this->current_index++;
			$this->save_states(false);
			
			if(!is_array($post)) {
				$post = array();
			}
			
			$post = array_merge(
				array(
					'id'   => 0,
					'type' => 'error',
				), $post
			);
			
			$post_id   = $post['id'];
			$post_type = $post['type'];
			
			$post = $this->load_file('posts', $post_id);
			if(is_wp_error($post)) {
				$this->log($post_id);
				$this->log($post->get_error_message());
				continue;
			}
			
			$this->process_post($post);
		}
	}
	
	/**
	 * Attempt to create a new menu item from import data
	 *
	 * Fails for draft, orphaned menu items and those without an associated nav_menu
	 * or an invalid nav_menu term. If the post type or term object which the menu item
	 * represents doesn't exist then the menu item will not be imported (waits until the
	 * end of the import to retry again before discarding).
	 *
	 * @param array $item Menu item details from WXR file
	 */
	function process_menu_item($item){
		$this->log("Process  menu {$item['post_id']}");
		// skip draft, orphaned menu items
		if('draft' == $item['status']) {
			return;
		}
		
		$menu_slug = false;
		if(isset($item['terms'])) {
			// loop through terms, assume first nav_menu term is correct menu
			foreach($item['terms'] as $term) {
				if(!is_array($term)) {
					$term = $this->load_file('taxonomy', $term);
				}
				if('nav_menu' == $term['term_taxonomy']) {
					$menu_slug = $term['term_slug'];
					break;
				}
			}
		}
		
		// no nav_menu term associated with this menu item
		if(!$menu_slug) {
			$this->log(__('Menu item skipped due to missing menu slug', 'wordpress-importer'));
			
			return;
		}
		
		$menu_id = term_exists($menu_slug, 'nav_menu');
		if(!$menu_id) {
			$this->log(sprintf(__('Menu item skipped due to invalid menu slug: %s', 'wordpress-importer'), esc_html($menu_slug)));
			
			return;
		} else {
			$menu_id = is_array($menu_id) ? $menu_id['term_id'] : $menu_id;
		}
		
		$meta = array();
		foreach($item['postmeta'] as $_meta) {
			$meta[$_meta['meta_key']] = $_meta['meta_value'];
		}
		
		if('taxonomy' == $meta['_menu_item_type'] && isset($this->processed_terms[intval($meta['_menu_item_object_id'])])) {
			$meta['_menu_item_object_id'] = $this->processed_terms[intval($meta['_menu_item_object_id'])];
		} else if('post_type' == $meta['_menu_item_type'] && isset($this->processed_posts[intval($meta['_menu_item_object_id'])])) {
			$meta['_menu_item_object_id'] = $this->processed_posts[intval($meta['_menu_item_object_id'])];
		} else if('custom' != $meta['_menu_item_type']) {
			// associated object is missing or not imported yet, we'll retry later
			$this->missing_menu_items[] = $item;
			$this->log(__('Menu missed', 'wordpress-importer'));
			$this->log($item);
			
			return;
		}
		
		if(isset($this->processed_menu_items[intval($meta['_menu_item_menu_item_parent'])])) {
			$meta['_menu_item_menu_item_parent'] = $this->processed_menu_items[intval($meta['_menu_item_menu_item_parent'])];
		} else if($meta['_menu_item_menu_item_parent']) {
			$this->menu_item_orphans[intval($item['post_id'])] = (int) $meta['_menu_item_menu_item_parent'];
			$meta['_menu_item_menu_item_parent']               = 0;
		}
		
		// wp_update_nav_menu_item expects CSS classes as a space separated string
		$meta['_menu_item_classes'] = maybe_unserialize($meta['_menu_item_classes']);
		if(is_array($meta['_menu_item_classes'])) {
			$meta['_menu_item_classes'] = implode(' ', $meta['_menu_item_classes']);
		}
		
		$meta = $this->fix_url($meta);
		
		$args = array(
			'menu-item-object-id'   => $meta['_menu_item_object_id'],
			'menu-item-object'      => $meta['_menu_item_object'],
			'menu-item-parent-id'   => $meta['_menu_item_menu_item_parent'],
			'menu-item-position'    => intval($item['menu_order']),
			'menu-item-type'        => $meta['_menu_item_type'],
			'menu-item-title'       => $item['post_title'],
			'menu-item-url'         => $this->fix_url($meta['_menu_item_url']),
			'menu-item-description' => $this->fix_url($item['post_content']),
			'menu-item-attr-title'  => $this->fix_url($item['post_excerpt']),
			'menu-item-target'      => $meta['_menu_item_target'],
			'menu-item-classes'     => $meta['_menu_item_classes'],
			'menu-item-xfn'         => $meta['_menu_item_xfn'],
			'menu-item-status'      => $item['status']
		);
		
		$id = wp_update_nav_menu_item($menu_id, 0, $args);
		
		if(is_wp_error($id)) {
			$this->log('Menu id '.$menu_id);
			$this->log($id->get_error_message());
		}
		if($id && !is_wp_error($id)) {
			$this->processed_menu_items[intval($item['post_id'])] = (int) $id;
			
			if(!empty($meta)) {
				$post_id = $id;
				foreach($meta as $_meta_key => $_meta_value) {
					if(in_array(
						$_meta_key, array(
							'_menu_item_object_id',
							'_menu_item_object',
							'_menu_item_menu_item_parent',
							'menu_order',
							'_menu_item_type',
							'post_title',
							'_menu_item_url',
							'post_content',
							'post_excerpt',
							'_menu_item_target',
							'_menu_item_classes',
							'_menu_item_xfn',
							'status',
						)
					)) {
						continue;
					}
					$key   = apply_filters('import_post_meta_key', $_meta_key, $post_id, $item);
					$value = false;
					
					if('_edit_last' == $key) {
						if(isset($this->processed_authors[intval($_meta_value)])) {
							$value = $this->processed_authors[intval($_meta_value)];
						} else {
							$key = false;
						}
					}
					
					if($key) {
						// export gets meta straight from the DB so could have a serialized string
						if(!$value) {
							$value = maybe_unserialize($_meta_value);
						}
						
						//add_post_meta( $post_id, $key, $value );
						add_post_meta($post_id, wp_slash($key), wp_slash($value));
						do_action('import_post_meta', $post_id, $key, $value);
					}
				}
			}
		}
		
		
	}
	
	/**
	 * If fetching attachments is enabled then attempt to create a new attachment
	 *
	 * @param array  $post Attachment post details from WXR
	 * @param string $url  URL to fetch attachment from
	 *
	 * @return int|WP_Error Post ID on success, WP_Error otherwise
	 */
	function process_attachment($post, $url){
		if(!$this->fetch_attachments) {
			return new WP_Error(
				'attachment_processing_error',
				__('Fetching attachments is not enabled', 'wordpress-importer')
			);
		}
		
		// if the URL is absolute, but does not contain address, then upload it assuming base_site_url
		if(preg_match('|^/[\w\W]+$|', $url)) {
			$url = rtrim($this->base_url, '/').$url;
		}
		
		$upload = $this->fetch_remote_file($url, $post);
		if(is_wp_error($upload)) {
			$this->log($post['ID']);
			$this->log($upload->get_error_message());
			
			return $upload;
		}
		
		if($info = wp_check_filetype($upload['file'])) {
			$post['post_mime_type'] = $info['type'];
		} else {
			return new WP_Error('attachment_processing_error', __('Invalid file type', 'wordpress-importer'));
		}
		
		$post['guid'] = $upload['url'];
		
		// as per wp-admin/includes/upload.php
		$post_id = wp_insert_attachment($post, $upload['file']);
		wp_update_attachment_metadata($post_id, wp_generate_attachment_metadata($post_id, $upload['file']));
		
		// remap resized image URLs, works by stripping the extension and remapping the URL stub.
		if(preg_match('!^image/!', $info['type'])) {
			$parts = pathinfo($url);
			$name  = basename($parts['basename'], ".{$parts['extension']}"); // PATHINFO_FILENAME in PHP 5.2
			
			$parts_new = pathinfo($upload['url']);
			$name_new  = basename($parts_new['basename'], ".{$parts_new['extension']}");
			
			$this->url_remap[$parts['dirname'].'/'.$name] = $parts_new['dirname'].'/'.$name_new;
		}
		
		return $post_id;
	}
	
	/**
	 * Attempt to download a remote file attachment
	 *
	 * @param string $url  URL of item to fetch
	 * @param array  $post Attachment details
	 *
	 * @return array|WP_Error Local file location details on success, WP_Error otherwise
	 */
	function fetch_remote_file($url, $post){
		// extract the file name and extension from the url
		$file_name = basename($url);
		
		// get placeholder file in the upload dir with a unique, sanitized filename
		$upload = wp_upload_bits($file_name, 0, '', $post['upload_date']);
		if($upload['error']) {
			return new WP_Error('upload_dir_error', $upload['error']);
		}
		
		// fetch the remote url and write it to the placeholder file
		$remote_response = wp_safe_remote_get(
			$url, array(
				'timeout'  => 300,
				'stream'   => true,
				'filename' => $upload['file'],
			)
		);
		
		$headers = wp_remote_retrieve_headers($remote_response);
		
		// request failed
		if(!$headers) {
			@unlink($upload['file']);
			
			return new WP_Error('import_file_error', __('Remote server did not respond', 'wordpress-importer'));
		}
		
		$remote_response_code = wp_remote_retrieve_response_code($remote_response);
		
		// make sure the fetch was successful
		if($remote_response_code != '200') {
			@unlink($upload['file']);
			
			return new WP_Error('import_file_error', sprintf(__('Remote server returned error response %1$d %2$s', 'wordpress-importer'), esc_html($remote_response_code), get_status_header_desc($remote_response_code)));
		}
		
		$filesize = filesize($upload['file']);
		
		if(isset($headers['content-length']) && $filesize != $headers['content-length']) {
			@unlink($upload['file']);
			
			return new WP_Error('import_file_error', __('Remote file is incorrect size', 'wordpress-importer'));
		}
		
		if(0 == $filesize) {
			@unlink($upload['file']);
			
			return new WP_Error('import_file_error', __('Zero size file downloaded', 'wordpress-importer'));
		}
		
		$max_size = (int) $this->max_attachment_size();
		if(!empty($max_size) && $filesize > $max_size) {
			@unlink($upload['file']);
			
			return new WP_Error('import_file_error', sprintf(__('Remote file is too large, limit is %s', 'wordpress-importer'), size_format($max_size)));
		}
		
		// keep track of the old and new urls, so we can substitute them later
		$this->url_remap[$url]          = $upload['url'];
		$this->url_remap[$post['guid']] = $upload['url']; // r13735, really needed?
		// keep track of the destination if the remote url is redirected somewhere else
		if(isset($headers['x-final-location']) && $headers['x-final-location'] != $url) {
			$this->url_remap[$headers['x-final-location']] = $upload['url'];
		}
		
		return $upload;
	}
	
	/**
	 * Attempt to associate posts and menu items with previously missing parents
	 *
	 * An imported post's parent may not have been imported when it was first created
	 * so try again. Similarly for child menu items and menu items which were missing
	 * the object (e.g. post) they represent in the menu
	 */
	function backfill_parents(){
		global $wpdb;
		
		// find parents for post orphans
		foreach($this->post_orphans as $child_id => $parent_id) {
			$local_child_id = $local_parent_id = false;
			if(isset($this->processed_posts[$child_id])) {
				$local_child_id = $this->processed_posts[$child_id];
			}
			if(isset($this->processed_posts[$parent_id])) {
				$local_parent_id = $this->processed_posts[$parent_id];
			}
			
			if($local_child_id && $local_parent_id) {
				$wpdb->update($wpdb->posts, array( 'post_parent' => $local_parent_id ), array( 'ID' => $local_child_id ), '%d', '%d');
				clean_post_cache($local_child_id);
			}
		}
		
		// all other posts/terms are imported, retry menu items with missing associated object
		$missing_menu_items = $this->missing_menu_items;
		foreach($missing_menu_items as $item) {
			$this->process_menu_item($item);
		}
		
		// find parents for menu item orphans
		foreach($this->menu_item_orphans as $child_id => $parent_id) {
			$local_child_id = $local_parent_id = 0;
			if(isset($this->processed_menu_items[$child_id])) {
				$local_child_id = $this->processed_menu_items[$child_id];
			}
			if(isset($this->processed_menu_items[$parent_id])) {
				$local_parent_id = $this->processed_menu_items[$parent_id];
			}
			
			if($local_child_id && $local_parent_id) {
				update_post_meta($local_child_id, '_menu_item_menu_item_parent', (int) $local_parent_id);
			}
		}
	}
	
	/**
	 * Use stored mapping information to update old attachment URLs
	 */
	function backfill_attachment_urls(){
		global $wpdb;
		// make sure we do the longest urls first, in case one is a substring of another
		
		$home     = get_home_url();
		$base_url = $this->import_data['base_url'];
		
		$uploads         = wp_upload_dir();
		$upload_url      = $this->import_data['upload_url'];
		$home_upload_url = $uploads['baseurl'];
		
		$res1 = $wpdb->query($wpdb->prepare("UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $upload_url, $home_upload_url));
		$res1 = $wpdb->query($wpdb->prepare("UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $base_url, $home));
		$res1 = $wpdb->query($wpdb->prepare("UPDATE {$wpdb->posts} SET guid = REPLACE(guid, %s, %s)", $upload_url, $home_upload_url));
		$res1 = $wpdb->query($wpdb->prepare("UPDATE {$wpdb->posts} SET guid = REPLACE(guid, %s, %s)", $base_url, $home));
	}
	
	/**
	 * Update _thumbnail_id meta to new, imported attachment IDs
	 */
	function remap_featured_images(){
		// cycle through posts that have a featured image
		foreach($this->featured_images as $post_id => $value) {
			if(isset($this->processed_posts[$value])) {
				$new_id = $this->processed_posts[$value];
				// only update if there's a difference
				if($new_id != $value) {
					update_post_meta($post_id, '_thumbnail_id', $new_id);
				}
			}
		}
	}
	
	/**
	 * Parse a JSON file
	 *
	 * @param string $file Path to WXR file for parsing
	 *
	 * @return array|WP_Error Information gathered from the WXR file
	 */
	function parse($file){
		if(!is_file($file) || !is_readable($file)) {
			return new WP_Error('File not found. '.$file);
		}
		
		$data = '';
		$fp   = fopen($file, 'r');
		while(!feof($fp)) {
			$data .= fread($fp, 1024);
		}
		fclose($fp);
		
		try {
			$_data = json_decode($data, true);
			
			if(!json_last_error()) {
				$data = $_data;
			} else {
				$data = new WP_Error('File broken. '.$file);
			}
			
		} catch(\Exception $exception) {
			$data = new WP_Error('File broken. '.$exception->getMessage());
		}
		
		return $data;
	}
	
	/**
	 * Decide if the given meta key maps to information we will want to import
	 *
	 * @param string $key The meta key to check
	 *
	 * @return string|bool The key if we do want to import, false if not
	 */
	function is_valid_meta_key($key){
		// skip attachment metadata since we'll regenerate it from scratch
		// skip _edit_lock as not relevant for import
		if(in_array($key, array( '_wp_attached_file', '_wp_attachment_metadata', '_edit_lock' ))) {
			return false;
		}
		
		return $key;
	}
	
	/**
	 * Decide whether or not the importer should attempt to download attachment files.
	 * Default is true, can be filtered via import_allow_fetch_attachments. The choice
	 * made at the import options screen must also be true, false here hides that checkbox.
	 *
	 * @return bool True if downloading attachments is allowed
	 */
	function allow_fetch_attachments(){
		return apply_filters('import_allow_fetch_attachments', true);
	}
	
	/**
	 * Decide what the maximum file size for downloaded attachments is.
	 * Default is 0 (unlimited), can be filtered via import_attachment_size_limit
	 *
	 * @return int Maximum attachment file size to import
	 */
	function max_attachment_size(){
		return apply_filters('import_attachment_size_limit', 0);
	}
	
	/**
	 * Added to http_request_timeout filter to force timeout at 60 seconds during import
	 *
	 * @return int 60
	 */
	function bump_request_timeout($val){
		return 60;
	}
	
	// return the difference in length between two strings
	function cmpr_strlen($a, $b){
		return strlen($b)-strlen($a);
	}
	
	
	public function load_file($folder, $file){
		if(!empty($folder)) {
			$folder .= '/';
		}
		$filename = $this->folder.$folder.$file.'.json';
		
		return $this->parse($filename);
	}
	
	/**
	 * @return array Filtered data
	 */
	protected function filter_data(&$array, $args = array( 'filter' => array(), 'remove' => false, 'field' => 'type' )){
		if(!is_array($args)) {
			$args = array( 'filter' => $args );
		}
		if(!is_array($args['filter'])) {
			$args['filter'] = array( $args['filter'] );
		}
		
		$args   = array_merge(array( 'filter' => array(), 'remove' => false, 'field' => 'type' ), $args);
		$field  = $args['field'];
		$remove = $args['remove'];
		$filter = $args['filter'];
		
		return array_filter(
			$array, function(&$item, $key) use (&$array, $filter, $remove, $field){
			if(key_exists($field, $item) && in_array($item[$field], $filter)) {
				if($remove) {
					unset($array[$key]);
				}
				
				return true;
			}
			
			return false;
		}, ARRAY_FILTER_USE_BOTH
		);
		
	}
	
	protected function add_post_to_schedule($post){
		if(!is_array($post)) {
			$post = $this->filter_data($this->import_data['posts'], array( 'filter' => $post, 'field' => 'id' ));
			if(count($post)) {
				$post = array_shift($post);
			} else {
				return;
			}
		}
		$_post = array_merge(
			array(
				'id'     => false,
				'title'  => "",
				'type'   => "none",
				'media'  => [],
				'terms'  => [],
				'header' => null,
				'footer' => null,
			), $post
		);
		if(!key_exists($_post['id'], $this->scheduled['posts']) && !!$_post['id']) {
			$terms = $this->filter_data($this->import_data['terms'], array( 'filter' => $_post['terms'], 'field' => 'id' ));
			array_map(array( $this, 'add_term_to_schedule' ), $terms);
			$attachments = $this->filter_data($this->import_data['attachments'], array( 'filter' => $_post['media'], 'field' => 'id' ));
			array_map(array( $this, 'add_attachment_to_schedule' ), $attachments);
			
			if($_post['header']) {
				$this->add_post_to_schedule($_post['header']);
			}
			if($_post['footer']) {
				$this->add_post_to_schedule($_post['footer']);
			}
			$this->scheduled['posts'][$_post['id']] = array_intersect_key($_post, array( 'id' => true, 'type' => true ));
		}
	}
	
	protected function add_term_to_schedule($term){
		if(!key_exists($term['id'], $this->scheduled['terms'])) {
			$this->scheduled['terms'][$term['id']] = $term;
		}
	}
	
	protected function add_attachment_to_schedule($attachment){
		if(!key_exists($attachment['id'], $this->scheduled['attachments'])) {
			$this->scheduled['attachments'][$attachment['id']] = $attachment;
		}
	}
	
	protected function save_scheduled($filter = array( 'all' => true )){
		if(!is_array($filter)) {
			$filter = array( 'all' => true );
		}
		
		$this->scheduled = array(
			'posts'       => array(),
			'terms'       => array(),
			'attachments' => array(),
			'categories'  => array(),
			'tags'        => array(),
			'menu_items'  => array(),
			'base_url'    => $this->import_data['base_url'],
			'rev_sliders' => array(),
		);
		
		$posts = array();
		
		if(isset($filter['all']) && $filter['all']) {
			$this->scheduled = $this->import_data;
		} else {
			if(count($filter)) {
				foreach($filter as $key => $value) {
					$isAll = (is_array($value) && count($value) === 1 && $value[0] === -1) || $value === true;
					switch($key) {
						case 'homepages':
							if($isAll) {
								$value = array_column($this->import_data['homepages'], 'id');
							}
							$posts = array_merge(
								$posts,
								$this->filter_data($this->import_data['posts'], array( 'filter' => $value, 'field' => 'id' ))
							);
							break;
						case 'post':
							$value = ($isAll ?
								$this->filter_data($this->import_data['posts'], 'post') :
								$this->filter_data($this->import_data['posts'], array( 'filter' => $value, 'field' => 'id' )));
							$posts = array_merge($posts, $value);
							break;
						case 'page':
							$value = ($isAll ?
								$this->filter_data($this->import_data['posts'], 'page') :
								$this->filter_data($this->import_data['posts'], array( 'filter' => $value, 'field' => 'id' )));
							$posts = array_merge($posts, $value);
							
							break;
						case 'team':
							$value = ($isAll ?
								$this->filter_data($this->import_data['posts'], 'team') :
								$this->filter_data($this->import_data['posts'], array( 'filter' => $value, 'field' => 'id' )));
							
							$posts = array_merge($posts, $value);
							break;
						case 'portfolio':
							$value = ($isAll ?
								$this->filter_data($this->import_data['posts'], 'portfolio') :
								$this->filter_data($this->import_data['posts'], array( 'filter' => $value, 'field' => 'id' )));
							$posts = array_merge($posts, $value);
							break;
						case 'rev_sliders':
							if($value && key_exists('rev_sliders', $this->import_data)) {
								$this->scheduled['rev_sliders'] = $this->import_data['rev_sliders'];
							}
							break;
						case 'headers_footers':
							if($value) {
								$_posts = array();
								if(key_exists('headers', $this->import_data)) {
									$_posts = array_merge($_posts, $this->import_data['headers']);
								}
								if(key_exists('footers', $this->import_data)) {
									$_posts = array_merge($_posts, $this->import_data['footers']);
								}
								
								$posts = array_merge($posts, $this->filter_data($this->import_data['posts'], array( 'filter' => $_posts, 'field' => 'id' )));
							}
							break;
						case 'cf7':
							if($value) {
								$value = $this->filter_data($this->import_data['posts'], 'wpcf7_contact_form');
								
								$posts = array_merge($posts, $value);
							}
							break;
						
						case 'tabs':
							if($value && key_exists('tabs', $this->import_data)) {
								$posts = array_merge($posts, $this->filter_data($this->import_data['posts'], array( 'filter' => $this->import_data['tabs'], 'field' => 'id' )));
							}
							break;
					}
				}
			}
			
			array_map(array( $this, 'add_post_to_schedule' ), $posts);
		}
		
		$file = $this->folder.'scheduled.json';
		$fp   = fopen($file, 'w+');
		if($fp) {
			$state   = json_encode($this->scheduled);
			$len     = strlen($state);
			$written = $fwrite = 0;
			
			if($len > 0) {
				while($len > $written && $fwrite !== false) {
					$line   = substr($state, $written, 256);
					$fwrite = fwrite($fp, $line);
					fflush($fp);
					if(false !== $fwrite) {
						$written += $fwrite;
					}
				}
			}
			
			fflush($fp);
			fclose($fp);
		}
	}
	
	public function load_scheduled_file(){
		$file            = $this->folder.'scheduled.json';
		$this->scheduled = $this->parse($file);
		
		$def = array(
			'categories' => array(),
			'tags'       => array(),
			'terms'      => array(),
			'posts'      => array(),
		);
		
		if(is_wp_error($this->scheduled)) {
			$this->log('Error loading import file.');
			
			return $def;
		}
		
		$this->scheduled = array_merge($def, $this->scheduled);
		
		$this->posts       = $this->scheduled['posts'];
		$this->terms       = $this->scheduled['terms'];
		$this->categories  = $this->scheduled['categories'];
		$this->tags        = $this->scheduled['tags'];
		$this->base_url    = esc_url($this->scheduled['base_url']);
		$this->attachments = $this->scheduled['attachments'];
		$this->menu_items  = $this->scheduled['menu_items'];
		$this->rev_sliders = $this->scheduled['rev_sliders'];
		
	}
	
	public function load_import_file(){
		$file              = $this->folder.'import.json';
		$this->import_data = $this->parse($file);
	}
	
	public function load_old_import_file(){
		$file = $this->theme_import_path.'import.json';
		
		return $this->parse($file);
	}
	
	public function import_theme_options(){
		$options = $this->load_file('', 'theme_options');
		$options = $this->fix_import_theme_options($options);
		update_option($this->theme, $options);
		
		/** Elementor */
		
		$customizer = $this->load_file('', 'customizer');
		if(!is_wp_error($customizer)) {
			Customizer::instance()->set_options($customizer);
		}
		
		$customizer = $this->load_file('', 'customizer_elementor');
		if(!is_wp_error($customizer)) {
			Customizer\Elementor::instance()->set_setting($customizer);
			Customizer\Elementor::instance()->save_settings();
		} else if(class_exists('Elementor\Plugin')) {
			$doc  = \Elementor\Plugin::instance()->documents;
			$kit  = \Elementor\Plugin::instance()->kits_manager;
			$data = array(
				'editor_post_id' => $kit->get_active_id(),
				'post_status'    => "publish",
				'status'         => "publish",
				'elements'       => array(),
				'settings'       => array(
					'container_width' => array(
						'size'  => 1190,
						'sizes' => [],
						'unit'  => "px",
					),
					'post_status'     => 'publish'
				)
			
			);
			
			$doc->ajax_save($data);
		}
		
	}
	
	public function available_widgets(){
		
		global $wp_registered_widget_controls;
		
		$widget_controls = $wp_registered_widget_controls;
		
		$available_widgets = array();
		
		foreach($widget_controls as $widget) {
			if(!empty($widget['id_base']) && !isset($available_widgets[$widget['id_base']])) { // no dupes
				$available_widgets[$widget['id_base']]['id_base'] = $widget['id_base'];
				$available_widgets[$widget['id_base']]['name']    = $widget['name'];
			}
		}
		
		return apply_filters('radium_theme_import_widget_available_widgets', $available_widgets);
		
	}
	
	public function import_widgets(){
		$data = $this->load_file('', 'widgets');
		
		global $wp_registered_sidebars;
		
		// Have valid data?
		// If no data or could not decode
		if(empty($data) || !is_array($data)) {
			return;
		}
		
		// Hook before import
		$data = apply_filters('radium_theme_import_widget_data', $data);
		
		// Get all available widgets site supports
		$available_widgets = $this->available_widgets();
		
		// Get all existing widget instances
		$widget_instances = array();
		foreach($available_widgets as $widget_data) {
			$widget_instances[$widget_data['id_base']] = get_option('widget_'.$widget_data['id_base']);
		}
		
		// Begin results
		$results = array();
		
		// Loop import data's sidebars
		foreach($data as $sidebar_id => $widgets) {
			
			
			// Skip inactive widgets
			// (should not be in export file)
			if('wp_inactive_widgets' == $sidebar_id) {
				continue;
			}
			
			// Check if sidebar is available on this site
			// Otherwise add widgets to inactive, and say so
			if(isset($wp_registered_sidebars[$sidebar_id])) {
				$sidebar_available    = true;
				$use_sidebar_id       = $sidebar_id;
				$sidebar_message_type = 'success';
				$sidebar_message      = '';
			} else {
				$sidebar_available    = false;
				$use_sidebar_id       = 'wp_inactive_widgets'; // add to inactive if sidebar does not exist in theme
				$sidebar_message_type = 'error';
				$sidebar_message      = __('Sidebar does not exist in theme (using Inactive)', 'radium');
			}
			
			// Result for sidebar
			$results[$sidebar_id]['name']         = !empty($wp_registered_sidebars[$sidebar_id]['name']) ? $wp_registered_sidebars[$sidebar_id]['name'] : $sidebar_id;
			$results[$sidebar_id]['message_type'] = $sidebar_message_type;
			$results[$sidebar_id]['message']      = $sidebar_message;
			$results[$sidebar_id]['widgets']      = array();
			
			// Loop widgets
			foreach($widgets as $widget_instance_id => $widget) {
				
				$fail = false;
				
				// Get id_base (remove -# from end) and instance ID number
				$id_base            = preg_replace('/-[0-9]+$/', '', $widget_instance_id);
				$instance_id_number = str_replace($id_base.'-', '', $widget_instance_id);
				
				// Does site support this widget?
				if(!$fail && !isset($available_widgets[$id_base])) {
					$fail                = true;
					$widget_message_type = 'error';
					$widget_message      = __('Site does not support widget', 'radium'); // explain why widget not imported
				}
				
				// Filter to modify settings before import
				// Do before identical check because changes may make it identical to end result (such as URL replacements)
				$widget = $this->fix_import_widget($widget, $id_base);
				
				// Does widget with identical settings already exist in same sidebar?
				if(!$fail && isset($widget_instances[$id_base])) {
					
					// Get existing widgets in this sidebar
					$sidebars_widgets = get_option('sidebars_widgets');
					$sidebar_widgets  = isset($sidebars_widgets[$use_sidebar_id]) ? $sidebars_widgets[$use_sidebar_id] : array(); // check Inactive if that's where will go
					
					// Loop widgets with ID base
					$single_widget_instances = !empty($widget_instances[$id_base]) ? $widget_instances[$id_base] : array();
					foreach($single_widget_instances as $check_id => $check_widget) {
						
						// Is widget in same sidebar and has identical settings?
						if(in_array("$id_base-$check_id", $sidebar_widgets) && (array) $widget == $check_widget) {
							
							$fail                = true;
							$widget_message_type = 'warning';
							$widget_message      = __('Widget already exists', 'radium'); // explain why widget not imported
							
							break;
							
						}
						
					}
					
				}
				
				// No failure
				if(!$fail) {
					
					// Add widget instance
					$single_widget_instances = get_option('widget_'.$id_base); // all instances for that widget ID base, get fresh every time
					$single_widget_instances = !empty($single_widget_instances) ? $single_widget_instances : array( '_multiwidget' => 1 ); // start fresh if have to
					
					$single_widget_instances[] = $widget; // add it
					
					// Get the key it was given
					end($single_widget_instances);
					$new_instance_id_number = key($single_widget_instances);
					
					// If key is 0, make it 1
					// When 0, an issue can occur where adding a widget causes data from other widget to load, and the widget doesn't stick (reload wipes it)
					if('0' === strval($new_instance_id_number)) {
						$new_instance_id_number                           = 1;
						$single_widget_instances[$new_instance_id_number] = $single_widget_instances[0];
						unset($single_widget_instances[0]);
					}
					
					// Move _multiwidget to end of array for uniformity
					if(isset($single_widget_instances['_multiwidget'])) {
						$multiwidget = $single_widget_instances['_multiwidget'];
						unset($single_widget_instances['_multiwidget']);
						$single_widget_instances['_multiwidget'] = $multiwidget;
					}
					
					// Update option with new widget
					update_option('widget_'.$id_base, $single_widget_instances);
					
					// Assign widget instance to sidebar
					$sidebars_widgets = get_option('sidebars_widgets'); // which sidebars have which widgets, get fresh every time
					if(!$sidebars_widgets) {
						$sidebars_widgets = array();
					}
					
					$new_instance_id                     = $id_base.'-'.$new_instance_id_number; // use ID number from new widget instance
					$sidebars_widgets[$use_sidebar_id][] = $new_instance_id; // add new instance to sidebar
					update_option('sidebars_widgets', $sidebars_widgets); // save the amended data
					
					// Success message
					if($sidebar_available) {
						$widget_message_type = 'success';
						$widget_message      = __('Imported', 'radium');
					} else {
						$widget_message_type = 'warning';
						$widget_message      = __('Imported to Inactive', 'radium');
					}
				}
				
				// Result for widget instance
				$results[$sidebar_id]['widgets'][$widget_instance_id]['name']         = isset($available_widgets[$id_base]['name']) ? $available_widgets[$id_base]['name'] : $id_base; // widget name or ID if name not available (not supported by site)
				$results[$sidebar_id]['widgets'][$widget_instance_id]['title']        = !empty($widget['title']) ? $widget['title'] : __('No Title', 'radium'); // show "No Title" if widget instance is untitled
				$results[$sidebar_id]['widgets'][$widget_instance_id]['message_type'] = $widget_message_type;
				$results[$sidebar_id]['widgets'][$widget_instance_id]['message']      = $widget_message;
			}
		}
		
		// Return results
		return apply_filters('radium_theme_import_widget_results', $results);
		
	}
	
	public function import_settings(){
		if(key_exists('home_page', $this->scheduled)) {
			$this->log('Import home page. '.$this->scheduled['home_page'].' -- '.$this->get_real_page_id($this->scheduled['home_page']));
			
			update_option('page_on_front', $this->get_real_page_id($this->scheduled['home_page']));
			update_option('show_on_front', 'page');
		}
		
	}
	
	public function get_real_page_id($page_id){
		return $page_id;
	}
	
	public function save_attachment_id($post_id, $postmeta){
		$this->set_real_id($post_id, $postmeta['import_id']);
	}
	
	public function fix_import_post($post, $postdata){
		return $this->fix_elementor_page($post, $postdata);
	}
	
	public function fix_import_widget($widget, $widget_name){
		if(in_array($widget_name, array( 'media_image' ))) {
			if(is_object($widget)) {
				if(property_exists($widget, 'attachment_id')) {
					$widget->attachment_id = $this->get_local_id($widget->attachment_id);
					$widget->url           = wp_get_attachment_image_url($widget->attachment_id, 'full');
					$widget->link_url      = get_permalink($widget->attachment_id);
				}
				if(property_exists($widget, 'content')) {
					$widget->content = $this->_replace_url($widget->content);
				}
			} else if(is_array($widget)) {
				if(key_exists('content', $widget)) {
					$widget['content'] = $this->_replace_url($widget['content']);
				}
			}
		}
		
		return $widget;
	}
	
	public function fix_import_theme_options($data){
		if(is_array($data) && count($data)) {
			foreach($data as &$value) {
				if(is_array($value)) {
					if(
						key_exists('url', $value)
						&& key_exists('id', $value)
						&& key_exists('thumbnail', $value)
					) {
						$value['id']        = $this->get_local_id($value['id']);
						$value['url']       = wp_get_attachment_image_url($value['id'], 'full');
						$value['thumbnail'] = wp_get_attachment_image_url($value['id'], 'thumbnail');
					} else if(key_exists('background-image', $value)
					          && key_exists('media', $value)
					) {
						$value['media']['id']        = $this->get_local_id($value['media']['id']);
						$value['media']['thumbnail'] = wp_get_attachment_image_url($value['media']['id'], 'thumbnail');
						$value['background-image']   = wp_get_attachment_image_url($value['media']['id'], 'full');
					}
				}
			}
		}
		
		return $data;
	}
	
	protected function set_real_id($local, $real){
		$this->processed_attachments[$real] = $local;
	}
	
	protected function get_local_id($real){
		return key_exists($real, $this->processed_attachments) ? $this->processed_attachments[$real] : $real;
	}
	
	protected function fix_elementor_page($post, $postdata = array()){
		if(class_exists('Elementor\Plugin')) {
			if(key_exists('postmeta', $post)) {
				foreach($post['postmeta'] as &$post_meta) {
					if(is_array($post_meta) && $post_meta['meta_key'] == '_elementor_data') {
						$meta = json_decode($post_meta['meta_value'], true);
						if(json_last_error()) {
							$meta = array();
						}
						
						if(is_array($meta) && count($meta)) {
							foreach($meta as &$level_0) {
								$this->fix_elementor_page_images($level_0);
							}
						}
						$post_meta['meta_value'] = wp_json_encode($meta);
					}
					
					if($post_meta['meta_key'] === '_elementor_css') {
						unset($post_meta);
					}
				}
			}
		}
		
		return $post;
	}
	
	protected function fix_elementor_page_images(&$item){
		if(key_exists('elType', $item)) {
			$this->replace_image_id($item);
		}
		if(key_exists('elements', $item) && is_array($item['elements']) && count($item['elements'])) {
			foreach($item['elements'] as &$element) {
				$this->fix_elementor_page_images($element);
			}
		}
	}
	
	protected function replace_image_id(&$item){
		$name = !in_array($item['elType'], array( 'section', 'column' )) ? $item['widgetType'] : $item['elType'];
		$widget_controls = $this->get_widget_controls($name);
		
		if(is_array($widget_controls) && count($widget_controls)) {
			foreach($item['settings'] as $control => &$control_settings) {
				if(in_array($control, $widget_controls)) {
					if(key_exists('id', $control_settings)) {
						$_new_id = $this->get_local_id($control_settings['id']);
						if($_new_id !== $control_settings['id']) {
							$control_settings['id']  = $_new_id;
							$control_settings['url'] = wp_get_attachment_image_url($_new_id, 'full');
						}
					} else {
						foreach($control_settings as &$control_setting) {
							$_new_id = $this->get_local_id($control_setting['id']);
							if($_new_id !== $control_setting['id']) {
								$control_setting['id']  = $_new_id;
								$control_setting['url'] = wp_get_attachment_image_url($_new_id, 'full');
							}
						}
					}
				}
			}
		}
	}
	
	protected function get_widget_controls($widget = false){
		static $widgets = null;
		
		if(false === $widget) {
			return $widgets;
		}
		
		if(null !== $widgets && key_exists($widget, $widgets)) {
			return $widgets[$widget];
		}
		$_widget = null;
		
		if (in_array($widget, array( 'section', 'column' ))) {
			$manager  = Elementor_Plugin::instance()->elements_manager;
			$_widget  = $manager->get_element_types($widget);
		} else {
			$manager  = Elementor_Plugin::instance()->widgets_manager;
			$_widget  = $manager->get_widget_types($widget);
		}
		
		$controls = is_null($_widget) ? array() : $_widget->get_controls();
		
		$controls = array_filter(
			$controls, function($control){
			return (key_exists('type', $control) && in_array($control['type'], $this->elementor_media_controls));
		}
		);
		
		$widgets[$widget] = array_keys($controls);
		
		return $widgets[$widget];
	}
}
© 2025 GrazzMean