$offset = isset($assoc_args['start']) ? (int)$assoc_args['start'] : 0; $max = isset($assoc_args['max']) ? (int)$assoc_args['max'] : -1; $processed = 0; while (true) { $posts = get_posts([ 'post_type' => 'post', 'post_status' => ['publish', 'draft'], 'numberposts' => $batch, 'offset' => $offset, ]); if (empty($posts)) { WP_CLI::log("✅ Done. All posts scanned."); break; } foreach ($posts as $post) { if ($max > 0 && $processed >= $max) { WP_CLI::log("âšī¸ Reached max limit ({$max}). Stopping."); return; } WP_CLI::log("🔎 Scanning post ID {$post->ID}"); if (has_post_thumbnail($post->ID)) { WP_CLI::log("📌 Already has featured image. Skipping."); continue; } preg_match_all('/]+src=["\']([^"\']+)["\']/i', $post->post_content, $matches); if (empty($matches[1])) { WP_CLI::log("âš ī¸ No images found in post content. Skipping."); file_put_contents('skipped_posts.log', "{$post->ID}\n", FILE_APPEND); continue; } foreach ($matches[1] as $img_url) { if (strpos($img_url, 'data:image') === 0) { WP_CLI::log("⛔ Skipping base64-encoded image."); continue; } WP_CLI::log("đŸ–ŧī¸ Trying: $img_url"); $image_id = media_sideload_image($img_url, $post->ID, null, 'id'); if (!is_wp_error($image_id)) { $meta = wp_get_attachment_metadata($image_id); $width = $meta['width'] ?? 0; $height = $meta['height'] ?? 0; if ($width < 300 || $height < 300) { WP_CLI::log("❌ Too small ({$width}x{$height}). Deleting."); wp_delete_attachment($image_id, true); continue; } set_post_thumbnail($post->ID, $image_id); WP_CLI::success("✅ Set image for post {$post->ID}"); break; } else { WP_CLI::warning("Failed to sideload image: " . $image_id->get_error_message()); file_put_contents('skipped_posts.log', "{$post->ID}\n", FILE_APPEND); } } $processed++; } $offset += $batch; gc_collect_cycles(); sleep(2); // Throttle to avoid system strain } peace - The Industry Dot Biz