Skip to content

Commit 4de196a

Browse files
authored
feat(type): Introduce Asset value object (#47)
1 parent 21972d0 commit 4de196a

File tree

7 files changed

+560
-0
lines changed

7 files changed

+560
-0
lines changed

phpstan-baseline.neon

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ parameters:
7878
count: 1
7979
path: src/Bridge/Faker/Provider/StoryblokProvider.php
8080

81+
-
82+
message: '#^Method Storyblok\\Api\\Bridge\\Faker\\Provider\\StoryblokProvider\:\:storyAssetResponse\(\) should return array\{id\: int, is_external_url\: bool, filename\: string\} but returns array\.$#'
83+
identifier: return.type
84+
count: 1
85+
path: src/Bridge/Faker/Provider/StoryblokProvider.php
86+
8187
-
8288
message: '#^Method Storyblok\\Api\\Bridge\\Faker\\Provider\\StoryblokProvider\:\:storyResponse\(\) should return array\{cv\: int, story\: array\<string, mixed\>, links\: array\<string\>, rels\: array\<string\>\} but returns array\.$#'
8389
identifier: return.type
@@ -90,6 +96,12 @@ parameters:
9096
count: 1
9197
path: src/Bridge/Faker/Provider/StoryblokProvider.php
9298

99+
-
100+
message: '#^Strict comparison using \!\=\= between array\{\} and numeric\-string will always evaluate to true\.$#'
101+
identifier: notIdentical.alwaysTrue
102+
count: 2
103+
path: src/Domain/Type/Asset.php
104+
93105
-
94106
message: '#^Property Storyblok\\Api\\Domain\\Value\\Datasource\:\:\$dimensions \(list\<Storyblok\\Api\\Domain\\Value\\DatasourceDimension\>\) does not accept array\<Storyblok\\Api\\Domain\\Value\\DatasourceDimension\>\.$#'
95107
identifier: assign.propertyType

src/Bridge/Faker/Generator.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
/**
2222
* @author Silas Joisten <[email protected]>
2323
*
24+
* @method array assetFilename(?int $width = null, ?int $height = null, ?string $extension = null)
2425
* @method array assetResponse(array $overrides = [])
2526
* @method array datasourceDimensionResponse(array $overrides = [])
2627
* @method array datasourceEntriesResponse(array $overrides = [])
@@ -38,6 +39,7 @@
3839
* @method array richTextResponse(array $overrides = [])
3940
* @method array spaceResponse(array $overrides = [])
4041
* @method array storiesResponse(array $overrides = [])
42+
* @method array storyAssetResponse(array $overrides = [])
4143
* @method array storyResponse(array $overrides = [])
4244
* @method array tagsResponse(array $overrides = [])
4345
*/

src/Bridge/Faker/Provider/StoryblokProvider.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,40 @@ public function richTextEmptyResponse(): array
609609
];
610610
}
611611

