gallery-widget.php
225 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Migration from Jetpack's Gallery Widget to WordPress' Core Gallery Widget. |
| 4 | * |
| 5 | * @since 5.5 |
| 6 | * |
| 7 | * @package automattic/jetpack |
| 8 | */ |
| 9 | |
| 10 | /** |
| 11 | * Migrates all active instances of Jetpack's Gallery widget to Core's Media Gallery widget. |
| 12 | */ |
| 13 | function jetpack_migrate_gallery_widget() { |
| 14 | // Only trigger the migration from wp-admin and outside unit tests. |
| 15 | if ( ! is_admin() || defined( 'PHPUNIT_JETPACK_TESTSUITE' ) ) { |
| 16 | return; |
| 17 | } |
| 18 | |
| 19 | // Only migrate if the new widget is available and we haven't yet migrated. |
| 20 | if ( ! class_exists( 'WP_Widget_Media_Gallery' ) || Jetpack_Options::get_option( 'gallery_widget_migration' ) ) { |
| 21 | return; |
| 22 | } |
| 23 | |
| 24 | $old_widgets = get_option( 'widget_gallery', array() ); |
| 25 | $media_gallery = get_option( 'widget_media_gallery', array() ); |
| 26 | $sidebars_widgets = wp_get_sidebars_widgets(); |
| 27 | |
| 28 | // Array to store legacy widget ids in to unregister on success. |
| 29 | $widgets_to_unregister = array(); |
| 30 | |
| 31 | $old_widgets = array_filter( $old_widgets, 'jetpack_migrate_gallery_widget_is_importable' ); |
| 32 | foreach ( $old_widgets as $id => $widget ) { |
| 33 | $new_id = $id; |
| 34 | |
| 35 | /* |
| 36 | * Try to get an unique id for the new type of widget. |
| 37 | * It may be the case that the user has already created a core Gallery Widget |
| 38 | * before the migration begins. (Maybe Jetpack was deactivated during core's upgrade). |
| 39 | */ |
| 40 | for ( // phpcs:ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed |
| 41 | $i = 0; |
| 42 | $i < 10 && array_key_exists( $new_id, array( $media_gallery ) ); |
| 43 | $i++, $new_id++ |
| 44 | ); |
| 45 | |
| 46 | $widget_copy = jetpack_migrate_gallery_widget_upgrade_widget( $widget ); |
| 47 | |
| 48 | if ( null === $widget_copy ) { |
| 49 | jetpack_migrate_gallery_widget_bump_stats( 'gallery-widget-skipped' ); |
| 50 | continue; |
| 51 | } |
| 52 | |
| 53 | $media_gallery[ $new_id ] = $widget_copy; |
| 54 | |
| 55 | $sidebars_widgets = jetpack_migrate_gallery_widget_update_sidebars( $sidebars_widgets, $id, $new_id ); |
| 56 | |
| 57 | $widgets_to_unregister[ $id ] = $new_id; |
| 58 | } |
| 59 | |
| 60 | if ( update_option( 'widget_media_gallery', $media_gallery ) ) { |
| 61 | |
| 62 | // Now un-register old widgets and register new. |
| 63 | foreach ( $widgets_to_unregister as $id => $new_id ) { |
| 64 | wp_unregister_sidebar_widget( "gallery-{$id}" ); |
| 65 | |
| 66 | // register new widget. |
| 67 | $media_gallery_widget = new WP_Widget_Media_Gallery(); |
| 68 | $media_gallery_widget->_set( $new_id ); |
| 69 | $media_gallery_widget->_register_one( $new_id ); |
| 70 | } |
| 71 | |
| 72 | wp_set_sidebars_widgets( $sidebars_widgets ); |
| 73 | |
| 74 | // Log if we migrated all, or some for this site. |
| 75 | foreach ( $widgets_to_unregister as $w ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
| 76 | jetpack_migrate_gallery_widget_bump_stats( 'gallery-widget-migrated' ); |
| 77 | } |
| 78 | |
| 79 | /* |
| 80 | * We need to refresh on widgets page for changes to take effect. |
| 81 | * The jetpack_refresh_on_widget_page function is already defined |
| 82 | * in migrate-to-core/image-widget.php |
| 83 | */ |
| 84 | add_action( 'current_screen', 'jetpack_refresh_on_widget_page' ); |
| 85 | } |
| 86 | Jetpack_Options::update_option( 'gallery_widget_migration', true ); |
| 87 | } |
| 88 | |
| 89 | /** |
| 90 | * Check if the widget can be imported. |
| 91 | * |
| 92 | * @param array $widget One of the Jetpack Gallery widgets to be transformed into a new Core Media Gallery Widget. |
| 93 | */ |
| 94 | function jetpack_migrate_gallery_widget_is_importable( $widget ) { |
| 95 | // Can be caused by instantiating but not populating a widget in the Customizer. |
| 96 | if ( empty( $widget ) ) { |
| 97 | return false; |
| 98 | } |
| 99 | |
| 100 | /* |
| 101 | * The array as stored in the option constains two keys and one |
| 102 | * is a string `_multiwidget` which does not represent a widget, so we skip it |
| 103 | */ |
| 104 | if ( ! is_array( $widget ) ) { |
| 105 | return false; |
| 106 | } |
| 107 | return true; |
| 108 | } |
| 109 | |
| 110 | /** |
| 111 | * Returns a transformed version of the Gallery Widget. |
| 112 | * Will return null if the widget is either empty, is not an array or has more keys than expected |
| 113 | * |
| 114 | * @param array $widget One of the Jetpack Gallery widgets to be transformed into a new Core Media Gallery Widget. |
| 115 | * |
| 116 | * @return array|null |
| 117 | */ |
| 118 | function jetpack_migrate_gallery_widget_upgrade_widget( $widget ) { |
| 119 | $allowed_keys = array( |
| 120 | 'ids' => '', |
| 121 | 'link' => '', |
| 122 | 'title' => '', |
| 123 | 'type' => '', |
| 124 | 'random' => '', |
| 125 | 'conditions' => '', |
| 126 | ); |
| 127 | |
| 128 | $default_data = array( |
| 129 | 'columns' => 3, |
| 130 | 'ids' => array(), |
| 131 | 'link_type' => '', |
| 132 | 'orderby_random' => false, |
| 133 | 'size' => 'thumbnail', |
| 134 | 'title' => '', |
| 135 | 'type' => '', |
| 136 | ); |
| 137 | |
| 138 | if ( ! jetpack_migrate_gallery_widget_is_importable( $widget ) ) { |
| 139 | return null; |
| 140 | } |
| 141 | // Ensure widget has no keys other than those expected. |
| 142 | // Not all widgets have conditions, so lets add it in. |
| 143 | $widget_copy = array_merge( array( 'conditions' => null ), $widget ); |
| 144 | $non_allowed_keys = array_diff_key( $widget_copy, $allowed_keys ); |
| 145 | if ( $non_allowed_keys !== array() ) { |
| 146 | jetpack_migrate_gallery_widget_bump_stats( 'extra-key' ); |
| 147 | |
| 148 | // Log the names of the keys not in our allowed list. |
| 149 | foreach ( $non_allowed_keys as $key => $value ) { |
| 150 | jetpack_migrate_gallery_widget_bump_stats( "extra-key-$key", 'migration-extra-key' ); |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | $widget_copy = array_merge( |
| 155 | $default_data, |
| 156 | $widget, |
| 157 | array( |
| 158 | // ids in Jetpack's Gallery are a string of comma-separated values. |
| 159 | // Core's Media Gallery Widget stores ids in an array. |
| 160 | 'ids' => explode( ',', $widget['ids'] ), |
| 161 | 'link_type' => $widget['link'], |
| 162 | 'orderby_random' => isset( $widget['random'] ) && 'on' === $widget['random'], |
| 163 | ) |
| 164 | ); |
| 165 | |
| 166 | // Unsetting old widget fields. |
| 167 | $widget_copy = array_diff_key( |
| 168 | $widget_copy, |
| 169 | array( |
| 170 | 'link' => false, |
| 171 | 'random' => false, |
| 172 | ) |
| 173 | ); |
| 174 | |
| 175 | return $widget_copy; |
| 176 | } |
| 177 | |
| 178 | /** |
| 179 | * Replaces the references to Jetpack Gallery Widget in the sidebars for references to the new version of the widget |
| 180 | * |
| 181 | * @param array $sidebars_widgets The sidebar widgets array to update. |
| 182 | * @param string $id Old id of the widget (basically its index in the array ). |
| 183 | * @param string $new_id New id that will be using on the sidebar as a new widget. |
| 184 | * |
| 185 | * @return mixed Updated sidebar widgets array |
| 186 | */ |
| 187 | function jetpack_migrate_gallery_widget_update_sidebars( $sidebars_widgets, $id, $new_id ) { |
| 188 | foreach ( $sidebars_widgets as $sidebar => $widgets ) { |
| 189 | $key = is_array( $widgets ) ? array_search( "gallery-{$id}", $widgets, true ) : false; |
| 190 | |
| 191 | if ( false !== $key ) { |
| 192 | $sidebars_widgets[ $sidebar ][ $key ] = "media_gallery-{$new_id}"; |
| 193 | |
| 194 | /* |
| 195 | * Check if the inactive widgets sidebar exists |
| 196 | * Related: https://core.trac.wordpress.org/ticket/14893 |
| 197 | */ |
| 198 | if ( ! isset( $sidebars_widgets['wp_inactive_widgets'] ) || ! is_array( $sidebars_widgets['wp_inactive_widgets'] ) ) { |
| 199 | $sidebars_widgets['wp_inactive_widgets'] = array(); |
| 200 | } |
| 201 | $sidebars_widgets['wp_inactive_widgets'][ $key ] = "gallery-{$id}"; |
| 202 | } |
| 203 | } |
| 204 | return $sidebars_widgets; |
| 205 | } |
| 206 | |
| 207 | /** |
| 208 | * Will bump stat in jetpack_gallery_widget_migration group. |
| 209 | * |
| 210 | * @param string $bin The bin to log into. |
| 211 | * @param string $group The group name. Defaults to "widget-migration". |
| 212 | */ |
| 213 | function jetpack_migrate_gallery_widget_bump_stats( $bin, $group = 'widget-migration' ) { |
| 214 | // If this is being run on .com bumps_stats_extra exists, but using the filter looks more elegant. |
| 215 | if ( function_exists( 'bump_stats_extras' ) ) { |
| 216 | $group = "jetpack-$group"; |
| 217 | do_action( 'jetpack_bump_stats_extra', $group, $bin ); |
| 218 | } else { |
| 219 | // $group is prepended with 'jetpack-' |
| 220 | $jetpack = Jetpack::init(); |
| 221 | $jetpack->stat( $group, $bin ); |
| 222 | } |
| 223 | } |
| 224 | add_action( 'widgets_init', 'jetpack_migrate_gallery_widget' ); |
| 225 |