loadHTML('' . $html); libxml_clear_errors(); $imgs = $dom->getElementsByTagName('img'); foreach ($imgs as $img) { $src = $img->getAttribute('src'); // Match base64 images if (preg_match('/^data:image\/([a-zA-Z0-9+]+);base64,(.*)$/s', $src, $matches)) { $savedAny = true; // <-- We are actually saving at least 1 image // Create folder ONLY when needed if (!$folderCreated) { if (!is_dir($targetDir)) { mkdir($targetDir, 0775, true); } $folderCreated = true; } $mimeType = strtolower($matches[1]); $base64 = $matches[2]; $binary = base64_decode($base64); if ($binary === false) { continue; } // Extension mapping switch ($mimeType) { case 'jpeg': case 'jpg': $ext = 'jpg'; break; case 'png': $ext = 'png'; break; case 'gif': $ext = 'gif'; break; case 'webp': $ext = 'webp'; break; default: $ext = 'png'; } // Secure random filename $uid = bin2hex(random_bytes(16)); $filename = "img_{$uid}.{$ext}"; $filePath = $targetDir . $filename; if (file_put_contents($filePath, $binary) !== false) { $webPath = "/" . $baseWebPath . $ownerId . "/" . $filename; $img->setAttribute('src', $webPath); } } } // If no images were processed, return original HTML immediately if (!$savedAny) { return $html; } // Extract body content only $body = $dom->getElementsByTagName('body')->item(0); if ($body) { $innerHTML = ''; foreach ($body->childNodes as $child) { $innerHTML .= $dom->saveHTML($child); } return $innerHTML; } return $html; } function cleanupUnusedImages(string $html, string $folderFsPath, string $folderWebPath) { $folderFsPath = rtrim($folderFsPath, '/\\') . '/'; $folderWebPath = rtrim($folderWebPath, '/\\') . '/'; if (!is_dir($folderFsPath)) { return; // no folder = nothing to delete } // 1. Get all files currently on disk $filesOnDisk = glob($folderFsPath . "*"); // 2. Find all preg_match_all('/]+src=["\']([^"\']+)["\']/i', $html, $matches); $htmlImagePaths = $matches[1] ?? []; // Normalize paths: keep only filenames belonging to this template folder $referencedFiles = []; foreach ($htmlImagePaths as $src) { if (strpos($src, $folderWebPath) !== false) { $filename = basename($src); $referencedFiles[] = $filename; } } // 3. Delete any physical file not referenced in the HTML foreach ($filesOnDisk as $filePath) { $filename = basename($filePath); if (!in_array($filename, $referencedFiles)) { unlink($filePath); } } }