Passed
Push — master ( 8ab35d...c4a5b0 )
by Caen
02:53 queued 11s
created

AbstractPage::parse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Hyde\Framework\Contracts;
4
5
use Hyde\Framework\Actions\SourceFileParser;
6
use Hyde\Framework\Concerns\FrontMatter\Schemas\PageSchema;
7
use Hyde\Framework\Helpers\Meta;
8
use Hyde\Framework\Hyde;
9
use Hyde\Framework\Models\FrontMatter;
10
use Hyde\Framework\Models\Pages\MarkdownPost;
11
use Hyde\Framework\Models\Route;
12
use Hyde\Framework\Services\DiscoveryService;
13
use Illuminate\Support\Collection;
14
15
/**
16
 * To ensure compatibility with the Hyde Framework, all Page Models should extend this class.
17
 *
18
 * Markdown-based Pages can extend the AbstractMarkdownPage class to get relevant helpers.
19
 *
20
 * To learn about what the methods do, see the PHPDocs in the PageContract.
21
 *
22
 * @see \Hyde\Framework\Contracts\PageContract
23
 * @see \Hyde\Framework\Contracts\AbstractMarkdownPage
24
 * @see \Hyde\Framework\Testing\Feature\AbstractPageTest
25
 */
26
abstract class AbstractPage implements PageContract, CompilableContract
27
{
28
    use PageSchema;
29
30
    public static string $sourceDirectory;
31
    public static string $outputDirectory;
32
    public static string $fileExtension;
33
    public static string $template;
34
35
    public string $identifier;
36
    public FrontMatter $matter;
37
38
    /** @inheritDoc */
39
    final public static function getSourceDirectory(): string
40
    {
41
        return unslash(static::$sourceDirectory);
42
    }
43
44
    /** @inheritDoc */
45
    final public static function getOutputDirectory(): string
46
    {
47
        return unslash(static::$outputDirectory);
48
    }
49
50
    /** @inheritDoc */
51
    final public static function getFileExtension(): string
52
    {
53
        return '.'.ltrim(static::$fileExtension, '.');
54
    }
55
56
    /** @inheritDoc */
57
    public static function parse(string $slug): PageContract
58
    {
59
        return (new SourceFileParser(static::class, $slug))->get();
60
    }
61
62
    /** @inheritDoc */
63
    public static function files(): array|false
64
    {
65
        return DiscoveryService::getSourceFileListForModel(static::class);
66
    }
67
68
    /** @inheritDoc */
69
    public static function all(): Collection
70
    {
71
        $collection = new Collection();
72
73
        foreach (static::files() as $basename) {
74
            $collection->push(static::parse($basename));
75
        }
76
77
        return $collection;
78
    }
79
80
    /** @inheritDoc */
81
    public static function qualifyBasename(string $basename): string
82
    {
83
        return static::getSourceDirectory().'/'.unslash($basename).static::getFileExtension();
84
    }
85
86
    /** @inheritDoc */
87
    public static function getOutputLocation(string $basename): string
88
    {
89
        // Using the trim function we ensure we don't have a leading slash when the output directory is the root directory.
90
        return trim(
91
            static::getOutputDirectory().'/'.unslash($basename),
92
            '/'
93
        ).'.html';
94
    }
95
96
    public function __construct(string $identifier = '', FrontMatter|array $matter = [])
97
    {
98
        $this->identifier = $identifier;
99
        $this->matter = $matter instanceof FrontMatter ? $matter : new FrontMatter($matter);
0 ignored issues
show
introduced by
$matter is never a sub-type of Hyde\Framework\Models\FrontMatter.
Loading history...
100
        $this->constructPageSchema();
101
    }
102
103
    /** @inheritDoc */
104
    public function get(string $key = null, mixed $default = null): mixed
105
    {
106
        if (property_exists($this, $key) && isset($this->$key)) {
0 ignored issues
show
Bug introduced by
It seems like $key can also be of type null; however, parameter $property of property_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

106
        if (property_exists($this, /** @scrutinizer ignore-type */ $key) && isset($this->$key)) {
Loading history...
107
            return $this->$key;
108
        }
109
110
        return $this->matter($key, $default);
111
    }
112
113
    /** @inheritDoc */
114
    public function matter(string $key = null, mixed $default = null): mixed
115
    {
116
        return $this->matter->get($key, $default);
117
    }
118
119
    /** @inheritDoc */
120
    public function getIdentifier(): string
121
    {
122
        return $this->identifier;
123
    }
124
125
    /** @inheritDoc */
126
    public function getSourcePath(): string
127
    {
128
        return static::qualifyBasename($this->identifier);
129
    }
130
131
    /** @inheritDoc */
132
    public function getOutputPath(): string
133
    {
134
        return static::getCurrentPagePath().'.html';
0 ignored issues
show
Bug Best Practice introduced by
The method Hyde\Framework\Contracts...e::getCurrentPagePath() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

134
        return static::/** @scrutinizer ignore-call */ getCurrentPagePath().'.html';
Loading history...
135
    }
136
137
    /** @inheritDoc */
138
    public function getCurrentPagePath(): string
139
    {
140
        return trim(static::getOutputDirectory().'/'.$this->identifier, '/');
141
    }
142
143
    /** @inheritDoc */
144
    public function getRoute(): Route
145
    {
146
        return new Route($this);
147
    }
148
149
    /** @inheritDoc */
150
    public function htmlTitle(): string
151
    {
152
        return config('site.name', 'HydePHP').' - '.$this->title;
153
    }
154
155
    /** @inheritDoc */
156
    public function getBladeView(): string
157
    {
158
        return static::$template;
159
    }
160
161
    /** @inheritDoc */
162
    abstract public function compile(): string;
163
164
    /**
165
     * @internal
166
     *
167
     * @return string[]
168
     *
169
     * @psalm-return list<string>
170
     */
171
    public function getDynamicMetadata(): array
172
    {
173
        $array = [];
174
175
        if (! empty($this->canonicalUrl)) {
176
            $array[] = Meta::link('canonical', $this->canonicalUrl);
177
        }
178
179
        if (! empty($this->title)) {
180
            $array[] = Meta::name('twitter:title', $this->htmlTitle());
181
            $array[] = Meta::property('title', $this->htmlTitle());
182
        }
183
184
        if ($this instanceof MarkdownPost) {
185
            $array[] = "\n<!-- Blog Post Meta Tags -->";
186
            foreach ($this->getMetadata() as $name => $content) {
187
                $array[] = Meta::name($name, $content);
188
            }
189
            foreach ($this->getMetaProperties() as $property => $content) {
190
                $array[] = Meta::property($property, $content);
191
            }
192
        }
193
194
        return $array;
195
    }
196
197
    public function renderPageMetadata(): string
198
    {
199
        return Meta::render(
200
            withMergedData: $this->getDynamicMetadata()
201
        );
202
    }
203
204
    public function showInNavigation(): bool
205
    {
206
        return ! $this->navigation['hidden'];
207
    }
208
209
    public function navigationMenuPriority(): int
210
    {
211
        return $this->navigation['priority'];
212
    }
213
214
    public function navigationMenuTitle(): string
215
    {
216
        return $this->navigation['title'];
217
    }
218
219
    /**
220
     * Not yet implemented.
221
     *
222
     * If an item returns a route collection,
223
     * it will automatically be made into a dropdown.
224
     *
225
     * @return \Illuminate\Support\Collection<\Hyde\Framework\Models\Route>
226
     */
227
    // public function navigationMenuChildren(): Collection;
228
}
229