image-widget.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?php
  2. /**
  3. * Migration from Jetpack's Image Widget to WordPress' Core Image Widget.
  4. *
  5. * @since 4.9
  6. *
  7. * @package Jetpack
  8. */
  9. /**
  10. * Migrates all active instances of Jetpack's image widget to Core's media image widget.
  11. */
  12. function jetpack_migrate_image_widget() {
  13. // Only trigger the migration from wp-admin
  14. if ( ! is_admin() ) {
  15. return;
  16. }
  17. // Only migrate if the new widget is available and we haven't yet migrated
  18. if ( ! class_exists( 'WP_Widget_Media_Image' ) || Jetpack_Options::get_option( 'image_widget_migration' ) ) {
  19. return;
  20. }
  21. $default_data = array(
  22. 'attachment_id' => 0,
  23. 'url' => '',
  24. 'title' => '',
  25. 'size' => 'custom',
  26. 'width' => 0,
  27. 'height' => 0,
  28. 'align' => 'none',
  29. 'caption' => '',
  30. 'alt' => '',
  31. 'link_type' => '',
  32. 'link_url' => '',
  33. 'image_classes' => '',
  34. 'link_classes' => '',
  35. 'link_rel' => '',
  36. 'image_title' => '',
  37. 'link_target_blank' => false,
  38. 'conditions' => null,
  39. );
  40. $old_widgets = get_option( 'widget_image', array() );
  41. $media_image = get_option( 'widget_media_image', array() );
  42. $sidebars_widgets = wp_get_sidebars_widgets();
  43. // Persist old and current widgets in backup table.
  44. jetpack_store_migration_data( 'widget_image', maybe_serialize( $old_widgets ) );
  45. if ( jetpack_get_migration_data( 'widget_image' ) !== $old_widgets ) {
  46. return false;
  47. }
  48. jetpack_store_migration_data( 'sidebars_widgets', maybe_serialize( $sidebars_widgets ) );
  49. if ( jetpack_get_migration_data( 'sidebars_widgets' ) !== $sidebars_widgets ) {
  50. return false;
  51. }
  52. // Array to store legacy widget ids in to unregister on success.
  53. $widgets_to_unregister = array();
  54. foreach ( $old_widgets as $id => $widget ) {
  55. if ( is_string( $id ) ) {
  56. continue;
  57. }
  58. // Can be caused by instanciating but not populating a widget in the Customizer.
  59. if ( empty( $widget ) ) {
  60. continue;
  61. }
  62. // Ensure widget has no keys other than those expected.
  63. // Not all widgets have conditions, so lets add it in.
  64. $widget_copy = array_merge( array( 'conditions' => null ), $widget );
  65. $non_whitelisted_keys = array_diff_key( $widget_copy, array(
  66. 'title' => '',
  67. 'img_url' => '',
  68. 'alt_text' => '',
  69. 'img_title' => '',
  70. 'caption' => '',
  71. 'align' => '',
  72. 'img_width' => '',
  73. 'img_height' => '',
  74. 'link' => '',
  75. 'link_target_blank' => '',
  76. 'conditions' => '',
  77. ) );
  78. if ( count( $non_whitelisted_keys ) > 0 ) {
  79. // skipping the widget in question
  80. continue;
  81. }
  82. $media_image[ $id ] = array_merge( $default_data, $widget, array(
  83. 'alt' => $widget['alt_text'],
  84. 'height' => $widget['img_height'],
  85. 'image_classes' => ! empty( $widget['align'] ) ? 'align' . $widget['align'] : '',
  86. 'image_title' => $widget['img_title'],
  87. 'link_url' => $widget['link'],
  88. 'url' => $widget['img_url'],
  89. 'width' => $widget['img_width'],
  90. ) );
  91. // Unsetting old widget fields
  92. $media_image[ $id ] = array_diff_key( $media_image[ $id ], array(
  93. 'align' => false,
  94. 'alt_text' => false,
  95. 'img_height' => false,
  96. 'img_title' => false,
  97. 'img_url' => false,
  98. 'img_width' => false,
  99. 'link' => false,
  100. ) );
  101. // Check if the image is in the media library.
  102. $image_basename = basename( $widget['img_url'] );
  103. if ( empty( $image_basename ) ) {
  104. continue;
  105. }
  106. $attachment_ids = get_posts( array(
  107. 'fields' => 'ids',
  108. 'meta_query' => array(
  109. array(
  110. 'value' => basename( $image_basename ),
  111. 'compare' => 'LIKE',
  112. 'key' => '_wp_attachment_metadata',
  113. ),
  114. ),
  115. 'post_status' => 'inherit',
  116. 'post_type' => 'attachment',
  117. 'suppress_filters' => false,
  118. ) );
  119. foreach ( $attachment_ids as $attachment_id ) {
  120. $image_meta = wp_get_attachment_metadata( $attachment_id );
  121. // Is it a full size image?
  122. $image_path_pieces = explode( '/', $image_meta['file'] );
  123. if ( $image_basename === array_pop( $image_path_pieces ) ) {
  124. $media_image[ $id ]['attachment_id'] = $attachment_id;
  125. // Set correct size if dimensions fit.
  126. if (
  127. $media_image[ $id ]['width'] == $image_meta['width'] ||
  128. $media_image[ $id ]['height'] == $image_meta['height']
  129. ) {
  130. $media_image[ $id ]['size'] = 'full';
  131. }
  132. break;
  133. }
  134. // Is it a down-sized image?
  135. foreach ( $image_meta['sizes'] as $size => $image ) {
  136. if ( false !== array_search( $image_basename, $image ) ) {
  137. $media_image[ $id ]['attachment_id'] = $attachment_id;
  138. // Set correct size if dimensions fit.
  139. if (
  140. $media_image[ $id ]['width'] == $image['width'] ||
  141. $media_image[ $id ]['height'] == $image['height']
  142. ) {
  143. $media_image[ $id ]['size'] = $size;
  144. }
  145. break 2;
  146. }
  147. }
  148. }
  149. if ( ! empty( $widget['link'] ) ) {
  150. $media_image[ $id ]['link_type'] = $widget['link'] === $widget['img_url'] ? 'file' : 'custom';
  151. }
  152. foreach ( $sidebars_widgets as $sidebar => $widgets ) {
  153. if (
  154. is_array( $widgets )
  155. && false !== ( $key = array_search( "image-{$id}", $widgets, true ) )
  156. ) {
  157. $sidebars_widgets[ $sidebar ][ $key ] = "media_image-{$id}";
  158. }
  159. }
  160. $widgets_to_unregister[] = $id;
  161. }
  162. if ( update_option( 'widget_media_image', $media_image ) ) {
  163. delete_option( 'widget_image' );
  164. // Now un-register old widgets and register new.
  165. foreach ( $widgets_to_unregister as $id ) {
  166. wp_unregister_sidebar_widget( "image-${id}" );
  167. // register new widget.
  168. $media_image_widget = new WP_Widget_Media_Image();
  169. $media_image_widget->_set( $id );
  170. $media_image_widget->_register_one( $id );
  171. }
  172. wp_set_sidebars_widgets( $sidebars_widgets );
  173. // We need to refresh on widgets page for changes to take effect.
  174. add_action( 'current_screen', 'jetpack_refresh_on_widget_page' );
  175. } else {
  176. $widget_media_image = get_option( 'widget_media_image' );
  177. if ( is_array( $widget_media_image ) ) {
  178. delete_option( 'widget_image' );
  179. }
  180. }
  181. Jetpack_Options::update_option( 'image_widget_migration', true );
  182. }
  183. add_action( 'widgets_init', 'jetpack_migrate_image_widget' );
  184. function jetpack_refresh_on_widget_page( $current ) {
  185. if ( 'widgets' === $current->base ) {
  186. wp_safe_redirect( admin_url( 'widgets.php' ) );
  187. exit;
  188. }
  189. }