PluginProbe
Elementor Website Builder – more than just a page builder / 3.2.4
Elementor Website Builder – more than just a page builder v3.2.4
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.4, at core/upgrade/upgrades.php

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