diff --git a/api.php b/api.php
index ecd96d5..4c693cc 100644
--- a/api.php
+++ b/api.php
@@ -105,191 +105,203 @@ function extractYear($dateStr) {
return '';
}
-// ── API DVDFr (SANS CACHE - Scraping HTML) ──
+// ── API DVDFr (réécriture complète) ──
function fetchDVDFr($ean, $pdo) {
- if (empty($ean) || strlen($ean) < 8) return null;
-
- // 🔥 SUPPRESSION DES APPELS À getCache() QUI N'EXISTE PLUS
-
- $ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
-
- // Étape 1 : Recherche via le site DVDfr (page HTML)
- $searchUrl = "https://www.dvdfr.com/search/?q=" . urlencode($ean);
-
- $ch = curl_init($searchUrl);
- curl_setopt_array($ch, [
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_TIMEOUT => 8,
- CURLOPT_CONNECTTIMEOUT => 5,
- CURLOPT_SSL_VERIFYPEER => false,
- CURLOPT_USERAGENT => $ua,
- CURLOPT_FOLLOWLOCATION => true,
- CURLOPT_HTTPHEADER => [
- 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
- 'Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',
- ],
- ]);
- $html = curl_exec($ch);
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
-
- if (!$html || $httpCode !== 200) {
- error_log("DVDFr: Échec recherche HTML - HTTP $httpCode");
- return null;
- }
-
- // Étape 2 : Extraire le lien vers la fiche du film
- $dvdUrl = null;
-
- if (preg_match('/]+href=["\']([^"\']+\.html)["\'][^>]*class=["\'][^"\']*result[^"\']*["\'][^>]*>/i', $html, $matches)) {
- $dvdUrl = $matches[1];
- if (strpos($dvdUrl, 'http') !== 0) {
- $dvdUrl = 'https://www.dvdfr.com' . $dvdUrl;
- }
- }
-
- if (!$dvdUrl && preg_match('/href=["\']([^"\']*' . preg_quote($ean, '/') . '[^"\']*\.html)["\']/i', $html, $matches)) {
- $dvdUrl = $matches[1];
- if (strpos($dvdUrl, 'http') !== 0) {
- $dvdUrl = 'https://www.dvdfr.com' . $dvdUrl;
- }
- }
-
- if (!$dvdUrl && preg_match('/]+href=["\'](https:\/\/www\.dvdfr\.com\/(?:dvd|blu-ray)\/[^"\']+\.html)["\']/i', $html, $matches)) {
- $dvdUrl = $matches[1];
- }
-
- if (!$dvdUrl) {
- error_log("DVDFr: Aucune fiche trouvée pour EAN $ean");
- return null;
- }
-
- error_log("DVDFr: Fiche trouvée - $dvdUrl");
-
- // Étape 3 : Récupérer la fiche complète
- $ch2 = curl_init($dvdUrl);
- curl_setopt_array($ch2, [
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_TIMEOUT => 8,
- CURLOPT_CONNECTTIMEOUT => 5,
- CURLOPT_SSL_VERIFYPEER => false,
- CURLOPT_USERAGENT => $ua,
- CURLOPT_FOLLOWLOCATION => true,
- CURLOPT_HTTPHEADER => [
- 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
- 'Accept-Language: fr-FR,fr;q=0.9',
- ],
- ]);
- $ficheHtml = curl_exec($ch2);
- curl_close($ch2);
-
- if (!$ficheHtml) {
- error_log("DVDFr: Impossible de charger la fiche");
- return null;
- }
-
- // Étape 4 : Extraire les données depuis le HTML
-$result = [
- 'poster' => '',
- 'publisher' => '',
- 'format' => '',
- 'length' => '',
- 'aspect' => '',
- 'discs' => '',
-];
+ if (empty($ean) || strlen((string)$ean) < 8) return null;
-// 🔥 EXTRACTION ROBUSTE DE L'AFFICHE (plusieurs méthodes fallback)
-// Méthode 1 : Chercher toutes les images et filtrer par taille/URL
-preg_match_all('/
]+src=["\']([^"\']+)["\'][^>]*>/i', $ficheHtml, $allImages);
-if (!empty($allImages[1])) {
- foreach ($allImages[1] as $imgUrl) {
- // Filtrer les images qui ressemblent à une jaquette
- if (preg_match('/(cover|jaquette|pochette|affiche|poster|front)/i', $imgUrl) ||
- preg_match('/\.(jpg|jpeg|png|webp)$/i', $imgUrl)) {
- // Vérifier que c'est bien une URL complète
- if (strpos($imgUrl, 'http') === 0) {
- $result['poster'] = $imgUrl;
- error_log("DVDFr: Affiche trouvée (méthode 1) - $imgUrl");
- break;
- } elseif (strpos($imgUrl, '//') === 0) {
- $result['poster'] = 'https:' . $imgUrl;
- error_log("DVDFr: Affiche trouvée (méthode 1b) - " . $result['poster']);
- break;
- } elseif (strpos($imgUrl, '/') === 0) {
- $result['poster'] = 'https://www.dvdfr.com' . $imgUrl;
- error_log("DVDFr: Affiche trouvée (méthode 1c) - " . $result['poster']);
+ $ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36';
+ $baseHeaders = [
+ 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
+ 'Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7',
+ 'Accept-Encoding: gzip, deflate, br',
+ 'Connection: keep-alive',
+ ];
+
+ // ── Helpers internes ──
+ $curlGet = function(string $url) use ($ua, $baseHeaders): ?string {
+ $ch = curl_init($url);
+ curl_setopt_array($ch, [
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_TIMEOUT => 10,
+ CURLOPT_CONNECTTIMEOUT => 5,
+ CURLOPT_SSL_VERIFYPEER => false,
+ CURLOPT_USERAGENT => $ua,
+ CURLOPT_FOLLOWLOCATION => true,
+ CURLOPT_MAXREDIRS => 5,
+ CURLOPT_ENCODING => '', // décompression auto (gzip, br…)
+ CURLOPT_HTTPHEADER => $baseHeaders,
+ CURLOPT_COOKIEFILE => '', // active le jar de cookies en mémoire
+ ]);
+ $body = curl_exec($ch);
+ $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ curl_close($ch);
+ if (!$body || $code !== 200) {
+ error_log("DVDFr curlGet: HTTP $code pour $url");
+ return null;
+ }
+ return $body;
+ };
+
+ $absoluteUrl = function(string $src): string {
+ if (strpos($src, 'http') === 0) return $src;
+ if (strpos($src, '//') === 0) return 'https:' . $src;
+ if (strpos($src, '/') === 0) return 'https://www.dvdfr.com' . $src;
+ return 'https://www.dvdfr.com/' . $src;
+ };
+
+ // ── ÉTAPE 1 : trouver l'URL de la fiche via la recherche ──
+ $searchHtml = $curlGet('https://www.dvdfr.com/search/?q=' . urlencode($ean));
+ if (!$searchHtml) {
+ error_log("DVDFr: échec de la page de recherche pour EAN $ean");
+ return null;
+ }
+
+ // Patterns par ordre de priorité
+ $ficheUrl = null;
+ $patterns = [
+ // lien direct vers une fiche /dvd/ ou /blu-ray/ contenant l'EAN dans l'URL
+ '@href=["\']([^"\']*(?:dvd|blu-ray|4k|vhs|cd|coffret)[^"\']+\.html)["\']@i',
+ // toute fiche .html dans le domaine dvdfr.com
+ '@href=["\'](?:https?://(?:www\.)?dvdfr\.com)?(/[^"\']+\.html)["\']@i',
+ ];
+ foreach ($patterns as $pattern) {
+ if (preg_match($pattern, $searchHtml, $m)) {
+ $ficheUrl = $absoluteUrl($m[1]);
+ break;
+ }
+ }
+
+ if (!$ficheUrl) {
+ error_log("DVDFr: aucune fiche trouvée pour EAN $ean");
+ return null;
+ }
+ error_log("DVDFr: fiche → $ficheUrl");
+
+ // ── ÉTAPE 2 : charger la fiche ──
+ $html = $curlGet($ficheUrl);
+ if (!$html) {
+ error_log("DVDFr: impossible de charger la fiche $ficheUrl");
+ return null;
+ }
+
+ // ── ÉTAPE 3 : extraction des données ──
+ $result = [
+ 'poster' => '',
+ 'title' => '',
+ 'publisher' => '',
+ 'format' => '',
+ 'length' => '',
+ 'aspect' => '',
+ 'discs' => '',
+ ];
+
+ // --- 3a. AFFICHE ---
+ // Priorité 1 : og:image (le plus fiable)
+ if (preg_match('/]+property=["\']og:image["\'][^>]+content=["\']([^"\']+)["\']/i', $html, $m) ||
+ preg_match('/]+content=["\']([^"\']+)["\'][^>]+property=["\']og:image["\']/i', $html, $m)) {
+ $result['poster'] = $m[1];
+ error_log("DVDFr: affiche via og:image → " . $result['poster']);
+ }
+
+ // Priorité 2 : JSON-LD
+ if (empty($result['poster'])) {
+ preg_match_all('/