@@ -74,6 +74,9 @@ class Media_Command extends WP_CLI_Command {
7474 * [--delete-unknown]
7575 * : Only delete thumbnails for old unregistered image sizes.
7676 *
77+ * [--update-attachment-refs]
78+ * : Update references to regenerated thumbnails in post content.
79+ *
7780 * [--yes]
7881 * : Answer yes to the confirmation message. Confirmation only shows when no IDs passed as arguments.
7982 *
@@ -123,7 +126,7 @@ class Media_Command extends WP_CLI_Command {
123126 * Success: Regenerated 3 of 3 images.
124127 *
125128 * @param string[] $args Positional arguments.
126- * @param array{image_size?: string|string[], 'skip-delete'?: bool, 'only-missing'?: bool, 'delete-unknown'?: bool, yes?: bool} $assoc_args Associative arguments.
129+ * @param array{image_size?: string|string[], 'skip-delete'?: bool, 'only-missing'?: bool, 'delete-unknown'?: bool, 'update-attachment-refs'?: bool, yes?: bool} $assoc_args Associative arguments.
127130 * @return void
128131 */
129132 public function regenerate ( $ args , $ assoc_args = array () ) {
@@ -172,6 +175,8 @@ public function regenerate( $args, $assoc_args = array() ) {
172175 $ skip_delete = false ;
173176 }
174177
178+ $ update_attachment_refs = Utils \get_flag_value ( $ assoc_args , 'update-attachment-refs ' );
179+
175180 $ additional_mime_types = array ();
176181
177182 if ( Utils \wp_version_compare ( '4.7 ' , '>= ' ) ) {
@@ -212,7 +217,7 @@ public function regenerate( $args, $assoc_args = array() ) {
212217 // @phpstan-ignore function.deprecated
213218 Utils \wp_clear_object_cache ();
214219 }
215- $ this ->process_regeneration ( $ post_id , $ skip_delete , $ only_missing , $ delete_unknown , $ image_sizes , $ number . '/ ' . $ count , $ successes , $ errors , $ skips );
220+ $ this ->process_regeneration ( $ post_id , $ skip_delete , $ only_missing , $ delete_unknown , $ image_sizes , $ update_attachment_refs , $ number . '/ ' . $ count , $ successes , $ errors , $ skips );
216221 }
217222
218223 if ( isset ( $ image_size_filters ) ) {
@@ -715,6 +720,7 @@ private function get_image_sizes_description( array $sizes, $noun, $default_if_e
715720 * @param bool $only_missing
716721 * @param bool $delete_unknown
717722 * @param string[] $image_sizes
723+ * @param bool $update_attachment_refs
718724 * @param string $progress
719725 * @param int $successes
720726 * @param int $errors
@@ -724,7 +730,7 @@ private function get_image_sizes_description( array $sizes, $noun, $default_if_e
724730 * @param-out int $skips
725731 * @return void
726732 */
727- private function process_regeneration ( $ id , $ skip_delete , $ only_missing , $ delete_unknown , $ image_sizes , $ progress , &$ successes , &$ errors , &$ skips ) {
733+ private function process_regeneration ( $ id , $ skip_delete , $ only_missing , $ delete_unknown , $ image_sizes , $ update_attachment_refs , $ progress , &$ successes , &$ errors , &$ skips ) {
728734
729735 $ title = get_the_title ( $ id );
730736 if ( '' === $ title ) {
@@ -752,6 +758,20 @@ private function process_regeneration( $id, $skip_delete, $only_missing, $delete
752758
753759 $ original_meta = wp_get_attachment_metadata ( $ id );
754760
761+ $ old_size_urls = array ();
762+ if ( $ update_attachment_refs && is_array ( $ original_meta ) && ! empty ( $ original_meta ['sizes ' ] ) ) {
763+ $ attachment_url = wp_get_attachment_url ( $ id );
764+ if ( $ attachment_url ) {
765+ $ dir_url = trailingslashit ( dirname ( $ attachment_url ) );
766+ $ sizes_to_track = $ image_sizes ?: array_keys ( $ original_meta ['sizes ' ] );
767+ foreach ( $ sizes_to_track as $ size ) {
768+ if ( ! empty ( $ original_meta ['sizes ' ][ $ size ]['file ' ] ) ) {
769+ $ old_size_urls [ $ size ] = $ dir_url . $ original_meta ['sizes ' ][ $ size ]['file ' ];
770+ }
771+ }
772+ }
773+ }
774+
755775 if ( $ delete_unknown ) {
756776 $ this ->delete_unknown_image_sizes ( $ id , $ fullsizepath );
757777
@@ -846,6 +866,31 @@ private function process_regeneration( $id, $skip_delete, $only_missing, $delete
846866
847867 WP_CLI ::log ( "$ progress Regenerated thumbnails for $ att_desc. " );
848868 }
869+
870+ if ( $ update_attachment_refs && ! empty ( $ old_size_urls ) && is_array ( $ metadata ) && ! empty ( $ metadata ['sizes ' ] ) ) {
871+ $ attachment_url = wp_get_attachment_url ( $ id );
872+ if ( $ attachment_url ) {
873+ $ dir_url = trailingslashit ( dirname ( $ attachment_url ) );
874+ /**
875+ * @var array<string, array<string, mixed>> $new_sizes
876+ */
877+ $ new_sizes = is_array ( $ metadata ['sizes ' ] ) ? $ metadata ['sizes ' ] : array ();
878+ foreach ( $ old_size_urls as $ size => $ old_url ) {
879+ $ size_data = $ new_sizes [ $ size ] ?? null ;
880+ if ( ! is_array ( $ size_data ) || empty ( $ size_data ['file ' ] ) ) {
881+ continue ;
882+ }
883+ /**
884+ * @var array{file: string} $size_data
885+ */
886+ $ new_url = $ dir_url . $ size_data ['file ' ];
887+ if ( $ old_url !== $ new_url ) {
888+ $ this ->update_post_content_for_attachment ( $ old_url , $ new_url );
889+ }
890+ }
891+ }
892+ }
893+
849894 ++$ successes ;
850895 }
851896
@@ -1762,4 +1807,26 @@ private function delete_unknown_image_sizes( $id, $fullsizepath ) {
17621807 // @phpstan-ignore argument.type
17631808 wp_update_attachment_metadata ( $ id , $ original_meta );
17641809 }
1810+
1811+ /**
1812+ * Updates post content replacing an old attachment URL with a new one.
1813+ *
1814+ * @param string $old_url Old thumbnail URL to search for.
1815+ * @param string $new_url New thumbnail URL to replace with.
1816+ * @return void
1817+ */
1818+ private function update_post_content_for_attachment ( $ old_url , $ new_url ) {
1819+ global $ wpdb ;
1820+ $ result = $ wpdb ->query (
1821+ $ wpdb ->prepare (
1822+ "UPDATE {$ wpdb ->posts } SET post_content = REPLACE(post_content, %s, %s) WHERE post_content LIKE %s " ,
1823+ $ old_url ,
1824+ $ new_url ,
1825+ '% ' . $ wpdb ->esc_like ( $ old_url ) . '% '
1826+ )
1827+ );
1828+ if ( false === $ result ) {
1829+ WP_CLI ::warning ( sprintf ( 'Failed to update post content references from "%s" to "%s". ' , $ old_url , $ new_url ) );
1830+ }
1831+ }
17651832}
0 commit comments