Passed
Push — master ( b2557e...f95421 )
by Caen
03:23 queued 19s
created

HydePage::getRoute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Hyde\Pages\Concerns;
6
7
use Hyde\Foundation\Facades;
8
use Hyde\Foundation\PageCollection;
9
use Hyde\Framework\Actions\SourceFileParser;
10
use Hyde\Framework\Concerns\InteractsWithFrontMatter;
11
use Hyde\Framework\Factories\Concerns\HasFactory;
12
use Hyde\Framework\Features\Metadata\PageMetadataBag;
13
use Hyde\Framework\Features\Navigation\NavigationData;
14
use Hyde\Framework\Services\DiscoveryService;
15
use Hyde\Hyde;
16
use Hyde\Markdown\Contracts\FrontMatter\PageSchema;
17
use Hyde\Markdown\Models\FrontMatter;
18
use Hyde\Support\Models\Route;
19
use Hyde\Support\Models\RouteKey;
20
use function unslash;
21
22
/**
23
 * The base class for all Hyde pages.
24
 *
25
 * To ensure compatibility with the Hyde Framework, all page models should extend this class.
26
 * Markdown-based pages can extend the BaseMarkdownPage class to get relevant helpers.
27
 *
28
 * Unlike other frameworks, in general you don't instantiate pages yourself in Hyde,
29
 * instead, the page models acts as blueprints defining information for Hyde to
30
 * know how to parse a file, and what data around it should be generated.
31
 *
32
 * To create a parsed file instance, you'd typically just create a source file,
33
 * and you can then access the parsed file from the HydeKernel's page index.
34
 * The source files are usually parsed by the SourceFileParser action.
35
 *
36
 * In Blade views, you can always access the current page instance being rendered using the $page variable.
37
 *
38
 * @see \Hyde\Pages\Concerns\BaseMarkdownPage
39
 * @see \Hyde\Framework\Testing\Feature\HydePageTest
40
 */
