Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
HydePageDataFactory
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
8 / 8
13
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 toArray
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 makeTitle
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 makeNavigation
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 findTitleForPage
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 findTitleFromMarkdownHeadings
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 findTitleFromParentIdentifier
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getMatter
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Hyde\Framework\Factories;
6
7use Hyde\Hyde;
8use Hyde\Markdown\Models\Markdown;
9use Hyde\Markdown\Models\FrontMatter;
10use Hyde\Markdown\Contracts\FrontMatter\PageSchema;
11use Hyde\Framework\Factories\Concerns\CoreDataObject;
12use Hyde\Framework\Features\Navigation\NavigationData;
13
14use function basename;
15use function dirname;
16use function str_contains;
17use function str_ends_with;
18use function str_starts_with;
19use function substr;
20use function trim;
21
22class HydePageDataFactory extends Concerns\PageDataFactory implements PageSchema
23{
24    /**
25     * The front matter properties supported by this factory.
26     */
27    final public const SCHEMA = PageSchema::PAGE_SCHEMA;
28
29    protected readonly string $title;
30    protected readonly ?NavigationData $navigation;
31    private readonly string $identifier;
32    private readonly Markdown|false $markdown;
33    private readonly FrontMatter $matter;
34
35    public function __construct(private readonly CoreDataObject $pageData)
36    {
37        $this->matter = $this->pageData->matter;
38        $this->markdown = $this->pageData->markdown;
39        $this->identifier = $this->pageData->identifier;
40
41        $this->title = $this->makeTitle();
42        $this->navigation = $this->makeNavigation();
43    }
44
45    /**
46     * @return array{title: string, navigation: \Hyde\Framework\Features\Navigation\NavigationData|null}
47     */
48    public function toArray(): array
49    {
50        return [
51            'title' => $this->title,
52            'navigation' => $this->navigation,
53        ];
54    }
55
56    protected function makeTitle(): string
57    {
58        return trim($this->findTitleForPage());
59    }
60
61    protected function makeNavigation(): NavigationData
62    {
63        return NavigationData::make((new NavigationDataFactory($this->pageData, $this->title))->toArray());
64    }
65
66    private function findTitleForPage(): string
67    {
68        return $this->getMatter('title')
69            ?? $this->findTitleFromMarkdownHeadings()
70            ?? $this->findTitleFromParentIdentifier()
71            ?? Hyde::makeTitle(basename($this->identifier));
72    }
73
74    private function findTitleFromMarkdownHeadings(): ?string
75    {
76        if ($this->markdown !== false) {
77            foreach ($this->markdown->toArray() as $line) {
78                if (str_starts_with($line, '# ')) {
79                    return trim(substr($line, 2), ' ');
80                }
81            }
82        }
83
84        return null;
85    }
86
87    private function findTitleFromParentIdentifier(): ?string
88    {
89        if (str_contains($this->identifier, '/') && str_ends_with($this->identifier, '/index')) {
90            return Hyde::makeTitle(basename(dirname($this->identifier)));
91        }
92
93        return null;
94    }
95
96    protected function getMatter(string $key): string|null
97    {
98        /** @var ?string $value */
99        $value = $this->matter->get($key);
100
101        return $value;
102    }
103}