PluginProbe ʕ •ᴥ•ʔ
Kubio AI Page Builder / 2.2.0
Kubio AI Page Builder v2.2.0
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 3 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
575 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 list( $wxr_file, $extra_options ) = DemoSitesHelpers::extractImporterFilesFromSource( $kds );
234
235 if ( is_wp_error( $wxr_file ) ) {
236 DemoSitesHelpers::logErrorAndSendAjaxResponse(
237 $wxr_file->get_error_message(),
238 $this->log_file_path,
239 esc_html__( 'Downloaded files', 'kubio' )
240 );
241 } else {
242 $this->wxr_file = $wxr_file;
243 $this->options = $extra_options;
244 }
245 } else {
246 DemoSitesHelpers::logErrorAndSendAjaxResponse(
247 esc_html__( 'Import file undefined', 'kubio' ),
248 $this->log_file_path,
249 esc_html__( 'Downloaded files', 'kubio' )
250 );
251 }
252
253 DemoSitesHelpers::appendToFile(
254 sprintf( /* translators: %s - the name of the selected import. */
255 __( 'The import files for: %s were successfully downloaded!', 'kubio' ),
256 $kds
257 ),
258 $this->log_file_path,
259 esc_html__( 'Downloaded files', 'kubio' )
260 );
261 }
262
263 private function getDemo() {
264 $demos = apply_filters( 'kubio/demo-sites/list', array() );
265 $slug = $this->slug;
266
267 return Arr::get( $demos, $slug, null );
268 }
269
270 private function prepareManualImport( $kds_file ) {
271
272 DemoSitesHelpers::appendToFile(
273 __( 'Manual kds import!', 'kubio' ),
274 $this->log_file_path,
275 esc_html__( 'Manual import', 'kubio' )
276 );
277
278 list( $wxr_file, $extra_options ) = DemoSitesHelpers::useUploadedKDSFile( Arr::get( $kds_file, 'tmp_name', null ) );
279 $this->wxr_file = $wxr_file;
280 $this->options = $extra_options;
281 }
282
283 /**
284 * Get the current state of selected data.
285 *
286 * @return array
287 */
288 public function getCurrentImportData() {
289 return array(
290 'log_file_path' => $this->log_file_path,
291 'slug' => $this->slug,
292 'wxr_file' => $this->wxr_file,
293 'options' => $this->options,
294 'before_import_executed' => $this->before_import_executed,
295 );
296 }
297
298 public function getBeforeImportActions() {
299 return array( 'init', 'prepare_templates', 'prepare_template_parts', 'prepare_menus', 'prepare_pages' );
300 }
301
302 /**
303 * This method executes the valid given $action, logs in case of error, and returns the status of ajax/cli queue.
304 * Based on the $ajax parameter it will kill the execution with an `wp_send_json` response or it will print the json.
305 *
306 * @param $action
307 * @param bool $ajax
308 * @return false|string|void
309 */
310 public function executeBeforeImportAction( $action, $ajax = true ) {
311 $actions = $this->getBeforeImportActions();
312 $action_index = array_search( $action, $actions );
313
314 if ( $action_index === false ) {
315 DemoSitesHelpers::sendAjaxError( __( 'Importer action not found', 'kubio' ) );
316 }
317
318 $this->logger->info( "Executing before import step: {$action}" );
319
320 switch ( $action ) {
321
322 case 'init':
323 $site_url = Arr::get( $this->options, 'site_url' );
324 if ( $site_url ) {
325 wp_remote_get( $site_url );
326 }
327 break;
328
329 case 'prepare_templates':
330 $this->prepareTemplates();
331 break;
332
333 case 'prepare_template_parts':
334 $this->prepareTemplateParts();
335 break;
336
337 case 'prepare_pages':
338 $this->preparePages();
339 break;
340
341 case 'prepare_menus':
342 $this->prepareMenus();
343 break;
344 }
345
346 if ( $action_index + 1 < count( $actions ) ) {
347 $response = array(
348 'status' => 'requires-new-ajax-call',
349 'before_import_action' => $actions[ $action_index + 1 ],
350 );
351
352 if ( $ajax ) {
353 wp_send_json( $response );
354 }
355
356 return wp_json_encode( $response );
357 }
358 }
359
360 private function prepareTemplates() {
361 $stylesheet = get_stylesheet();
362 $ids = get_posts(
363 array(
364 'post_type' => 'wp_template',
365 'post_status' => array( 'publish' ),
366 'posts_per_page' => - 1,
367 'tax_query' => array(
368 array(
369 'taxonomy' => 'wp_theme',
370 'field' => 'name',
371 'terms' => array( $stylesheet ),
372 ),
373 ),
374 'fields' => 'ids',
375 )
376 );
377
378 foreach ( $ids as $id ) {
379 wp_delete_post( $id, true );
380 }
381 }
382
383 private function prepareTemplateParts() {
384 $stylesheet = get_stylesheet();
385 $ids = get_posts(
386 array(
387 'post_type' => 'wp_template_part',
388 'post_status' => array( 'publish' ),
389 'posts_per_page' => - 1,
390 'tax_query' => array(
391 array(
392 'taxonomy' => 'wp_theme',
393 'field' => 'name',
394 'terms' => array( $stylesheet ),
395 ),
396 ),
397 'fields' => 'ids',
398 )
399 );
400
401 foreach ( $ids as $id ) {
402 wp_delete_post( $id, true );
403 }
404 }
405
406 private function preparePages() {
407 $ids = get_posts(
408 array(
409 'post_type' => 'page',
410 'post_status' => array( 'publish', 'draft' ),
411 'posts_per_page' => - 1,
412 'fields' => 'ids',
413 )
414 );
415
416 foreach ( $ids as $id ) {
417 wp_delete_post( $id, false );
418 }
419 }
420
421 private function prepareMenus() {
422 $menus = wp_get_nav_menus();
423
424 /** @var \WP_Term $menu */
425 foreach ( $menus as $menu ) {
426 $index = - 1;
427 do {
428 $index ++;
429 list($base_name) = sscanf( $menu->name, '%s - %s' );
430
431 $new_name = sprintf(
432 '%s - %s',
433 $base_name,
434 // translators: %s - menu item name e.g. "Home", "Contact"
435 $index ? sprintf( __( 'Old %s', 'kubio' ), $index ) : __( 'Old', 'kubio' )
436 );
437
438 } while ( ! ! get_term_by( 'name', $new_name, 'nav_menu' ) );
439
440 wp_update_nav_menu_object(
441 $menu->term_id,
442 array(
443 'menu-name' => $new_name,
444 )
445 );
446 }
447
448 }
449
450 /**
451 * Send a JSON response with final report or simply returns the json if $ajax is false.
452 *
453 * @param bool $ajax
454 * @return false|string
455 */
456 private function afterImport( $ajax = true ) {
457
458 $this->useExistingImporterData();
459
460 if ( $this->slug ) {
461 Flags::set( 'last_imported_starter', $this->slug );
462 }
463
464 // Delete importer data transient for current import.
465 delete_transient( DemoSitesHelpers::IMPORT_TRANSIENT );
466
467 $response = array(
468 'status' => 'finished',
469 );
470
471 if ( $ajax ) {
472 wp_send_json( $response );
473 }
474
475 return wp_json_encode( $response );
476 }
477
478 //this updates the count column in the wp_term_taxonomy table because in some cases it was still at 0 showing empty menus
479 public function updateMenuItemsCount( $wxr_importer ) {
480 $update_taxonomy = 'nav_menu';
481 $menus_id_map = Arr::get( $wxr_importer->get_mapping(), 'menus_map', array() );
482 wp_update_term_count_now( $menus_id_map, $update_taxonomy );
483 }
484 /**
485 * @param WXRImporter $wxr_importer
486 */
487 public function postProcessContentImport( $wxr_importer ) {
488 $this->updateThemeMods( $wxr_importer );
489 $this->updateLogos( $wxr_importer );
490 $this->updateFrontPages( $wxr_importer );
491 $this->updateGlobalNonKubioTemplates();
492 $this->updateMenuItemsCount( $wxr_importer );
493 }
494
495
496 private function updateGlobalNonKubioTemplates() {
497 wp_cache_flush();
498 $blog_templates = array(
499 'singular' => 'single',
500 'home' => 'index',
501 );
502
503 foreach ( $blog_templates as $template => $replacement ) {
504 if ( kubio_has_block_template( $template ) ) {
505 $replacement_template = kubio_get_block_template( $replacement );
506 if ( $replacement_template ) {
507 Importer::createTemplate( $template, $replacement_template->content, true, 'kubio' );
508 }
509 }
510 }
511 }
512
513 /**
514 * @param WXRImporter $wxr_importer
515 */
516 private function updateThemeMods( $wxr_importer ) {
517
518 $theme_mods = Arr::get( $this->options, 'customizer', array() );
519
520 unset( $theme_mods[0] );
521
522 // update nav menu locations
523 $menus_id_map = Arr::get( $wxr_importer->get_mapping(), 'menus_map', array() );
524 $nav_menu_locations = Arr::get( $theme_mods, 'nav_menu_locations', array() );
525 foreach ( $nav_menu_locations as $location => $term_id ) {
526 $next_term_id = Arr::get( $menus_id_map, $term_id, null );
527
528 if ( $next_term_id ) {
529 $nav_menu_locations[ $location ] = (int) $next_term_id;
530 } else {
531 unset( $nav_menu_locations[ $location ] );
532 }
533 }
534 $theme_mods['nav_menu_locations'] = $nav_menu_locations;
535
536 $theme = get_option( 'stylesheet' );
537
538 update_option( "theme_mods_$theme", $theme_mods );
539 }
540
541 /**
542 * @param WXRImporter $wxr_importer
543 */
544 private function updateLogos( $wxr_importer ) {
545 $alternate_logo_image = kubio_get_global_data( 'alternateLogo' );
546 $post_mapping = Arr::get( $wxr_importer->get_mapping(), 'post', array() );
547 if ( $alternate_logo_image ) {
548 kubio_set_global_data( 'alternateLogo', Arr::get( $post_mapping, $alternate_logo_image, $alternate_logo_image ) );
549 }
550
551 $logos_options = array( 'site_logo', 'site_icon' );
552
553 foreach ( $logos_options as $option ) {
554 $value = Arr::get( $this->options, "options.{$option}", 0 );
555 $value = Arr::get( $post_mapping, $value, $value );
556 update_option( $option, is_numeric( $value ) ? intval( $value ) : $value );
557 }
558 }
559
560 /**
561 * @param WXRImporter $wxr_importer
562 */
563 private function updateFrontPages( $wxr_importer ) {
564 $page_options = array( 'page_on_front', 'page_for_posts', 'show_on_front' );
565
566 $post_mapping = Arr::get( $wxr_importer->get_mapping(), 'post', array() );
567
568 foreach ( $page_options as $option ) {
569 $value = Arr::get( $this->options, "options.{$option}", 0 );
570 $value = Arr::get( $post_mapping, $value, $value );
571 update_option( $option, is_numeric( $value ) ? intval( $value ) : $value );
572 }
573 }
574 }
575