PDO::ERRMODE_EXCEPTION, ]); echo "=== Fix image paths (Joomla `images/...` → WP uploads) ===\n"; echo $dry_run ? "[DRY RUN]\n\n" : "[LIVE RUN]\n\n"; $stmt = $pdo->query(" SELECT ID, post_title, post_content FROM wp_posts WHERE post_status IN ('publish','draft') AND post_type IN ('post','page') AND ( post_content LIKE '%src=\"images/%' OR post_content LIKE \"%src='images/%\" OR post_content LIKE '%href=\"images/%' OR post_content LIKE \"%href='images/%\" ) "); $posts = $stmt->fetchAll(PDO::FETCH_ASSOC); echo "Posts candidatos: " . count($posts) . "\n\n"; $stats = [ 'posts_changed' => 0, 'posts_unchanged' => 0, 'refs_rewritten' => 0, 'refs_missing_file' => 0, ]; $missing = []; // path => count $missing_per_post = []; // ID => [path,...] // (src|href)= ( " | ' ) images/... ( " | ' ) $pattern = '/\b(src|href)=("|\')images\/([^"\']+)\2/i'; $update = $pdo->prepare("UPDATE wp_posts SET post_content = ? WHERE ID = ?"); foreach ($posts as $post) { $original = $post['post_content']; $pid = (int)$post['ID']; $content = preg_replace_callback( $pattern, function ($m) use ($uploads_fs, $uploads_url, &$stats, &$missing, &$missing_per_post, $pid) { $attr = $m[1]; $quote = $m[2]; $rel_enc = $m[3]; // tal como aparece en HTML (puede ir URL-encoded) $rel_dec = urldecode($rel_enc); // para mirar el filesystem $fs_path = $uploads_fs . '/' . $rel_dec; if (is_file($fs_path)) { $stats['refs_rewritten']++; return $attr . '=' . $quote . $uploads_url . '/' . $rel_enc . $quote; } $stats['refs_missing_file']++; $missing[$rel_dec] = ($missing[$rel_dec] ?? 0) + 1; $missing_per_post[$pid][] = $rel_dec; return $m[0]; // dejar sin tocar }, $original ); if ($content !== $original) { $stats['posts_changed']++; if (!$dry_run) { $update->execute([$content, $pid]); } } else { $stats['posts_unchanged']++; } } echo "=== Resumen ===\n"; echo "Posts modificados: {$stats['posts_changed']}\n"; echo "Posts sin cambios: {$stats['posts_unchanged']}\n"; echo "Referencias reescritas: {$stats['refs_rewritten']}\n"; echo "Referencias sin fichero: {$stats['refs_missing_file']}\n"; echo "Rutas faltantes únicas: " . count($missing) . "\n"; if (!empty($missing)) { arsort($missing); $log_path = '/tmp/fix_image_paths_missing.log'; $lines = []; foreach ($missing as $path => $n) { $lines[] = sprintf("%4d %s", $n, $path); } file_put_contents($log_path, implode("\n", $lines) . "\n"); echo "\nLog rutas faltantes (orden por #ocurrencias): $log_path\n"; echo "Top 15:\n"; $i = 0; foreach ($missing as $path => $n) { echo sprintf(" %4d %s\n", $n, $path); if (++$i >= 15) break; } // breakdown por carpeta raíz (segmento tras `images/`) $by_root = []; foreach ($missing as $path => $n) { $root = explode('/', $path)[0] ?? '?'; $by_root[$root] = ($by_root[$root] ?? 0) + $n; } arsort($by_root); echo "\nFaltantes por carpeta raíz:\n"; foreach ($by_root as $root => $n) { echo sprintf(" %4d images/%s/\n", $n, $root); } } echo "\nHecho.\n";