@@ -874,7 +874,8 @@ private function process_regeneration( $id, $skip_delete, $only_missing, $delete
874874 /**
875875 * @var array<string, array<string, mixed>> $new_sizes
876876 */
877- $ new_sizes = is_array ( $ metadata ['sizes ' ] ) ? $ metadata ['sizes ' ] : array ();
877+ $ new_sizes = is_array ( $ metadata ['sizes ' ] ) ? $ metadata ['sizes ' ] : array ();
878+ $ url_replacements = array ();
878879 foreach ( $ old_size_urls as $ size => $ old_url ) {
879880 $ size_data = $ new_sizes [ $ size ] ?? null ;
880881 if ( ! is_array ( $ size_data ) || empty ( $ size_data ['file ' ] ) ) {
@@ -885,9 +886,12 @@ private function process_regeneration( $id, $skip_delete, $only_missing, $delete
885886 */
886887 $ new_url = $ dir_url . $ size_data ['file ' ];
887888 if ( $ old_url !== $ new_url ) {
888- $ this -> update_post_content_for_attachment ( $ old_url, $ new_url ) ;
889+ $ url_replacements [ $ old_url ] = $ new_url ;
889890 }
890891 }
892+ if ( ! empty ( $ url_replacements ) ) {
893+ $ this ->update_post_content_for_attachment ( $ url_replacements );
894+ }
891895 }
892896 }
893897
@@ -1809,24 +1813,43 @@ private function delete_unknown_image_sizes( $id, $fullsizepath ) {
18091813 }
18101814
18111815 /**
1812- * Updates post content replacing an old attachment URL with a new one.
1816+ * Updates post content replacing old attachment URLs with new ones in a single query.
1817+ *
1818+ * Applies all replacements as nested REPLACE() calls so only one table scan is needed.
18131819 *
1814- * @param string $old_url Old thumbnail URL to search for.
1815- * @param string $new_url New thumbnail URL to replace with.
1820+ * @param array<string, string> $url_replacements Map of old URL => new URL.
18161821 * @return void
18171822 */
1818- private function update_post_content_for_attachment ( $ old_url , $ new_url ) {
1823+ private function update_post_content_for_attachment ( array $ url_replacements ) {
18191824 global $ wpdb ;
1825+
1826+ if ( empty ( $ url_replacements ) ) {
1827+ return ;
1828+ }
1829+
1830+ $ replace_expr = 'post_content ' ;
1831+ $ replace_args = array ();
1832+ $ where_clauses = array ();
1833+ $ where_args = array ();
1834+
1835+ foreach ( $ url_replacements as $ old_url => $ new_url ) {
1836+ $ replace_expr = "REPLACE( $ replace_expr, %s, %s) " ;
1837+ $ replace_args [] = $ old_url ;
1838+ $ replace_args [] = $ new_url ;
1839+ $ where_clauses [] = 'post_content LIKE %s ' ;
1840+ $ where_args [] = '% ' . $ wpdb ->esc_like ( $ old_url ) . '% ' ;
1841+ }
1842+
1843+ $ where_sql = implode ( ' OR ' , $ where_clauses );
1844+ // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
18201845 $ 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- )
1846+ $ wpdb ->prepare ( "UPDATE {$ wpdb ->posts } SET post_content = {$ replace_expr } WHERE {$ where_sql }" , ...array_merge ( $ replace_args , $ where_args ) )
18271847 );
1848+ // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
18281849 if ( false === $ result ) {
1829- WP_CLI ::warning ( sprintf ( 'Failed to update post content references from "%s" to "%s". ' , $ old_url , $ new_url ) );
1850+ WP_CLI ::warning ( 'Failed to update post content references for attachment. ' );
1851+ } else {
1852+ wp_cache_set ( 'last_changed ' , microtime (), 'posts ' );
18301853 }
18311854 }
18321855}
0 commit comments