Passed
Push — master ( 12fba8...1f8afc )
by Caen
04:01 queued 12s
created

HydePageDataFactory::findTitleForPage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Hyde\Framework\Factories;
6
7
use Hyde\Framework\Concerns\InteractsWithFrontMatter;
8
use Hyde\Framework\Factories\Concerns\CoreDataObject;
9
use Hyde\Framework\Features\Navigation\NavigationData;
10
use Hyde\Hyde;
11
use Hyde\Markdown\Contracts\FrontMatter\PageSchema;
12
use Hyde\Markdown\Models\FrontMatter;
13
use Hyde\Markdown\Models\Markdown;
14
use function substr;
15
use function trim;
16
17
class HydePageDataFactory extends Concerns\PageDataFactory implements PageSchema
18
{
19
    use InteractsWithFrontMatter;
20
21
    /**
22
     * The front matter properties supported by this factory.
23
     */
24
    final public const SCHEMA = PageSchema::PAGE_SCHEMA;
25
26
    protected readonly string $title;
27
    protected readonly ?string $canonicalUrl;
28
    protected readonly ?NavigationData $navigation;
29
    private readonly string $routeKey;
30
    private readonly string $outputPath;
31
    private readonly string $identifier;
32
    private readonly string $pageClass;
33
    private readonly Markdown|false $markdown;
34
    private readonly FrontMatter $matter;
35
36
    public function __construct(private readonly CoreDataObject $pageData)
37
    {
38
        $this->matter = $this->pageData->matter;
0 ignored issues
show
Bug introduced by
The property matter is declared read-only in Hyde\Framework\Factories\HydePageDataFactory.
Loading history...
39
        $this->markdown = $this->pageData->markdown;
0 ignored issues
show
Bug introduced by
The property markdown is declared read-only in Hyde\Framework\Factories\HydePageDataFactory.
Loading history...
40
        $this->pageClass = $this->pageData->pageClass;
0 ignored issues
show
Bug introduced by
The property pageClass is declared read-only in Hyde\Framework\Factories\HydePageDataFactory.
Loading history...
41
        $this->identifier = $this->pageData->identifier;
0 ignored issues
show
Bug introduced by
The property identifier is declared read-only in Hyde\Framework\Factories\HydePageDataFactory.
Loading history...
42
        $this->outputPath = $this->pageData->outputPath;
0 ignored issues
show
Bug introduced by
The property outputPath is declared read-only in Hyde\Framework\Factories\HydePageDataFactory.
Loading history...
43
        $this->routeKey = $this->pageData->routeKey;
0 ignored issues
show
Bug introduced by
The property routeKey is declared read-only in Hyde\Framework\Factories\HydePageDataFactory.
Loading history...
44
45
        $this->title = $this->makeTitle();
0 ignored issues
show
Bug introduced by
The property title is declared read-only in Hyde\Framework\Factories\HydePageDataFactory.
Loading history...
46
        $this->canonicalUrl = $this->makeCanonicalUrl();
0 ignored issues
show
Bug introduced by
The property canonicalUrl is declared read-only in Hyde\Framework\Factories\HydePageDataFactory.
Loading history...
47
        $this->navigation = $this->makeNavigation();
0 ignored issues
show
Bug introduced by
The property navigation is declared read-only in Hyde\Framework\Factories\HydePageDataFactory.
Loading history...
48
    }
49
50
    /**
51
     * @return array{title: string, canonicalUrl: string|null, navigation: \Hyde\Framework\Features\Navigation\NavigationData|null}
52
     */
53
    public function toArray(): array
54
    {
55
        return [
0 ignored issues
show
introduced by
The expression return array('title' => ...' => $this->navigation) returns an array which contains values of type Hyde\Framework\Features\...n\NavigationData|string which are incompatible with the return type Illuminate\Contracts\Support\TValue mandated by Illuminate\Contracts\Support\Arrayable::toArray().
Loading history...
56
            'title' => $this->title,
57
            'canonicalUrl' => $this->canonicalUrl,
58
            'navigation' => $this->navigation,
59
        ];
60
    }
61
62
    protected function makeTitle(): string
63
    {
64
        return trim($this->findTitleForPage());
65
    }
66
67
    protected function makeCanonicalUrl(): ?string
68
    {
69
        return $this->getCanonicalUrl();
70
    }
71
72
    protected function makeNavigation(): NavigationData
73
    {
74
        return NavigationData::make((new NavigationDataFactory($this->pageData, $this->title))->toArray());
75
    }
76
77
    private function findTitleForPage(): string
78
    {
79
        return $this->matter('title')
80
            ?? $this->findTitleFromMarkdownHeadings()
81
            ?? $this->findTitleFromParentIdentifier()
82
            ?? Hyde::makeTitle(basename($this->identifier));
83
    }
84
85
    private function findTitleFromMarkdownHeadings(): ?string
86
    {
87
        if ($this->markdown !== false) {
88
            foreach ($this->markdown->toArray() as $line) {
89
                if (str_starts_with($line, '# ')) {
90
                    return trim(substr($line, 2), ' ');
91
                }
92
            }
93
        }
94
95
        return null;
96
    }
97
98
    private function findTitleFromParentIdentifier(): ?string
99
    {
100
        if (str_contains($this->identifier, '/') && str_ends_with($this->identifier, '/index')) {
101
            return Hyde::makeTitle(basename(dirname($this->identifier)));
102
        }
103
104
        return null;
105
    }
106
107
    private function getCanonicalUrl(): ?string
108
    {
109
        if (! empty($this->matter('canonicalUrl'))) {
110
            return $this->matter('canonicalUrl');
111
        }
112
113
        if (Hyde::hasSiteUrl() && ! empty($this->identifier)) {
114
            return Hyde::url($this->outputPath);
115
        }
116
117
        return null;
118
    }
119
}
120