PluginProbe ʕ •ᴥ•ʔ
Advanced Import / trunk
Advanced Import vtrunk
trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 2.0.0
advanced-import / admin / class-advanced-import-admin.php
advanced-import / admin Last commit date
class-advanced-import-admin.php 3 weeks ago class-advanced-import-template.php 3 months ago class-advanced-import-tracking.php 3 weeks ago class-elementor-import.php 3 weeks ago class-reset.php 3 weeks ago index.php 5 years ago
class-advanced-import-admin.php
2906 lines
1 <?php // phpcs:ignore WordPress.Files.FileName
2 /**
3 * Advanced Import Admin class
4 *
5 * Collection of admin hooks
6 *
7 * @package Advanced_Import
8 * @since 1.0.0
9 */
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 /**
16 * The admin-specific functionality of the plugin.
17 *
18 * Defines the plugin name, version, and two examples hooks for how to
19 * enqueue the admin-specific stylesheet and JavaScript.
20 *
21 * @package Advanced_Import
22 * @subpackage Advanced_Import/admin
23 * @author Addons Press <addonspress.com>
24 */
25 class Advanced_Import_Admin {
26
27 /**
28 * The Name of this plugin.
29 *
30 * @since 1.0.0
31 * @access private
32 * @var string $plugin_name The ID of this plugin.
33 */
34 private $plugin_name;
35
36 /**
37 * The version of this plugin.
38 *
39 * @since 1.0.0
40 * @access private
41 * @var string $version The current version of this plugin.
42 */
43 private $version;
44
45 /**
46 * The Current theme name
47 *
48 * @since 1.0.0
49 * @access public
50 * @var string $theme_name The Current theme name.
51 */
52 public $theme_name = '';
53
54 /**
55 * Current step
56 *
57 * @since 1.0.0
58 * @access protected
59 * @var string $step Current step.
60 */
61 protected $step = '';
62
63 /**
64 * Array of steps
65 *
66 * @since 1.0.0
67 * @access public
68 * @var array $steps Array of steps.
69 */
70 protected $steps = array();
71
72 /**
73 * Demo lists
74 *
75 * @since 1.0.0
76 * @access public
77 * @var array $demo_lists Array of demo lists.
78 */
79 public $demo_lists = array();
80
81 /**
82 * Demo lists
83 *
84 * @since 1.0.0
85 * @access public
86 * @var array $demo_lists Array of demo lists.
87 */
88 public $is_pro_active = false;
89
90 /**
91 * Array of delayed post for late process
92 *
93 * @since 1.0.0
94 * @access public
95 * @var array $delay_posts Array of delayed post for late process.
96 */
97 private $delay_posts = array();
98
99 /**
100 * Store logs and errors
101 *
102 * @since 1.0.0
103 * @access public
104 * @var array $logs Store logs and errors.
105 */
106 public $logs = array();
107
108 /**
109 * Store errors
110 *
111 * @since 1.0.0
112 * @access public
113 * @var array $errors Store errors.
114 */
115 public $errors = array();
116
117 /**
118 * Current added Menu hook_suffix
119 *
120 * @since 1.0.0
121 * @access public
122 * @var array $logs Store logs and errors.
123 */
124 public $hook_suffix;
125
126 /**
127 * Slug of the import page
128 *
129 * @since 1.0.0
130 * @access public
131 * @var string $logs Store logs and errors.
132 */
133 private $current_template_type;
134
135 /**
136 * Slug of the import page
137 *
138 * @since 1.0.0
139 * @access public
140 * @var string $logs Store logs and errors.
141 */
142 private $current_template_url;
143
144 /**
145 * Total requests
146 *
147 * @since 1.3.3
148 * @access public
149 * @var int $total_request Store total request for progress bar.
150 */
151 private $total_request;
152 private $current_request = 0;
153
154 /**
155 * Initialize the class and set its properties.
156 *
157 * @since 1.0.0
158 */
159 public function __construct() {}
160
161 /**
162 * Main Advanced_Import_Admin Instance
163 * Initialize the class and set its properties.
164 *
165 * @since 1.0.0
166 * @return object $instance Advanced_Import_Admin Instance
167 */
168 public static function instance() {
169
170 // Store the instance locally to avoid private static replication.
171 static $instance = null;
172
173 // Only run these methods if they haven't been ran previously.
174 if ( null === $instance ) {
175 $instance = new Advanced_Import_Admin();
176 $instance->plugin_name = ADVANCED_IMPORT_PLUGIN_NAME;
177 $instance->version = ADVANCED_IMPORT_VERSION;
178
179 /*page slug using theme name */
180 $instance->theme_name = sanitize_key( get_option( 'template' ) );
181
182 }
183
184 // Always return the instance.
185 return $instance;
186 }
187
188 /**
189 * Add plugin menu items.
190 *
191 * @access public
192 *
193 * @since 1.0.0
194 * @param string[] $actions An array of plugin action links. By default this can include
195 * 'activate', 'deactivate', and 'delete'. With Multisite active
196 * this can also include 'network_active' and 'network_only' items.
197 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
198 * @param array $plugin_data An array of plugin data. See get_plugin_data()
199 * and the {@see 'plugin_row_meta'} filter for the list
200 * of possible values.
201 * @param string $context The plugin context. By default this can include 'all',
202 * 'active', 'inactive', 'recently_activated', 'upgrade',
203 * 'mustuse', 'dropins', and 'search'.
204 * @return array settings schema for this plugin.
205 */
206 public function add_plugin_links( $actions, $plugin_file, $plugin_data, $context ) {
207 $actions[] = '<a href="' . esc_url( menu_page_url( 'advanced-import', false ) ) . '">' . esc_html__( 'Import', 'advanced-import' ) . '</a>';
208 return $actions;
209 }
210
211 /**
212 * Check if template is available to import
213 *
214 * @since 1.0.8
215 * @param array $item current array of demo list.
216 * @return boolean
217 */
218 public function is_template_available( $item ) {
219 $is_available = false;
220
221 /*if pro active everything is available*/
222 if ( isset( $item['has_access'] ) && $item['has_access'] ) {
223 $is_available = true;
224 } elseif ( $this->is_pro_active ) {
225 $is_available = true;
226 } elseif ( ! isset( $item['is_pro'] ) ) {/*if is_pro not set the $item is available*/
227 $is_available = true;/*template available since */
228 } elseif ( isset( $item['is_pro'] ) && ! $item['is_pro'] ) {/*if is_pro not set but it is false, it will be free and avialable*/
229 $is_available = true;
230 }
231
232 return (bool) apply_filters( 'advanced_import_is_template_available', $is_available, $item );
233 }
234
235 /**
236 * Check if template is available to import
237 *
238 * @since 1.0.8
239 * @param array $item current array of demo list.
240 * @return boolean
241 */
242 public function is_pro( $item ) {
243 $is_pro = false;
244 if ( isset( $item['is_pro'] ) && $item['is_pro'] ) {
245 $is_pro = true;
246 }
247
248 return (bool) apply_filters( 'advanced_import_is_pro', $is_pro, $item );
249 }
250
251 /**
252 * Return Template Button
253 *
254 * @since 1.0.8
255 * @param array $item current array of demo list.
256 * @return string
257 */
258 public function template_button( $item ) {
259 if ( $this->is_template_available( $item ) ) {
260 $button = '<a class="button ai-demo-import ai-item-import is-button is-default is-primary is-large button-primary" href="#" aria-label="' . esc_attr__( 'Import', 'advanced-import' ) . '"';
261
262 if ( isset( $item['theme']['slug'] ) && advanced_import_get_current_theme_slug() !== $item['theme']['slug'] ) {
263 $button .= ' data-theme="' . esc_attr( wp_json_encode( $item['theme'] ) ) . '"';
264 }
265 if ( isset( $item['plugins'] ) && is_array( $item['plugins'] ) ) {
266 $button .= ' data-plugins="' . esc_attr( wp_json_encode( $item['plugins'] ) ) . '"';
267 }
268
269 $button .= '><span class="dashicons dashicons-download"></span>' . esc_html__( 'Import', 'advanced-import' ) . '</a>';
270 } else {
271 $button = '<a class="button is-button is-default is-primary is-large button-primary"';
272 $button .= ' href="' . esc_url( isset( $item['pro_url'] ) ? $item['pro_url'] : '#' ) . '"';
273 $button .= ' target="_blank"';
274 $button .= ' aria-label="' . esc_attr__( 'View Pro', 'advanced-import' ) . '">';
275 $button .= '<span class="dashicons dashicons-awards"></span>' . esc_html__( 'View Pro', 'advanced-import' ) . '</a>';
276 }
277
278 $render_button = apply_filters( 'advanced_import_template_import_button', $button, $item );
279 return $render_button;
280 }
281
282 /**
283 * Enquee styles
284 *
285 * @since 1.4.6
286 * @return void
287 */
288 public function wp_enqueue_styles() {
289 $asset = require ADVANCED_IMPORT_PATH . 'build/index.asset.php';
290 wp_enqueue_style( $this->plugin_name, ADVANCED_IMPORT_URL . 'build/index.css', array( 'wp-admin', 'dashicons' ), $asset['version'], 'all' );
291 wp_enqueue_media();
292 }
293
294 /**
295 * Enquee scripts
296 *
297 * @since 1.4.6
298 * @return void
299 */
300 public function wp_enqueue_scripts() {
301 $asset = require ADVANCED_IMPORT_PATH . 'build/index.asset.php';
302
303 wp_enqueue_script(
304 'isotope',
305 ADVANCED_IMPORT_URL . '/assets/library/isotope/isotope.pkgd' . ADVANCED_IMPORT_SCRIPT_PREFIX . '.js',
306 array( 'jquery' ),
307 '3.0.6',
308 true
309 );
310
311 wp_enqueue_script(
312 'sweetalert2',
313 ADVANCED_IMPORT_URL . '/assets/library/sweetalert2/sweetalert2.all' . ADVANCED_IMPORT_SCRIPT_PREFIX . '.js',
314 array( 'jquery' ),
315 '3.0.6',
316 true
317 );
318
319 wp_enqueue_script( $this->plugin_name, ADVANCED_IMPORT_URL . 'build/index.js', array_merge( $asset['dependencies'], array( 'jquery' ,'masonry') ), $asset['version'], true );
320 wp_localize_script(
321 $this->plugin_name,
322 'advanced_import_object',
323 array(
324 'ajaxurl' => admin_url( 'admin-ajax.php' ),
325 'wpnonce' => wp_create_nonce( 'advanced-import' ),
326 'text' => array(
327 'failed' => esc_html__( 'Failed', 'advanced-import' ),
328 'error' => esc_html__( 'Error', 'advanced-import' ),
329 'skip' => esc_html__( 'Skipping', 'advanced-import' ),
330 'confirmImport' => array(
331 'title' => esc_html__( 'Advanced Import! Just a step away', 'advanced-import' ),
332 'html' => sprintf(
333 /* translators: 1: message 1, 2: message 2., 3: message 3., 4: message 4. */
334 __( 'Importing demo data is the easiest way to setup your theme. It will allow you to quickly edit everything instead of creating content from scratch. Also, read following points before importing the demo: %1$s %2$s %3$s %4$s', 'advanced-import' ),
335 '<ol><li class="warning">' . __( 'It is highly recommended to import demo on fresh WordPress installation to exactly replicate the theme demo. If no important data on your site, you can reset it from Reset Wizard at the top', 'advanced-import' ) . '</li>',
336 '<li>' . __( 'No existing posts, pages, categories, images, custom post types or any other data will be deleted or modified.', 'advanced-import' ) . '</li>',
337 '<li>' . __( 'It will install the plugins required for demo and activate them. Also posts, pages, images, widgets, & other data will get imported.', 'advanced-import' ) . '</li>',
338 '<li class="ai-theme-info">' . __( 'The demo will install following theme:', 'advanced-import' ) . 'ai_replace_theme' . '</li>' .
339 '<li class="ai-plugin-info">' . __( 'The demo will install following plugin/s:', 'advanced-import' ) . 'ai_replace_plugins' . '</li>' .
340 '<li>' . __( 'Please click on the Import button and wait, it will take some time to import the data.', 'advanced-import' ) . '</li></ol>'
341 ),
342 'confirmButtonText' => esc_html__( 'Yes, Import Demo!', 'advanced-import' ),
343 'cancelButtonText' => esc_html__( 'Cancel', 'advanced-import' ),
344 'no_plugins' => esc_html__( 'No plugins will be installed.', 'advanced-import' ),
345 ),
346 'confirmReset' => array(
347 'title' => esc_html__( 'Are you sure?', 'advanced-import' ),
348 'text' => __( "You won't be able to revert this!", 'advanced-import' ),
349 'confirmButtonText' => esc_html__( 'Yes, Reset', 'advanced-import' ),
350 'cancelButtonText' => esc_html__( 'Cancel', 'advanced-import' ),
351 'resetting' => esc_html__( 'Resetting! Starting WordPress in Default Mode.', 'advanced-import' ),
352 ),
353 'resetSuccess' => array(
354 'title' => esc_html__( 'Reset Successful', 'advanced-import' ),
355 'confirmButtonText' => esc_html__( 'Ok', 'advanced-import' ),
356 ),
357 'failedImport' => array(
358 'code' => __( 'Error Code:', 'advanced-import' ),
359 'text' => __( 'Contact theme author or try again', 'advanced-import' ),
360 'pluginError' => __( 'Your WordPress could not install the plugin correctly. You have to install the following plugin manually:', 'advanced-import' ),
361 'plugin' => __( 'Plugin:', 'advanced-import' ),
362 'slug' => __( 'Slug:', 'advanced-import' ),
363 ),
364 'successImport' => array(
365 'confirmButtonText' => esc_html__( 'Visit My Site', 'advanced-import' ),
366 'cancelButtonText' => esc_html__( 'Okay', 'advanced-import' ),
367 ),
368 ),
369 )
370 );
371 }
372
373 /**
374 * Register the stylesheets for the admin area.
375 *
376 * @since 1.0.8
377 * @param string $hook_suffix current hook.
378 * @return void
379 */
380 public function enqueue_styles( $hook_suffix ) {
381 if ( ! is_array( $this->hook_suffix ) || ! in_array( $hook_suffix, $this->hook_suffix ) ) {
382 return;
383 }
384 $this->wp_enqueue_styles();
385 }
386
387 /**
388 * Register the JavaScript for the admin area.
389 *
390 * @since 1.0.8
391 * @param string $hook_suffix current hook.
392 * @return void
393 */
394 public function enqueue_scripts( $hook_suffix ) {
395 if ( ! is_array( $this->hook_suffix ) || ! in_array( $hook_suffix, $this->hook_suffix ) ) {
396 return;
397 }
398 $this->wp_enqueue_scripts();
399 }
400
401 /**
402 * Adding new mime types.
403 *
404 * @access public
405 * @since 1.0.0
406 * @param array $mimes existing mime types.
407 * @return array
408 */
409 public function mime_types( $mimes = array() ) {
410 $add_mimes = array(
411 'json' => 'application/json',
412 );
413
414 return array_merge( $mimes, $add_mimes );
415 }
416
417 /**
418 * Determine if the user already has theme content installed.
419 *
420 * @access public
421 */
422 public function is_possible_upgrade() {
423 return false;
424 }
425
426 /**
427 * Validate that unzipped content contains only JSON files and an uploads folder.
428 *
429 * @access private
430 * @param array|null $dirlist Directory listing from WP_Filesystem.
431 * @return bool True if valid, false otherwise.
432 */
433 private function validate_unzipped_content( $dirlist ) {
434 foreach ( (array) $dirlist as $filename => $fileinfo ) {
435 if ( $fileinfo['type'] == 'd' ) {
436 if ( $filename == 'uploads' ) {
437 continue;
438 }
439 return false;
440 } else {
441 $filetype = wp_check_filetype( $filename, $this->mime_types() );
442 if ( empty( $filetype['ext'] ) || $filetype['ext'] != 'json' ) {
443 return false;
444 }
445 }
446 }
447 return true;
448 }
449
450 /**
451 * Add admin menus
452 *
453 * @access public
454 */
455 public function import_menu() {
456 $this->hook_suffix[] = add_theme_page( esc_html__( 'Demo Import ', 'advanced-import' ), esc_html__( 'Demo Import', 'advanced-import' ), 'manage_options', 'advanced-import', array( $this, 'demo_import_screen' ) );
457 $this->hook_suffix[] = add_management_page( esc_html__( 'Advanced Import', 'advanced-import' ), esc_html__( 'Advanced Import', 'advanced-import' ), 'manage_options', 'advanced-import-tool', array( $this, 'demo_import_screen' ) );
458 $this->hook_suffix = apply_filters( 'advanced_import_menu_hook_suffix', $this->hook_suffix );
459 }
460
461 /**
462 * Show the setup
463 *
464 * @access public
465 * @return void
466 */
467 public function demo_import_screen() {
468 do_action( 'advanced_import_before_demo_import_screen' );
469
470 $this->step = isset( $_GET['step'] ) ? sanitize_key( wp_unslash( $_GET['step'] ) ) : current( array_keys( $this->steps ) );
471
472 echo '<div class="ai-body">';
473
474 $this->get_header();
475
476 echo '<div class="ai-content">';
477 echo '<div class="ai-content-blocker hidden">';
478 echo '<div class="ai-notification-title"><p>' . esc_html__( 'Processing... Please do not refresh this page or do not go to other url!', 'advanced-import' ) . '</p></div>';
479 echo '<div id="ai-demo-popup"></div>';
480 echo '</div>';
481 $this->init_demo_import();
482 echo '</div>';
483 echo '</div>';/*ai-body*/
484 do_action( 'advanced_import_after_demo_import_screen' );
485 }
486
487 /**
488 * Get header of setup
489 *
490 * @access public
491 * @return void
492 */
493 public function get_header() {
494 global $pagenow;
495
496 $welcome_msg = "<div class='ai-header'>";
497 /* translators: 1: current theme */
498 $welcome_msg .= '<h1>' . sprintf( esc_html__( 'Welcome to the Advanced Import for %s.', 'advanced-import' ), wp_get_theme() ) . '</h1>';
499 if ( $pagenow != 'tools.php' ) {
500 /* translators: 1: current theme */
501 $welcome_msg .= ' <p>' . sprintf( esc_html__( 'Thank you for choosing the %s theme. This quick demo import setup will help you configure your new website like theme demo. It will install the required WordPress plugins, default content and tell you a little about Help &amp; Support options. It should only take less than 5 minutes.', 'advanced-import' ), wp_get_theme() ) . '</p>';
502 }
503 $welcome_msg .= '</div>';
504 echo wp_kses_post( apply_filters( 'advanced_import_welcome_message', $welcome_msg ) );
505
506 if ( get_theme_mod( 'advanced_import_setup_complete', false ) && $pagenow != 'tools.php' ) {
507 ?>
508 <p><?php esc_html_e( 'It looks like you have already run the demo import for this theme.', 'advanced-import' ); ?></p>
509 <?php
510 }
511 }
512
513 /**
514 * Handle the demo content upload and called to process
515 * Ajax callback
516 *
517 * @return void
518 */
519 public function upload_zip() {
520 if ( isset( $_FILES['ai-upload-zip-archive']['name'] ) && ! empty( $_FILES['ai-upload-zip-archive']['name'] ) ) {
521 /*check for security*/
522 if ( ! current_user_can( 'upload_files' ) ) {
523 wp_send_json_error(
524 array(
525 'message' => esc_html__( 'Sorry, you are not allowed to install demo on this site.', 'advanced-import' ),
526 )
527 );
528 }
529 check_admin_referer( 'advanced-import' );
530
531 /*file process*/
532 require_once ABSPATH . 'wp-admin/includes/file.php';
533 WP_Filesystem();
534 global $wp_filesystem;
535 $wp_filesystem->rmdir( ADVANCED_IMPORT_TEMP, true );
536 $upload_zip_archive = $_FILES['ai-upload-zip-archive']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
537 $unzipfile = unzip_file( $upload_zip_archive['tmp_name'], ADVANCED_IMPORT_TEMP );
538 if ( is_wp_error( $unzipfile ) ) {
539 wp_send_json_error(
540 array(
541 'message' => esc_html__( 'Error on unzipping, Please try again', 'advanced-import' ),
542 )
543 );
544 }
545 /*(check) Zip should contain json file and uploads folder only*/
546 $dirlist = $wp_filesystem->dirlist( ADVANCED_IMPORT_TEMP );
547 if ( ! $this->validate_unzipped_content( $dirlist ) ) {
548 $wp_filesystem->rmdir( ADVANCED_IMPORT_TEMP, true );
549 wp_send_json_error(
550 array(
551 'message' => esc_html__( 'Invalid Zip File', 'advanced-import' ),
552 )
553 );
554 }
555 wp_send_json_success(
556 array(
557 'message' => esc_html__( 'Success', 'advanced-import' ),
558 )
559 );
560 }
561 wp_send_json_error(
562 array(
563 'message' => esc_html__( 'No Zip File Found', 'advanced-import' ),
564 )
565 );
566 }
567
568 /**
569 * Download Zip file/ Move it to temp import folder
570 * Ajax callback
571 *
572 * @return mixed
573 */
574 public function demo_download_and_unzip() {
575
576 /*check for security*/
577 if ( ! current_user_can( 'upload_files' ) ) {
578 wp_send_json_error(
579 array(
580 'message' => esc_html__( 'Sorry, you are not allowed to install demo on this site.', 'advanced-import' ),
581 )
582 );
583 }
584 check_admin_referer( 'advanced-import' );
585
586 /*get file and what should do*/
587 $demo_file = isset( $_POST['demo_file'] )
588 ? ( is_array( $_POST['demo_file'] )
589 ? array_map( 'sanitize_text_field', wp_unslash( $_POST['demo_file'] ) )
590 : sanitize_text_field( wp_unslash( $_POST['demo_file'] ) ) )
591 : '';
592 $demo_file_type = isset( $_POST['demo_file_type'] ) ? sanitize_text_field( wp_unslash( $_POST['demo_file_type'] ) ) : '';
593
594 /*from file*/
595 if ( $demo_file_type == 'file' ) {
596 require_once ABSPATH . 'wp-admin/includes/file.php';
597 WP_Filesystem();
598 global $wp_filesystem;
599 $wp_filesystem->rmdir( ADVANCED_IMPORT_TEMP, true );
600 $unzipfile = unzip_file( $demo_file, ADVANCED_IMPORT_TEMP );
601 if ( is_wp_error( $unzipfile ) ) {
602 wp_send_json_error(
603 array(
604 'message' => esc_html__( 'Error on unzipping, Please try again', 'advanced-import' ),
605 )
606 );
607 }
608 /*(check) Zip should contain json file and uploads folder only*/
609 $dirlist = $wp_filesystem->dirlist( ADVANCED_IMPORT_TEMP );
610 if ( ! $this->validate_unzipped_content( $dirlist ) ) {
611 $wp_filesystem->rmdir( ADVANCED_IMPORT_TEMP, true );
612 wp_send_json_error(
613 array(
614 'message' => esc_html__( 'Invalid Zip File', 'advanced-import' ),
615 )
616 );
617 }
618 wp_send_json_success(
619 array(
620 'message' => esc_html__( 'Success', 'advanced-import' ),
621 )
622 );
623 } elseif ( $demo_file_type == 'url' ) {
624
625 if ( is_array( $demo_file ) ) {
626 wp_send_json_error(
627 array(
628 'error' => 1,
629 'message' => esc_html__( 'Invalid demo file URL.', 'advanced-import' ),
630 )
631 );
632 }
633
634 $demo_file = esc_url_raw( $demo_file, array( 'http', 'https' ) );
635 if ( empty( $demo_file ) || ! wp_http_validate_url( $demo_file ) ) {
636 wp_send_json_error(
637 array(
638 'error' => 1,
639 'message' => esc_html__( 'Invalid demo file URL.', 'advanced-import' ),
640 )
641 );
642 }
643
644 $demo_file_host = wp_parse_url( $demo_file, PHP_URL_HOST );
645 if ( empty( $demo_file_host ) ) {
646 wp_send_json_error(
647 array(
648 'error' => 1,
649 'message' => esc_html__( 'Invalid demo file URL host.', 'advanced-import' ),
650 )
651 );
652 }
653
654 $allowed_hosts = (array) apply_filters( 'advanced_import_allowed_demo_hosts', array() );
655 if ( ! empty( $allowed_hosts ) ) {
656 $allowed_hosts = array_map( 'strtolower', array_map( 'trim', $allowed_hosts ) );
657 if ( ! in_array( strtolower( $demo_file_host ), $allowed_hosts, true ) ) {
658 wp_send_json_error(
659 array(
660 'error' => 1,
661 'message' => esc_html__( 'Demo URL host is not allowed.', 'advanced-import' ),
662 )
663 );
664 }
665 }
666
667 $max_size = (int) apply_filters( 'advanced_import_attachment_size_limit', 0 );
668 $request_args = array(
669 'timeout' => 30,
670 'redirection' => 3,
671 'reject_unsafe_urls' => true,
672 );
673 if ( ! empty( $max_size ) ) {
674 $request_args['limit_response_size'] = $max_size;
675 }
676
677 /*finally fetch the file from remote*/
678 $response = wp_safe_remote_get( $demo_file, $request_args );
679
680 if ( ! is_wp_error( $response ) ) {
681 $response_code = (int) wp_remote_retrieve_response_code( $response );
682 $response_body = wp_remote_retrieve_body( $response );
683 if ( 200 !== $response_code || empty( $response_body ) ) {
684 wp_send_json_error(
685 array(
686 'error' => 1,
687 'message' => esc_html__( 'Remote file could not be downloaded.', 'advanced-import' ),
688 )
689 );
690 }
691
692 require_once ABSPATH . 'wp-admin/includes/file.php';
693 WP_Filesystem();
694 global $wp_filesystem;
695 $file_permission = defined( 'FS_CHMOD_DIR' ) ? FS_CHMOD_DIR : 0755;
696 if ( ! file_exists( ADVANCED_IMPORT_TEMP_ZIP ) ) {
697 $wp_filesystem->mkdir( ADVANCED_IMPORT_TEMP_ZIP, $file_permission, true );
698 }
699 $temp_import_zip = trailingslashit( ADVANCED_IMPORT_TEMP_ZIP ) . 'temp-import.zip';
700 $file_mode = defined( 'FS_CHMOD_FILE' ) ? FS_CHMOD_FILE : 0644;
701 $wp_filesystem->put_contents( $temp_import_zip, $response_body, $file_mode );
702
703 } else {
704 /*required to download file failed.*/
705 wp_send_json_error(
706 array(
707 'error' => 1,
708 'message' => esc_html__( 'Remote server did not respond, Contact to Theme Author', 'advanced-import' ),
709 )
710 );
711 }
712
713 $file_size = filesize( $temp_import_zip );
714
715 /*if file size is 0*/
716 if ( 0 == $file_size ) {
717 $wp_filesystem->rmdir( ADVANCED_IMPORT_TEMP_ZIP, true );
718 wp_send_json_error(
719 array(
720 'error' => 1,
721 'message' => esc_html__( 'Zero size file downloaded, Contact to Theme Author', 'advanced-import' ),
722 )
723 );
724 }
725
726 /*if file is too large*/
727 if ( ! empty( $max_size ) && $file_size > $max_size ) {
728 $wp_filesystem->rmdir( ADVANCED_IMPORT_TEMP_ZIP, true );
729 wp_send_json_error(
730 array(
731 'error' => 1,
732 /* translators: %s: maximum file size */
733 'message' => sprintf( esc_html__( 'Remote file is too large, limit is %s', 'advanced-import' ), size_format( $max_size ) ),
734 )
735 );
736 }
737
738 /*if we are here then unzip file*/
739 $unzipfile = unzip_file( $temp_import_zip, ADVANCED_IMPORT_TEMP );
740 if ( is_wp_error( $unzipfile ) ) {
741 wp_send_json_error(
742 array(
743 'error' => 1,
744 'message' => esc_html__( 'Error on unzipping, Please try again', 'advanced-import' ),
745 )
746 );
747 }
748 $wp_filesystem->rmdir( ADVANCED_IMPORT_TEMP_ZIP, true );
749
750 /*(check) Zip should contain json file and uploads folder only*/
751 $dirlist = $wp_filesystem->dirlist( ADVANCED_IMPORT_TEMP );
752 if ( ! $this->validate_unzipped_content( $dirlist ) ) {
753 $wp_filesystem->rmdir( ADVANCED_IMPORT_TEMP, true );
754 wp_send_json_error(
755 array(
756 'message' => esc_html__( 'Invalid Zip File', 'advanced-import' ),
757 )
758 );
759 }
760 wp_send_json_success(
761 array(
762 'message' => esc_html__( 'Success', 'advanced-import' ),
763 )
764 );
765
766 } else {
767 wp_send_json_error(
768 array(
769 'error' => 1,
770 'message' => esc_html__( 'File not allowed', 'advanced-import' ),
771 )
772 );
773 }
774 }
775
776 /**
777 * List Demo List
778 *
779 * @return void
780 */
781 public function demo_list( $demo_lists, $total_demo, $zip_form = true ) {
782 ?>
783 <div class="ai-filter-header">
784 <div class="ai-filter-tabs">
785 <ul class="ai-types ai-filter-group" data-filter-group="secondary">
786 <li class="ai-filter-btn-active ai-filter-btn ai-type-filter" data-filter="*">
787 <?php esc_html_e( 'All', 'advanced-import' ); ?>
788 <span class="ai-count"></span>
789 </li>
790 <?php
791 $types = array_column( $demo_lists, 'type' );
792 $unique_types = array_unique( $types );
793 foreach ( $unique_types as $cat_index => $single_type ) {
794 ?>
795 <li class="ai-filter-btn ai-type-filter" data-filter=".<?php echo esc_attr( strtolower( $single_type ) ); ?>">
796 <?php echo esc_html( ucfirst( $single_type ) ); ?>
797 <span class="ai-count"></span>
798
799 </li>
800 <?php
801 }
802 ?>
803 </ul>
804 <div class="ai-search-control">
805 <input id="ai-filter-search-input" class="ai-search-filter" type="text" placeholder="<?php esc_attr_e( 'Search...', 'advanced-import' ); ?>">
806 </div>
807 <?php
808 if ( $zip_form ) {
809 ?>
810 <ul class="ai-form-type">
811 <li class="ai-form-file-import">
812 <?php esc_html_e( 'Upload zip', 'advanced-import' ); ?>
813 </li>
814 </ul>
815 <?php
816 }
817 ?>
818 </div>
819 </div>
820 <div class="ai-filter-content" id="ai-filter-content">
821 <div class="ai-actions ai-sidebar">
822 <div class="ai-import-available-categories">
823 <h3><?php esc_html_e( 'Categories', 'advanced-import' ); ?></h3>
824 <div class="ai-import-fp-wrap">
825 <ul class="ai-import-fp-lists ai-filter-group" data-filter-group="pricing">
826 <li class="ai-fp-filter ai-filter-btn ai-filter-btn-active" data-filter="*">All</li>
827 <li class="ai-fp-filter ai-filter-btn" data-filter=".ai-fp-filter-free">Free</li>
828 <li class="ai-fp-filter ai-filter-btn" data-filter=".ai-fp-filter-pro">Pro</li>
829 </ul>
830 </div>
831 <ul class="ai-import-available-categories-lists ai-filter-group" data-filter-group="primary">
832 <li class="ai-filter-btn-active ai-filter-btn" data-filter="*">
833 <?php esc_html_e( 'All Categories', 'advanced-import' ); ?>
834 <span class="ai-count"></span>
835 </li>
836 <?php
837 $categories = array_column( $demo_lists, 'categories' );
838 $unique_categories = array();
839 if ( is_array( $categories ) && ! empty( $categories ) ) {
840 foreach ( $categories as $demo_index => $demo_cats ) {
841 foreach ( $demo_cats as $cat_index => $single_cat ) {
842 if ( in_array( $single_cat, $unique_categories ) ) {
843 continue;
844 }
845 $unique_categories[] = $single_cat;
846 ?>
847 <li class="ai-filter-btn" data-filter=".<?php echo esc_attr( strtolower( $single_cat ) ); ?>">
848 <?php echo esc_html( ucfirst( $single_cat ) ); ?>
849 <span class="ai-count"></span>
850 </li>
851 <?php
852 }
853 }
854 }
855 ?>
856 </ul>
857 </div>
858
859 </div>
860 <div class="ai-filter-content-wrapper">
861 <?php
862 foreach ( $demo_lists as $key => $demo_list ) {
863
864 /*Check for required fields*/
865 if ( ! isset( $demo_list['title'] ) || ! isset( $demo_list['screenshot_url'] ) || ! isset( $demo_list['demo_url'] ) ) {
866 continue;
867 }
868
869 $template_url = isset( $demo_list['template_url'] ) ? $demo_list['template_url'] : '';
870 if ( is_array( $template_url ) ) {
871 $data_template = 'data-template_url="' . esc_attr( wp_json_encode( $template_url ) ) . '"';
872 $data_template_type = 'data-template_type="array"';
873 } elseif ( $template_url ) {
874 $data_template = 'data-template_url="' . esc_attr( $template_url ) . '"';
875 if ( is_file( $template_url ) && filesize( $template_url ) > 0 ) {
876 $data_template_type = 'data-template_type="file"';
877 } else {
878 $data_template_type = 'data-template_type="url"';
879 }
880 } else {
881 $data_template = 'data-template_url="' . esc_attr( wp_json_encode( $template_url ) ) . '"';
882 $data_template_type = 'data-template_type="array"';
883 }
884 ?>
885 <div aria-label="<?php echo esc_attr( $demo_list['title'] ); ?>"
886 class="ai-item
887 <?php
888 echo isset( $demo_list['categories'] ) ? esc_attr( implode( ' ', $demo_list['categories'] ) ) : '';
889 echo isset( $demo_list['type'] ) ? ' ' . esc_attr( $demo_list['type'] ) : '';
890 echo $this->is_pro( $demo_list ) ? ' ai-fp-filter-pro' : ' ai-fp-filter-free';
891 echo $this->is_template_available( $demo_list ) ? '' : ' ai-pro-item'
892 ?>
893 "
894 <?php
895 if ( $this->is_template_available( $demo_list ) ) {
896 echo $data_template . ' ' . $data_template_type; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
897 }
898 ?>
899 >
900 <?php
901 wp_nonce_field( 'advanced-import' );
902 ?>
903 <div class="ai-item-preview">
904 <div class="ai-item-screenshot">
905 <img src="<?php echo esc_url( $demo_list['screenshot_url'] ); ?>">
906 </div>
907 <h4 class="ai-author-info"><?php esc_html_e( 'Author: ', 'advanced-import' ); ?><?php echo esc_html( isset( $demo_list['author'] ) ? $demo_list['author'] : wp_get_theme()->get( 'Author' ) ); ?></h4>
908 <div class="ai-details">
909 <?php
910 if ( isset( $demo_list['theme']['title'] ) ) {
911 echo esc_html( $demo_list['theme']['title'] );
912 } else {
913 esc_html_e( 'Details', 'advanced-import' );
914 }
915 ?>
916 </div>
917 <?php
918 if ( $this->is_pro( $demo_list ) ) {
919 ?>
920 <span class="ai-premium-label"><?php esc_html_e( 'Premium', 'advanced-import' ); ?></span>
921 <?php
922 }
923 ?>
924 </div>
925 <div class="ai-item-footer">
926 <div class="ai-item-footer_meta">
927 <h3 class="theme-name"><?php echo esc_html( $demo_list['title'] ); ?></h3>
928 <div class="ai-item-footer-actions">
929 <a class="button ai-item-demo-link" href="<?php echo esc_url( $demo_list['demo_url'] ); ?>" target="_blank">
930 <span class="dashicons dashicons-visibility"></span><?php esc_html_e( 'Preview', 'advanced-import' ); ?>
931 </a>
932 <?php
933 echo $this->template_button( $demo_list ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
934 ?>
935 </div>
936 <?php
937 $keywords = isset( $demo_list['keywords'] ) ? $demo_list['keywords'] : array();
938 if ( ! empty( $keywords ) ) {
939 echo '<ul class="ai-keywords hidden">';
940 foreach ( $keywords as $cat_index => $single_keywords ) {
941 ?>
942 <li class="<?php echo esc_attr( strtolower( $single_keywords ) ); ?>"><?php echo esc_html( ucfirst( $single_keywords ) ); ?></li>
943 <?php
944 }
945 echo '</ul>';
946 }
947 ?>
948
949 </div>
950
951 </div>
952 </div>
953 <?php
954 }
955 ?>
956 </div>
957 </div>
958 <?php
959 }
960
961 /**
962 * List Demo Form
963 *
964 * @return void
965 */
966 public function demo_import_form( $total_demo = 0 ) {
967 ?>
968 <div class="ai-form <?php echo $total_demo > 0 ? 'hidden' : ''; ?>">
969 <form action="" method="post" enctype="multipart/form-data" id="ai-upload-zip-form">
970 <h3 class="media-title"><?php esc_html_e( 'Upload a zip file containing demo content', 'advanced-import' ); ?> </h3>
971 <div class="input-file"><input type="file" name="ai-upload-zip-archive" id="ai-upload-zip-archive" size="50" /></div>
972 <p>
973 <?php
974 wp_nonce_field( 'advanced-import' );
975 /* translators: %s: maximum upload file size */
976 echo esc_html( sprintf( __( 'Maximum upload file size: %s', 'advanced-import' ), size_format( wp_max_upload_size() ) ) );
977 ?>
978 </p>
979 <div id='ai-empty-file' class="error hidden">
980 <p>
981 <?php esc_html_e( 'Select File and Try Again!', 'advanced-import' ); ?>
982 </p>
983 </div>
984 <p class="ai-form-import-actions step">
985 <button class="button-primary button button-large button-upload-demo" type="submit">
986 <?php esc_html_e( 'Upload Demo Zip', 'advanced-import' ); ?>
987 </button>
988 <a href="<?php echo esc_url( wp_get_referer() && ! strpos( wp_get_referer(), 'update.php' ) ? wp_get_referer() : admin_url( '' ) ); ?>" class="button button-large">
989 <?php esc_html_e( 'Not right now', 'advanced-import' ); ?>
990 </a>
991 </p>
992 <div id='ai-ajax-install-result'></div>
993 </form>
994 </div>
995 <?php
996 }
997
998 /**
999 * 1st step of demo import view
1000 * Upload Zip file
1001 * Demo List
1002 */
1003 public function init_demo_import() {
1004
1005 global $pagenow;
1006 $total_demo = 0;
1007 if ( $pagenow != 'tools.php' ) {
1008 $this->demo_lists = apply_filters( 'advanced_import_demo_lists', array() );
1009 $this->is_pro_active = apply_filters( 'advanced_import_is_pro_active', $this->is_pro_active );
1010 $demo_lists = $this->demo_lists;
1011
1012 $total_demo = is_array( $demo_lists ) ? count( $demo_lists ) : 0;
1013 if ( $total_demo >= 1 ) {
1014 $this->demo_list( $demo_lists, $total_demo );
1015 }
1016 }
1017
1018 $this->demo_import_form( $total_demo );
1019 }
1020
1021 /**
1022 * 1.5 step Before Plugin Installation step View
1023 * return void || boolean
1024 */
1025 public function theme_screen() {
1026
1027 /*check for security*/
1028 check_admin_referer( 'advanced-import' );
1029 $theme_info_raw = isset( $_POST['themeInfo'] ) ? wp_unslash( $_POST['themeInfo'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1030 if ( is_array( $theme_info_raw ) ) {
1031 $theme_info = $theme_info_raw;
1032 } elseif ( is_string( $theme_info_raw ) ) {
1033 $theme_info = (array) json_decode( $theme_info_raw, true );
1034 if ( ! is_array( $theme_info ) ) {
1035 $theme_info = array();
1036 }
1037 } else {
1038 $theme_info = array();
1039 }
1040 $theme_info = array_map( 'sanitize_text_field', $theme_info );
1041 if ( ! current_user_can( 'install_themes' ) || ! $theme_info ) {
1042 wp_send_json_error(
1043 array(
1044 'message' => esc_html__( 'Sorry, you are not allowed to install demo on this site.', 'advanced-import' ),
1045 )
1046 );
1047 }
1048
1049 /*for safety: delete_transient();*/
1050 $this->reset_transient();
1051
1052 do_action( 'advanced_import_before_theme_screen' );
1053 ?>
1054 <div class="ai-notification-title">
1055 <p><?php
1056 /* translators: %s: theme name */
1057 printf( esc_html__( 'We are installing the %s theme...', 'advanced-import' ), esc_html( $theme_info['title'] ) );
1058 ?></p>
1059 </div>
1060
1061 <?php
1062 do_action( 'advanced_import_after_theme_screen' );
1063 exit;
1064 }
1065
1066 /*
1067 callback function for wp_ajax_install_theme
1068 * Install and activate theme
1069 * */
1070 function install_theme() {
1071
1072 /*check for security*/
1073 check_admin_referer( 'advanced-import' );
1074 $theme_info_raw = isset( $_POST['themeInfo'] ) ? wp_unslash( $_POST['themeInfo'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1075 if ( is_array( $theme_info_raw ) ) {
1076 $theme_info = $theme_info_raw;
1077 } elseif ( is_string( $theme_info_raw ) ) {
1078 $theme_info = (array) json_decode( $theme_info_raw, true );
1079 if ( ! is_array( $theme_info ) ) {
1080 $theme_info = array();
1081 }
1082 } else {
1083 $theme_info = array();
1084 }
1085 $theme_info = array_map( 'sanitize_text_field', $theme_info );
1086 if ( ! current_user_can( 'install_themes' ) || ! $theme_info ) {
1087 wp_send_json_error(
1088 array(
1089 'message' => esc_html__( 'Sorry, you are not allowed to install demo on this site.', 'advanced-import' ),
1090 )
1091 );
1092 }
1093
1094 $theme_info['name'] = $theme_info['title'];
1095 $result = advanced_import_install_theme( $theme_info );
1096
1097 if ( ! $result['success'] ) {
1098 $response['errorCode'] = $result['code'];
1099 $response['errorMessage'] = $result['message'];
1100
1101 wp_send_json_error( $result );
1102 }
1103 wp_send_json_success( $result );
1104 }
1105
1106 /**
1107 * 2nd step Plugin Installation step View
1108 * return void || boolean
1109 */
1110 public function plugin_screen() {
1111
1112 /*check for security*/
1113 if ( ! current_user_can( 'upload_files' ) ) {
1114 wp_send_json_error(
1115 array(
1116 'message' => esc_html__( 'Sorry, you are not allowed to install demo on this site.', 'advanced-import' ),
1117 )
1118 );
1119 }
1120
1121 check_admin_referer( 'advanced-import' );
1122
1123 /*for safety: delete_transient();*/
1124 $this->reset_transient();
1125
1126 do_action( 'advanced_import_before_plugin_screen' );
1127 ?>
1128 <div class="ai-notification-title">
1129 <p><?php esc_html_e( 'Your website needs a few essential plugins. We are installing them...', 'advanced-import' ); ?></p>
1130 </div>
1131 <ul class="ai-plugins-wrap hidden">
1132 <?php
1133 $recommended_plugins_raw = isset( $_POST['recommendedPlugins'] ) ? wp_unslash( $_POST['recommendedPlugins'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1134 if ( is_array( $recommended_plugins_raw ) ) {
1135 $recommended_plugins = $recommended_plugins_raw;
1136 } elseif ( is_string( $recommended_plugins_raw ) ) {
1137 $recommended_plugins = (array) json_decode( $recommended_plugins_raw, true );
1138 if ( ! is_array( $recommended_plugins ) ) {
1139 $recommended_plugins = array();
1140 }
1141 } else {
1142 $recommended_plugins = array();
1143 }
1144 $recommended_plugins = array_map( function( $plugin ) {
1145 return is_array( $plugin ) ? array_map( 'sanitize_text_field', $plugin ) : sanitize_text_field( (string) $plugin );
1146 }, $recommended_plugins );
1147 if ( count( $recommended_plugins ) ) {
1148 foreach ( $recommended_plugins as $index => $recommended_plugin ) {
1149 ?>
1150 <li
1151 data-name="<?php echo esc_attr( isset( $recommended_plugin['name'] ) ? $recommended_plugin['name'] : '' ); ?>"
1152 data-slug="<?php echo esc_attr( $recommended_plugin['slug'] ); ?>"
1153 data-main_file ="<?php echo esc_attr( isset( $recommended_plugin['main_file'] ) ? $recommended_plugin['main_file'] : $recommended_plugin['slug'] . '.php' ); ?>"
1154 data-source="<?php echo esc_url( isset( $recommended_plugin['source'] ) ? $recommended_plugin['source'] : '' ); ?>" >
1155 <?php echo esc_html( isset( $recommended_plugin['name'] ) ? $recommended_plugin['name'] : '' ); ?>
1156 </li>
1157 <?php
1158 }
1159 } else {
1160 ?>
1161 <li id="ai-no-recommended-plugins"><?php esc_html_e( 'No Recommended Plugins', 'advanced-import' ); ?></li>
1162 <?php
1163 }
1164 ?>
1165 </ul>
1166 <?php
1167 do_action( 'advanced_import_after_plugin_screen' );
1168 exit;
1169 }
1170
1171 /**
1172 * 3rd steps helper functions
1173 * Get json from json file
1174 *
1175 * @param string $file file url.
1176 * @return mixed
1177 */
1178 public function get_json_data_from_file( $file ) {
1179
1180 if ( get_transient( $file ) ) {
1181 return get_transient( $file );
1182 }
1183
1184 if ( $this->current_template_type == 'array' ) {
1185 $type = strtok( $file, '.' );
1186 if ( isset( $this->current_template_url[ $type ] ) ) {
1187 $template_url = esc_url_raw( $this->current_template_url[ $type ], array( 'http', 'https' ) );
1188 if ( empty( $template_url ) || ! wp_http_validate_url( $template_url ) ) {
1189 return array();
1190 }
1191
1192 $request = wp_safe_remote_get(
1193 $template_url,
1194 array(
1195 'timeout' => 30,
1196 'redirection' => 3,
1197 'reject_unsafe_urls' => true,
1198 )
1199 );
1200 if ( is_wp_error( $request ) || 200 !== (int) wp_remote_retrieve_response_code( $request ) ) {
1201 return array();
1202 }
1203
1204 $response = wp_remote_retrieve_body( $request );
1205 if ( empty( $response ) ) {
1206 return array();
1207 }
1208
1209 $result = json_decode( $response, true );
1210 set_transient( $file, $result, 1000 );
1211 return $result;
1212 }
1213 return array();
1214 }
1215
1216 if ( is_file( ADVANCED_IMPORT_TEMP . basename( $file ) ) ) {
1217 require_once ABSPATH . 'wp-admin/includes/file.php';
1218 WP_Filesystem();
1219 global $wp_filesystem;
1220 $file_name = ADVANCED_IMPORT_TEMP . basename( $file );
1221 if ( file_exists( $file_name ) ) {
1222 $result = json_decode( $wp_filesystem->get_contents( $file_name ), true );
1223 set_transient( $file, $result, 1000 );
1224 return $result;
1225 }
1226 }
1227 return array();
1228 }
1229
1230 public function get_main_content_json() {
1231 return $this->get_json_data_from_file( 'content.json' );
1232 }
1233 public function get_widgets_json() {
1234 return $this->get_json_data_from_file( 'widgets.json' );
1235 }
1236
1237 public function get_theme_options_json() {
1238 return $this->get_json_data_from_file( 'options.json' );
1239 }
1240
1241 /*
1242 * return array
1243 */
1244 private function advanced_import_setup_content_steps() {
1245
1246 $total_content = 0;
1247
1248 $content = array();
1249
1250 /*check if there is files*/
1251 $content_data = $this->get_main_content_json();
1252 foreach ( $content_data as $post_type => $post_data ) {
1253 if ( count( $post_data ) ) {
1254 $total_content += count( $post_data );
1255 $first = current( $post_data );
1256 $post_type_title = ! empty( $first['type_title'] ) ? $first['type_title'] : ucwords( $post_type ) . 's';
1257 $content[ $post_type ] = array(
1258 'title' => $post_type_title,
1259 /* translators: %s: post type title */
1260 'description' => sprintf( esc_html__( 'This will create default %s as seen in the demo.', 'advanced-import' ), $post_type_title ),
1261 'pending' => esc_html__( 'Pending.', 'advanced-import' ),
1262 'installing' => esc_html__( 'Installing.', 'advanced-import' ),
1263 'success' => esc_html__( 'Success.', 'advanced-import' ),
1264 'install_callback' => array( $this, 'import_content_post_type_data' ),
1265 'checked' => $this->is_possible_upgrade() ? 0 : 1,
1266 // dont check if already have content installed.
1267 );
1268 }
1269 }
1270 /*
1271 array adjustment
1272 TODO : Remove it after adjustment on Advanced Import
1273 */
1274 /*Put post 3nd last*/
1275 $post = isset( $content['post'] ) ? $content['post'] : array();
1276 if ( $post ) {
1277 unset( $content['post'] );
1278 $content['post'] = $post;
1279 }
1280 /*Put page 2nd last*/
1281 $page = isset( $content['page'] ) ? $content['page'] : array();
1282 if ( $page ) {
1283 unset( $content['page'] );
1284 $content['page'] = $page;
1285
1286 }
1287 /*Put nav 1last*/
1288 $nav = isset( $content['nav_menu_item'] ) ? $content['nav_menu_item'] : array();
1289 if ( $nav ) {
1290 unset( $content['nav_menu_item'] );
1291 $content['nav_menu_item'] = $nav;
1292 }
1293
1294 /*
1295 Put last*/
1296 /*For Gutenberg navigation*/
1297 $nav = isset( $content['wp_navigation'] ) ? $content['wp_navigation'] : array();
1298 if ( $nav ) {
1299 unset( $content['wp_navigation'] );
1300 $content['wp_navigation'] = $nav;
1301 }
1302
1303 $template_part = isset( $content['wp_template_part'] ) ? $content['wp_template_part'] : array();
1304 if ( $template_part ) {
1305 unset( $content['wp_template_part'] );
1306 $content['wp_template_part'] = $template_part;
1307 }
1308 /*check if there is files*/
1309 $widget_data = $this->get_widgets_json();
1310 if ( ! empty( $widget_data ) ) {
1311 $total_content += 1;
1312
1313 $content['widgets'] = array(
1314 'title' => esc_html__( 'Widgets', 'advanced-import' ),
1315 'description' => esc_html__( 'Insert default sidebar widgets as seen in the demo.', 'advanced-import' ),
1316 'pending' => esc_html__( 'Pending.', 'advanced-import' ),
1317 'installing' => esc_html__( 'Installing Default Widgets.', 'advanced-import' ),
1318 'success' => esc_html__( 'Success.', 'advanced-import' ),
1319 'install_callback' => array( $this, 'import_content_widgets_data' ),
1320 'checked' => $this->is_possible_upgrade() ? 0 : 1,
1321 // dont check if already have content installed.
1322 );
1323 }
1324 $options_data = $this->get_theme_options_json();
1325 if ( ! empty( $options_data ) ) {
1326 $total_content += 1;
1327 $content['settings'] = array(
1328 'title' => esc_html__( 'Settings', 'advanced-import' ),
1329 'description' => esc_html__( 'Configure default settings.', 'advanced-import' ),
1330 'pending' => esc_html__( 'Pending.', 'advanced-import' ),
1331 'installing' => esc_html__( 'Installing Default Settings.', 'advanced-import' ),
1332 'success' => esc_html__( 'Success.', 'advanced-import' ),
1333 'install_callback' => array( $this, 'import_menu_and_options' ),
1334 'checked' => $this->is_possible_upgrade() ? 0 : 1,
1335 // dont check if already have content installed.
1336 );
1337 }
1338 $content = apply_filters( 'advanced_import_' . $this->theme_name . '_theme_view_setup_step_content', $content );
1339
1340 $this->total_request = $total_content;
1341 return $content;
1342 }
1343
1344 /**
1345 * 3rd Step Step for content, widget, setting import
1346 * Page setup
1347 */
1348 public function content_screen() {
1349
1350 /*check for security*/
1351 if ( ! current_user_can( 'upload_files' ) ) {
1352 wp_send_json_error(
1353 array(
1354 'message' => esc_html__( 'Sorry, you are not allowed to install demo on this site.', 'advanced-import' ),
1355 )
1356 );
1357 }
1358 check_admin_referer( 'advanced-import' );
1359
1360 if ( isset( $_POST['template_url'] ) ) {
1361 $template_url = wp_unslash( $_POST['template_url'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1362 if ( is_array( $template_url ) ) {
1363 $this->current_template_url = array_map( 'sanitize_url', $template_url );
1364 } else {
1365 $this->current_template_url = sanitize_url( $template_url );
1366 }
1367 $this->current_template_type = isset( $_POST['template_type'] ) ? sanitize_text_field( wp_unslash( $_POST['template_type'] ) ) : '';
1368 }
1369
1370 do_action( 'advanced_import_before_content_screen' );
1371
1372 ?>
1373 <div class="ai-notification-title">
1374 <p>
1375 <?php
1376 esc_html_e( 'It\'s time to insert some demo content for your new WordPress Site. Once inserted, this content can be managed from the WordPress admin dashboard. ', 'advanced-import' )
1377 ?>
1378 </p>
1379 </div>
1380
1381 <table class="ai-pages hidden">
1382 <thead>
1383 <tr>
1384 <th class="check"></th>
1385 <th class="item"><?php esc_html_e( 'Item', 'advanced-import' ); ?></th>
1386 <th class="description"><?php esc_html_e( 'Description', 'advanced-import' ); ?></th>
1387 <th class="status"><?php esc_html_e( 'Status', 'advanced-import' ); ?></th>
1388 </tr>
1389 </thead>
1390 <tbody>
1391 <?php
1392 $setup_content_steps = $this->advanced_import_setup_content_steps();
1393 foreach ( $setup_content_steps as $slug => $default ) {
1394 ?>
1395 <tr class="ai-available-content" data-content="<?php echo esc_attr( $slug ); ?>">
1396 <td>
1397 <input type="checkbox" name="import_content[<?php echo esc_attr( $slug ); ?>]" class="ai-available-content" id="import_content_<?php echo esc_attr( $slug ); ?>" value="1" <?php echo ( ! isset( $default['checked'] ) || $default['checked'] ) ? ' checked' : ''; ?>>
1398 </td>
1399 <td>
1400 <label for="import_content_<?php echo esc_attr( $slug ); ?>">
1401 <?php echo esc_html( $default['title'] ); ?>
1402 </label>
1403 </td>
1404 <td class="description">
1405 <?php echo esc_html( $default['description'] ); ?>
1406 </td>
1407 <td class="status">
1408 <span>
1409 <?php echo esc_html( $default['pending'] ); ?>
1410 </span>
1411 </td>
1412 </tr>
1413 <?php } ?>
1414 </tbody>
1415 </table>
1416 <?php
1417 do_action( 'advanced_import_after_content_screen' );
1418
1419 exit;
1420 }
1421
1422 /*
1423 * import ajax content
1424 * return JSON
1425 */
1426 public function import_content() {
1427 /*check for security*/
1428 if ( ! check_ajax_referer( 'advanced-import', 'wpnonce' ) ) {
1429 wp_send_json_error(
1430 array(
1431 'message' => esc_html__( 'Security check failed.', 'advanced-import' ),
1432 )
1433 );
1434 }
1435
1436 if ( ! current_user_can( 'upload_files' ) ) {
1437 wp_send_json_error(
1438 array(
1439 'message' => esc_html__( 'Sorry, you are not allowed to install demo on this site.', 'advanced-import' ),
1440 )
1441 );
1442 }
1443 if ( isset( $_POST['template_url'] ) ) {
1444 $template_url = wp_unslash( $_POST['template_url'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1445 if ( is_array( $template_url ) ) {
1446 $this->current_template_url = array_map( 'sanitize_url', $template_url );
1447 } else {
1448 $this->current_template_url = sanitize_url( $template_url );
1449 }
1450 $this->current_template_type = isset( $_POST['template_type'] ) ? sanitize_text_field( wp_unslash( $_POST['template_type'] ) ) : '';
1451 }
1452
1453 /*Move to Trash default page and post*/
1454 $sample_page = advanced_import_get_post_by_title( 'Sample Page', 'page' );
1455 $hello_world_post = advanced_import_get_post_by_title( 'Hello world!', 'post' );
1456 if ( is_object( $sample_page ) ) {
1457 wp_trash_post( $sample_page->ID );
1458 }
1459 if ( is_object( $hello_world_post ) ) {
1460 wp_trash_post( $hello_world_post->ID );
1461 }
1462
1463 $content_slug = isset( $_POST['content'] ) ? sanitize_title( wp_unslash( $_POST['content'] ) ) : '';
1464
1465 $content = $this->advanced_import_setup_content_steps();
1466
1467 /*check for security again*/
1468 if ( ! check_ajax_referer( 'advanced-import', 'wpnonce' ) || empty( $content_slug ) || ! isset( $content[ $content_slug ] ) ) {
1469 wp_send_json_error(
1470 array(
1471 'error' => 1,
1472 'message' => esc_html__( 'No content Found', 'advanced-import' ),
1473 )
1474 );
1475 }
1476
1477 $json = false;
1478 $this_content = $content[ $content_slug ];
1479
1480 if ( isset( $_POST['proceed'] ) || apply_filters( 'advanced_import_force_proceed', false ) ) {
1481
1482 /*install the content*/
1483 $this->log( esc_html__( 'Starting import for ', 'advanced-import' ) . $content_slug );
1484
1485 /*init delayed posts from transient.*/
1486 $this->delay_posts = get_transient( 'delayed_posts' );
1487 if ( ! is_array( $this->delay_posts ) ) {
1488 $this->delay_posts = array();
1489 }
1490
1491 if ( ! empty( $this_content['install_callback'] ) ) {
1492 /*
1493 install_callback includes following functions
1494 * import_content_post_type_data
1495 * import_content_widgets_data
1496 * import_menu_and_options
1497 * */
1498 $result = call_user_func( $this_content['install_callback'] );
1499 if ( $result ) {
1500
1501 $this->log( esc_html__( 'Finish writing ', 'advanced-import' ) . count( $this->delay_posts, COUNT_RECURSIVE ) . esc_html__( ' delayed posts to transient ', 'advanced-import' ) );
1502 set_transient( 'delayed_posts', $this->delay_posts, 60 * 60 * 24 );
1503
1504 /*
1505 if there is retry, retry it
1506 or finish it*/
1507 if ( is_array( $result ) && isset( $result['retry'] ) ) {
1508 /*we split the stuff up again.*/
1509 $json = array(
1510 'url' => admin_url( 'admin-ajax.php' ),
1511 'action' => 'import_content',
1512 'proceed' => 'true',
1513 'retry' => time(),
1514 'retry_count' => $result['retry_count'],
1515 'content' => $content_slug,
1516 '_wpnonce' => wp_create_nonce( 'advanced-import' ),
1517 'message' => $this_content['installing'],
1518 'logs' => $this->logs,
1519 'errors' => $this->errors,
1520 'template_url' => $this->current_template_url,
1521 'template_type' => $this->current_template_type,
1522
1523 );
1524 } else {
1525 $json = array(
1526 'done' => 1,
1527 'message' => $this_content['success'],
1528 'debug' => $result,
1529 'logs' => $this->logs,
1530 'errors' => $this->errors,
1531 );
1532 }
1533 }
1534 }
1535 } else {
1536
1537 $json = array(
1538 'url' => admin_url( 'admin-ajax.php' ),
1539 'action' => 'import_content',
1540 'proceed' => 'true',
1541 'content' => $content_slug,
1542 '_wpnonce' => wp_create_nonce( 'advanced-import' ),
1543 'message' => $this_content['installing'],
1544 'logs' => $this->logs,
1545 'errors' => $this->errors,
1546 'template_url' => $this->current_template_url,
1547 'template_type' => $this->current_template_type,
1548 );
1549 }
1550
1551 if ( $json ) {
1552 $json['hash'] = md5( serialize( $json ) ); /*used for checking if duplicates happen, move to next plugin*/
1553 wp_send_json( $json );
1554 } else {
1555 wp_send_json_error(
1556 array(
1557 'message' => esc_html__( 'Error', 'advanced-import' ),
1558 'logs' => $this->logs,
1559 'errors' => $this->errors,
1560 )
1561 );
1562 }
1563 exit;
1564 }
1565
1566 /*
1567 callback function to importing post type
1568 * all post type is imported from here
1569 * return mix
1570 * */
1571 private function import_content_post_type_data() {
1572 if ( ! check_ajax_referer( 'advanced-import', 'wpnonce' ) ) {
1573 return false;
1574 }
1575
1576 $post_type = ! empty( $_POST['content'] ) ? sanitize_text_field( wp_unslash( $_POST['content'] ) ) : false;
1577 $all_data = $this->get_main_content_json();
1578 if ( ! $post_type || ! isset( $all_data[ $post_type ] ) ) {
1579 return false;
1580 }
1581
1582 /*Import 10 posts at a time*/
1583 $limit = 10 + ( isset( $_REQUEST['retry_count'] ) ? absint( wp_unslash( $_REQUEST['retry_count'] ) ) : 0 );
1584
1585 $limit = apply_filters( 'advanced_import_limit_at_time', $limit );
1586 $x = 0;
1587 foreach ( $all_data[ $post_type ] as $post_data ) {
1588
1589 $this->process_import_single_post( $post_type, $post_data );
1590
1591 if ( $x++ > $limit ) {
1592 return array(
1593 'retry' => 1,
1594 'retry_count' => $limit,
1595 );
1596 }
1597 }
1598
1599 /*processed delayed posts*/
1600 $this->process_delayed_posts();
1601
1602 /*process child posts*/
1603 $this->processpost_orphans();
1604
1605 return true;
1606 }
1607
1608 /*
1609 set and get transient imported_term_ids
1610 return mix*/
1611 public function imported_term_id( $original_term_id, $new_term_id = false ) {
1612 $terms = get_transient( 'imported_term_ids' );
1613 if ( ! is_array( $terms ) ) {
1614 $terms = array();
1615 }
1616 if ( $new_term_id ) {
1617 if ( ! isset( $terms[ $original_term_id ] ) ) {
1618 $this->log( esc_html__( 'Insert old TERM ID ', 'advanced-import' ) . $original_term_id . esc_html__( ' as new TERM ID: ', 'advanced-import' ) . $new_term_id );
1619 } elseif ( $terms[ $original_term_id ] != $new_term_id ) {
1620 $this->error( 'Replacement OLD TERM ID ' . $original_term_id . ' overwritten by new TERM ID: ' . $new_term_id );
1621 }
1622 $terms[ $original_term_id ] = $new_term_id;
1623 set_transient( 'imported_term_ids', $terms, 60 * 60 * 24 );
1624 } elseif ( $original_term_id && isset( $terms[ $original_term_id ] ) ) {
1625 return $terms[ $original_term_id ];
1626 }
1627
1628 return false;
1629 }
1630
1631 /**
1632 * Set and get imported post IDs from transient.
1633 *
1634 * @since 1.0.0
1635 * @param int|string|false $original_id Original post ID.
1636 * @param int|string|false $new_id New post ID to map.
1637 * @return int|string|array|false Mapped ID, array of all IDs, or false.
1638 */
1639 public function imported_post_id( $original_id = false, $new_id = false ) {
1640 if ( is_array( $original_id ) || is_object( $original_id ) ) {
1641 return false;
1642 }
1643 $post_ids = get_transient( 'imported_post_ids' );
1644 if ( ! is_array( $post_ids ) ) {
1645 $post_ids = array();
1646 }
1647 if ( $new_id ) {
1648 if ( ! isset( $post_ids[ $original_id ] ) ) {
1649 $this->log( esc_html__( 'Insert old ID ', 'advanced-import' ) . $original_id . esc_html__( ' as new ID: ', 'advanced-import' ) . $new_id );
1650 } elseif ( $post_ids[ $original_id ] != $new_id ) {
1651 $this->error( esc_html__( 'Replacement OLD ID ', 'advanced-import' ) . $original_id . ' overwritten by new ID: ' . $new_id );
1652 }
1653 $post_ids[ $original_id ] = $new_id;
1654 set_transient( 'imported_post_ids', $post_ids, 60 * 60 * 24 );
1655 } elseif ( $original_id && isset( $post_ids[ $original_id ] ) ) {
1656 return $post_ids[ $original_id ];
1657 } elseif ( $original_id === false ) {
1658 return $post_ids;
1659 }
1660 return false;
1661 }
1662
1663 /**
1664 * Set and get post orphans/post parent mapping from transient.
1665 * If parent is not already imported, the child will be orphaned.
1666 *
1667 * @since 1.0.0
1668 * @param int|string|false $original_id Original post ID.
1669 * @param int|string|false $missing_parent_id Missing parent ID to map.
1670 * @return int|string|array|false Mapped parent ID, array of all orphans, or false.
1671 */
1672 private function post_orphans( $original_id = false, $missing_parent_id = false ) {
1673 $post_ids = get_transient( 'post_orphans' );
1674 if ( ! is_array( $post_ids ) ) {
1675 $post_ids = array();
1676 }
1677 if ( $missing_parent_id ) {
1678 $post_ids[ $original_id ] = $missing_parent_id;
1679 set_transient( 'post_orphans', $post_ids, 60 * 60 * 24 );
1680 } elseif ( $original_id && isset( $post_ids[ $original_id ] ) ) {
1681 return $post_ids[ $original_id ];
1682 } elseif ( $original_id === false ) {
1683 return $post_ids;
1684 }
1685 return false;
1686 }
1687
1688
1689 /**
1690 * Set delayed post for later processing.
1691 *
1692 * @since 1.0.0
1693 * @param string $post_type Post type slug.
1694 * @param array $post_data Post data array.
1695 * @return void
1696 */
1697 private function delay_post_process( $post_type, $post_data ) {
1698 if ( ! isset( $this->delay_posts[ $post_type ] ) ) {
1699 $this->delay_posts[ $post_type ] = array();
1700 }
1701 $this->delay_posts[ $post_type ][ $post_data['post_id'] ] = $post_data;
1702 }
1703
1704
1705 /**
1706 * Import a single post or content item.
1707 *
1708 * @since 1.0.0
1709 * @param string $post_type Post type slug.
1710 * @param array $post_data Post data array.
1711 * @param int $delayed Whether this is a delayed import (0 or 1).
1712 * @return bool True on success, false on failure.
1713 */
1714 private function process_import_single_post( $post_type, $post_data, $delayed = 0 ) {
1715
1716 $this->current_request = $this->current_request + 1;
1717
1718 $this->log( esc_html__( 'Processing ', 'advanced-import' ) . $post_type . ' ' . $post_data['post_id'] );
1719 $original_post_data = $post_data;
1720
1721 /*if there is not post type return false*/
1722 if ( ! post_type_exists( $post_type ) ) {
1723 return false;
1724 }
1725
1726 /*if it is aready imported return*/
1727 if ( $this->imported_post_id( $post_data['post_id'] ) ) {
1728 return true; /*already done*/
1729 }
1730
1731 /*set post_name id for empty post name/title*/
1732 if ( empty( $post_data['post_title'] ) && empty( $post_data['post_name'] ) ) {
1733 $post_data['post_name'] = $post_data['post_id'];
1734 }
1735
1736 /*set post_type on $post_data*/
1737 $post_data['post_type'] = $post_type;
1738
1739 /*post_orphans/post parent management */
1740 $post_parent = isset( $post_data['post_parent'] ) ? absint( $post_data['post_parent'] ) : false;
1741 if ( $post_parent ) {
1742 /*if we already know the parent, map it to the new local imported ID*/
1743 if ( $this->imported_post_id( $post_parent ) ) {
1744 $post_data['post_parent'] = $this->imported_post_id( $post_parent );
1745 } else {
1746 /*if there is not parent imported, child will be orphans*/
1747 $this->post_orphans( absint( $post_data['post_id'] ), $post_parent );
1748 $post_data['post_parent'] = 0;
1749 }
1750 }
1751
1752 $foundid = 0;
1753
1754 /*
1755 check if already exists by post_name and post_title*/
1756 /*don't use post_exists because it will dupe up on media with same name but different slug*/
1757 if ( ! empty( $post_data['post_title'] ) && ! empty( $post_data['post_name'] ) ) {
1758 global $wpdb;
1759 $cache_key = 'ai_post_lookup_' . md5( $post_data['post_name'] . '|' . $post_data['post_title'] . '|' . $post_type );
1760 $pages = wp_cache_get( $cache_key, 'advanced_import' );
1761 if ( false === $pages ) {
1762 $pages = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
1763 $wpdb->prepare(
1764 "SELECT ID, post_name, post_parent, post_type FROM {$wpdb->posts} WHERE post_name = %s AND post_title = %s AND post_type = %s",
1765 array(
1766 $post_data['post_name'],
1767 $post_data['post_title'],
1768 $post_type,
1769 )
1770 ),
1771 OBJECT_K
1772 );
1773 wp_cache_set( $cache_key, $pages, 'advanced_import' );
1774 }
1775
1776 foreach ( (array) $pages as $page ) {
1777 if ( $page->post_name == $post_data['post_name'] ) {
1778 $foundid = $page->ID;
1779 }
1780 }
1781 }
1782
1783 /*
1784 * todo it may not required
1785 * backwards compat with old import format.*/
1786 if ( isset( $post_data['meta'] ) ) {
1787 foreach ( $post_data['meta'] as $key => $meta ) {
1788 if ( is_array( $meta ) && count( $meta ) == 1 ) {
1789 $single_meta = current( $meta );
1790 if ( ! is_array( $single_meta ) ) {
1791 $post_data['meta'][ $key ] = $single_meta;
1792 }
1793 }
1794 }
1795 }
1796
1797 /*finally process*/
1798 switch ( $post_type ) {
1799
1800 /*case attachment*/
1801 case 'attachment':
1802 /*import media via url*/
1803 if ( isset( $post_data['guid'] ) && ! empty( $post_data['guid'] ) ) {
1804
1805 /*check if this has already been imported.*/
1806 $old_guid = $post_data['guid'];
1807 if ( $this->imported_post_id( $old_guid ) ) {
1808 return true; /*already done*/
1809 }
1810
1811 $remote_url = $post_data['guid'];
1812
1813 $post_data['upload_date'] = gmdate( 'Y/m', strtotime( $post_data['post_date_gmt'] ) );
1814
1815 if ( isset( $post_data['meta'] ) ) {
1816 foreach ( $post_data['meta'] as $key => $meta ) {
1817 if ( $key == '_wp_attached_file' ) {
1818 foreach ( (array) $meta as $meta_val ) {
1819 if ( preg_match( '%^[0-9]{4}/[0-9]{2}%', $meta_val, $date_matches ) ) {
1820 $post_data['upload_date'] = $date_matches[0];
1821 }
1822 }
1823 }
1824 }
1825 }
1826
1827 /*upload the file*/
1828 $upload = $this->import_image_and_file( $remote_url, $post_data );
1829
1830 /*if error on upload*/
1831 if ( ! is_array( $upload ) || is_wp_error( $upload ) ) {
1832 /*todo: error*/
1833 return false;
1834 }
1835
1836 /*check file type, if file type not found return false*/
1837 if ( $info = wp_check_filetype( $upload['file'] ) ) {
1838 $post_data['post_mime_type'] = $info['type'];
1839 } else {
1840 return false;
1841 }
1842
1843 /*set guid file url*/
1844 $post_data['guid'] = $upload['url'];
1845
1846 /*
1847 * insert attachment
1848 *https://developer.wordpress.org/reference/functions/wp_insert_attachment/
1849 * */
1850 $attach_id = wp_insert_attachment( $post_data, $upload['file'] );
1851 if ( $attach_id ) {
1852
1853 /*update meta*/
1854 if ( ! empty( $post_data['meta'] ) ) {
1855 foreach ( $post_data['meta'] as $meta_key => $meta_val ) {
1856 if ( $meta_key != '_wp_attached_file' && ! empty( $meta_val ) ) {
1857 update_post_meta( $attach_id, $meta_key, $meta_val );
1858 }
1859 }
1860 }
1861 /* Update metadata for an attachment.*/
1862 $file_path = $upload['file'];
1863
1864 if ( file_exists( $file_path ) && is_readable( $file_path ) ) {
1865 $metadata = wp_generate_attachment_metadata( $attach_id, $file_path );
1866 if ( ! is_wp_error( $metadata ) ) {
1867 wp_update_attachment_metadata( $attach_id, $metadata );
1868 }
1869 } elseif ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
1870 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
1871 trigger_error( esc_html( "Attachment file missing or unreadable: $file_path" ), E_USER_WARNING );
1872 }
1873
1874 /*remap resized image URLs, works by stripping the extension and remapping the URL stub.*/
1875 if ( preg_match( '!^image/!', $info['type'] ) ) {
1876 $parts = pathinfo( $remote_url );
1877 $name = basename( $parts['basename'], ".{$parts['extension']}" ); // PATHINFO_FILENAME in PHP 5.2.
1878
1879 $parts_new = pathinfo( $upload['url'] );
1880 $name_new = basename( $parts_new['basename'], ".{$parts_new['extension']}" );
1881
1882 $this->imported_post_id( $parts['dirname'] . '/' . $name, $parts_new['dirname'] . '/' . $name_new );
1883 }
1884 $this->imported_post_id( $post_data['post_id'], $attach_id );
1885 }
1886 }
1887 break;
1888
1889 /*TODO*/
1890 case 'elementor_library':
1891 if ( ! empty( $post_data['meta'] ) && is_array( $post_data['meta'] ) ) {
1892
1893 /*fix for double json encoded stuff*/
1894 foreach ( $post_data['meta'] as $meta_key => $meta_val ) {
1895 if ( is_string( $meta_val ) && strlen( $meta_val ) && $meta_val[0] == '[' ) {
1896 $test_json = json_decode( $meta_val, true );
1897 if ( json_last_error() === JSON_ERROR_NONE && is_array( $test_json ) ) {
1898 $post_data['meta'][ $meta_key ] = $test_json;
1899 }
1900 }
1901 }
1902
1903 array_walk_recursive(
1904 $post_data['meta'],
1905 array(
1906 advanced_import_elementor(),
1907 'elementor_id_import',
1908 )
1909 );
1910 }
1911 /*do further filter if you need*/
1912 $post_data['post_id'] = apply_filters( 'advanced_import_post_data', $post_data );
1913
1914 /*finally insert post data*/
1915 if ( $foundid > 0 ) {
1916 $post_data['ID'] = $foundid;
1917 $post_id = wp_update_post( $post_data, true );
1918 } else {
1919 $post_id = wp_insert_post( $post_data, true );
1920 }
1921 if ( ! is_wp_error( $post_id ) ) {
1922
1923 /*set id on imported_post_id*/
1924 $this->imported_post_id( $post_data['post_id'], $post_id );
1925
1926 /*add/update post meta*/
1927 if ( ! empty( $post_data['meta'] ) ) {
1928 foreach ( $post_data['meta'] as $meta_key => $meta_val ) {
1929 /*if the post has a featured image, take note of this in case of remap*/
1930 if ( '_thumbnail_id' == $meta_key ) {
1931 /*find this inserted id and use that instead.*/
1932 $inserted_id = $this->imported_post_id( intval( $meta_val ) );
1933 if ( $inserted_id ) {
1934 $meta_val = $inserted_id;
1935 }
1936 }
1937 /*update meta*/
1938 update_post_meta( $post_id, $meta_key, $meta_val );
1939 }
1940 }
1941 }
1942 // not needed
1943 // update_option('elementor_active_kit', $post_id);
1944 if (
1945 defined( 'ELEMENTOR_VERSION' )
1946 ||
1947 defined( 'ELEMENTOR_PRO_VERSION' )
1948 ) {
1949 \Elementor\Plugin::$instance->files_manager->clear_cache();
1950 }
1951 break;
1952
1953 default:
1954 /*Process Post Meta*/
1955 if ( ! empty( $post_data['meta'] ) && is_array( $post_data['meta'] ) ) {
1956
1957 /*fix for double json encoded stuff*/
1958 foreach ( $post_data['meta'] as $meta_key => $meta_val ) {
1959 if ( is_string( $meta_val ) && strlen( $meta_val ) && $meta_val[0] == '[' ) {
1960 $test_json = json_decode( $meta_val, true );
1961 if ( json_last_error() === JSON_ERROR_NONE && is_array( $test_json ) ) {
1962 $post_data['meta'][ $meta_key ] = $test_json;
1963 }
1964 }
1965 }
1966
1967 // array_walk_recursive( $post_data['meta'], array( advanced_import_elementor(), 'elementor_id_import' ) );
1968
1969 /*todo gutenberg and page builders*/
1970
1971 /*
1972 replace menu data
1973 work out what we're replacing. a tax, page, term etc..*/
1974 if ( isset( $post_data['meta']['_menu_item_menu_item_parent'] ) && 0 != $post_data['meta']['_menu_item_menu_item_parent'] ) {
1975 $new_parent_id = $this->imported_post_id( $post_data['meta']['_menu_item_menu_item_parent'] );
1976 if ( ! $new_parent_id ) {
1977 if ( $delayed ) {
1978 /*already delayed, unable to find this meta value, skip inserting it*/
1979 $this->error( esc_html__( 'Unable to find replacement. Continue anyway.... content will most likely break..', 'advanced-import' ) );
1980 } else {
1981 /*not found , delay it*/
1982 $this->error( esc_html__( 'Unable to find replacement. Delaying....', 'advanced-import' ) );
1983 $this->delay_post_process( $post_type, $original_post_data );
1984 return false;
1985 }
1986 }
1987 $post_data['meta']['_menu_item_menu_item_parent'] = $new_parent_id;
1988 }
1989
1990 /*if _menu_item_type*/
1991 if ( isset( $post_data['meta']['_menu_item_type'] ) ) {
1992
1993 switch ( $post_data['meta']['_menu_item_type'] ) {
1994 case 'post_type':
1995 if ( ! empty( $post_data['meta']['_menu_item_object_id'] ) ) {
1996 $new_parent_id = $this->imported_post_id( $post_data['meta']['_menu_item_object_id'] );
1997 if ( ! $new_parent_id ) {
1998 if ( $delayed ) {
1999 /*already delayed, unable to find this meta value, skip inserting it*/
2000 $this->error( esc_html__( 'Unable to find replacement. Continue anyway.... content will most likely break..', 'advanced-import' ) );
2001 } else {
2002 /*not found , delay it*/
2003 $this->error( esc_html__( 'Unable to find replacement. Delaying....', 'advanced-import' ) );
2004 $this->delay_post_process( $post_type, $original_post_data );
2005 return false;
2006 }
2007 }
2008 $post_data['meta']['_menu_item_object_id'] = $new_parent_id;
2009 }
2010 break;
2011
2012 case 'taxonomy':
2013 if ( ! empty( $post_data['meta']['_menu_item_object_id'] ) ) {
2014 $new_parent_id = $this->imported_term_id( $post_data['meta']['_menu_item_object_id'] );
2015 if ( ! $new_parent_id ) {
2016 if ( $delayed ) {
2017 /*already delayed, unable to find this meta value, skip inserting it*/
2018 $this->error( esc_html__( 'Unable to find replacement. Continue anyway.... content will most likely break..', 'advanced-import' ) );
2019 } else {
2020 /*not found , delay it*/
2021 $this->error( esc_html__( 'Unable to find replacement. Delaying....', 'advanced-import' ) );
2022 $this->delay_post_process( $post_type, $original_post_data );
2023 return false;
2024 }
2025 }
2026 $post_data['meta']['_menu_item_object_id'] = $new_parent_id;
2027 }
2028 break;
2029 }
2030 }
2031 }
2032
2033 /*
2034 post content parser
2035 for shortcode post id replacement*/
2036 $post_data['post_content'] = $this->parse_shortcode_meta_content( $post_data['post_content'] );
2037
2038 $replace_tax_id_keys = array(
2039 'taxonomies',
2040 );
2041 foreach ( $replace_tax_id_keys as $replace_key ) {
2042 if ( preg_match_all( '# ' . $replace_key . '="(\d+)"#', $post_data['post_content'], $matches ) ) {
2043 foreach ( $matches[0] as $match_id => $string ) {
2044 $new_id = $this->imported_term_id( $matches[1][ $match_id ] );
2045 if ( $new_id ) {
2046 $post_data['post_content'] = str_replace( $string, ' ' . $replace_key . '="' . $new_id . '"', $post_data['post_content'] );
2047 } else {
2048 $this->error( esc_html__( 'Unable to find TAXONOMY replacement for ', 'advanced-import' ) . $replace_key . '="' . $matches[1][ $match_id ] . esc_html__( 'in content.', 'advanced-import' ) );
2049 if ( $delayed ) {
2050 /*already delayed, unable to find this meta value, skip inserting it*/
2051 $this->error( esc_html__( 'Unable to find replacement. Continue anyway.... content will most likely break..', 'advanced-import' ) );
2052 } else {
2053 /*not found , delay it*/
2054 $this->delay_post_process( $post_type, $original_post_data );
2055 return false;
2056 }
2057 }
2058 }
2059 }
2060 }
2061
2062 /*do further filter if you need*/
2063 $post_data = apply_filters( 'advanced_import_post_data', $post_data );
2064
2065 /*finally insert post data*/
2066
2067 if ( $foundid > 0 ) {
2068 $post_data['ID'] = $foundid;
2069 /*finally insert post data*/
2070 $post_id = wp_update_post( $post_data, true );
2071 } else {
2072 $post_id = wp_insert_post( $post_data, true );
2073 }
2074 if ( ! is_wp_error( $post_id ) ) {
2075
2076 /*set id on imported_post_id*/
2077 $this->imported_post_id( $post_data['post_id'], $post_id );
2078
2079 /*add/update post meta*/
2080 if ( ! empty( $post_data['meta'] ) ) {
2081 foreach ( $post_data['meta'] as $meta_key => $meta_val ) {
2082 /*if the post has a featured image, take note of this in case of remap*/
2083 if ( '_thumbnail_id' == $meta_key ) {
2084 /*find this inserted id and use that instead.*/
2085 $inserted_id = $this->imported_post_id( intval( $meta_val ) );
2086 if ( $inserted_id ) {
2087 $meta_val = $inserted_id;
2088 }
2089 } elseif ( '_elementor_data' == $meta_key ) {
2090 advanced_import_elementor()->elementor_data_posts( $post_id, $meta_val );
2091 }
2092 /*update meta*/
2093 update_post_meta( $post_id, $meta_key, $meta_val );
2094 }
2095 }
2096
2097 if ( ! empty( $post_data['terms'] ) ) {
2098 $terms_to_set = array();
2099 foreach ( $post_data['terms'] as $term_slug => $terms ) {
2100 foreach ( $terms as $term ) {
2101 $taxonomy = $term['taxonomy'];
2102 if ( taxonomy_exists( $taxonomy ) ) {
2103 $term_exists = term_exists( $term['slug'], $taxonomy );
2104 $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : $term_exists;
2105 if ( ! $term_id ) {
2106 if ( ! empty( $term['parent'] ) ) {
2107 /*see if we have imported this yet?*/
2108 $term['parent'] = $this->imported_term_id( $term['parent'] );
2109 }
2110 $term_id_tax_id = wp_insert_term( $term['name'], $taxonomy, $term );
2111 if ( ! is_wp_error( $term_id_tax_id ) ) {
2112 $term_id = $term_id_tax_id['term_id'];
2113 } else {
2114 // todo - error
2115 continue;
2116 }
2117 }
2118 /*set term_id on imported_term_id*/
2119 $this->imported_term_id( $term['term_id'], $term_id );
2120
2121 /*add the term meta.*/
2122 if ( $term_id && ! empty( $term['meta'] ) && is_array( $term['meta'] ) ) {
2123
2124 $replace_post_ids = apply_filters(
2125 'advanced_import_replace_post_ids',
2126 array(
2127 'image_id',
2128 'thumbnail_id',
2129 'author_picture',
2130 )
2131 );
2132 foreach ( $term['meta'] as $meta_key => $meta_val ) {
2133 // we have to replace certain meta_key/meta_val
2134 // e.g. thumbnail id from woocommerce product categories.
2135
2136 if ( in_array( $meta_key, $replace_post_ids ) ) {
2137
2138 if ( $new_meta_val = $this->imported_post_id( $meta_val ) ) {
2139 /*use this new id.*/
2140 $meta_val = $new_meta_val;
2141 }
2142 }
2143 update_term_meta( $term_id, $meta_key, $meta_val );
2144 }
2145 }
2146 $terms_to_set[ $taxonomy ][] = intval( $term_id );
2147 }
2148 }
2149 }
2150 foreach ( $terms_to_set as $tax => $ids ) {
2151 wp_set_post_terms( $post_id, $ids, $tax );
2152 }
2153
2154 if ( ( isset( $post_data['meta']['_elementor_data'] ) && ! empty( $post_data['meta']['_elementor_data'] ) ) ||
2155 ( isset( $post_data['meta']['_elementor_css'] ) && ! empty( $post_data['meta']['_elementor_css'] ) )
2156 ) {
2157 advanced_import_elementor()->elementor_post( $post_id );
2158 }
2159
2160 /*Gutentor*/
2161 $post = get_post( $post_id );
2162 $content = $post->post_content;
2163 if ( preg_match_all( '/data-gpid="(.*?)\" /', $content, $matches ) ) {
2164 foreach ( $matches[0] as $match_id => $string ) {
2165 $content = str_replace( $matches[0][ $match_id ], 'data-gpid="' . $post_id . '" ', $content );
2166 }
2167 }
2168 $post->post_content = $content;
2169 wp_update_post( $post );
2170 }
2171 }
2172 break;
2173 }
2174
2175 return true;
2176 }
2177
2178 /*Shortcode/Meta/Post Ids fixed start*/
2179
2180 /*
2181 * since 1.2.3
2182 * return the difference in length between two strings
2183 * */
2184 public function strlen_diff( $a, $b ) {
2185 return strlen( $b ) - strlen( $a );
2186 }
2187
2188
2189 /*
2190 * since 1.2.3
2191 * helper function to parse url, shortcode, post ids form provided content
2192 * * currently uses on meta and post content
2193 * */
2194 public function parse_shortcode_meta_content( $content ) {
2195 /*we have to format the post content. rewriting images and gallery stuff*/
2196 $replace = $this->imported_post_id();
2197
2198 /*filters urls for replace*/
2199 $urls_replace = array();
2200 foreach ( $replace as $key => $val ) {
2201 if ( $key && $val && ! is_numeric( $key ) && ! is_numeric( $val ) ) {
2202 $urls_replace[ $key ] = $val;
2203 }
2204 }
2205 /*replace image/file urls*/
2206 if ( $urls_replace ) {
2207 uksort( $urls_replace, array( &$this, 'strlen_diff' ) );
2208 foreach ( $urls_replace as $from_url => $to_url ) {
2209 $content = str_replace( $from_url, $to_url, $content );
2210 }
2211 }
2212
2213 /*gallery fixed*/
2214 if ( preg_match_all( '#\[gallery[^\]]*\]#', $content, $matches ) ) {
2215 foreach ( $matches[0] as $match_id => $string ) {
2216 if ( preg_match( '#ids="([^"]+)"#', $string, $ids_matches ) ) {
2217 $ids = explode( ',', $ids_matches[1] );
2218 foreach ( $ids as $key => $val ) {
2219 $new_id = $val ? $this->imported_post_id( $val ) : false;
2220 if ( ! $new_id ) {
2221 unset( $ids[ $key ] );
2222 } else {
2223 $ids[ $key ] = $new_id;
2224 }
2225 }
2226 $new_ids = implode( ',', $ids );
2227 $content = str_replace( $ids_matches[0], 'ids="' . $new_ids . '"', $content );
2228 }
2229 }
2230 }
2231
2232 /*contact form 7 id fixes.*/
2233 if ( preg_match_all( '#\[contact-form-7[^\]]*\]#', $content, $matches ) ) {
2234 foreach ( $matches[0] as $match_id => $string ) {
2235 if ( preg_match( '#id="(\d+)"#', $string, $id_match ) ) {
2236 $new_id = $this->imported_post_id( $id_match[1] );
2237 if ( $new_id ) {
2238 $content = str_replace( $id_match[0], 'id="' . $new_id . '"', $content );
2239 } else {
2240 /*no imported ID found. remove this entry.*/
2241 $content = str_replace( $matches[0], '(insert contact form here)', $content );
2242 }
2243 }
2244 }
2245 }
2246
2247 /*Gutentor*/
2248 if ( preg_match_all( '/\"pTaxTerm"(.*?)\]/', $content, $matches ) ) {
2249 foreach ( $matches[0] as $match_id => $string ) {
2250 if ( preg_match_all( '/\"value":(.*?)\}/', $string, $matches1 ) ) {
2251 foreach ( $matches1[0] as $match_id1 => $string1 ) {
2252 $new_id = $this->imported_term_id( $matches1[1][ $match_id1 ] );
2253 $content = str_replace( $string1, '"value":' . $new_id . '}', $content );
2254 }
2255 }
2256 }
2257 }
2258 if ( preg_match_all( '/\"e14TaxTerm"(.*?)\]/', $content, $matches ) ) {
2259 foreach ( $matches[0] as $match_id => $string ) {
2260 if ( preg_match_all( '/\"value":(.*?)\}/', $string, $matches1 ) ) {
2261 foreach ( $matches1[0] as $match_id1 => $string1 ) {
2262 $new_id = $this->imported_term_id( $matches1[1][ $match_id1 ] );
2263 $content = str_replace( $string1, '"value":' . $new_id . '}', $content );
2264 }
2265 }
2266 }
2267 }
2268 if ( preg_match_all( '/data-gpid="(.*?)\" /', $content, $matches ) ) {
2269 foreach ( $matches[0] as $match_id => $string ) {
2270 $new_id = $this->imported_post_id( $matches[1][ $match_id ] );
2271 $content = str_replace( $matches[0][ $match_id ], 'data-gpid="' . $new_id . '" ', $content );
2272 }
2273 }
2274 if ( preg_match_all( '/\"p4PostId"(.*?)\,/', $content, $matches ) ) {
2275 foreach ( $matches[0] as $match_id => $string ) {
2276 $new_id = $this->imported_post_id( $matches[1][ $match_id ] );
2277 $content = str_replace( $matches[0][ $match_id ], '"p4PostId":' . $new_id . ',', $content );
2278 }
2279 }
2280
2281 /*Gutenberg ref id changed*/
2282 if ( preg_match_all( '/\{"ref":(\d+)\}/', $content, $matches ) ) {
2283 foreach ( $matches[0] as $match_id => $string ) {
2284 $new_id = $this->imported_post_id( $matches[1][ $match_id ] );
2285 if ( $new_id ) {
2286 $content = str_replace( $string, '{"ref":' . $new_id . '}', $content );
2287 }
2288 }
2289 }
2290 /* Replace for menu item like "page","id":147 */
2291 if ( preg_match_all( '/"page","id":(\d+)/', $content, $matches ) ) {
2292 foreach ( $matches[0] as $match_id => $string ) {
2293 $old_id = $matches[1][ $match_id ];
2294 $new_id = $this->imported_post_id( $old_id );
2295 if ( $new_id ) {
2296 $content = str_replace( $string, '"page","id":' . $new_id, $content );
2297 }
2298 }
2299 }
2300
2301 $replaced_data = apply_filters(
2302 'advanced_import_replace_content_string',
2303 $content
2304 );
2305 return $replaced_data;
2306 }
2307 /*Shortcode/Meta/Post Ids fixed end*/
2308
2309 /*update parent page id for child page*/
2310 private function processpost_orphans() {
2311
2312 /*get post orphans to find it parent*/
2313 $orphans = $this->post_orphans();
2314 foreach ( $orphans as $original_post_id => $original_post_parent_id ) {
2315 if ( $original_post_parent_id ) {
2316 if ( $this->imported_post_id( $original_post_id ) && $this->imported_post_id( $original_post_parent_id ) ) {
2317 $post_data = array();
2318 $post_data['ID'] = $this->imported_post_id( $original_post_id );
2319 $post_data['post_parent'] = $this->imported_post_id( $original_post_parent_id );
2320 wp_update_post( $post_data );
2321 $this->post_orphans( $original_post_id, 0 ); /*ignore future*/
2322 }
2323 }
2324 }
2325 }
2326
2327 /*
2328 Process delayed post
2329 */
2330 private function process_delayed_posts( $last_delay = false ) {
2331
2332 $this->log( esc_html__( 'Processing ', 'advanced-import' ) . count( $this->delay_posts, COUNT_RECURSIVE ) . esc_html__( 'delayed posts', 'advanced-import' ) );
2333 for ( $x = 1; $x < 4; $x++ ) {
2334 foreach ( $this->delay_posts as $delayed_post_type => $delayed_post_data_s ) {
2335 foreach ( $delayed_post_data_s as $delayed_post_id => $delayed_post_data ) {
2336
2337 /*already processed*/
2338 if ( $this->imported_post_id( $delayed_post_data['post_id'] ) ) {
2339 $this->log( $x . esc_html__( '- Successfully processed ', 'advanced-import' ) . $delayed_post_type . esc_html__( ' ID ', 'advanced-import' ) . $delayed_post_data['post_id'] . esc_html__( ' previously.', 'advanced-import' ) );
2340
2341 /*already processed, remove it from delay_posts*/
2342 unset( $this->delay_posts[ $delayed_post_type ][ $delayed_post_id ] );
2343 $this->log( esc_html__( ' ( ', 'advanced-import' ) . count( $this->delay_posts, COUNT_RECURSIVE ) . esc_html__( ' delayed posts remain ) ', 'advanced-import' ) );
2344 }
2345 /*Process it*/
2346 elseif ( $this->process_import_single_post( $delayed_post_type, $delayed_post_data, $last_delay ) ) {
2347 $this->log( $x . esc_html__( ' - Successfully found delayed replacement for ', 'advanced-import' ) . $delayed_post_type . esc_html__( ' ID ', 'advanced-import' ) . $delayed_post_data['post_id'] );
2348
2349 /*successfully processed, remove it from delay_posts*/
2350 unset( $this->delay_posts[ $delayed_post_type ][ $delayed_post_id ] );
2351 $this->log( esc_html__( ' ( ', 'advanced-import' ) . count( $this->delay_posts, COUNT_RECURSIVE ) . esc_html__( ' delayed posts remain ) ', 'advanced-import' ) );
2352 } else {
2353 $this->log( $x . esc_html__( ' - Not found delayed replacement for ', 'advanced-import' ) . $delayed_post_type . esc_html__( ' ID ', 'advanced-import' ) . $delayed_post_data['post_id'] );
2354 }
2355 }
2356 }
2357 }
2358 }
2359
2360 /*Get file from url , download it and add to local*/
2361 private function import_image_and_file( $url, $post ) {
2362
2363 /*extract the file name and extension from the url*/
2364 $file_name = basename( $url );
2365 $local_file = ADVANCED_IMPORT_TEMP_UPLOADS . $file_name;
2366 $upload = false;
2367 $headers = array();
2368
2369 /*
2370 if file is already on local, return file information
2371 It means media is on local, while exporting media*/
2372 if ( is_file( $local_file ) && filesize( $local_file ) > 0 ) {
2373 require_once ABSPATH . 'wp-admin/includes/file.php';
2374 WP_Filesystem();
2375 global $wp_filesystem;
2376 $file_data = $wp_filesystem->get_contents( $local_file );
2377 $upload = wp_upload_bits( $file_name, null, $file_data, $post['upload_date'] );
2378 if ( $upload['error'] ) {
2379 return new WP_Error( 'upload_dir_error', $upload['error'] );
2380 }
2381 }
2382
2383 /*if there is no file on local or error on local file need to fetch it*/
2384 if ( ! $upload || $upload['error'] ) {
2385
2386 /*get placeholder file in the upload dir with a unique, sanitized filename*/
2387 $upload = wp_upload_bits( $file_name, null, '', $post['upload_date'] );
2388 if ( $upload['error'] ) {
2389 return new WP_Error( 'upload_dir_error', $upload['error'] );
2390 }
2391
2392 $max_size = (int) apply_filters( 'advanced_import_attachment_size_limit', 0 );
2393
2394 $url = esc_url_raw( $url, array( 'http', 'https' ) );
2395 if ( empty( $url ) || ! wp_http_validate_url( $url ) ) {
2396 wp_delete_file( $upload['file'] );
2397 return new WP_Error( 'import_file_error', esc_html__( 'Invalid remote file URL', 'advanced-import' ) );
2398 }
2399
2400 $request_args = array(
2401 'timeout' => 30,
2402 'redirection' => 3,
2403 'reject_unsafe_urls' => true,
2404 );
2405 if ( ! empty( $max_size ) ) {
2406 $request_args['limit_response_size'] = $max_size;
2407 }
2408
2409 /*finally fetch the file from remote*/
2410 $response = wp_safe_remote_get( $url, $request_args );
2411 if ( ! is_wp_error( $response ) ) {
2412 $response_code = (int) wp_remote_retrieve_response_code( $response );
2413 $response_body = wp_remote_retrieve_body( $response );
2414 if ( 200 !== $response_code || empty( $response_body ) ) {
2415 wp_delete_file( $upload['file'] );
2416 return new WP_Error( 'import_file_error', esc_html__( 'Remote file could not be downloaded', 'advanced-import' ) );
2417 }
2418
2419 require_once ABSPATH . 'wp-admin/includes/file.php';
2420 $headers = (array) wp_remote_retrieve_headers( $response );
2421 WP_Filesystem();
2422 global $wp_filesystem;
2423 $file_mode = defined( 'FS_CHMOD_FILE' ) ? FS_CHMOD_FILE : 0644;
2424 $wp_filesystem->put_contents( $upload['file'], $response_body, $file_mode );
2425 } else {
2426 /*required to download file failed.*/
2427 wp_delete_file( $upload['file'] );
2428 return new WP_Error( 'import_file_error', esc_html__( 'Remote server did not respond', 'advanced-import' ) );
2429 }
2430
2431 $file_size = filesize( $upload['file'] );
2432
2433 /*check for size*/
2434 if ( isset( $headers['content-length'] ) && $file_size != (int) $headers['content-length'] ) {
2435 wp_delete_file( $upload['file'] );
2436 return new WP_Error( 'import_file_error', esc_html__( 'Remote file is incorrect size', 'advanced-import' ) );
2437 }
2438
2439 /*if file size is 0*/
2440 if ( 0 == $file_size ) {
2441 wp_delete_file( $upload['file'] );
2442 return new WP_Error( 'import_file_error', esc_html__( 'Zero size file downloaded', 'advanced-import' ) );
2443 }
2444
2445 /*if file is too large*/
2446 if ( ! empty( $max_size ) && $file_size > $max_size ) {
2447 wp_delete_file( $upload['file'] );
2448 /* translators: %s: maximum file size */
2449 return new WP_Error( 'import_file_error', sprintf( esc_html__( 'Remote file is too large, limit is %s', 'advanced-import' ), size_format( $max_size ) ) );
2450 }
2451 }
2452
2453 /*keep track of the old and new urls so we can substitute them later*/
2454 $this->imported_post_id( $url, $upload['url'] );
2455 $this->imported_post_id( $post['guid'], $upload['url'] );
2456
2457 /*keep track of the destination if the remote url is redirected somewhere else*/
2458 if ( isset( $headers['x-final-location'] ) && $headers['x-final-location'] != $url ) {
2459 $this->imported_post_id( $headers['x-final-location'], $upload['url'] );
2460 }
2461 return $upload;
2462 }
2463
2464 /*
2465 Replace necessary ID by Local imported ID
2466 */
2467 private function replace_old_id_to_new( $option_value, $index_key = false ) {
2468
2469 /*Post IDS*/
2470 $replace_post_ids = apply_filters(
2471 'advanced_import_replace_post_ids',
2472 array(
2473 'page_id',
2474 'post_id',
2475 'image_id',
2476 'selectpage',
2477 'page_on_front',
2478 'page_for_posts',
2479 'first_page_id',
2480 'second_page_id',
2481 /*woocommerce pages*/
2482 'woocommerce_shop_page_id',
2483 'woocommerce_cart_page_id',
2484 'woocommerce_checkout_page_id',
2485 'woocommerce_pay_page_id',
2486 'woocommerce_thanks_page_id',
2487 'woocommerce_myaccount_page_id',
2488 'woocommerce_edit_address_page_id',
2489 'woocommerce_view_order_page_id',
2490 'woocommerce_terms_page_id',
2491 /*gutentor*/
2492 'wp_block_id',
2493 )
2494 );
2495
2496 /*Terms IDS*/
2497 $replace_term_ids = apply_filters(
2498 'advanced_import_replace_term_ids',
2499 array(
2500 'cat_id',
2501 'nav_menu',
2502 'online-shop-feature-product-cat',
2503 'online_shop_featured_cats',
2504 'online_shop_wc_product_cat',
2505 'online_shop_wc_product_tag',
2506 )
2507 );
2508
2509 /*replace terms in keys*/
2510
2511 if ( is_array( $option_value ) ) {
2512 foreach ( $option_value as $key => $replace_old_value ) {
2513
2514 if ( is_array( $replace_old_value ) && ! is_null( $replace_old_value ) ) {
2515 $option_value[ $key ] = $this->replace_old_id_to_new( $replace_old_value );
2516 } elseif ( $this->isJson( $replace_old_value ) && is_string( $replace_old_value ) && ! is_null( $replace_old_value ) ) {
2517 $value_array = json_decode( $replace_old_value, true );
2518 if ( is_array( $value_array ) ) {
2519 $option_value[ $key ] = wp_json_encode( $this->replace_old_id_to_new( $value_array ) );
2520 } elseif ( in_array( $key, $replace_post_ids ) && $key !== 0 ) {
2521 $new_id = $this->imported_post_id( $replace_old_value );
2522 if ( $new_id ) {
2523 $option_value[ $key ] = $new_id;
2524 }
2525 } elseif ( in_array( $key, $replace_term_ids ) && $key !== 0 ) {
2526 $new_id = $this->imported_term_id( $replace_old_value );
2527 if ( $new_id ) {
2528 $option_value[ $key ] = $new_id;
2529 }
2530 } else {
2531 $option_value[ $key ] = $replace_old_value;
2532 }
2533 } elseif ( in_array( $key, $replace_post_ids ) && $key !== 0 ) {
2534
2535 $new_id = $this->imported_post_id( $replace_old_value );
2536 if ( ! $new_id ) {
2537 /* nothing for now*/
2538 } else {
2539 $option_value[ $key ] = $new_id;
2540 }
2541 } elseif ( in_array( $key, $replace_term_ids ) && $key !== 0 ) {
2542 $new_id = $this->imported_term_id( $replace_old_value );
2543 if ( $new_id ) {
2544 $option_value[ $key ] = $new_id;
2545 }
2546 } else {
2547 $option_value[ $key ] = $replace_old_value;
2548 }
2549 }
2550 } elseif ( is_numeric( $option_value ) && $index_key ) {
2551
2552 if ( in_array( $index_key, $replace_post_ids ) && $index_key !== 0 ) {
2553
2554 $new_id = $this->imported_post_id( $option_value );
2555 if ( ! $new_id ) {
2556 /* nothing for now*/
2557 } else {
2558 $option_value = $new_id;
2559 }
2560 } elseif ( in_array( $index_key, $replace_term_ids ) && $index_key !== 0 ) {
2561 $new_id = $this->imported_term_id( $option_value );
2562 if ( $new_id ) {
2563 $option_value = $new_id;
2564 }
2565 }
2566 }
2567
2568 return $option_value;
2569 }
2570
2571 /*
2572 * Callback function to importing widgets data
2573 * all widgets data is imported from here
2574 * return mix
2575 * */
2576 private function import_content_widgets_data() {
2577 $this->current_request = $this->current_request + 1;
2578
2579 $import_widget_data = $this->get_widgets_json();
2580 $import_widget_positions = $import_widget_data['widget_positions'];
2581 $import_widget_options = $import_widget_data['widget_options'];
2582
2583 /* get sidebars_widgets */
2584 $widget_positions = get_option( 'sidebars_widgets' );
2585 if ( ! is_array( $widget_positions ) ) {
2586 $widget_positions = array();
2587 }
2588
2589 foreach ( $import_widget_options as $widget_name => $widget_options ) {
2590
2591 /*replace $widget_options elements with updated imported entries.*/
2592 foreach ( $widget_options as $widget_option_id => $widget_option ) {
2593 $widget_options[ $widget_option_id ] = $this->replace_old_id_to_new( $widget_option, $widget_option_id );
2594 }
2595 $existing_options = get_option( 'widget_' . $widget_name, array() );
2596 if ( ! is_array( $existing_options ) ) {
2597 $existing_options = array();
2598 }
2599 $new_options = $widget_options + $existing_options;
2600
2601 $new_options = apply_filters( 'advanced_import_new_options', $new_options );
2602
2603 advanced_import_update_option( 'widget_' . $widget_name, $new_options );
2604 }
2605
2606 $sidebars_widgets = array_merge( $widget_positions, $import_widget_positions );
2607 $sidebars_widgets = apply_filters( 'advanced_import_sidebars_widgets', $sidebars_widgets, $this );
2608 advanced_import_update_option( 'sidebars_widgets', $sidebars_widgets );
2609
2610 return true;
2611 }
2612
2613 /**
2614 * Check if string is json.
2615 *
2616 * @since 1.0.0
2617 * @access public
2618 *
2619 * @param string $string Check if valid JSON.
2620 * @return boolean
2621 */
2622 function isJson( $string ) {
2623 if ( ! is_string( $string ) ) {
2624 return false;
2625 }
2626 json_decode( $string, true );
2627 return json_last_error() === JSON_ERROR_NONE;
2628 }
2629
2630 /*
2631 callback function to importing menus and options data
2632 * all menus and import data is imported from here
2633 * return mix
2634 * */
2635 public function import_menu_and_options() {
2636 $this->current_request = $this->current_request + 1;
2637
2638 /*final wrap up of delayed posts.*/
2639 $this->process_delayed_posts( true );
2640
2641 /*Elementor posts*/
2642 advanced_import_elementor()->process_elementor_posts();
2643
2644 /*it includes options and menu data*/
2645 $theme_options = $this->get_theme_options_json();
2646
2647 /*options data*/
2648 $custom_options = $theme_options['options'];
2649
2650 /*menu data*/
2651 $menu_ids = isset( $theme_options['menu'] ) ? $theme_options['menu'] : array();
2652
2653 /*we also want to update the widget area manager options.*/
2654 if ( is_array( $custom_options ) ) {
2655 foreach ( $custom_options as $option => $value ) {
2656 /*replace old entries with updated imported entries.*/
2657 $value = $this->replace_old_id_to_new( $value, $option );
2658
2659 /*we have to update widget page numbers with imported page numbers.*/
2660 if (
2661 preg_match( '#(wam__position_)(\d+)_#', $option, $matches ) ||
2662 preg_match( '#(wam__area_)(\d+)_#', $option, $matches )
2663 ) {
2664 $new_page_id = $this->imported_post_id( $matches[2] );
2665 if ( $new_page_id ) {
2666 // we have a new page id for this one. import the new setting value.
2667 $option = str_replace( $matches[1] . $matches[2] . '_', $matches[1] . $new_page_id . '_', $option );
2668 }
2669 } elseif ( $value && ! empty( $value['custom_logo'] ) ) {
2670 $new_logo_id = $this->imported_post_id( $value['custom_logo'] );
2671 if ( $new_logo_id ) {
2672 $value['custom_logo'] = $new_logo_id;
2673 }
2674 }
2675 /** For Gutentor */
2676 elseif ( strpos( $option, 'gutentor-cat' ) !== false ) {
2677 $cat_id = substr( $option, strrpos( $option, '-' ) + 1 );
2678 if ( 'child' !== $cat_id ) {
2679 $new_cat_id = $this->imported_term_id( $cat_id );
2680 $option = str_replace( $cat_id, $new_cat_id, $option );
2681 }
2682 }
2683 advanced_import_update_option( $option, $value );
2684 }
2685 }
2686
2687 /*
2688 Options completed
2689 Menu Start*/
2690 $save = array();
2691 if ( $menu_ids ) {
2692 foreach ( $menu_ids as $menu_id => $term_id ) {
2693 $new_term_id = $this->imported_term_id( $term_id );
2694 if ( $new_term_id ) {
2695 $save[ $menu_id ] = $new_term_id;
2696 }
2697 }
2698 }
2699
2700 if ( $save ) {
2701 set_theme_mod( 'nav_menu_locations', array_map( 'absint', $save ) );
2702 }
2703
2704 global $wp_rewrite;
2705 advanced_import_update_option( 'rewrite_rules', false );
2706 $wp_rewrite->flush_rules( false );
2707
2708 return true;
2709 }
2710
2711 public function log( $message ) {
2712 $this->logs[] = $message;
2713 }
2714
2715
2716 public function error( $message ) {
2717 $this->logs[] = esc_html__( 'ERROR!!!! ', 'advanced-import' ) . $message;
2718 }
2719
2720 public function reset_transient() {
2721 delete_transient( 'content.json' );
2722 delete_transient( 'widgets.json' );
2723 delete_transient( 'options.json' );
2724 delete_transient( 'delayed_posts' );
2725 delete_transient( 'imported_term_ids' );
2726 delete_transient( 'imported_post_ids' );
2727 delete_transient( 'post_orphans' );
2728 delete_transient( 'adi_elementor_data_posts' );
2729 }
2730
2731 /*
2732 Callback function to completed
2733 * Show Completed Message
2734 * */
2735 public function complete_screen() {
2736
2737 /*check for security*/
2738 if ( ! check_ajax_referer( 'advanced-import', 'wpnonce' ) ) {
2739 wp_die( esc_html__( 'Security check failed.', 'advanced-import' ) );
2740 }
2741
2742 if ( ! current_user_can( 'upload_files' ) ) {
2743 wp_send_json_error(
2744 array(
2745 'message' => esc_html__( 'Sorry, you are not allowed to install demo on this site.', 'advanced-import' ),
2746 )
2747 );
2748 }
2749
2750 require_once ABSPATH . 'wp-admin/includes/file.php';
2751 WP_Filesystem();
2752 global $wp_filesystem;
2753 $wp_filesystem->rmdir( ADVANCED_IMPORT_TEMP, true );
2754
2755 set_theme_mod( 'advanced_import_setup_complete', time() );
2756
2757 /*delete_transient();*/
2758 $this->reset_transient();
2759
2760 $message = '<div class="ai-notification-title">';
2761 $message .= '<p>' . esc_html__( 'Your Website is Ready!', 'advanced-import' ) . '</p>';
2762 /* translators: %1$s: opening anchor tag, %2$s: closing anchor tag */
2763 $message .= '<p class="ai-actions-buttons">' . sprintf( esc_html__( ' %1$sVisit your Site%2$s ', 'advanced-import' ), '<a target="_blank" href="' . esc_url( home_url( '/' ) ) . '">', '</a>' ) . '</p>';
2764 /* translators: %1$s: opening anchor tag, %2$s: closing anchor tag */
2765 $message .= '<p>' . sprintf( esc_html__( 'Congratulations! All Data is imported successfully. From %1$s WordPress dashboard%2$s you can make changes and modify any of the default content to suit your needs.', 'advanced-import' ), '<a href="' . esc_url( admin_url() ) . '">', '</a>' ) . '</p>';
2766 $message .= '</div>';
2767
2768 $message = apply_filters( 'advanced_import_complete_message', $message );
2769
2770 do_action( 'advanced_import_before_complete_screen' );
2771 echo wp_kses_post( $message );
2772 do_action( 'advanced_import_after_complete_screen' );
2773 exit;
2774 }
2775
2776 /*
2777 callback function for wp_ajax_install_plugin
2778 * Install plugin
2779 * */
2780 function install_plugin() {
2781
2782 /*check for security*/
2783 check_admin_referer( 'advanced-import' );
2784
2785 if ( empty( $_POST['plugin'] ) || empty( $_POST['slug'] ) ) {
2786 wp_send_json_error(
2787 array(
2788 'slug' => '',
2789 'errorCode' => 'no_plugin_specified',
2790 'errorMessage' => __( 'No plugin specified.', 'advanced-import' ),
2791 )
2792 );
2793 }
2794
2795 $slug = sanitize_key( wp_unslash( $_POST['slug'] ) );
2796 $plugin = plugin_basename( sanitize_text_field( wp_unslash( $_POST['plugin'] ) ) );
2797
2798 $plugin_info = array();
2799 $plugin_info['name'] = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : '';
2800 $plugin_info['slug'] = $slug;
2801 $plugin_info['plugin'] = $plugin;
2802 $plugin_info['source'] = isset( $_POST['source'] ) ? esc_url_raw( wp_unslash( $_POST['source'] ) ) : '';
2803
2804 $result = advanced_import_install_plugin( $plugin_info );
2805
2806 $response = array();
2807
2808 $response['success'] = $result['success'];
2809 $response['plugin'] = $plugin;
2810 $response['slug'] = $slug;
2811 if ( ! $result['success'] ) {
2812 $response['errorCode'] = $result['code'];
2813 $response['errorMessage'] = $result['message'];
2814
2815 wp_send_json_error( $response );
2816 }
2817 wp_send_json_success( $response );
2818 }
2819
2820 /**
2821 * Add help text to the current screen.
2822 *
2823 * @since 1.0.0
2824 * @param WP_Screen $screen Current WP_Screen object.
2825 * @return void
2826 */
2827 public function help_tabs( $screen ) {
2828 if ( ! is_array( $this->hook_suffix ) || ! in_array( $screen->base, $this->hook_suffix ) ) {
2829 return;
2830 }
2831 $current_url = advanced_import_current_url();
2832
2833 $screen->add_help_tab(
2834 array(
2835 'id' => 'ai_help_tab_info',
2836 'title' => __( 'Information', 'advanced-import' ),
2837 'content' =>
2838 '<h2>' . __( 'Information', 'advanced-import' ) . '</h2>' .
2839 '<p>' . sprintf(
2840 /* translators: %s: link to Advanced Export plugin */
2841 __( 'Export you content via, <a href="%s" target="_blank">Advanced Export</a>. You can import export content, widget, customizer and media files too.', 'advanced-import' ),
2842 'https://wordpress.org/plugins/advanced-export/'
2843 ) . '</p>' .
2844 '<p>' . sprintf(
2845 /* translators: %1$s: link to Advanced Export, %2$s: link to Advanced Import */
2846 __( 'The zip file exported via <a href="%1$s" target="_blank">Advanced Export</a>. can be imported from this plugin <a href="%2$s">Advanced Import</a>.', 'advanced-import' ),
2847 'https://wordpress.org/support/plugin/advanced-export',
2848 'https://wordpress.org/support/plugin/advanced-import'
2849 ) . '</p>' .
2850 '<p><a href="' . 'https://wordpress.org/support/plugin/advanced-import' . '" class="button button-primary" target="_blank">' . __( 'Community forum', 'advanced-import' ) . '</a> <a href="' . 'https://www.addonspress.com/' . '" class="button" target="_blank">' . __( 'Author', 'advanced-import' ) . '</a></p>',
2851 )
2852 );
2853
2854 $reset_url = wp_nonce_url(
2855 add_query_arg( 'ai_reset_wordpress', 'true', $current_url ),
2856 'ai_reset_wordpress',
2857 'ai_reset_wordpress_nonce'
2858 );
2859 $screen->add_help_tab(
2860 array(
2861 'id' => 'ai_help_tab_reset',
2862 'title' => __( 'Reset wizard', 'advanced-import' ),
2863 'content' =>
2864 '<h2><strong>' . __( 'WordPress Reset', 'advanced-import' ) . '</strong></h2>' .
2865 '<p>' . __( 'If no important data on your site. You can reset the WordPress back to default again!', 'advanced-import' ) . '</p>' .
2866 '<p class="submit">' . wp_nonce_field( 'advanced-import-reset', 'advanced-import-reset', true, false ) . '<a href="' . esc_url( $reset_url ) . '" class="button button-primary ai-wp-reset">' . __( 'Run the Reset Wizard', 'advanced-import' ) . '</a></p>',
2867 )
2868 );
2869
2870 $screen->set_help_sidebar(
2871 '<p><strong>' . __( 'More information:', 'advanced-import' ) . '</strong></p>' .
2872 '<p><a href="' . 'https://wordpress.org/plugins/advanced-export/' . '" target="_blank">' . __( 'Advanced Export', 'advanced-import' ) . '</a></p>' .
2873 '<p><a href="' . 'https://wordpress.org/plugins/advanced-import/' . '" target="_blank">' . __( 'Advanced Import', 'advanced-import' ) . '</a></p>'
2874 );
2875
2876 global $advanced_import_tracking;
2877 ob_start();
2878 $advanced_import_tracking->admin_notice( true );
2879 $has_admin_notice = ob_get_contents();
2880 ob_end_clean();
2881 if ( $has_admin_notice ) {
2882 $has_admin_notice = '<h2><strong>' . __( 'Allow Track', 'advanced-import' ) . '</strong></h2>' . $has_admin_notice;
2883 $screen->add_help_tab(
2884 array(
2885 'id' => 'ai_help_tab_track',
2886 'title' => __( 'Allow Track', 'advanced-import' ),
2887 'content' => $has_admin_notice,
2888 )
2889 );
2890 }
2891 }
2892 }
2893
2894 /**
2895 * Begins execution of the plugin.
2896 *
2897 * Since everything within the plugin is registered via hooks,
2898 * then kicking off the plugin from this point in the file does
2899 * not affect the page life cycle.
2900 *
2901 * @since 1.0.0
2902 */
2903 function advanced_import_admin() {
2904 return Advanced_Import_Admin::instance();
2905 }
2906