mirror of
https://github.com/scummvm/scummvm-web.git
synced 2026-05-21 05:40:47 +00:00
710b95a5f4
When PHP functions fail they often return false instead of the expected object type. CHeck for this value and fail properly.
183 lines
5.9 KiB
PHP
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();
|
|
}
|
|
}
|