Actualiser api.php

This commit is contained in:
2026-06-21 14:37:06 +02:00
parent d96938eff6
commit b014c9027d
+187 -163
View File
@@ -5,18 +5,20 @@ header("Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization"); header("Access-Control-Allow-Headers: Content-Type, Authorization");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Pragma: no-cache"); header("Pragma: no-cache");
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200); http_response_code(200);
exit; exit;
} }
define('ENCRYPTION_KEY', 'MaCleSecreteSuperRobuste123!'); define('ENCRYPTION_KEY', 'MaCleSecreteSuperRobuste123!');
try { try {
$pdo = new PDO("mysql:host=localhost;dbname=mon_cinema;charset=utf8mb4", "root", "", [ $pdo = new PDO("mysql:host=localhost;dbname=mon_cinema;charset=utf8mb4", "root", "", [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]); ]);
// Création des tables (rating changé en DECIMAL(3,1) pour accepter les notes Letterboxd comme 2.5, 3.5)
$pdo->exec("CREATE TABLE IF NOT EXISTS users ( $pdo->exec("CREATE TABLE IF NOT EXISTS users (
id INT PRIMARY KEY, username VARCHAR(50) NOT NULL, password_hash VARCHAR(255) NOT NULL id INT PRIMARY KEY, username VARCHAR(50) NOT NULL, password_hash VARCHAR(255) NOT NULL
)"); )");
@@ -27,7 +29,6 @@ try {
id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255), id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255),
poster TEXT, rating DECIMAL(3,1) DEFAULT 3.0, review TEXT, streaming VARCHAR(255) poster TEXT, rating DECIMAL(3,1) DEFAULT 3.0, review TEXT, streaming VARCHAR(255)
)"); )");
// Force la mise à jour de la colonne si la table existe déjà
$pdo->exec("ALTER TABLE critiques MODIFY COLUMN rating DECIMAL(3,1) DEFAULT 3.0;"); $pdo->exec("ALTER TABLE critiques MODIFY COLUMN rating DECIMAL(3,1) DEFAULT 3.0;");
$pdo->exec("CREATE TABLE IF NOT EXISTS videotheque ( $pdo->exec("CREATE TABLE IF NOT EXISTS videotheque (
id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255), id BIGINT PRIMARY KEY, title VARCHAR(255) NOT NULL, year VARCHAR(10), director VARCHAR(255),
@@ -86,14 +87,71 @@ function getTmdbApiKey($pdo) {
return decryptData($row['key_value']); return decryptData($row['key_value']);
} }
// ── FONCTION HTTP UNIFIÉE (cURL ou file_get_contents) ──
function httpGet($url, $timeout = 8) {
if (function_exists('curl_init')) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERAGENT, 'MonCinema/1.0');
$res = curl_exec($ch);
curl_close($ch);
return $res ?: null;
}
$ctx = stream_context_create(['http' => ['timeout' => $timeout, 'user_agent' => 'MonCinema/1.0']]);
return @file_get_contents($url, false, $ctx);
}
// ── RÉCUPÉRATION IMAGE VIA EAN (Open Library API) ──
function fetchImageByEAN($ean) {
if (empty($ean) || strlen($ean) < 10) return null;
// Open Library API (gratuit, sans clé)
$url = "https://openlibrary.org/api/books?bibkeys=ISBN:{$ean}&jscmd=data&format=json";
$res = httpGet($url, 5);
if ($res) {
$data = json_decode($res, true);
$key = "ISBN:{$ean}";
if (isset($data[$key])) {
// Priorité : cover (grande image) > thumbnail
if (!empty($data[$key]['cover']['large'])) {
return $data[$key]['cover']['large'];
}
if (!empty($data[$key]['cover']['medium'])) {
return $data[$key]['cover']['medium'];
}
if (!empty($data[$key]['cover']['small'])) {
return $data[$key]['cover']['small'];
}
}
}
// Fallback : Google Books API
$url = "https://www.googleapis.com/books/v1/volumes?q=isbn:{$ean}&maxResults=1";
$res = httpGet($url, 5);
if ($res) {
$data = json_decode($res, true);
if (!empty($data['items'][0]['volumeInfo']['imageLinks']['thumbnail'])) {
return str_replace('http:', 'https:', $data['items'][0]['volumeInfo']['imageLinks']['thumbnail']);
}
}
return null;
}
// ── RÉCUPÉRATION DONNÉES TMDB ──
function fetchTmdbData($title, $year, $apiKey) { function fetchTmdbData($title, $year, $apiKey) {
if (empty($apiKey) || empty($title)) return null; if (empty($apiKey) || empty($title)) return null;
$searchUrl = "https://api.themoviedb.org/3/search/movie?api_key={$apiKey}&query=" . urlencode($title) . "&year={$year}&language=fr-FR";
$searchRes = @file_get_contents($searchUrl); // Nettoyage du titre (enlever [Blu-ray], [Édition Collector], etc.)
if (!$searchRes && function_exists('curl_init')) { $cleanTitle = preg_replace('/\s*\[.*?\]\s*/', '', $title);
$ch = curl_init($searchUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 5); $searchRes = curl_exec($ch); curl_close($ch); $cleanTitle = trim($cleanTitle);
}
$searchUrl = "https://api.themoviedb.org/3/search/movie?api_key={$apiKey}&query=" . urlencode($cleanTitle) . "&year={$year}&language=fr-FR";
$searchRes = httpGet($searchUrl, 8);
if (!$searchRes) return null; if (!$searchRes) return null;
$searchData = json_decode($searchRes, true); $searchData = json_decode($searchRes, true);
if (empty($searchData['results'])) return null; if (empty($searchData['results'])) return null;
@@ -103,35 +161,38 @@ function fetchTmdbData($title, $year, $apiKey) {
// Récupération Réalisateur // Récupération Réalisateur
$creditsUrl = "https://api.themoviedb.org/3/movie/{$movieId}/credits?api_key={$apiKey}&language=fr-FR"; $creditsUrl = "https://api.themoviedb.org/3/movie/{$movieId}/credits?api_key={$apiKey}&language=fr-FR";
$creditsRes = @file_get_contents($creditsUrl); $creditsRes = httpGet($creditsUrl, 8);
if (!$creditsRes && function_exists('curl_init')) {
$ch = curl_init($creditsUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 5); $creditsRes = curl_exec($ch); curl_close($ch);
}
$director = ''; $director = '';
if ($creditsRes) { if ($creditsRes) {
$creditsData = json_decode($creditsRes, true); $creditsData = json_decode($creditsRes, true);
if (!empty($creditsData['crew'])) { if (!empty($creditsData['crew'])) {
foreach ($creditsData['crew'] as $crew) { foreach ($creditsData['crew'] as $crew) {
if ($crew['job'] === 'Director' || $crew['job'] === 'Directing') { $director = $crew['name']; break; } if ($crew['job'] === 'Director') {
$director = $crew['name'];
break;
}
} }
} }
} }
// 🎬 Récupération Streaming (France) // Récupération Streaming (France)
$streaming = ''; $streaming = '';
$watchUrl = "https://api.themoviedb.org/3/movie/{$movieId}/watch/providers?api_key={$apiKey}"; $watchUrl = "https://api.themoviedb.org/3/movie/{$movieId}/watch/providers?api_key={$apiKey}";
$watchRes = @file_get_contents($watchUrl); $watchRes = httpGet($watchUrl, 8);
if (!$watchRes && function_exists('curl_init')) {
$ch = curl_init($watchUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 5); $watchRes = curl_exec($ch); curl_close($ch);
}
if ($watchRes) { if ($watchRes) {
$watchData = json_decode($watchRes, true); $watchData = json_decode($watchRes, true);
$frProviders = $watchData['results']['FR'] ?? []; $frProviders = $watchData['results']['FR'] ?? [];
$platforms = []; $platforms = [];
if (!empty($frProviders['flatrate'])) { foreach ($frProviders['flatrate'] as $p) $platforms[] = $p['provider_name']; } if (!empty($frProviders['flatrate'])) {
foreach ($frProviders['flatrate'] as $p) $platforms[] = $p['provider_name'];
}
if (empty($platforms)) { if (empty($platforms)) {
if (!empty($frProviders['rent'])) { foreach ($frProviders['rent'] as $p) $platforms[] = $p['provider_name'] . ' (loc.)'; } if (!empty($frProviders['rent'])) {
if (!empty($frProviders['buy'])) { foreach ($frProviders['buy'] as $p) $platforms[] = $p['provider_name'] . ' (achat)'; } foreach ($frProviders['rent'] as $p) $platforms[] = $p['provider_name'] . ' (loc.)';
}
if (!empty($frProviders['buy'])) {
foreach ($frProviders['buy'] as $p) $platforms[] = $p['provider_name'] . ' (achat)';
}
} }
if (!empty($platforms)) $streaming = implode(', ', array_unique($platforms)); if (!empty($platforms)) $streaming = implode(', ', array_unique($platforms));
} }
@@ -139,9 +200,30 @@ function fetchTmdbData($title, $year, $apiKey) {
return ['director' => $director, 'poster' => $poster, 'streaming' => $streaming]; return ['director' => $director, 'poster' => $poster, 'streaming' => $streaming];
} }
// ── ROUTEUR PRINCIPAL ── // ── PARSING DU FORMAT (Blu-ray, DVD, etc.) depuis le titre ──
function detectFormat($title, $description = '') {
$text = strtoupper($title . ' ' . $description);
if (strpos($text, '4K') !== false || strpos($text, 'UHD') !== false) return 'Blu-ray 4K';
if (strpos($text, 'BLU-RAY') !== false || strpos($text, 'BLURAY') !== false) return 'Blu-ray';
if (strpos($text, 'DVD') !== false) return 'DVD';
if (strpos($text, 'VHS') !== false) return 'VHS';
if (strpos($text, 'COFFRET') !== false || strpos($text, 'TRILOGIE') !== false || strpos($text, 'INTEGRALE') !== false) return 'Coffret DVD';
return 'DVD';
}
// ── EXTRACTION ANNÉE depuis publish_date ──
function extractYear($publishDate) {
if (empty($publishDate)) return '';
if (preg_match('/(\d{4})/', $publishDate, $matches)) {
return $matches[1];
}
return '';
}
// ── ROUTEUR PRINCIPAL ─
$action = $_GET['action'] ?? ''; $action = $_GET['action'] ?? '';
$data = json_decode(file_get_contents('php://input'), true) ?? []; $data = json_decode(file_get_contents('php://input'), true) ?? [];
switch ($action) { switch ($action) {
case 'check_security_status': case 'check_security_status':
$stmt = $pdo->query("SELECT COUNT(*) FROM users"); $stmt = $pdo->query("SELECT COUNT(*) FROM users");
@@ -200,26 +282,20 @@ switch ($action) {
$type = $data['type'] ?? 'critique'; $type = $data['type'] ?? 'critique';
$id = !empty($data['id']) ? $data['id'] : makeStableId($data['title'] ?? '', $data['year'] ?? '0000'); $id = !empty($data['id']) ? $data['id'] : makeStableId($data['title'] ?? '', $data['year'] ?? '0000');
if (empty($data['director']) || empty($data['poster']) || empty($data['streaming'])) { if (empty($data['director']) || empty($data['poster'])) {
$apiKey = getTmdbApiKey($pdo); $apiKey = getTmdbApiKey($pdo);
$tmdbData = fetchTmdbData($data['title'] ?? '', $data['year'] ?? '', $apiKey); $tmdbData = fetchTmdbData($data['title'] ?? '', $data['year'] ?? '', $apiKey);
if ($tmdbData) { if ($tmdbData) {
if (empty($data['director'])) $data['director'] = $tmdbData['director']; if (empty($data['director'])) $data['director'] = $tmdbData['director'];
if (empty($data['poster'])) $data['poster'] = $tmdbData['poster']; if (empty($data['poster'])) $data['poster'] = $tmdbData['poster'];
if (empty($data['streaming'])) {
$data['streaming'] = !empty($tmdbData['streaming'])
? $tmdbData['streaming']
: 'Disponible en support physique ou Cinéma';
}
} elseif (empty($data['streaming'])) {
$data['streaming'] = 'Disponible en support physique ou Cinéma';
} }
} }
if ($type === 'critique') { if ($type === 'critique') {
$sql = "INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming) $sql = "INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=VALUES(director), poster=VALUES(poster), rating=VALUES(rating), review=VALUES(review), streaming=VALUES(streaming)"; ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=VALUES(director),
poster=VALUES(poster), rating=VALUES(rating), review=VALUES(review), streaming=VALUES(streaming)";
$stmt = $pdo->prepare($sql); $stmt = $pdo->prepare($sql);
$stmt->execute([ $stmt->execute([
$id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '', $id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '',
@@ -228,7 +304,10 @@ switch ($action) {
} else { } else {
$sql = "INSERT INTO videotheque (id, title, year, director, poster, format, length, publisher, ean_isbn13, number_of_discs, aspect_ratio, description) $sql = "INSERT INTO videotheque (id, title, year, director, poster, format, length, publisher, ean_isbn13, number_of_discs, aspect_ratio, description)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=VALUES(director), poster=VALUES(poster), format=VALUES(format), length=VALUES(length), publisher=VALUES(publisher), ean_isbn13=VALUES(ean_isbn13), number_of_discs=VALUES(number_of_discs), aspect_ratio=VALUES(aspect_ratio), description=VALUES(description)"; ON DUPLICATE KEY UPDATE title=VALUES(title), year=VALUES(year), director=VALUES(director),
poster=VALUES(poster), format=VALUES(format), length=VALUES(length), publisher=VALUES(publisher),
ean_isbn13=VALUES(ean_isbn13), number_of_discs=VALUES(number_of_discs),
aspect_ratio=VALUES(aspect_ratio), description=VALUES(description)";
$stmt = $pdo->prepare($sql); $stmt = $pdo->prepare($sql);
$stmt->execute([ $stmt->execute([
$id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '', $id, $data['title'] ?? '', $data['year'] ?? '', $data['director'] ?? '',
@@ -266,169 +345,114 @@ switch ($action) {
echo json_encode(["success" => false, "error" => "Aucun élément sélectionné."]); echo json_encode(["success" => false, "error" => "Aucun élément sélectionné."]);
} }
break; break;
case 'import_batch': case 'import_batch':
checkAuth($pdo); checkAuth($pdo);
$items = $data['items'] ?? []; $items = $data['items'] ?? [];
$type = $data['type'] ?? 'critique'; $type = $data['type'] ?? 'videotheque';
$tmdbApiKey = getTmdbApiKey($pdo); $tmdbApiKey = getTmdbApiKey($pdo);
$imported = 0; $imported = 0;
$results = [];
foreach ($items as $rowData) { foreach ($items as $rowData) {
$title = $rowData['Name'] ?? $rowData['title'] ?? 'Sans titre'; // ── MAPPING FLEXIBLE DES COLONNES (adapté à votre CSV) ──
$year = $rowData['Year'] ?? $rowData['year'] ?? '0000'; $title = $rowData['title'] ?? $rowData['Name'] ?? $rowData['Title'] ?? 'Sans titre';
$director = $rowData['Director'] ?? $rowData['director'] ?? ''; $year = extractYear($rowData['publish_date'] ?? $rowData['Year'] ?? $rowData['year'] ?? '');
$poster = $rowData['Poster'] ?? $rowData['poster'] ?? $rowData['image'] ?? ''; $director = $rowData['director'] ?? $rowData['Director'] ?? '';
$poster = $rowData['poster'] ?? $rowData['Poster'] ?? $rowData['image'] ?? '';
$ean = $rowData['ean_isbn13'] ?? $rowData['EAN'] ?? $rowData['ean'] ?? '';
$publisher = $rowData['publisher'] ?? $rowData['Publisher'] ?? '';
$description = $rowData['description'] ?? $rowData['Description'] ?? '';
$length = $rowData['length'] ?? $rowData['Length'] ?? '';
$discs = $rowData['number_of_discs'] ?? $rowData['Number of Discs'] ?? 1;
$aspect = $rowData['aspect_ratio'] ?? $rowData['Aspect Ratio'] ?? '';
$creators = $rowData['creators'] ?? $rowData['Creators'] ?? '';
$firstName = $rowData['first_name'] ?? '';
$lastName = $rowData['last_name'] ?? '';
// Appel TMDB pour combler les trous (Réal, Affiche, Streaming) // Si pas de réalisateur, essayer first_name + last_name
if (empty($director) && !empty($firstName) && !empty($lastName)) {
$director = trim($firstName . ' ' . $lastName);
}
// Détection automatique du format
$format = $rowData['format'] ?? $rowData['Format'] ?? detectFormat($title, $description);
// ── RÉCUPÉRATION IMAGE (priorité : EAN > TMDB) ──
$imageRetrieved = false;
// 1. Essayer via EAN (jaquette DVD/Blu-ray)
if (empty($poster) && !empty($ean)) {
$eanImage = fetchImageByEAN($ean);
if ($eanImage) {
$poster = $eanImage;
$imageRetrieved = true;
}
}
// 2. Si pas d'image EAN, essayer TMDB (affiche du film)
if (empty($poster) && $tmdbApiKey) {
$tmdbData = fetchTmdbData($title, $year, $tmdbApiKey); $tmdbData = fetchTmdbData($title, $year, $tmdbApiKey);
if ($tmdbData) { if ($tmdbData) {
if (empty($director)) $director = $tmdbData['director']; if (empty($director)) $director = $tmdbData['director'];
if (empty($poster)) $poster = $tmdbData['poster']; if (!empty($tmdbData['poster'])) {
$poster = $tmdbData['poster'];
$imageRetrieved = true;
}
}
} }
$id = makeStableId($title, $year); $id = makeStableId($title, $year);
if ($type === 'critique') { if ($type === 'critique') {
$rating = isset($rowData['Rating']) && $rowData['Rating'] !== '' ? (float)$rowData['Rating'] : 3.0; $rating = isset($rowData['Rating']) && $rowData['Rating'] !== '' ? (float)$rowData['Rating'] : 3.0;
$review = $rowData['Review'] ?? $rowData['review'] ?? ''; $review = $rowData['Review'] ?? $rowData['review'] ?? $description;
$csvStreaming = $rowData['Streaming'] ?? $rowData['streaming'] ?? ''; $streaming = $rowData['Streaming'] ?? $rowData['streaming'] ?? 'Disponible en support physique ou Cinéma';
$streaming = !empty($csvStreaming) ? $csvStreaming : (!empty($tmdbData['streaming']) ? $tmdbData['streaming'] : 'Disponible en support physique ou Cinéma');
$sql = "INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming) $sql = "INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE ON DUPLICATE KEY UPDATE rating=VALUES(rating), review=IF(VALUES(review)!='',VALUES(review),review),
rating = VALUES(rating), director=IF(VALUES(director)!='',VALUES(director),director),
review = IF(VALUES(review) != '', VALUES(review), review), poster=IF(VALUES(poster)!='',VALUES(poster),poster),
director = IF(VALUES(director) != '', VALUES(director), director), streaming=IF(VALUES(streaming)!='',VALUES(streaming),streaming)";
poster = IF(VALUES(poster) != '', VALUES(poster), poster),
streaming = IF(VALUES(streaming) != '', VALUES(streaming), streaming)";
$stmt = $pdo->prepare($sql); $stmt = $pdo->prepare($sql);
$stmt->execute([$id, $title, $year, $director, $poster, $rating, $review, $streaming]); $stmt->execute([$id, $title, $year, $director, $poster, $rating, $review, $streaming]);
} else { } else {
$format = $rowData['format'] ?? $rowData['Format'] ?? '';
$length = $rowData['length'] ?? $rowData['Length'] ?? '';
$publisher = $rowData['publisher'] ?? $rowData['Publisher'] ?? '';
$ean = $rowData['ean_isbn13'] ?? $rowData['EAN'] ?? '';
$discs = $rowData['number_of_discs'] ?? 1;
$aspect = $rowData['aspect_ratio'] ?? '';
$desc = $rowData['description'] ?? $rowData['Description'] ?? '';
$sql = "INSERT INTO videotheque (id, title, year, director, poster, format, length, publisher, ean_isbn13, number_of_discs, aspect_ratio, description) $sql = "INSERT INTO videotheque (id, title, year, director, poster, format, length, publisher, ean_isbn13, number_of_discs, aspect_ratio, description)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE ON DUPLICATE KEY UPDATE director=IF(VALUES(director)!='',VALUES(director),director),
director = IF(VALUES(director) != '', VALUES(director), director), poster=IF(VALUES(poster)!='',VALUES(poster),poster),
poster = IF(VALUES(poster) != '', VALUES(poster), poster), format=IF(VALUES(format)!='',VALUES(format),format),
format = IF(VALUES(format) != '', VALUES(format), format), length=IF(VALUES(length)!='',VALUES(length),length),
length = IF(VALUES(length) != '', VALUES(length), length), publisher=IF(VALUES(publisher)!='',VALUES(publisher),publisher),
publisher = IF(VALUES(publisher) != '', VALUES(publisher), publisher), ean_isbn13=IF(VALUES(ean_isbn13)!='',VALUES(ean_isbn13),ean_isbn13),
ean_isbn13 = IF(VALUES(ean_isbn13) != '', VALUES(ean_isbn13), ean_isbn13), number_of_discs=IF(VALUES(number_of_discs)!=1,VALUES(number_of_discs),number_of_discs),
number_of_discs = IF(VALUES(number_of_discs) != 1, VALUES(number_of_discs), number_of_discs), aspect_ratio=IF(VALUES(aspect_ratio)!='',VALUES(aspect_ratio),aspect_ratio),
aspect_ratio = IF(VALUES(aspect_ratio) != '', VALUES(aspect_ratio), aspect_ratio), description=IF(VALUES(description)!='',VALUES(description),description)";
description = IF(VALUES(description) != '', VALUES(description), description)";
$stmt = $pdo->prepare($sql); $stmt = $pdo->prepare($sql);
$stmt->execute([$id, $title, $year, $director, $poster, $format, $length, $publisher, $ean, $discs, $aspect, $desc]); $stmt->execute([$id, $title, $year, $director, $poster, $format, $length, $publisher, $ean, $discs, $aspect, $description]);
} }
$imported++; $imported++;
$results[] = [
'title' => $title,
'poster' => !empty($poster),
'ean' => $ean,
'image_source' => $imageRetrieved ? ($ean ? 'EAN' : 'TMDB') : 'none'
];
} }
echo json_encode(["success" => true, "imported" => $imported]);
echo json_encode(["success" => true, "imported" => $imported, "details" => $results]);
break; break;
case 'import_csv':
checkAuth($pdo);
if (isset($_FILES['csv_file'])) {
$file = $_FILES['csv_file']['tmp_name'];
$type = $_POST['type'] ?? 'critique';
$tmdbApiKey = getTmdbApiKey($pdo);
try { case 'test_image_ean':
if (($handle = fopen($file, "r")) !== FALSE) { // Endpoint de test pour vérifier la récupération d'image par EAN
$header = fgetcsv($handle, 0, ","); $ean = $_GET['ean'] ?? '';
if (!$header) throw new Exception("Impossible de lire l'en-tête du CSV."); if (empty($ean)) {
echo json_encode(["error" => "EAN requis"]);
// 🧹 Nettoyage du BOM UTF-8 (très fréquent sur les exports Letterboxd/Excel) break;
$header[0] = str_replace("\xEF\xBB\xBF", '', $header[0]);
$header = array_map('trim', $header);
$imported = 0;
while (($row = fgetcsv($handle, 0, ",")) !== FALSE) {
if (count($row) !== count($header)) continue; // Ignore les lignes vides ou mal formées
$rowData = array_combine($header, $row);
$title = $rowData['Name'] ?? $rowData['title'] ?? 'Sans titre';
$year = $rowData['Year'] ?? $rowData['year'] ?? '0000';
$director = $rowData['Director'] ?? $rowData['director'] ?? '';
$poster = $rowData['Poster'] ?? $rowData['poster'] ?? $rowData['image'] ?? '';
// 🔍 RÉCUPÉRATION AUTO TMDB (toujours appelé pour récupérer le streaming)
$tmdbData = fetchTmdbData($title, $year, $tmdbApiKey);
if ($tmdbData) {
if (empty($director)) $director = $tmdbData['director'];
if (empty($poster)) $poster = $tmdbData['poster'];
}
$id = makeStableId($title, $year);
if ($type === 'critique') {
// 🌟 Conservation de la précision Letterboxd (2.5, 3.5, etc.)
$rating = (isset($rowData['Rating']) && $rowData['Rating'] !== '') ? (float)$rowData['Rating'] : 3.0;
$review = $rowData['Review'] ?? $rowData['review'] ?? '';
$csvStreaming = $rowData['Streaming'] ?? $rowData['streaming'] ?? '';
// Si le CSV ne fournit pas l'info, on utilise celle de TMDB ou le message par défaut
if (!empty($csvStreaming)) {
$streaming = $csvStreaming;
} elseif (!empty($tmdbData['streaming'])) {
$streaming = $tmdbData['streaming'];
} else {
$streaming = 'Disponible en support physique ou Cinéma';
}
$sql = "INSERT INTO critiques (id, title, year, director, poster, rating, review, streaming)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
rating = VALUES(rating),
review = IF(VALUES(review) != '', VALUES(review), review),
director = IF(VALUES(director) != '', VALUES(director), director),
poster = IF(VALUES(poster) != '', VALUES(poster), poster),
streaming = IF(VALUES(streaming) != '', VALUES(streaming), streaming)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$id, $title, $year, $director, $poster, $rating, $review, $streaming]);
} else {
$format = $rowData['format'] ?? $rowData['Format'] ?? '';
$length = $rowData['length'] ?? $rowData['Length'] ?? '';
$publisher = $rowData['publisher'] ?? $rowData['Publisher'] ?? '';
$ean = $rowData['ean_isbn13'] ?? $rowData['EAN'] ?? '';
$discs = $rowData['number_of_discs'] ?? 1;
$aspect = $rowData['aspect_ratio'] ?? '';
$desc = $rowData['description'] ?? $rowData['Description'] ?? '';
$sql = "INSERT INTO videotheque (id, title, year, director, poster, format, length, publisher, ean_isbn13, number_of_discs, aspect_ratio, description)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
director = IF(VALUES(director) != '', VALUES(director), director),
poster = IF(VALUES(poster) != '', VALUES(poster), poster),
format = IF(VALUES(format) != '', VALUES(format), format),
length = IF(VALUES(length) != '', VALUES(length), length),
publisher = IF(VALUES(publisher) != '', VALUES(publisher), publisher),
ean_isbn13 = IF(VALUES(ean_isbn13) != '', VALUES(ean_isbn13), ean_isbn13),
number_of_discs = IF(VALUES(number_of_discs) != 1, VALUES(number_of_discs), number_of_discs),
aspect_ratio = IF(VALUES(aspect_ratio) != '', VALUES(aspect_ratio), aspect_ratio),
description = IF(VALUES(description) != '', VALUES(description), description)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$id, $title, $year, $director, $poster, $format, $length, $publisher, $ean, $discs, $aspect, $desc]);
}
$imported++;
}
fclose($handle);
echo json_encode(["success" => true, "imported" => $imported]);
} else {
throw new Exception("Impossible d'ouvrir le fichier.");
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode(["error" => "Erreur lors de l'import : " . $e->getMessage()]);
}
} else {
http_response_code(400);
echo json_encode(["error" => "Aucun fichier reçu."]);
} }
$image = fetchImageByEAN($ean);
echo json_encode(["ean" => $ean, "image" => $image]);
break; break;
} }