612+
public function assetFilename(?int $width = null, ?int $height = null, ?string $extension = null): string
613+
{
614+
return \sprintf(
615+
'%s_%dx%d.%s',
616+
$this->generator->word(),
617+
$width ?? $this->generator->randomNumber(),
618+
$height ?? $this->generator->randomNumber(),
619+
$extension ?? $this->generator->fileExtension(),
620+
);
621+
}
622+
623+
/**
624+
* @param mixed[] $overrides
625+
*
626+
* @return array{
627+
* id: int,
628+
* is_external_url: bool,
629+
* filename: string,
630+
* }
631+
*/
632+
public function storyAssetResponse(array $overrides = []): array
633+
{
634+
$response = [
635+
'id' => $this->generator->numberBetween(1, 1000000),
636+
'is_external_url' => false,
637+
'filename' => \sprintf('https://a.storyblok.com/f/287488/%dx%d/xxxxxx/%s.png', $this->generator->word(), 1920, 1080),
638+
];
639+
640+
return array_replace_recursive(
641+
$response,
642+
$overrides,
643+
);
644+
}
645+
612646
public function relation(): string
613647
{
614648
return \sprintf(

src/Domain/Type/Asset.php

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of storyblok/php-content-api-client.
7+
*
8+
* (c) Storyblok GmbH <[email protected]>
9+
* in cooperation with SensioLabs Deutschland <[email protected]>
10+
*
11+
* For the full copyright and license information, please view the LICENSE
12+
* file that was distributed with this source code.
13+
*/
14+
15+
namespace Storyblok\Api\Domain\Type;
16+
17+
use OskarStark\Value\TrimmedNonEmptyString;
18+
use Storyblok\Api\Domain\Value\Id;
19+
use Webmozart\Assert\Assert;
20+
use function Safe\preg_match;
21+
22+
/**
23+
* @experimental This class is experimental and may change in future versions.
24+
*
25+
* @author Silas Joisten <[email protected]>
26+
*/
27+
final readonly class Asset
28+
{
29+
public Id $id;
30+
public string $url;
31+
public string $name;
32+
public string $extension;
33+
public ?string $alt;
34+
public ?string $title;
35+
public ?string $focus;
36+
public ?string $source;
37+
public ?string $copyright;
38+
public bool $isExternalUrl;
39+
public int $width;
40+
public int $height;
41+
public Orientation $orientation;
42+
43+
/**
44+
* @param array<string, mixed> $values
45+
*/
46+
public function __construct(array $values)
47+
{
48+
Assert::keyExists($values, 'id');
49+
Assert::integer($values['id']);
50+
$this->id = new Id($values['id']);
51+
52+
Assert::keyExists($values, 'filename');
53+
$this->url = TrimmedNonEmptyString::fromString($values['filename'])->toString();
54+
55+
Assert::keyExists($values, 'is_external_url');
56+
$this->isExternalUrl = true === $values['is_external_url'];
57+
58+
$alt = null;
59+
60+
if (\array_key_exists('alt', $values) && '' !== $values['alt'] && null !== $values['alt']) {
61+
$alt = TrimmedNonEmptyString::fromString($values['alt'])->toString();
62+
}
63+
64+
$this->alt = $alt;
65+
66+
$title = null;
67+
68+
if (\array_key_exists('title', $values) && '' !== $values['title'] && null !== $values['title']) {
69+
$title = TrimmedNonEmptyString::fromString($values['title'])->toString();
70+
}
71+
72+
$this->title = $title;
73+
74+
$focus = null;
75+
76+
if (\array_key_exists('focus', $values) && '' !== $values['focus'] && null !== $values['focus']) {
77+
$focus = TrimmedNonEmptyString::fromString($values['focus'])->toString();
78+
}
79+
80+
$this->focus = $focus;
81+
82+
$source = null;
83+
84+
if (\array_key_exists('source', $values) && '' !== $values['source'] && null !== $values['source']) {
85+
$source = TrimmedNonEmptyString::fromString($values['source'])->toString();
86+
}
87+
88+
$this->source = $source;
89+
90+
$copyright = null;
91+
92+
if (\array_key_exists('copyright', $values) && '' !== $values['copyright'] && null !== $values['copyright']) {
93+
$copyright = TrimmedNonEmptyString::fromString($values['copyright'])->toString();
94+
}
95+
96+
$this->copyright = $copyright;
97+
98+
$this->extension = pathinfo($this->url, \PATHINFO_EXTENSION);
99+
$this->name = pathinfo($this->url, \PATHINFO_FILENAME);
100+
101+
preg_match('/(?P<width>\d+)x(?P<height>\d+)/', $this->url, $dimensions);
102+
103+
$width = 0;
104+
105+
if (\array_key_exists('width', $dimensions) && [] !== $dimensions['width']) {
106+
$width = (int) $dimensions['width'];
107+
}
108+
109+
$this->width = $width;
110+
111+
$height = 0;
112+
113+
if (\array_key_exists('height', $dimensions) && [] !== $dimensions['height']) {
114+
$height = (int) $dimensions['height'];
115+
}
116+
117+
$this->height = $height;
118+
119+
$orientation = Orientation::Unknown;
120+
121+
if (0 < $this->width && 0 < $this->height) {
122+
$ratio = $this->width / $this->height;
123+
124+
$orientation = Orientation::Portrait;
125+
126+
if (\abs(1 - $ratio) <= 0.1) {
127+
$orientation = Orientation::Square;
128+
} elseif ($this->width > $this->height) {
129+
$orientation = Orientation::Landscape;
130+
}
131+
}
132+
133+
$this->orientation = $orientation;
134+
}
135+
}

src/Domain/Type/Orientation.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of storyblok/php-content-api-client.
7+
*
8+
* (c) Storyblok GmbH <[email protected]>
9+
* in cooperation with SensioLabs Deutschland <[email protected]>
10+
*
11+
* For the full copyright and license information, please view the LICENSE
12+
* file that was distributed with this source code.
13+
*/
14+
15+
namespace Storyblok\Api\Domain\Type;
16+
17+
use OskarStark\Enum\Trait\Comparable;
18+
19+
/**
20+
* @experimental This class is experimental and may change in future versions.
21+
*
22+
* @author Silas Joisten <[email protected]>
23+
*/
24+
enum Orientation: string
25+
{
26+
use Comparable;
27+
28+
case Square = 'square';
29+
case Landscape = 'landscape';
30+
case Portrait = 'portrait';
31+
case Unknown = 'unknown';
32+
}

0 commit comments

Comments
 (0)