Skip to content

Commit 0d407d4

Browse files
authored
Feat: Store info about extras (#65)
1 parent 2ed7b40 commit 0d407d4

File tree

9 files changed

+157
-1
lines changed

9 files changed

+157
-1
lines changed

src/DTO/DownloadDescription.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,15 @@ public function __construct(
1919
$this->md5 = $md5;
2020
}
2121
}
22+
23+
public function __unserialize(array $data): void
24+
{
25+
if (is_string($data['gogGameId'])) {
26+
$data['gogGameId'] = (int) $data['gogGameId'];
27+
}
28+
29+
foreach ($data as $key => $value) {
30+
$this->$key = $value;
31+
}
32+
}
2233
}

src/DTO/GameDetail.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
final readonly class GameDetail
99
{
1010
/**
11-
* @param array<DownloadDescription> $downloads
11+
* @param array<DownloadDescription> $downloads
12+
* @param array<GameExtra> $extras
1213
*/
1314
public function __construct(
1415
public int $id,
@@ -18,6 +19,16 @@ public function __construct(
1819
#[ArrayType(type: DownloadDescription::class)]
1920
public array $downloads,
2021
public string $slug,
22+
public array $extras,
2123
) {
2224
}
25+
26+
public function __unserialize(array $data): void
27+
{
28+
$data['extras'] ??= [];
29+
30+
foreach ($data as $key => $value) {
31+
$this->$key = $value;
32+
}
33+
}
2334
}

src/DTO/GameExtra.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace App\DTO;
4+
5+
final readonly class GameExtra
6+
{
7+
public function __construct(
8+
public int $id,
9+
public string $name,
10+
public int $size,
11+
public string $url,
12+
public int $gogGameId,
13+
) {
14+
}
15+
}

src/Migration/Migration6.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace App\Migration;
4+
5+
use PDO;
6+
7+
final readonly class Migration6 implements Migration
8+
{
9+
10+
public function migrate(PDO $pdo): void
11+
{
12+
$pdo->exec('create table game_extras (
13+
id integer primary key autoincrement,
14+
extra_id integer unique,
15+
name text,
16+
size integer,
17+
url text,
18+
gog_game_id integer,
19+
game_id integer,
20+
foreign key (game_id) references games(id) on delete cascade on update cascade
21+
)');
22+
}
23+
24+
public function getVersion(): int
25+
{
26+
return 6;
27+
}
28+
}

src/Service/OwnedItemsManager.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,10 @@ private function getGameDetail(OwnedItemInfo $item, int $httpTimeout): ?GameDeta
269269
fn (array $item) => $item['title'],
270270
$ownedContent['dlcs'],
271271
);
272+
$ownedExtrasTitles = array_map(
273+
fn (array $item) => $item['name'],
274+
$ownedContent['extras'],
275+
);
272276

273277
$generalResponse = $this->httpClient->request(
274278
Request::METHOD_GET,
@@ -293,6 +297,10 @@ private function getGameDetail(OwnedItemInfo $item, int $httpTimeout): ?GameDeta
293297
$generalContent['expanded_dlcs'] ?? [],
294298
fn (array $item) => in_array($item['title'], $ownedDlcTitles, true),
295299
);
300+
$generalContent['downloads']['bonus_content'] = array_filter(
301+
$generalContent['downloads']['bonus_content'] ?? [],
302+
fn (array $item) => in_array($item['name'], $ownedExtrasTitles, true),
303+
);
296304