41
abstract class HydePage implements PageSchema
42
{
43
    use InteractsWithFrontMatter;
44
    use HasFactory;
0 ignored issues
show
Bug introduced by
The trait Hyde\Framework\Factories\Concerns\HasFactory requires the property $markdown which is not provided by Hyde\Pages\Concerns\HydePage.
Loading history...
45
46
    public static string $sourceDirectory;
47
    public static string $outputDirectory;
48
    public static string $fileExtension;
49
    public static string $template;
50
51
    public string $identifier;
52
    public string $routeKey;
53
54
    public FrontMatter $matter;
55
    public PageMetadataBag $metadata;
56
57
    public string $title;
58
    public ?string $canonicalUrl = null;
59
    public ?NavigationData $navigation = null;
60
61
    public static function make(string $identifier = '', FrontMatter|array $matter = []): static
62
    {
63
        return new static($identifier, $matter);
64
    }
65
66
    public function __construct(string $identifier = '', FrontMatter|array $matter = [])
67
    {
68
        $this->identifier = $identifier;
69
        $this->routeKey = RouteKey::fromPage(static::class, $identifier)->get();
70
71
        $this->matter = $matter instanceof FrontMatter ? $matter : new FrontMatter($matter);
0 ignored issues
show
introduced by
$matter is never a sub-type of Hyde\Markdown\Models\FrontMatter.
Loading history...
72
        $this->constructPageSchemas();
73
        $this->metadata = new PageMetadataBag($this);
74
    }
75
76
    // Section: Query
77
78
    /**
79
     * Get a page instance from the Kernel's page index by its identifier.
80
     *
81
     *
82
     * @throws \Hyde\Framework\Exceptions\FileNotFoundException If the page does not exist.
83
     */
84
    public static function get(string $identifier): HydePage
85
    {
86
        return Hyde::pages()->getPage(static::sourcePath($identifier));
87
    }
88
89
    /**
90
     * Parse a source file into a page model instance.
91
     *
92
     * @param  string  $identifier  The identifier of the page to parse.
93
     * @return static New page model instance for the parsed source file.
94
     *
95
     * @throws \Hyde\Framework\Exceptions\FileNotFoundException If the file does not exist.
96
     */
97
    public static function parse(string $identifier): HydePage
98
    {
99
        return (new SourceFileParser(static::class, $identifier))->get();
100
    }
101
102
    /**
103
     * Get an array of all the source file identifiers for the model.
104
     *
105
     * Essentially an alias of DiscoveryService::getAbstractPageList().
106
     *
107
     * @return array<string>
108
     */
109
    public static function files(): array
110
    {
111
        return DiscoveryService::getSourceFileListForModel(static::class);
112
    }
113
114
    /**
115
     * Get a collection of all pages, parsed into page models.
116
     *
117
     * @return \Hyde\Foundation\PageCollection<\Hyde\Pages\Concerns\HydePage>
118
     */
119
    public static function all(): PageCollection
120
    {
121
        return Facades\PageCollection::getPages(static::class);
0 ignored issues
show
Bug introduced by
The method getPages() does not exist on Hyde\Foundation\Facades\PageCollection. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

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

121
        return Facades\PageCollection::/** @scrutinizer ignore-call */ getPages(static::class);
Loading history...
122
    }
123
124
    // Section: Filesystem
125
126
    /**
127
     * Get the directory in where source files are stored.
128
     */
129
    final public static function sourceDirectory(): string
130
    {
131
        return unslash(static::$sourceDirectory);
132
    }
133
134
    /**
135
     * Get the output subdirectory to store compiled HTML.
136
     */
137
    final public static function outputDirectory(): string
138
    {
139
        return unslash(static::$outputDirectory);
140
    }
141
142
    /**
143
     * Get the file extension of the source files.
144
     */
145
    final public static function fileExtension(): string
146
    {
147
        return rtrim('.'.ltrim(static::$fileExtension, '.'), '.');
148
    }
149
150
    /**
151
     * Qualify a page identifier into a local file path for the page source file relative to the project root.
152
     */
153
    public static function sourcePath(string $identifier): string
154
    {
155
        return unslash(static::sourceDirectory().'/'.unslash($identifier).static::fileExtension());
156
    }
157
158
    /**
159
     * Qualify a page identifier into a target output file path relative to the _site output directory.
160
     */
161
    public static function outputPath(string $identifier): string
162
    {
163
        return RouteKey::fromPage(static::class, $identifier).'.html';
164
    }
165
166
    /**
167
     * Get an absolute file path to the page's source directory, or a file within it.
168
     */
169
    public static function path(string $path = ''): string
170
    {
171
        return Hyde::path(unslash(static::sourceDirectory().'/'.unslash($path)));
172
    }
173
174
    /**
175
     * Get the route key base for the page model.
176
     */
177
    public static function baseRouteKey(): string
178
    {
179
        return static::outputDirectory();
180
    }
181
182
    /**
183
     * Compile the page into static HTML.
184
     *
185
     * @return string The compiled HTML for the page.
186
     */
187
    abstract public function compile(): string;
188
189
    /**
190
     * Get the path to the instance source file, relative to the project root.
191
     */
192
    public function getSourcePath(): string
193
    {
194
        return unslash(static::sourcePath($this->identifier));
195
    }
196
197
    /**
198
     * Get the path where the compiled page will be saved.
199
     *
200
     * @return string Path relative to the site output directory.
201
     */
202
    public function getOutputPath(): string
203
    {
204
        return unslash(static::outputPath($this->identifier));
205
    }
206
207
    // Section: Routing
208
209
    /**
210
     * Get the route key for the page.
211
     *
212
     * The route key is the URL path relative to the site root.
213
     *
214
     * For example, if the compiled page will be saved to _site/docs/index.html,
215
     * then this method will return 'docs/index'. Route keys are used to
216
     * identify pages, similar to how named routes work in Laravel.
217
     *
218
     * @return string The page's route key.
219
     */
220
    public function getRouteKey(): string
221
    {
222
        return $this->routeKey;
223
    }
224
225
    /**
226
     * Get the route for the page.
227
     *
228
     * @return \Hyde\Support\Models\Route The page's route.
229
     */
230
    public function getRoute(): Route
231
    {
232
        return \Hyde\Facades\Route::get($this->getRouteKey()) ?? new Route($this);
233
    }
234
235
    /**
236
     * Format the page instance to a URL path (relative to site root) with support for pretty URLs if enabled.
237
     */
238
    public function getLink(): string
239
    {
240
        return Hyde::formatLink($this->getOutputPath());
241
    }
242
243
    // Section: Getters
244
245
    /**
246
     * Get the page model's identifier property.
247
     *
248
     * The identifier is the part between the source directory and the file extension.
249
     * It may also be known as a 'slug', or previously 'basename'.
250
     *
251
     * For example, the identifier of a source file stored as '_pages/about/contact.md'
252
     * would be 'about/contact', and 'pages/about.md' would simply be 'about'.
253
     *
254
     * @return string The page's identifier.
255
     */
256
    public function getIdentifier(): string
257
    {
258
        return $this->identifier;
259
    }
260
261
    /**
262
     * Get the Blade template for the page.
263
     *
264
     * @return string Blade template/view key.
265
     */
266
    public function getBladeView(): string
267
    {
268
        return static::$template;
269
    }
270
271
    // Section: Accessors
272
273
    /**
274
     * Get the page title to display in HTML tags like <title> and <meta> tags.
275
     */
276
    public function htmlTitle(): string
277
    {
278
        return config('site.name', 'HydePHP').' - '.$this->title;
279
    }
280
281
    public function metadata(): PageMetadataBag
282
    {
283
        return $this->metadata;
284
    }
285
286
    public function showInNavigation(): bool
287
    {
288
        return ! $this->navigation['hidden'];
289
    }
290
291
    public function navigationMenuPriority(): int
292
    {
293
        return $this->navigation['priority'];
294
    }
295
296
    public function navigationMenuLabel(): string
297
    {
298
        return $this->navigation['label'];
299
    }
300
301
    public function navigationMenuGroup(): ?string
302
    {
303
        return $this->navigation['group'];
304
    }
305
}
306