Files
Critters/api/critter-details.php
pauljd 35d187b4c2
pauljd/davidson-ci: Davidson CI / quality (push) Successful in 13s
pauljd/davidson-ci: Davidson CI / ai-review (push) Successful in 1m0s
further Davidson CI testing
2026-09-09 22:55:59 +01:00

146 lines
5.1 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require __DIR__ . '/../session.php';
require __DIR__ . '/../db.php';
start_app_session();
header('Content-Type: application/json');
$pdo = getDbConnection();
enforce_session_version($pdo);
if (!isset($_SESSION['user_id'])) {
http_response_code(401);
echo json_encode(['error' => 'Not authenticated']);
exit;
}
function fetchOwnedCritter(PDO $pdo, int $userId, int $critterId): array|false
{
$stmt = $pdo->prepare('
SELECT c.id AS id, c.isFavorite AS isFavorite, c.isArchived AS isArchived,
c.adjective_id AS adjective_id, c.noun_id AS noun_id, c.verb_id AS verb_id, c.location_id AS location_id,
a.value AS adjective, n.value AS noun, v.value AS verb, l.value AS location, c.image AS image
FROM critters c
JOIN adjectives a ON a.id = c.adjective_id
JOIN nouns n ON n.id = c.noun_id
JOIN verbs v ON v.id = c.verb_id
JOIN locations l ON l.id = c.location_id
WHERE c.id = :id AND c.author_id = :author_id
');
$stmt->execute(['id' => $critterId, 'author_id' => $userId]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
$method = $_SERVER['REQUEST_METHOD'];
$critterId = $method === 'POST'
? filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT)
: filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if (!$critterId) {
http_response_code(400);
echo json_encode(['error' => 'Invalid critter id']);
exit;
}
$critter = fetchOwnedCritter($pdo, (int) $_SESSION['user_id'], $critterId);
if (!$critter) {
http_response_code(404);
echo json_encode(['error' => 'Critter not found']);
exit;
}
if ($method === 'POST' && !csrf_verify($_POST['csrf_token'] ?? null)) {
http_response_code(403);
echo json_encode(['error' => 'Invalid CSRF token']);
exit;
}
if ($method === 'POST') {
$action = $_POST['action'] ?? '';
if ($action === 'toggle_favorite') {
$newValue = $critter['isFavorite'] ? 0 : 1;
$stmt = $pdo->prepare('UPDATE critters SET isFavorite = :value WHERE id = :id');
$stmt->execute(['value' => $newValue, 'id' => $critterId]);
$critter['isFavorite'] = $newValue;
} elseif ($action === 'toggle_archived') {
$newValue = $critter['isArchived'] ? 0 : 1;
$stmt = $pdo->prepare('UPDATE critters SET isArchived = :value WHERE id = :id');
$stmt->execute(['value' => $newValue, 'id' => $critterId]);
$critter['isArchived'] = $newValue;
}
}
$flourishes = [
'Always up for a new adventure!',
'This one has a real personality.',
'Ready to make new friends.',
"There's never a dull moment with this critter.",
'One of a kind, through and through.',
'A firm favorite in the collection.',
'Full of charm and curiosity.',
];
$flourish = $flourishes[array_rand($flourishes)];
$description = 'A ' . $critter['adjective'] . ' ' . $critter['noun'] . ' who ' . $critter['verb'] . ' ' . $critter['location'] . '. ' . $flourish;
$prompt = "A {$critter['adjective']} {$critter['noun']} {$critter['verb']} {$critter['location']} in a high quality 3d animation art style. The image should be vibrant and colorful, capturing the essence of the action and setting.";
$rarityTiers = [
['label' => 'Common', 'classes' => 'bg-pink-100 text-pink-700'],
['label' => 'Rare', 'classes' => 'bg-blue-100 text-blue-700'],
['label' => 'Legendary', 'classes' => 'bg-amber-100 text-amber-700'],
];
$rarityRoll = $critter['id'] % 10;
if ($rarityRoll >= 9) {
$rarity = $rarityTiers[2];
} elseif ($rarityRoll >= 6) {
$rarity = $rarityTiers[1];
} else {
$rarity = $rarityTiers[0];
}
$resolution = null;
$fileSize = null;
$createdAt = null;
if (!empty($critter['image'])) {
$imagePath = __DIR__ . '/../critter-images/' . $critter['image'];
if (is_file($imagePath)) {
$dimensions = @getimagesize($imagePath);
if ($dimensions) {
$resolution = $dimensions[0] . ' × ' . $dimensions[1];
}
$bytes = @filesize($imagePath);
if ($bytes !== false) {
$fileSize = round($bytes / 1024) . ' KB';
}
$mtime = @filemtime($imagePath);
if ($mtime !== false) {
$createdAt = date('j M Y, H:i', $mtime);
}
}
}
echo json_encode([
'id' => (int) $critter['id'],
'title' => ucwords($critter['adjective'] . ' ' . $critter['noun']),
'adjective' => ucfirst($critter['adjective']),
'noun' => ucfirst($critter['noun']),
'verb' => ucfirst($critter['verb']),
'location' => ucfirst($critter['location']),
'isFavorite' => (bool) $critter['isFavorite'],
'isArchived' => (bool) $critter['isArchived'],
'rarity' => $rarity,
'description' => $description,
'prompt' => $prompt,
'createdAt' => $createdAt,
'resolution' => $resolution,
'fileSize' => $fileSize,
'imageUrl' => $critter['image'] ? 'critter-images/' . $critter['image'] : null,
'shareUrl' => 'single-critter.php?id=' . $critter['id'],
'createSimilarUrl' => 'create-critter.php?adjective_id=' . $critter['adjective_id']
. '&noun_id=' . $critter['noun_id']
. '&verb_id=' . $critter['verb_id']
. '&location_id=' . $critter['location_id'],
]);