297305
$detail = $this->serializer->deserialize($generalContent, GameDetail::class, [
298306
'id' => $item->getId(),

src/Service/Persistence/PersistenceManagerSqlite.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,17 @@ public function getLocalGameData(): ?array
9696
$downloadsQuery->execute([$next['id']]);
9797
$downloads = $downloadsQuery->fetchAll(PDO::FETCH_ASSOC);
9898

99+
$extrasQuery = $pdo->prepare('select * from game_extras where game_id = ?');
100+
$extrasQuery->execute([$next['id']]);
101+
$extras = $extrasQuery->fetchAll(PDO::FETCH_ASSOC);
102+
99103
$result[] = $this->serializer->deserialize([
100104
'id' => $next['game_id'],
101105
'title' => $next['title'],
102106
'cdKey' => $next['cd_key'] ?? '',
103107
'downloads' => $downloads,
104108
'slug' => $next['slug'] ?? '',
109+
'extras' => $extras,
105110
], GameDetail::class);
106111
}
107112

@@ -145,6 +150,23 @@ public function storeSingleGameDetail(GameDetail $detail): void
145150
$download->gogGameId,
146151
]);
147152
}
153+
foreach ($detail->extras as $extra) {
154+
$pdo->prepare('insert into game_extras (extra_id, name, size, url, gog_game_id, game_id)
155+
values (?, ?, ?, ?, ?, ?)
156+
on conflict (extra_id) do update set name = excluded.name,
157+
size = excluded.size,
158+
url = excluded.url,
159+
gog_game_id = excluded.gog_game_id,
160+
game_id = excluded.game_id
161+
')->execute([
162+
$extra->id,
163+
$extra->name,
164+
$extra->size,
165+
$extra->url,
166+
$extra->gogGameId,
167+
$id,
168+
]);
169+
}
148170
}
149171

150172
public function storeSetting(Setting $setting, float|bool|int|string|null $value): void

src/Service/Serializer/GameDetailNormalizer.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use App\DTO\DownloadDescription;
66
use App\DTO\GameDetail;
7+
use App\DTO\GameExtra;
78
use App\DTO\MultipleValuesWrapper;
89
use App\Service\Serializer;
910

@@ -44,12 +45,29 @@ public function normalize(array $value, array $context, Serializer $serializer):
4445
}
4546
}
4647

48+
$extras = [];
49+
foreach ($value['extras'] ?? $value['downloads']['bonus_content'] ?? [] as $extra) {
50+
$extra['gogGameId'] ??= $value['id'] ?? $context['id'];
51+
$extras[] = $serializer->deserialize($extra, GameExtra::class);
52+
}
53+
54+
$finalExtras = [];
55+
foreach ($extras as $key => $extra) {
56+
if ($extra instanceof MultipleValuesWrapper) {
57+
unset($extras[$key]);
58+
$finalExtras = [...$finalExtras, ...$extra];
59+
} else {
60+
$finalExtras[] = $extra;
61+
}
62+
}
63+
4764
return new GameDetail(
4865
id: $value['id'] ?? $context['id'],
4966
title: $value['title'],
5067
cdKey: '', // todo
5168
downloads: $finalDownloads,
5269
slug: $value['slug'] ?? $context['slug'],
70+
extras: $finalExtras,
5371
);
5472
}
5573

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace App\Service\Serializer;
4+
5+
use App\DTO\GameExtra;
6+
use App\DTO\MultipleValuesWrapper;
7+
use App\Service\Serializer;
8+
9+
final readonly class GameExtraNormalizer implements SerializerNormalizer
10+
{
11+
public function normalize(array $value, array $context, Serializer $serializer): MultipleValuesWrapper|GameExtra
12+
{
13+
if (isset($value['total_size'])) {
14+
$result = [];
15+
foreach ($value['files'] as $file) {
16+
$result[] = new GameExtra(
17+
id: $value['id'],
18+
name: $value['name'],
19+
size: $file['size'],
20+
url: $file['downlink'],
21+
gogGameId: $value['gogGameId'],
22+
);
23+
}
24+
25+
return new MultipleValuesWrapper($result);
26+
}
27+
28+
return new GameExtra(
29+
id: $value['extra_id'],
30+
name: $value['name'],
31+
size: $value['size'],
32+
url: $value['url'],
33+
gogGameId: $value['gog_game_id'],
34+
);
35+
}
36+
37+
public function supports(string $class): bool
38+
{
39+
return is_a($class, GameExtra::class, true);
40+
}
41+
}

src/Trait/FilteredGamesResolverTrait.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ function (GameDetail $game) use ($englishFallback, $languages) {
151151
cdKey: $game->cdKey,
152152
downloads: $downloads,
153153
slug: $game->slug,
154+
extras: $game->extras,
154155
);
155156
},
156157
$iterable,
@@ -174,6 +175,7 @@ function (GameDetail $game) use ($operatingSystems) {
174175
cdKey: $game->cdKey,
175176
downloads: $downloads,
176177
slug: $game->slug,
178+
extras: $game->extras,
177179
);
178180
},
179181
$iterable,

0 commit comments

Comments
 (0)