PluginProbe ʕ •ᴥ•ʔ
Kubio AI Page Builder / 2.4.3
Kubio AI Page Builder v2.4.3
2.8.4 2.8.3 2.8.2 2.8.1 trunk 1.0.0 1.0.1 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.9.0 2.0.0 2.1.1 2.1.2 2.1.3 2.2.0 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.5 2.5.0 2.5.1 2.5.2 2.5.3 2.6.0 2.6.1 2.6.2 2.6.3 2.6.5 2.6.6 2.6.7 2.7.0 2.7.1 2.7.2 2.7.3 2.8.0
kubio / lib / src / DemoSites / DemoSitesImporter.php
kubio / lib / src / DemoSites Last commit date
DemoSites.php 2 years ago DemoSitesHelpers.php 2 years ago DemoSitesImportBlockMap.php 4 years ago DemoSitesImporter.php 2 years ago DemoSitesLogger.php 4 years ago DemoSitesRepository.php 2 years ago WXRExporter.php 4 years ago WXRImporter.php 2 years ago
DemoSitesImporter.php
581 lines
1 <?php
2
3 namespace Kubio\DemoSites;
4
5 use IlluminateAgnostic\Arr\Support\Arr;
6 use Kubio\Core\Importer;
7 use Kubio\Flags;
8
9 class DemoSitesImporter {
10 private $logger = null;
11 private $slug = 0;
12 private $log_file_path;
13
14 private $importer;
15 private $wxr_file;
16 private $before_import_executed = false;
17 private $options;
18 private $config;
19
20 public function __construct( $type = 'ajax', $config = array() ) {
21 if ( $type === 'ajax' ) {
22 // pick up only a few keys from the request.
23 $this->config = wp_parse_args(
24 $_REQUEST,
25 array(
26 'is_stepped' => true,
27 'first_call' => false,
28 'before_import_action' => '',
29 'fetch_attachments' => false,
30 )
31 );
32 } else {
33 $this->config = wp_parse_args(
34 $config,
35 array(
36 'is_stepped' => false,
37 'fetch_attachments' => false,
38 )
39 );
40
41 // on cli we only set these once.
42 $this->setLogger();
43 $this->setImporter( $this->config );
44 $this->maybeCleanupData();
45
46 DemoSitesHelpers::setImportStartTime();
47
48 $this->log_file_path = DemoSitesHelpers::getLogFile();
49 $this->logger->logger_file = $this->log_file_path;
50 }
51
52 $this->slug = Arr::get( $this->config, 'slug', 0 );
53 add_action( 'wp_ajax_kubio-demo-site-import-data', array( $this, 'ajaxImportDemoData' ) );
54 }
55
56 public static function load() {
57 new static();
58 }
59
60 /**
61 * This is the ajax callback added to `wp_ajax_kubio-demo-site-import-data` and it will import a demo-data by a
62 * given slug, and it will kill the execution with a json message on success ore failure.
63 *
64 */
65 public function ajaxImportDemoData() {
66 $this->setLogger();
67 $this->setImporter( $this->config );
68 $this->maybeCleanupData();
69
70 DemoSitesHelpers::verifyAjaxCall();
71
72 // Is this a new AJAX call to continue the previous import?
73 $use_existing_importer_data = $this->useExistingImporterData();
74
75 if ( ! $use_existing_importer_data ) {
76 DemoSitesHelpers::setImportStartTime();
77
78 $this->log_file_path = DemoSitesHelpers::getLogFile();
79 }
80
81 $this->logger->logger_file = $this->log_file_path;
82
83 $this->setIniMemoryLimit();
84
85 if ( ! $use_existing_importer_data ) {
86 $kds_file = Arr::get( $_FILES, 'kds_file', null );
87 if ( ! $kds_file ) {
88 $this->prepareRemoteImport();
89 } else {
90 $this->prepareManualImport( $kds_file );
91 }
92 }
93
94 DemoSitesHelpers::setImportDataTransient( $this->getCurrentImportData() );
95
96 if ( ! $this->before_import_executed ) {
97
98 $before_import_action = Arr::get( $this->config, 'before_import_action', null );
99
100 if ( ! $before_import_action ) {
101 $response = array(
102 'status' => 'requires-new-ajax-call',
103 'before_import_action' => 'init',
104 );
105 wp_send_json( $response );
106 } else {
107 $this->executeBeforeImportAction( $before_import_action );
108 }
109
110 $this->before_import_executed = true;
111 DemoSitesHelpers::setImportDataTransient( $this->getCurrentImportData() );
112 $response = array(
113 'status' => 'requires-new-ajax-call',
114 'log' => 'Before import executed',
115 );
116 wp_send_json( $response );
117
118 }
119
120 if ( $this->wxr_file && file_exists( $this->wxr_file ) ) {
121 add_action( 'kubio/demo-site-import/post-process', array( $this, 'postProcessContentImport' ) );
122 $this->importer->import_content( $this->wxr_file );
123 }
124
125 $this->afterImport();
126 }
127
128 /**
129 * This method is used to import a demo-data design via WP CLI for a given slug.
130 * eg: `wp kubio:import-design accounting-demo-site`
131 *
132 * @return false|string
133 */
134 public function cliImportDemoData( $args ) {
135 $this->setIniMemoryLimit();
136
137 if ( isset( $args['is_custom'] ) && $args['is_custom'] ) {
138 $this->loadKDSFile( $args['kds_url'] );
139 } else {
140 $this->prepareRemoteImport();
141 }
142
143 DemoSitesHelpers::setImportDataTransient( $this->getCurrentImportData() );
144
145 if ( $this->wxr_file && file_exists( $this->wxr_file ) ) {
146 add_action( 'kubio/demo-site-import/post-process', array( $this, 'postProcessContentImport' ) );
147 $this->importer->import_content( $this->wxr_file );
148 }
149
150 return $this->afterImport( false );
151 }
152
153 /**
154 * A methods which sets `$this->logger` as an instance of `DemoSitesLogger`
155 */
156 private function setLogger() {
157 $this->logger = new DemoSitesLogger();
158 $this->logger->min_level = 'info';
159 $this->logger->logger_file = '';
160 }
161
162 /**
163 * A methods which sets `$this->importer` as an instance of `WXRImporter`
164 */
165 private function setImporter( $config ) {
166 if ( ! class_exists( '\WP_Importer' ) ) {
167 require ABSPATH . '/wp-admin/includes/class-wp-importer.php';
168 }
169
170 $this->importer = new WXRImporter(
171 array(
172 'fetch_attachments' => Arr::get( $config, 'fetch_attachments', true ),
173 'is_stepped' => Arr::get( $config, 'is_stepped', true ),
174 ),
175 $this->logger
176 );
177
178 }
179
180 /**
181 * In the first call try to delete old transients.
182 */
183 private function maybeCleanupData() {
184 if ( Arr::get( $this->config, 'first_call', null ) ) {
185 delete_transient( DemoSitesHelpers::IMPORT_TRANSIENT );
186 $this->importer->delete_import_data_transient();
187 }
188 }
189
190 /**
191 * Try to set a ini value of 512M for `memory_limit`.
192 * If it is not allowed warn in the logs about it.
193 */
194 private function setIniMemoryLimit() {
195 if ( ! @ini_set( 'memory_limit', '512M' ) ) {
196 DemoSitesHelpers::appendToFile(
197 esc_html__( 'Warn: Unable set memory_limit', 'kubio' ),
198 $this->log_file_path
199 );
200 }
201 }
202
203 private function useExistingImporterData() {
204 if ( $data = get_transient( DemoSitesHelpers::IMPORT_TRANSIENT ) ) {
205 $this->log_file_path = empty( $data['log_file_path'] ) ? '' : $data['log_file_path'];
206 $this->slug = empty( $data['slug'] ) ? null : $data['slug'];
207 $this->wxr_file = empty( $data['wxr_file'] ) ? array() : $data['wxr_file'];
208 $this->options = empty( $data['options'] ) ? array() : $data['options'];
209 $this->before_import_executed = empty( $data['before_import_executed'] ) ? array() : $data['before_import_executed'];
210
211 return true;
212 }
213
214 return false;
215 }
216
217 private function prepareRemoteImport() {
218 $this->logger->info( 'Prepare remote import' );
219
220 $demo = $this->getDemo();
221 if ( $demo !== null ) {
222 $kds = Arr::get( $demo, 'kds_url', null );
223 $this->loadKDSFile( $kds );
224 } else {
225 // Send JSON Error response to the AJAX call.
226 DemoSitesHelpers::sendAjaxError( esc_html__( 'No import files specified!', 'kubio' ) );
227 }
228 }
229
230
231 private function loadKDSFile( $kds ) {
232 if ( $kds ) {
233 $result = DemoSitesHelpers::extractImporterFilesFromSource( $kds );
234
235 if ( is_wp_error( $result ) ) {
236 DemoSitesHelpers::sendAjaxError( $result->get_error_message() );
237 }
238
239 list( $wxr_file, $extra_options ) = $result;
240
241 if ( is_wp_error( $wxr_file ) ) {
242 DemoSitesHelpers::logErrorAndSendAjaxResponse(
243 $wxr_file->get_error_message(),
244 $this->log_file_path,
245 esc_html__( 'Downloaded files', 'kubio' )
246 );
247 } else {
248 $this->wxr_file = $wxr_file;
249 $this->options = $extra_options;
250 }
251 } else {
252 DemoSitesHelpers::logErrorAndSendAjaxResponse(
253 esc_html__( 'Import file undefined', 'kubio' ),
254 $this->log_file_path,
255 esc_html__( 'Downloaded files', 'kubio' )
256 );
257 }
258
259 DemoSitesHelpers::appendToFile(
260 sprintf( /* translators: %s - the name of the selected import. */
261 __( 'The import files for: %s were successfully downloaded!', 'kubio' ),
262 $kds
263 ),
264 $this->log_file_path,
265 esc_html__( 'Downloaded files', 'kubio' )
266 );
267 }
268
269 private function getDemo() {
270 $demos = apply_filters( 'kubio/demo-sites/list', array() );
271 $slug = $this->slug;
272
273 return Arr::get( $demos, $slug, null );
274 }
275
276 private function prepareManualImport( $kds_file ) {
277
278 DemoSitesHelpers::appendToFile(
279 __( 'Manual kds import!', 'kubio' ),
280 $this->log_file_path,
281 esc_html__( 'Manual import', 'kubio' )
282 );
283
284 list( $wxr_file, $extra_options ) = DemoSitesHelpers::useUploadedKDSFile( Arr::get( $kds_file, 'tmp_name', null ) );
285 $this->wxr_file = $wxr_file;
286 $this->options = $extra_options;
287 }
288
289 /**
290 * Get the current state of selected data.
291 *
292 * @return array
293 */
294 public function getCurrentImportData() {
295 return array(
296 'log_file_path' => $this->log_file_path,
297 'slug' => $this->slug,
298 'wxr_file' => $this->wxr_file,
299 'options' => $this->options,
300 'before_import_executed' => $this->before_import_executed,
301 );
302 }
303
304 public function getBeforeImportActions() {
305 return array( 'init', 'prepare_templates', 'prepare_template_parts', 'prepare_menus', 'prepare_pages' );
306 }
307
308 /**
309 * This method executes the valid given $action, logs in case of error, and returns the status of ajax/cli queue.
310 * Based on the $ajax parameter it will kill the execution with an `wp_send_json` response or it will print the json.
311 *
312 * @param $action
313 * @param bool $ajax
314 * @return false|string|void
315 */
316 public function executeBeforeImportAction( $action, $ajax = true ) {
317 $actions = $this->getBeforeImportActions();
318 $action_index = array_search( $action, $actions );
319
320 if ( $action_index === false ) {
321 DemoSitesHelpers::sendAjaxError( __( 'Importer action not found', 'kubio' ) );
322 }
323
324 $this->logger->info( "Executing before import step: {$action}" );
325
326 switch ( $action ) {
327
328 case 'init':
329 $site_url = Arr::get( $this->options, 'site_url' );
330 if ( $site_url ) {
331 wp_remote_get( $site_url );
332 }
333 break;
334
335 case 'prepare_templates':
336 $this->prepareTemplates();
337 break;
338
339 case 'prepare_template_parts':
340 $this->prepareTemplateParts();
341 break;
342
343 case 'prepare_pages':
344 $this->preparePages();
345 break;
346
347 case 'prepare_menus':
348 $this->prepareMenus();
349 break;
350 }
351
352 if ( $action_index + 1 < count( $actions ) ) {
353 $response = array(
354 'status' => 'requires-new-ajax-call',
355 'before_import_action' => $actions[ $action_index + 1 ],
356 );
357
358 if ( $ajax ) {
359 wp_send_json( $response );
360 }
361
362 return wp_json_encode( $response );
363 }
364 }
365
366 private function prepareTemplates() {
367 $stylesheet = get_stylesheet();
368 $ids = get_posts(
369 array(
370 'post_type' => 'wp_template',
371 'post_status' => array( 'publish' ),
372 'posts_per_page' => - 1,
373 'tax_query' => array(
374 array(
375 'taxonomy' => 'wp_theme',
376 'field' => 'name',
377 'terms' => array( $stylesheet ),
378 ),
379 ),
380 'fields' => 'ids',
381 )
382 );
383
384 foreach ( $ids as $id ) {
385 wp_delete_post( $id, true );
386 }
387 }
388
389 private function prepareTemplateParts() {
390 $stylesheet = get_stylesheet();
391 $ids = get_posts(
392 array(
393 'post_type' => 'wp_template_part',
394 'post_status' => array( 'publish' ),
395 'posts_per_page' => - 1,
396 'tax_query' => array(
397 array(
398 'taxonomy' => 'wp_theme',
399 'field' => 'name',
400 'terms' => array( $stylesheet ),
401 ),
402 ),
403 'fields' => 'ids',
404 )
405 );
406
407 foreach ( $ids as $id ) {
408 wp_delete_post( $id, true );
409 }
410 }
411
412 private function preparePages() {
413 $ids = get_posts(
414 array(
415 'post_type' => 'page',
416 'post_status' => array( 'publish', 'draft' ),
417 'posts_per_page' => - 1,
418 'fields' => 'ids',
419 )
420 );
421
422 foreach ( $ids as $id ) {
423 wp_delete_post( $id, false );
424 }
425 }
426
427 private function prepareMenus() {
428 $menus = wp_get_nav_menus();
429
430 /** @var \WP_Term $menu */
431 foreach ( $menus as $menu ) {
432 $index = - 1;
433 do {
434 $index ++;
435 list($base_name) = sscanf( $menu->name, '%s - %s' );
436
437 $new_name = sprintf(
438 '%s - %s',
439 $base_name,
440 // translators: %s - menu item name e.g. "Home", "Contact"
441 $index ? sprintf( __( 'Old %s', 'kubio' ), $index ) : __( 'Old', 'kubio' )
442 );
443
444 } while ( ! ! get_term_by( 'name', $new_name, 'nav_menu' ) );
445
446 wp_update_nav_menu_object(
447 $menu->term_id,
448 array(
449 'menu-name' => $new_name,
450 )
451 );
452 }
453
454 }
455
456 /**
457 * Send a JSON response with final report or simply returns the json if $ajax is false.
458 *
459 * @param bool $ajax
460 * @return false|string
461 */
462 private function afterImport( $ajax = true ) {
463
464 $this->useExistingImporterData();
465
466 if ( $this->slug ) {
467 Flags::set( 'last_imported_starter', $this->slug );
468 }
469
470 // Delete importer data transient for current import.
471 delete_transient( DemoSitesHelpers::IMPORT_TRANSIENT );
472
473 $response = array(
474 'status' => 'finished',
475 );
476
477 if ( $ajax ) {
478 wp_send_json( $response );
479 }
480
481 return wp_json_encode( $response );
482 }
483
484 //this updates the count column in the wp_term_taxonomy table because in some cases it was still at 0 showing empty menus
485 public function updateMenuItemsCount( $wxr_importer ) {
486 $update_taxonomy = 'nav_menu';
487 $menus_id_map = Arr::get( $wxr_importer->get_mapping(), 'menus_map', array() );
488 wp_update_term_count_now( $menus_id_map, $update_taxonomy );
489 }
490 /**
491 * @param WXRImporter $wxr_importer
492 */
493 public function postProcessContentImport( $wxr_importer ) {
494 $this->updateThemeMods( $wxr_importer );
495 $this->updateLogos( $wxr_importer );
496 $this->updateFrontPages( $wxr_importer );
497 $this->updateGlobalNonKubioTemplates();
498 $this->updateMenuItemsCount( $wxr_importer );
499 }
500
501
502 private function updateGlobalNonKubioTemplates() {
503 wp_cache_flush();
504 $blog_templates = array(
505 'singular' => 'single',
506 'home' => 'index',
507 );
508
509 foreach ( $blog_templates as $template => $replacement ) {
510 if ( kubio_has_block_template( $template ) ) {
511 $replacement_template = kubio_get_block_template( $replacement );
512 if ( $replacement_template ) {
513 Importer::createTemplate( $template, $replacement_template->content, true, 'kubio' );
514 }
515 }
516 }
517 }
518
519 /**
520 * @param WXRImporter $wxr_importer
521 */
522 private function updateThemeMods( $wxr_importer ) {
523
524 $theme_mods = Arr::get( $this->options, 'customizer', array() );
525
526 unset( $theme_mods[0] );
527
528 // update nav menu locations
529 $menus_id_map = Arr::get( $wxr_importer->get_mapping(), 'menus_map', array() );
530 $nav_menu_locations = Arr::get( $theme_mods, 'nav_menu_locations', array() );
531 foreach ( $nav_menu_locations as $location => $term_id ) {
532 $next_term_id = Arr::get( $menus_id_map, $term_id, null );
533
534 if ( $next_term_id ) {
535 $nav_menu_locations[ $location ] = (int) $next_term_id;
536 } else {
537 unset( $nav_menu_locations[ $location ] );
538 }
539 }
540 $theme_mods['nav_menu_locations'] = $nav_menu_locations;
541
542 $theme = get_option( 'stylesheet' );
543
544 update_option( "theme_mods_$theme", $theme_mods );
545 }
546
547 /**
548 * @param WXRImporter $wxr_importer
549 */
550 private function updateLogos( $wxr_importer ) {
551 $alternate_logo_image = kubio_get_global_data( 'alternateLogo' );
552 $post_mapping = Arr::get( $wxr_importer->get_mapping(), 'post', array() );
553 if ( $alternate_logo_image ) {
554 kubio_set_global_data( 'alternateLogo', Arr::get( $post_mapping, $alternate_logo_image, $alternate_logo_image ) );
555 }
556
557 $logos_options = array( 'site_logo', 'site_icon' );
558
559 foreach ( $logos_options as $option ) {
560 $value = Arr::get( $this->options, "options.{$option}", 0 );
561 $value = Arr::get( $post_mapping, $value, $value );
562 update_option( $option, is_numeric( $value ) ? intval( $value ) : $value );
563 }
564 }
565
566 /**
567 * @param WXRImporter $wxr_importer
568 */
569 private function updateFrontPages( $wxr_importer ) {
570 $page_options = array( 'page_on_front', 'page_for_posts', 'show_on_front' );
571
572 $post_mapping = Arr::get( $wxr_importer->get_mapping(), 'post', array() );
573
574 foreach ( $page_options as $option ) {
575 $value = Arr::get( $this->options, "options.{$option}", 0 );
576 $value = Arr::get( $post_mapping, $value, $value );
577 update_option( $option, is_numeric( $value ) ? intval( $value ) : $value );
578 }
579 }
580 }
581