Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
31 / 31
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
FeaturedImageFactory
100.00% covered (success)
100.00%
31 / 31
100.00% covered (success)
100.00%
6 / 6
10
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 toArray
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 make
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 makeSource
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 normalizeLocalImagePath
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getStringMatter
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace Hyde\Framework\Factories;
6
7use Hyde\Hyde;
8use RuntimeException;
9use Illuminate\Support\Str;
10use Hyde\Markdown\Models\FrontMatter;
11use Hyde\Foundation\Kernel\Hyperlinks;
12use Hyde\Framework\Features\Blogging\Models\FeaturedImage;
13use Hyde\Markdown\Contracts\FrontMatter\SubSchemas\FeaturedImageSchema;
14
15use function str_starts_with;
16use function is_string;
17use function Hyde\unslash;
18
19class FeaturedImageFactory extends Concerns\PageDataFactory implements FeaturedImageSchema
20{
21    final public const SCHEMA = FeaturedImageSchema::FEATURED_IMAGE_SCHEMA;
22
23    protected readonly string $source;
24    protected readonly ?string $altText;
25    protected readonly ?string $titleText;
26    protected readonly ?string $authorName;
27    protected readonly ?string $authorUrl;
28    protected readonly ?string $copyrightText;
29    protected readonly ?string $licenseName;
30    protected readonly ?string $licenseUrl;
31
32    public function __construct(
33        private readonly FrontMatter $matter,
34        private readonly ?string $filePath = null,
35    ) {
36        $this->source = $this->makeSource();
37        $this->altText = $this->getStringMatter('image.altText');
38        $this->titleText = $this->getStringMatter('image.titleText');
39        $this->authorName = $this->getStringMatter('image.authorName');
40        $this->authorUrl = $this->getStringMatter('image.authorUrl');
41        $this->copyrightText = $this->getStringMatter('image.copyright');
42        $this->licenseName = $this->getStringMatter('image.licenseName');
43        $this->licenseUrl = $this->getStringMatter('image.licenseUrl');
44    }
45
46    /**
47     * @return array{source: string, altText: string|null, titleText: string|null, authorName: string|null, authorUrl: string|null, copyrightText: string|null, licenseName: string|null, licenseUrl: string|null}
48     */
49    public function toArray(): array
50    {
51        return [
52            'source' => $this->source,
53            'altText' => $this->altText,
54            'titleText' => $this->titleText,
55            'authorName' => $this->authorName,
56            'authorUrl' => $this->authorUrl,
57            'copyrightText' => $this->copyrightText,
58            'licenseName' => $this->licenseName,
59            'licenseUrl' => $this->licenseUrl,
60        ];
61    }
62
63    public static function make(FrontMatter $matter, ?string $filePath = null): FeaturedImage
64    {
65        return new FeaturedImage(...(new static($matter, $filePath))->toArray());
66    }
67
68    protected function makeSource(): string
69    {
70        $value = $this->getStringMatter('image') ?? $this->getStringMatter('image.source');
71
72        if (empty($value)) {
73            throw new RuntimeException(sprintf('No featured image source was found in "%s"', $this->filePath ?? 'unknown file'));
74        }
75
76        if (Hyperlinks::isRemote($value)) {
77            return $value;
78        }
79
80        return self::normalizeLocalImagePath($value);
81    }
82
83    protected static function normalizeLocalImagePath(string $path): string
84    {
85        $path = Hyde::pathToRelative($path);
86
87        $path = Str::after($path, Hyde::getMediaDirectory());
88        $path = Str::after($path, Hyde::getMediaOutputDirectory());
89
90        return str_starts_with($path, '//') ? $path : unslash($path);
91    }
92
93    protected function getStringMatter(string $key): ?string
94    {
95        /** @var string|null $value */
96        $value = $this->matter->get($key);
97
98        return is_string($value) ? $value : null;
99    }
100}