Publier Globinours 1.0.0-rc.3
This commit is contained in:
parent
ea8c24d622
commit
9a2b4068da
325 changed files with 38230 additions and 20 deletions
296
app/Controllers/AnimalPhotoActions.php
Normal file
296
app/Controllers/AnimalPhotoActions.php
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
trait AnimalPhotoActions
|
||||
{
|
||||
public static function uploadPhoto(): void
|
||||
{
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo h(t('error.method_not_allowed'));
|
||||
return;
|
||||
}
|
||||
|
||||
$id = (int) ($_POST['animal_id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
http_response_code(400);
|
||||
echo h(t('error.bad_request'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($_FILES['photo']) || $_FILES['photo']['error'] !== UPLOAD_ERR_OK) {
|
||||
http_response_code(400);
|
||||
echo h(t('error.upload_failed'));
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::pdo();
|
||||
|
||||
$tmp = $_FILES['photo']['tmp_name'];
|
||||
$orig = (string) ($_FILES['photo']['name'] ?? 'photo');
|
||||
$size = (int) ($_FILES['photo']['size'] ?? 0);
|
||||
$mime = (string) ($_FILES['photo']['type'] ?? '');
|
||||
|
||||
$base = preg_replace('/[^a-zA-Z0-9._-]+/', '_', pathinfo($orig, PATHINFO_FILENAME));
|
||||
$base = $base ?: 'photo';
|
||||
$dir = __DIR__ . '/../../public/media/animals/' . $id;
|
||||
try {
|
||||
$stored = ImageService::storeUploaded($tmp, $dir, $base, 'photo');
|
||||
$filename = $stored['filename'];
|
||||
$mime = $stored['mime'];
|
||||
$size = $stored['size'];
|
||||
} catch (Throwable $e) {
|
||||
http_response_code(400);
|
||||
echo h($e->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
// si aucune photo primaire, celle-ci devient primaire
|
||||
$stmt = $db->prepare('SELECT COUNT(*) FROM animal_photos WHERE animal_id=:id AND is_primary=1');
|
||||
$stmt->execute([':id' => $id]);
|
||||
$hasPrimary = (int) $stmt->fetchColumn() > 0;
|
||||
|
||||
$stmt = $db->prepare('
|
||||
INSERT INTO animal_photos(animal_id, filename, original_name, mime, size_bytes, is_primary)
|
||||
VALUES(:aid,:fn,:orig,:mime,:sz,:prim)
|
||||
');
|
||||
$stmt->execute([
|
||||
':aid' => $id,
|
||||
':fn' => $filename,
|
||||
':orig' => $orig,
|
||||
':mime' => $mime,
|
||||
':sz' => $size,
|
||||
':prim' => $hasPrimary ? 0 : 1,
|
||||
]);
|
||||
|
||||
header('Location: /animal?id=' . $id);
|
||||
exit();
|
||||
}
|
||||
|
||||
public static function uploadPhotos(): void
|
||||
{
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
|
||||
http_response_code(405);
|
||||
return;
|
||||
}
|
||||
|
||||
$animalId = (int) ($_POST['animal_id'] ?? 0);
|
||||
if ($animalId <= 0) {
|
||||
http_response_code(400);
|
||||
echo h(t('error.bad_request'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($_FILES['photos'])) {
|
||||
http_response_code(400);
|
||||
echo h(t('error.no_files'));
|
||||
return;
|
||||
}
|
||||
|
||||
$isPublic = (int) ($_POST['is_public'] ?? 1 ? 1 : 0);
|
||||
$redirectHash = trim((string) ($_POST['redirect_hash'] ?? ''));
|
||||
|
||||
$db = DB::pdo();
|
||||
self::ensureAnimalMediaDir($animalId);
|
||||
|
||||
$files = $_FILES['photos'];
|
||||
$count = is_array($files['name']) ? count($files['name']) : 1;
|
||||
|
||||
// Y a-t-il déjà une photo principale ?
|
||||
$hasPrimary = (bool) $db
|
||||
->query(
|
||||
'
|
||||
SELECT 1 FROM animal_photos
|
||||
WHERE animal_id=' .
|
||||
(int) $animalId .
|
||||
'
|
||||
AND is_primary=1
|
||||
LIMIT 1
|
||||
',
|
||||
)
|
||||
->fetchColumn();
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$name = is_array($files['name']) ? $files['name'][$i] : $files['name'];
|
||||
$tmp = is_array($files['tmp_name']) ? $files['tmp_name'][$i] : $files['tmp_name'];
|
||||
$err = is_array($files['error']) ? $files['error'][$i] : $files['error'];
|
||||
|
||||
if ($err !== UPLOAD_ERR_OK) {
|
||||
continue;
|
||||
}
|
||||
if (!is_uploaded_file($tmp)) {
|
||||
continue;
|
||||
}
|
||||
if (!self::isAllowedImage($tmp)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$base = self::safeFilename(pathinfo($name, PATHINFO_FILENAME));
|
||||
$targetDir = $isPublic === 1 ? self::animalMediaDir($animalId) : PrivateMediaService::animalDir($animalId);
|
||||
if ($isPublic === 0) {
|
||||
PrivateMediaService::ensure($targetDir);
|
||||
}
|
||||
try {
|
||||
$stored = ImageService::storeUploaded($tmp, $targetDir, $base, 'photo');
|
||||
$final = $stored['filename'];
|
||||
if ($isPublic === 0) {
|
||||
@chmod($stored['path'], 0600);
|
||||
}
|
||||
} catch (Throwable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// RÈGLE : jamais une privée en principale
|
||||
$isPrimary = !$hasPrimary && $isPublic === 1 ? 1 : 0;
|
||||
if ($isPrimary === 1) {
|
||||
$hasPrimary = true;
|
||||
}
|
||||
|
||||
$st = $db->prepare('
|
||||
INSERT INTO animal_photos(animal_id, filename, is_primary, is_public)
|
||||
VALUES(:aid,:fn,:p,:pub)
|
||||
');
|
||||
$st->execute([
|
||||
':aid' => $animalId,
|
||||
':fn' => $final,
|
||||
':p' => $isPrimary,
|
||||
':pub' => $isPublic,
|
||||
]);
|
||||
}
|
||||
|
||||
$db->prepare(
|
||||
"
|
||||
UPDATE animals
|
||||
SET updated_at=datetime('now')
|
||||
WHERE id=:id
|
||||
",
|
||||
)->execute([':id' => $animalId]);
|
||||
|
||||
// Retour direct sur onglet photos
|
||||
$hash = $redirectHash !== '' && $redirectHash[0] === '#' ? $redirectHash : '';
|
||||
header('Location: /animal?id=' . $animalId . $hash);
|
||||
exit();
|
||||
}
|
||||
|
||||
public static function setPrimaryPhoto(): void
|
||||
{
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
|
||||
http_response_code(405);
|
||||
return;
|
||||
}
|
||||
|
||||
$animalId = (int) ($_POST['animal_id'] ?? 0);
|
||||
$photoId = (int) ($_POST['photo_id'] ?? 0);
|
||||
if ($animalId <= 0 || $photoId <= 0) {
|
||||
http_response_code(400);
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::pdo();
|
||||
$stmt = $db->prepare('SELECT filename,is_public FROM animal_photos WHERE id=:pid AND animal_id=:aid');
|
||||
$stmt->execute([':pid' => $photoId, ':aid' => $animalId]);
|
||||
$photo = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$photo) {
|
||||
http_response_code(404);
|
||||
echo h(t('error.photo_not_found'));
|
||||
return;
|
||||
}
|
||||
$moved = false;
|
||||
try {
|
||||
if ((int) $photo['is_public'] !== 1) {
|
||||
PrivateMediaService::moveVisibility($animalId, (string) $photo['filename'], true);
|
||||
$moved = true;
|
||||
}
|
||||
$db->beginTransaction();
|
||||
$db->prepare('UPDATE animal_photos SET is_primary=0 WHERE animal_id=:aid')->execute([':aid' => $animalId]);
|
||||
$db->prepare('UPDATE animal_photos SET is_primary=1,is_public=1 WHERE id=:pid AND animal_id=:aid')->execute(
|
||||
[':pid' => $photoId, ':aid' => $animalId],
|
||||
);
|
||||
$db->commit();
|
||||
} catch (Throwable $e) {
|
||||
if ($db->inTransaction()) {
|
||||
$db->rollBack();
|
||||
}
|
||||
if ($moved) {
|
||||
try {
|
||||
PrivateMediaService::moveVisibility($animalId, (string) $photo['filename'], false);
|
||||
} catch (Throwable) {
|
||||
}
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
// Historique si tu veux
|
||||
if (method_exists(__CLASS__, 'logHistory')) {
|
||||
self::logHistory($animalId, 'photo', 'Photo principale modifiée');
|
||||
}
|
||||
|
||||
header('Location: /animal?id=' . $animalId);
|
||||
exit();
|
||||
}
|
||||
|
||||
public static function deletePhoto(): void
|
||||
{
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
|
||||
http_response_code(405);
|
||||
return;
|
||||
}
|
||||
|
||||
$animalId = (int) ($_POST['animal_id'] ?? 0);
|
||||
$photoId = (int) ($_POST['photo_id'] ?? 0);
|
||||
if ($animalId <= 0 || $photoId <= 0) {
|
||||
http_response_code(400);
|
||||
return;
|
||||
}
|
||||
|
||||
$db = DB::pdo();
|
||||
|
||||
$st = $db->prepare(
|
||||
'SELECT filename, is_primary, is_public FROM animal_photos WHERE id=:pid AND animal_id=:aid',
|
||||
);
|
||||
$st->execute([':pid' => $photoId, ':aid' => $animalId]);
|
||||
$row = $st->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$row) {
|
||||
header('Location: /animal?id=' . $animalId);
|
||||
exit();
|
||||
}
|
||||
|
||||
$filename = (string) $row['filename'];
|
||||
$wasPrimary = (int) $row['is_primary'] === 1;
|
||||
|
||||
$db->prepare('DELETE FROM animal_photos WHERE id=:pid AND animal_id=:aid')->execute([
|
||||
':pid' => $photoId,
|
||||
':aid' => $animalId,
|
||||
]);
|
||||
|
||||
$path =
|
||||
((int) ($row['is_public'] ?? 1) === 1
|
||||
? self::animalMediaDir($animalId)
|
||||
: PrivateMediaService::animalDir($animalId)) .
|
||||
'/' .
|
||||
$filename;
|
||||
if (is_file($path)) {
|
||||
@unlink($path);
|
||||
}
|
||||
|
||||
// Si on a supprimé la principale, on met la plus récente restante en principale
|
||||
if ($wasPrimary) {
|
||||
$pid = $db
|
||||
->query('SELECT id FROM animal_photos WHERE animal_id=' . (int) $animalId . ' ORDER BY id DESC LIMIT 1')
|
||||
->fetchColumn();
|
||||
if ($pid) {
|
||||
$db->prepare('UPDATE animal_photos SET is_primary=1 WHERE id=:pid')->execute([':pid' => (int) $pid]);
|
||||
}
|
||||
}
|
||||
|
||||
$db->prepare("UPDATE animals SET updated_at=datetime('now') WHERE id=:id")->execute([':id' => $animalId]);
|
||||
|
||||
if (method_exists(__CLASS__, 'logHistory')) {
|
||||
self::logHistory($animalId, 'photo', 'Photo supprimée');
|
||||
}
|
||||
|
||||
header('Location: /animal?id=' . $animalId);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue