Files
scummvm-web/include/Models/ScreenshotsModel.php
T
Le Philousophe 710b95a5f4 WEB: Better error handling
When PHP functions fail they often return false instead of the expected
object type.
CHeck for this value and fail properly.
2025-08-24 12:32:47 +02:00

183 lines
5.9 KiB
PHP

<?php
namespace ScummVM\Models;
use ScummVM\OrmObjects\GameQuery;
use ScummVM\OrmObjects\Screenshot;
use ScummVM\OrmObjects\ScreenshotQuery;
use Propel\Runtime\Collection\Collection;
/**
* The ScreenshotsModel will generate Screenshot objects.
*/
class ScreenshotsModel extends BasicModel
{
const INVALID_TARGET = 'Invalid target specified.';
const INVALID_CATEGORY = 'Invalid category specified.';
const SUBCATEGORY_COLUMN = '(case when game.series_id is null then screenshot.id else game.series_id end)';
/**
* @return array<string, array{'title': string, 'category': string,
* 'games': array<string, array{'name': string, 'count': int}>}>
*/
public function getAllCategories(): array
{
$categories = ScreenshotQuery::create()->findCategories();
$data = [];
foreach ($categories as $category) {
$category_key = $category['category_key'];
$category_name = $category['category_name'];
$subcategory_key = $category['subcategory_key'];
$subcategory_name = $category['subcategory_name'];
if (!isset($data[$category_key])) {
$data[$category_key] = [
'title' => "$category_name Games",
'category' => $category_key,
'games' => [],
];
}
$data[$category_key]['games'][$subcategory_key] = [
'name' => $subcategory_name,
'count' => $this->getScreenshotCount($subcategory_key)
];
}
return $data;
}
/**
* Get all screenshots in one category.
*
* @return array{'title': string, 'category': string, 'games': array<string, Screenshot>}
*/
public function getScreenshotsByCompanyId(string $companyId): array
{
$cache_key = "c_{$companyId}";
$data = $this->getFromCache($cache_key);
if (!$data) {
$screenshots = ScreenshotQuery::create()
->filterByCompanyId($companyId)
->withColumn(self::SUBCATEGORY_COLUMN, 'subcategory')
->find();
if ($screenshots->count() === 0) {
throw new \ErrorException(self::INVALID_CATEGORY);
}
$data = [
'title' => $screenshots[0]->getGame()->getCompany()->getName() . ' Games',
'category' => $companyId,
'games' => $this->combineSubcategories($screenshots)
];
$this->saveToCache($data, $cache_key);
}
return $data;
}
/**
* Get screenshots for a specific target.
*
* @return Screenshot[]
*/
public function getScreenshotsBySubcategory(string $target)
{
$cache_key = "s_{$target}";
$data = $this->getFromCache($cache_key);
if (!$data) {
$screenshots = ScreenshotQuery::create()
->joinGame()
->withColumn(self::SUBCATEGORY_COLUMN, 'subcategory')
->where('subcategory = ?', $target, \PDO::PARAM_STR)
->find();
$combinedScreenshot = $this->combineScreenshots($screenshots);
if (is_null($combinedScreenshot)) {
throw new \ErrorException(self::INVALID_TARGET);
}
$data = [$combinedScreenshot];
$this->saveToCache($data, $cache_key);
}
return $data;
}
/**
* Combines multiple screenshots into a single screenshot
*
* @param Collection $screenshots
*/
private function combineScreenshots(iterable $screenshots): ?Screenshot
{
$count = $screenshots->count();
if ($count === 0) {
return null;
} elseif ($count === 1) {
$screenshots[0]->getFiles();
return $screenshots[0];
} else {
$shot = $screenshots[0];
$shot->getFiles();
for ($i=1; $i < $count; $i++) {
$shot->addFiles($screenshots[$i]->getFiles());
}
return $shot;
}
}
/**
* combineSubcategories
*
* @param Collection $screenshots
* @return array<string, Screenshot>
*/
private function combineSubcategories(iterable $screenshots)
{
$combined = [];
foreach ($screenshots as $screenshot) {
$subcategory = $screenshot->getSubcategory();
if (isset($combined[$subcategory])) {
$combined[$subcategory]->addFiles($screenshot->getFiles());
} else {
$screenshot->getFiles();
$combined[$subcategory] = $screenshot;
}
}
\ksort($combined, SORT_STRING);
return $combined;
}
/**
* Returns the number of screenshot files associated with a given game or series of games
* @param $gameOrSeriesId the id of a game or a game series
* @return int the number of screenshot files
*/
private function getScreenshotCount(string $gameOrSeriesId)
{
// Check if the id is a series.
$games = GameQuery::create()->findBySeriesId($gameOrSeriesId);
if (count($games) == 0) {
// If not, then the id must be for a single game
// We have to check this second because of name collisions with series, e.g. myst
$games = GameQuery::create()->findById($gameOrSeriesId);
}
$count = 0;
// Iterate over each game and count the number of screenshot files
foreach ($games as $game) {
$list = glob(DIR_STATIC . DIR_SCREENSHOTS . '/' .
str_replace(':', '/', $game->getId()) . '/*_full.png');
if ($list === false) {
continue;
}
$count += count($list);
}
return $count;
}
/**
* Get a random screenshot (an object and not a filename).
*/
public function getRandomScreenshot(): Screenshot
{
return ScreenshotQuery::create()->findRandom();
}
}