PluginProbe
Elementor Website Builder – more than just a page builder / 3.2.0
Elementor Website Builder – more than just a page builder v3.2.0
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / core / upgrade / upgrades.php

upgrades.php in Elementor Website Builder – more than just a page builder 3.2.0, at core/upgrade/upgrades.php

960 lines 25.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Core\Upgrade;
3
4 use Elementor\Core\Breakpoints\Manager as Breakpoints_Manager;
5 use Elementor\Core\Experiments\Manager as Experiments_Manager;
6 use Elementor\Core\Kits\Documents\Tabs\Settings_Layout;
7 use Elementor\Core\Responsive\Responsive;
8 use Elementor\Core\Settings\Manager as SettingsManager;
9 use Elementor\Icons_Manager;
10 use Elementor\Modules\Usage\Module;
11 use Elementor\Plugin;
12 use Elementor\Utils;
13
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit; // Exit if accessed directly.
16 }
17
18 /**
19 * Elementor upgrades.
20 *
21 * Elementor upgrades handler class is responsible for updating different
22 * Elementor versions.
23 *
24 * @since 1.0.0
25 */
26 class Upgrades {
27
28 /**
29 * Upgrade Elementor 0.3.2
30 *
31 * Change the image widget link URL, setting is to `custom` link.
32 *
33 * @since 2.0.0
34 * @static
35 * @access public
36 */
37 public static function _v_0_3_2() {
38 global $wpdb;
39
40 $post_ids = $wpdb->get_col(
41 'SELECT `post_id` FROM `' . $wpdb->postmeta . '`
42 WHERE `meta_key` = \'_elementor_version\'
43 AND `meta_value` = \'0.1\';'
44 );
45
46 if ( empty( $post_ids ) ) {
47 return;
48 }
49
50 foreach ( $post_ids as $post_id ) {
51 $document = Plugin::$instance->documents->get( $post_id );
52
53 if ( $document ) {
54 $data = $document->get_elements_data();
55 }
56
57 if ( empty( $data ) ) {
58 continue;
59 }
60
61 $data = Plugin::$instance->db->iterate_data( $data, function( $element ) {
62 if ( empty( $element['widgetType'] ) || 'image' !== $element['widgetType'] ) {
63 return $element;
64 }
65
66 if ( ! empty( $element['settings']['link']['url'] ) && ! isset( $element['settings']['link_to'] ) ) {
67 $element['settings']['link_to'] = 'custom';
68 }
69
70 return $element;
71 } );
72
73 $document = Plugin::$instance->documents->get( $post_id );
74
75 $document->save( [
76 'elements' => $data,
77 ] );
78 }
79 }
80
81 /**
82 * Upgrade Elementor 0.9.2
83 *
84 * Change the icon widget, icon-box widget and the social-icons widget,
85 * setting their icon padding size to an empty string.
86 *
87 * Change the image widget, setting the image size to full image size.
88 *
89 * @since 2.0.0
90 * @static
91 * @access public
92 */
93 public static function _v_0_9_2() {
94 global $wpdb;
95
96 // Fix Icon/Icon Box Widgets padding.
97 $post_ids = $wpdb->get_col(
98 'SELECT `post_id` FROM `' . $wpdb->postmeta . '`
99 WHERE `meta_key` = \'_elementor_version\'
100 AND `meta_value` = \'0.2\';'
101 );
102
103 if ( empty( $post_ids ) ) {
104 return;
105 }
106
107 foreach ( $post_ids as $post_id ) {
108 $document = Plugin::$instance->documents->get( $post_id );
109
110 if ( $document ) {
111 $data = $document->get_elements_data();
112 }
113
114 if ( empty( $data ) ) {
115 continue;
116 }
117
118 $data = Plugin::$instance->db->iterate_data( $data, function( $element ) {
119 if ( empty( $element['widgetType'] ) ) {
120 return $element;
121 }
122
123 if ( in_array( $element['widgetType'], [ 'icon', 'icon-box', 'social-icons' ] ) ) {
124 if ( ! empty( $element['settings']['icon_padding']['size'] ) ) {
125 $element['settings']['icon_padding']['size'] = '';
126 }
127 }
128
129 if ( 'image' === $element['widgetType'] ) {
130 if ( empty( $element['settings']['image_size'] ) ) {
131 $element['settings']['image_size'] = 'full';
132 }
133 }
134
135 return $element;
136 } );
137
138 $document = Plugin::$instance->documents->get( $post_id );
139
140 $document->save( [
141 'elements' => $data,
142 ] );
143 }
144 }
145
146 /**
147 * Upgrade Elementor 0.11.0
148 *
149 * Change the button widget sizes, setting up new button sizes.
150 *
151 * @since 2.0.0
152 * @static
153 * @access public
154 */
155 public static function _v_0_11_0() {
156 global $wpdb;
157
158 // Fix Button widget to new sizes options.
159 $post_ids = $wpdb->get_col(
160 'SELECT `post_id` FROM `' . $wpdb->postmeta . '`
161 WHERE `meta_key` = \'_elementor_version\'
162 AND `meta_value` = \'0.3\';'
163 );
164
165 if ( empty( $post_ids ) ) {
166 return;
167 }
168
169 foreach ( $post_ids as $post_id ) {
170 $document = Plugin::$instance->documents->get( $post_id );
171
172 if ( $document ) {
173 $data = $document->get_elements_data();
174 }
175
176 if ( empty( $data ) ) {
177 continue;
178 }
179
180 $data = Plugin::$instance->db->iterate_data( $data, function( $element ) {
181 if ( empty( $element['widgetType'] ) ) {
182 return $element;
183 }
184
185 if ( 'button' === $element['widgetType'] ) {
186 $size_to_replace = [
187 'small' => 'xs',
188 'medium' => 'sm',
189 'large' => 'md',
190 'xl' => 'lg',
191 'xxl' => 'xl',
192 ];
193
194 if ( ! empty( $element['settings']['size'] ) ) {
195 $old_size = $element['settings']['size'];
196
197 if ( isset( $size_to_replace[ $old_size ] ) ) {
198 $element['settings']['size'] = $size_to_replace[ $old_size ];
199 }
200 }
201 }
202
203 return $element;
204 } );
205
206 $document = Plugin::$instance->documents->get( $post_id );
207
208 $document->save( [
209 'elements' => $data,
210 ] );
211 }
212 }
213
214 /**
215 * Upgrade Elementor 2.0.0
216 *
217 * Fix post titles for old autosave drafts that saved with the format 'Auto Save 2018-03-18 17:24'.
218 *
219 * @static
220 * @since 2.0.0
221 * @access public
222 */
223 public static function _v_2_0_0() {
224 global $wpdb;
225
226 $posts = $wpdb->get_results(
227 'SELECT `ID`, `post_title`, `post_parent`
228 FROM `' . $wpdb->posts . '` p
229 LEFT JOIN `' . $wpdb->postmeta . '` m ON p.ID = m.post_id
230 WHERE `post_status` = \'inherit\'
231 AND `post_title` = CONCAT(\'Auto Save \', DATE_FORMAT(post_date, "%Y-%m-%d %H:%i"))
232 AND m.`meta_key` = \'_elementor_data\';'
233 );
234
235 if ( empty( $posts ) ) {
236 return;
237 }
238
239 foreach ( $posts as $post ) {
240 wp_update_post( [
241 'ID' => $post->ID,
242 'post_title' => get_the_title( $post->post_parent ),
243 ] );
244 }
245 }
246
247 /**
248 * Upgrade Elementor 2.0.1
249 *
250 * Fix post titles for old autosave drafts that saved with the format 'Auto Save...'.
251 *
252 * @since 2.0.2
253 * @static
254 * @access public
255 */
256 public static function _v_2_0_1() {
257 global $wpdb;
258
259 $posts = $wpdb->get_results(
260 'SELECT `ID`, `post_title`, `post_parent`
261 FROM `' . $wpdb->posts . '` p
262 LEFT JOIN `' . $wpdb->postmeta . '` m ON p.ID = m.post_id
263 WHERE `post_status` = \'inherit\'
264 AND `post_title` REGEXP \'^Auto Save [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$\'
265 AND m.`meta_key` = \'_elementor_data\';'
266 );
267
268 if ( empty( $posts ) ) {
269 return;
270 }
271
272 foreach ( $posts as $post ) {
273 $parent = get_post( $post->post_parent );
274 $title = isset( $parent->post_title ) ? $parent->post_title : '';
275
276 wp_update_post( [
277 'ID' => $post->ID,
278 'post_title' => $title,
279 ] );
280 }
281 }
282
283 /**
284 * Upgrade Elementor 2.0.10
285 *
286 * Fix post titles for old autosave drafts that saved with the format 'Auto Save...'.
287 * Fix also Translated titles.
288 *
289 * @since 2.0.10
290 * @static
291 * @access public
292 */
293 public static function _v_2_0_10() {
294 global $wpdb;
295
296 $posts = $wpdb->get_results(
297 'SELECT `ID`, `post_title`, `post_parent`
298 FROM `' . $wpdb->posts . '` p
299 LEFT JOIN `' . $wpdb->postmeta . '` m ON p.ID = m.post_id
300 WHERE `post_status` = \'inherit\'
301 AND `post_title` REGEXP \'[[:alnum:]]+ [[:alnum:]]+ [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$\'
302 AND m.`meta_key` = \'_elementor_data\';'
303 );
304
305 if ( empty( $posts ) ) {
306 return;
307 }
308
309 foreach ( $posts as $post ) {
310 $parent = get_post( $post->post_parent );
311 $title = isset( $parent->post_title ) ? $parent->post_title : '';
312
313 wp_update_post( [
314 'ID' => $post->ID,
315 'post_title' => $title,
316 ] );
317 }
318 }
319
320 public static function _v_2_1_0() {
321 global $wpdb;
322
323 // upgrade `video` widget settings (merge providers).
324 $post_ids = $wpdb->get_col(
325 'SELECT `post_id` FROM `' . $wpdb->postmeta . '` WHERE `meta_key` = "_elementor_data" AND `meta_value` LIKE \'%"widgetType":"video"%\';'
326 );
327
328 if ( empty( $post_ids ) ) {
329 return;
330 }
331
332 foreach ( $post_ids as $post_id ) {
333 $do_update = false;
334 $document = Plugin::$instance->documents->get( $post_id );
335
336 if ( $document ) {
337 $data = $document->get_elements_data();
338 }
339
340 if ( empty( $data ) ) {
341 continue;
342 }
343
344 $data = Plugin::$instance->db->iterate_data( $data, function( $element ) use ( &$do_update ) {
345 if ( empty( $element['widgetType'] ) || 'video' !== $element['widgetType'] ) {
346 return $element;
347 }
348
349 $replacements = [];
350
351 if ( empty( $element['settings']['video_type'] ) || 'youtube' === $element['settings']['video_type'] ) {
352 $replacements = [
353 'yt_autoplay' => 'autoplay',
354 'yt_controls' => 'controls',
355 'yt_mute' => 'mute',
356 'yt_rel' => 'rel',
357 'link' => 'youtube_url',
358 ];
359 } elseif ( 'vimeo' === $element['settings']['video_type'] ) {
360 $replacements = [
361 'vimeo_autoplay' => 'autoplay',
362 'vimeo_loop' => 'loop',
363 'vimeo_color' => 'color',
364 'vimeo_link' => 'vimeo_url',
365 ];
366 }
367
368 // cleanup old unused settings.
369 unset( $element['settings']['yt_rel_videos'] );
370
371 foreach ( $replacements as $old => $new ) {
372 if ( ! empty( $element['settings'][ $old ] ) ) {
373 $element['settings'][ $new ] = $element['settings'][ $old ];
374 $do_update = true;
375 }
376 }
377
378 return $element;
379 } );
380
381 // Only update if needed.
382 if ( ! $do_update ) {
383 continue;
384 }
385
386 // We need the `wp_slash` in order to avoid the unslashing during the `update_post_meta`
387 $json_value = wp_slash( wp_json_encode( $data ) );
388
389 update_metadata( 'post', $post_id, '_elementor_data', $json_value );
390
391 // Clear WP cache for next step.
392 wp_cache_flush();
393 } // End foreach().
394 }
395
396 /**
397 * @param Updater $updater
398 *
399 * @return bool
400 */
401 public static function _v_2_3_0_widget_image( $updater ) {
402 global $wpdb;
403
404 // upgrade `video` widget settings (merge providers).
405 $post_ids = $updater->query_col(
406 'SELECT `post_id` FROM `' . $wpdb->postmeta . '` WHERE `meta_key` = "_elementor_data" AND (
407 `meta_value` LIKE \'%"widgetType":"image"%\'
408 OR `meta_value` LIKE \'%"widgetType":"theme-post-featured-image"%\'
409 OR `meta_value` LIKE \'%"widgetType":"theme-site-logo"%\'
410 OR `meta_value` LIKE \'%"widgetType":"woocommerce-category-image"%\'
411 );'
412 );
413
414 if ( empty( $post_ids ) ) {
415 return false;
416 }
417
418 $widgets = [
419 'image',
420 'theme-post-featured-image',
421 'theme-site-logo',
422 'woocommerce-category-image',
423 ];
424
425 foreach ( $post_ids as $post_id ) {
426 // Clear WP cache for next step.
427 wp_cache_flush();
428
429 $do_update = false;
430
431 $document = Plugin::$instance->documents->get( $post_id );
432
433 if ( ! $document ) {
434 continue;
435 }
436
437 $data = $document->get_elements_data();
438
439 if ( empty( $data ) ) {
440 continue;
441 }
442
443 $data = Plugin::$instance->db->iterate_data( $data, function( $element ) use ( &$do_update, $widgets ) {
444 if ( empty( $element['widgetType'] ) || ! in_array( $element['widgetType'], $widgets ) ) {
445 return $element;
446 }
447
448 if ( ! empty( $element['settings']['caption'] ) ) {
449 if ( ! isset( $element['settings']['caption_source'] ) ) {
450 $element['settings']['caption_source'] = 'custom';
451
452 $do_update = true;
453 }
454 }
455
456 return $element;
457 } );
458
459 // Only update if needed.
460 if ( ! $do_update ) {
461 continue;
462 }
463
464 // We need the `wp_slash` in order to avoid the unslashing during the `update_post_meta`
465 $json_value = wp_slash( wp_json_encode( $data ) );
466
467 update_metadata( 'post', $post_id, '_elementor_data', $json_value );
468 } // End foreach().
469
470 return $updater->should_run_again( $post_ids );
471 }
472
473 /**
474 * @param Updater $updater
475 *
476 * @return bool
477 */
478 public static function _v_2_3_0_template_type( $updater ) {
479 global $wpdb;
480
481 $post_ids = $updater->query_col(
482 'SELECT p.ID
483 FROM `' . $wpdb->posts . '` AS p
484 LEFT JOIN `' . $wpdb->postmeta . '` AS pm1 ON (p.ID = pm1.post_id)
485 LEFT JOIN `' . $wpdb->postmeta . '` AS pm2 ON (pm1.post_id = pm2.post_id AND pm2.meta_key = "_elementor_template_type")
486 WHERE p.post_status != "inherit" AND pm1.`meta_key` = "_elementor_data" AND pm2.post_id IS NULL;'
487 );
488
489 if ( empty( $post_ids ) ) {
490 return false;
491 }
492
493 foreach ( $post_ids as $post_id ) {
494 // Clear WP cache for next step.
495 wp_cache_flush();
496
497 $document = Plugin::$instance->documents->get( $post_id );
498
499 if ( ! $document ) {
500 continue;
501 }
502
503 $document->save_template_type();
504 } // End foreach().
505
506 return $updater->should_run_again( $post_ids );
507 }
508
509 /**
510 * Set FontAwesome Migration needed flag
511 */
512 public static function _v_2_6_0_fa4_migration_flag() {
513 add_option( 'elementor_icon_manager_needs_update', 'yes' );
514 add_option( 'elementor_load_fa4_shim', 'yes' );
515 }
516
517 /**
518 * migrate Icon control string value to Icons control array value
519 *
520 * @param array $element
521 * @param array $args
522 *
523 * @return mixed
524 */
525 public static function _migrate_icon_fa4_value( $element, $args ) {
526 $widget_id = $args['widget_id'];
527
528 if ( empty( $element['widgetType'] ) || $widget_id !== $element['widgetType'] ) {
529 return $element;
530 }
531 foreach ( $args['control_ids'] as $old_name => $new_name ) {
532 // exit if new value exists
533 if ( isset( $element['settings'][ $new_name ] ) ) {
534 continue;
535 }
536
537 // exit if no value to migrate
538 if ( ! isset( $element['settings'][ $old_name ] ) ) {
539 continue;
540 }
541
542 $element['settings'][ $new_name ] = Icons_Manager::fa4_to_fa5_value_migration( $element['settings'][ $old_name ] );
543 $args['do_update'] = true;
544 }
545 return $element;
546 }
547
548 /**
549 * Set FontAwesome 5 value Migration on for button widget
550 *
551 * @param Updater $updater
552 */
553 public static function _v_2_6_6_fa4_migration_button( $updater ) {
554 $changes = [
555 [
556 'callback' => [ 'Elementor\Core\Upgrade\Upgrades', '_migrate_icon_fa4_value' ],
557 'control_ids' => [
558 'icon' => 'selected_icon',
559 ],
560 ],
561 ];
562 Upgrade_Utils::_update_widget_settings( 'button', $updater, $changes );
563 Upgrade_Utils::_update_widget_settings( 'icon-box', $updater, $changes );
564 }
565
566 /**
567 * Update database to separate page from post.
568 *
569 * @param Updater $updater
570 *
571 * @param string $type
572 *
573 * @return bool
574 */
575 public static function rename_document_base_to_wp( $updater, $type ) {
576 global $wpdb;
577
578 $post_ids = $updater->query_col( $wpdb->prepare(
579 "SELECT p1.ID FROM {$wpdb->posts} AS p
580 LEFT JOIN {$wpdb->posts} AS p1 ON (p.ID = p1.post_parent || p.ID = p1.ID)
581 WHERE p.post_type = %s;", $type ) );
582
583 if ( empty( $post_ids ) ) {
584 return false;
585 }
586
587 $sql_post_ids = implode( ',', $post_ids );
588
589 $wpdb->query( $wpdb->prepare(
590 "UPDATE $wpdb->postmeta SET meta_value = %s
591 WHERE meta_key = '_elementor_template_type' && post_id in ( %s );
592 ", 'wp-' . $type, $sql_post_ids ) );
593
594 return $updater->should_run_again( $post_ids );
595 }
596
597 /**
598 * Update database to separate page from post.
599 *
600 * @param Updater $updater
601 *
602 * @return bool
603 */
604 // Because the query is slow on large sites, temporary don't upgrade.
605 /* public static function _v_2_7_0_rename_document_types_to_wp( $updater ) {
606 return self::rename_document_base_to_wp( $updater, 'post' ) || self::rename_document_base_to_wp( $updater, 'page' );
607 }*/
608
609 // Upgrade code was fixed & moved to _v_2_7_1_remove_old_usage_data.
610 /* public static function _v_2_7_0_remove_old_usage_data() {} */
611
612 // Upgrade code moved to _v_2_7_1_recalc_usage_data.
613 /* public static function _v_2_7_0_recalc_usage_data( $updater ) {} */
614
615 /**
616 * Don't use the old data anymore.
617 * Since 2.7.1 the key was changed from `elementor_elements_usage` to `elementor_controls_usage`.
618 */
619 public static function _v_2_7_1_remove_old_usage_data() {
620 delete_option( 'elementor_elements_usage' );
621 delete_post_meta_by_key( '_elementor_elements_usage' );
622 }
623
624 /**
625 * Recalc usage.
626 *
627 * @param Updater $updater
628 *
629 * @return bool
630 */
631 public static function recalc_usage_data( $updater ) {
632 /** @var Module $module */
633 $module = Plugin::$instance->modules_manager->get_modules( 'usage' );
634
635 $post_count = $module->recalc_usage( $updater->get_limit(), $updater->get_current_offset() );
636
637 return ( $post_count === $updater->get_limit() );
638 }
639
640 public static function _v_2_7_1_recalc_usage_data( $updater ) {
641 return self::recalc_usage_data( $updater );
642 }
643
644 public static function _v_2_8_3_recalc_usage_data( $updater ) {
645 // Re-calc since older version(s) had invalid values.
646 return self::recalc_usage_data( $updater );
647 }
648
649 /**
650 * Move general & lightbox settings to active kit and all it's revisions.
651 *
652 * @param Updater $updater
653 *
654 * @return bool
655 */
656 public static function _v_3_0_0_move_general_settings_to_kit( $updater ) {
657 $callback = function( $kit_id ) {
658 $kit = Plugin::$instance->documents->get( $kit_id );
659
660 if ( ! $kit ) {
661 self::notice( 'Kit not found. nothing to do.' );
662 return;
663 }
664
665 $meta_key = \Elementor\Core\Settings\Page\Manager::META_KEY;
666 $current_settings = get_option( '_elementor_general_settings', [] );
667 // Take the `space_between_widgets` from the option due to a bug on E < 3.0.0 that the value `0` is stored separated.
668 $current_settings['space_between_widgets'] = get_option( 'elementor_space_between_widgets', '' );
669 $current_settings[ Breakpoints_Manager::BREAKPOINT_SETTING_PREFIX . 'md' ] = get_option( 'elementor_viewport_md', '' );
670 $current_settings[ Breakpoints_Manager::BREAKPOINT_SETTING_PREFIX . 'lg' ] = get_option( 'elementor_viewport_lg', '' );
671
672 $kit_settings = $kit->get_meta( $meta_key );
673
674 // Already exist.
675 if ( isset( $kit_settings['default_generic_fonts'] ) ) {
676 self::notice( 'General Settings already exist. nothing to do.' );
677 return;
678 }
679
680 if ( empty( $current_settings ) ) {
681 self::notice( 'Current settings are empty. nothing to do.' );
682 return;
683 }
684
685 if ( ! $kit_settings ) {
686 $kit_settings = [];
687 }
688
689 // Convert some setting to Elementor slider format.
690 $settings_to_slider = [
691 'container_width',
692 'space_between_widgets',
693 ];
694
695 foreach ( $settings_to_slider as $setting ) {
696 if ( isset( $current_settings[ $setting ] ) ) {
697 $current_settings[ $setting ] = [
698 'unit' => 'px',
699 'size' => $current_settings[ $setting ],
700 ];
701 }
702 }
703
704 $kit_settings = array_merge( $kit_settings, $current_settings );
705
706 $page_settings_manager = SettingsManager::get_settings_managers( 'page' );
707 $page_settings_manager->save_settings( $kit_settings, $kit_id );
708 };
709
710 return self::move_settings_to_kit( $callback, $updater );
711 }
712
713 /**
714 * Move default colors settings to active kit and all it's revisions.
715 *
716 * @param Updater $updater
717 *
718 * @return bool
719 */
720 public static function _v_3_0_0_move_default_colors_to_kit( $updater, $include_revisions = true ) {
721 $callback = function( $kit_id ) {
722 if ( ! Plugin::$instance->kits_manager->is_custom_colors_enabled() ) {
723 self::notice( 'System colors are disabled. nothing to do.' );
724 return;
725 }
726
727 $kit = Plugin::$instance->documents->get( $kit_id );
728
729 // Already exist. use raw settings that doesn't have default values.
730 $meta_key = \Elementor\Core\Settings\Page\Manager::META_KEY;
731 $kit_raw_settings = $kit->get_meta( $meta_key );
732 if ( isset( $kit_raw_settings['system_colors'] ) ) {
733 self::notice( 'System colors already exist. nothing to do.' );
734 return;
735 }
736
737 $scheme_obj = Plugin::$instance->schemes_manager->get_scheme( 'color' );
738
739 $default_colors = $scheme_obj->get_scheme();
740
741 $new_ids = [
742 'primary',
743 'secondary',
744 'text',
745 'accent',
746 ];
747
748 foreach ( $default_colors as $index => $color ) {
749 $kit->add_repeater_row( 'system_colors', [
750 '_id' => $new_ids[ $index - 1 ], // $default_colors starts from 1.
751 'title' => $color['title'],
752 'color' => strtoupper( $color['value'] ),
753 ] );
754 }
755 };
756
757 return self::move_settings_to_kit( $callback, $updater, $include_revisions );
758 }
759
760 /**
761 * Move saved colors settings to active kit and all it's revisions.
762 *
763 * @param Updater $updater
764 *
765 * @return bool
766 */
767 public static function _v_3_0_0_move_saved_colors_to_kit( $updater, $include_revisions = true ) {
768 $callback = function( $kit_id ) {
769 $kit = Plugin::$instance->documents->get( $kit_id );
770
771 // Already exist. use raw settings that doesn't have default values.
772 $meta_key = \Elementor\Core\Settings\Page\Manager::META_KEY;
773 $kit_raw_settings = $kit->get_meta( $meta_key );
774 if ( isset( $kit_raw_settings['custom_colors'] ) ) {
775 self::notice( 'Custom colors already exist. nothing to do.' );
776 return;
777 }
778
779 $system_colors_rows = $kit->get_settings( 'system_colors' );
780
781 if ( ! $system_colors_rows ) {
782 $system_colors_rows = [];
783 }
784
785 $system_colors = [];
786
787 foreach ( $system_colors_rows as $color_row ) {
788 $system_colors[] = strtoupper( $color_row['color'] );
789 }
790
791 $saved_scheme_obj = Plugin::$instance->schemes_manager->get_scheme( 'color-picker' );
792
793 $current_saved_colors_rows = $saved_scheme_obj->get_scheme();
794
795 $current_saved_colors = [];
796
797 foreach ( $current_saved_colors_rows as $color_row ) {
798 $current_saved_colors[] = strtoupper( $color_row['value'] );
799 }
800
801 $colors_to_save = array_diff( $current_saved_colors, $system_colors );
802
803 if ( empty( $colors_to_save ) ) {
804 self::notice( 'Saved colors not found. nothing to do.' );
805 return;
806 }
807
808 foreach ( $colors_to_save as $index => $color ) {
809 $kit->add_repeater_row( 'custom_colors', [
810 '_id' => Utils::generate_random_string(),
811 'title' => __( 'Saved Color', 'elementor' ) . ' #' . ( $index + 1 ),
812 'color' => $color,
813 ] );
814 }
815 };
816
817 return self::move_settings_to_kit( $callback, $updater, $include_revisions );
818 }
819
820 /**
821 * Move default typography settings to active kit and all it's revisions.
822 *
823 * @param Updater $updater
824 *
825 * @return bool
826 */
827 public static function _v_3_0_0_move_default_typography_to_kit( $updater, $include_revisions = true ) {
828 $callback = function( $kit_id ) {
829 if ( ! Plugin::$instance->kits_manager->is_custom_typography_enabled() ) {
830 self::notice( 'System typography is disabled. nothing to do.' );
831 return;
832 }
833
834 $kit = Plugin::$instance->documents->get( $kit_id );
835
836 // Already exist. use raw settings that doesn't have default values.
837 $meta_key = \Elementor\Core\Settings\Page\Manager::META_KEY;
838 $kit_raw_settings = $kit->get_meta( $meta_key );
839 if ( isset( $kit_raw_settings['system_typography'] ) ) {
840 self::notice( 'System typography already exist. nothing to do.' );
841 return;
842 }
843
844 $scheme_obj = Plugin::$instance->schemes_manager->get_scheme( 'typography' );
845
846 $default_typography = $scheme_obj->get_scheme();
847
848 $new_ids = [
849 'primary',
850 'secondary',
851 'text',
852 'accent',
853 ];
854
855 foreach ( $default_typography as $index => $typography ) {
856 $kit->add_repeater_row( 'system_typography', [
857 '_id' => $new_ids[ $index - 1 ], // $default_typography starts from 1.
858 'title' => $typography['title'],
859 'typography_typography' => 'custom',
860 'typography_font_family' => $typography['value']['font_family'],
861 'typography_font_weight' => $typography['value']['font_weight'],
862 ] );
863 }
864 };
865
866 return self::move_settings_to_kit( $callback, $updater, $include_revisions );
867 }
868
869 public static function v_3_1_0_move_optimized_dom_output_to_experiments() {
870 $saved_option = get_option( 'elementor_optimized_dom_output' );
871
872 if ( $saved_option ) {
873 $new_option = 'enabled' === $saved_option ? Experiments_Manager::STATE_ACTIVE : Experiments_Manager::STATE_INACTIVE;
874
875 add_option( 'elementor_experiment-e_dom_optimization', $new_option );
876 }
877 }
878
879 public static function _v_3_2_0_migrate_breakpoints_to_new_system( $updater, $include_revisions = true ) {
880 $callback = function( $kit_id ) {
881 $kit = Plugin::$instance->documents->get( $kit_id );
882
883 $kit_settings = $kit->get_settings();
884
885 $prefix = Breakpoints_Manager::BREAKPOINT_SETTING_PREFIX;
886 $old_mobile_option_key = $prefix . 'md';
887 $old_tablet_option_key = $prefix . 'lg';
888
889 $breakpoint_values = [
890 $old_mobile_option_key => Plugin::$instance->kits_manager->get_current_settings( $old_mobile_option_key ),
891 $old_tablet_option_key => Plugin::$instance->kits_manager->get_current_settings( $old_tablet_option_key ),
892 ];
893
894 // Breakpoint values are either a number, or an empty string (empty setting).
895 array_walk( $breakpoint_values, function( &$breakpoint_value, $breakpoint_key ) {
896 if ( $breakpoint_value ) {
897 // If the saved breakpoint value is a number, 1px is reduced because the new breakpoints system is
898 // based on max-width, as opposed to the old breakpoints system that worked based on min-width.
899 $breakpoint_value--;
900 }
901
902 return $breakpoint_value;
903 } );
904
905 $kit_settings[ $prefix . Breakpoints_Manager::BREAKPOINT_KEY_MOBILE ] = $breakpoint_values[ $old_mobile_option_key ];
906 $kit_settings[ $prefix . Breakpoints_Manager::BREAKPOINT_KEY_TABLET ] = $breakpoint_values[ $old_tablet_option_key ];
907
908 $page_settings_manager = SettingsManager::get_settings_managers( 'page' );
909 $page_settings_manager->save_settings( $kit_settings, $kit_id );
910 };
911
912 return self::move_settings_to_kit( $callback, $updater, $include_revisions );
913 }
914
915 /**
916 * @param callback $callback
917 * @param Updater $updater
918 *
919 * @param bool $include_revisions
920 *
921 * @return mixed
922 */
923 private static function move_settings_to_kit( $callback, $updater, $include_revisions = true ) {
924 $active_kit_id = Plugin::$instance->kits_manager->get_active_id();
925 if ( ! $active_kit_id ) {
926 self::notice( 'Active kit not found. nothing to do.' );
927 return false;
928 }
929
930 $offset = $updater->get_current_offset();
931
932 // On first iteration apply on active kit itself.
933 // (don't include it with revisions in order to avoid offset/iteration count wrong numbers)
934 if ( 0 === $offset ) {
935 $callback( $active_kit_id );
936 }
937
938 if ( ! $include_revisions ) {
939 return false;
940 }
941
942 $revisions_ids = wp_get_post_revisions( $active_kit_id, [
943 'fields' => 'ids',
944 'posts_per_page' => $updater->get_limit(),
945 'offset' => $offset,
946 ] );
947
948 foreach ( $revisions_ids as $revision_id ) {
949 $callback( $revision_id );
950 }
951
952 return $updater->should_run_again( $revisions_ids );
953 }
954
955 private static function notice( $message ) {
956 $logger = Plugin::$instance->logger->get_logger();
957 $logger->notice( $message );
958 }
959 }
960