Passed
Push — master ( 522b19...2b20f6 )
by Caen
03:49 queued 13s
created

DiscoveryService::findModelFromFilePath()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 11
nc 5
nop 1
dl 0
loc 21
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
namespace Hyde\Framework\Services;
4
5
use Hyde\Framework\Contracts\AbstractPage;
6
use Hyde\Framework\Hyde;
7
use Hyde\Framework\Models\Pages\BladePage;
8
use Hyde\Framework\Models\Pages\DocumentationPage;
9
use Hyde\Framework\Models\Pages\MarkdownPage;
10
use Hyde\Framework\Models\Pages\MarkdownPost;
11
12
/**
13
 * The core service that powers all HydePHP file auto-discovery.
14
 *
15
 * Contains service methods to return helpful collections of arrays and lists,
16
 * and provides helper methods for source file auto-discovery used in the site
17
 * building process to determine where files are located and how to parse them.
18
 *
19
 * The CollectionService was in v0.53.0 merged into this class.
20
 */
21
class DiscoveryService
22
{
23
    public static function getParserClassForModel(string $model): string
24
    {
25
        /** @var AbstractPage $model */
26
        return $model::getParserClass();
27
    }
28
29
    /**
30
     * Create and get a constructed instance of a Model's Parser class.
31
     *
32
     * @param  string  $model  Class constant of the Model to get the Parser for.
33
     * @param  string  $slug  The slug of the source file to parse.
34
     *
35
     * @example getParserForModel(MarkdownPost::class, 'hello-world')
36
     *
37
     * @return object The constructed Parser instance.
38
     */
39
    public static function getParserInstanceForModel(string $model, string $slug): object
40
    {
41
        /** @var AbstractPage $model */
42
        return new $model::$parserClass($slug);
43
    }
44
45
    /**
46
     * Get the file extension for a models source files.
47
     */
48
    public static function getFileExtensionForModelFiles(string $model): string
49
    {
50
        /** @var AbstractPage $model */
51
        return $model::getFileExtension();
52
    }
53
54
    /**
55
     * Get the source directory path of a model.
56
     */
57
    public static function getFilePathForModelClassFiles(string $model): string
58
    {
59
        /** @var AbstractPage $model */
60
        return $model::getSourceDirectory();
61
    }
62
63
    /**
64
     * Determine the Page Model to use for a given file path.
65
     *
66
     * @deprecated v0.47.0-beta - Use the Router instead.
67
     *
68
     * @param  string  $filepath
69
     * @return string|false The model class constant, or false if none was found.
70
     *
71
     * @see \Hyde\Framework\Testing\Unit\DiscoveryServiceCanFindModelFromCustomSourceFilePathTest
72
     */
73
    public static function findModelFromFilePath(string $filepath): string|false
74
    {
75
        if (str_starts_with($filepath, MarkdownPost::getSourceDirectory())) {
76
            return MarkdownPost::class;
77
        }
78
79
        if (str_starts_with($filepath, DocumentationPage::getSourceDirectory())) {
80
            return DocumentationPage::class;
81
        }
82
83
        if (str_starts_with($filepath, MarkdownPage::getSourceDirectory())
84
            && str_ends_with($filepath, '.md')) {
85
            return MarkdownPage::class;
86
        }
87
88
        if (str_starts_with($filepath, BladePage::getSourceDirectory())
89
            && str_ends_with($filepath, '.blade.php')) {
90
            return BladePage::class;
91
        }
92
93
        return false;
94
    }
95
96
    /**
97
     * Create a filepath that can be opened in the browser from a terminal.
98
     *
99
     * @param  string  $filepath
100
     * @return string
101
     */
102
    public static function createClickableFilepath(string $filepath): string
103
    {
104
        if (realpath($filepath) === false) {
105
            return $filepath;
106
        }
107
108
        return 'file://'.str_replace(
109
            '\\',
110
            '/',
111
            realpath($filepath)
112
        );
113
    }
114
115
    /**
116
     * Get all the Markdown files in the _docs directory.
117
     *
118
     * @return array
119
     */
120
    public static function getDocumentationPageFiles(): array
121
    {
122
        return self::getSourceFileListForModel(DocumentationPage::class);
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::getSourceFi...cumentationPage::class) could return the type false which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
123
    }
124
125
    /**
126
     * Supply a model::class constant and get a list of all the existing source file base names.
127
     *
128
     * @param  string  $model
129
     * @return array|false array on success, false if the class was not found
130
     *
131
     * @example DiscoveryService::getSourceFileListForModel(BladePage::class)
132
     */
133
    public static function getSourceFileListForModel(string $model): array|false
134
    {
135
        if (! class_exists($model) || ! is_subclass_of($model, AbstractPage::class)) {
136
            return false;
137
        }
138
139
        // Scan the source directory, and directories therein, for files that match the model's file extension.
140
141
        $files = [];
142
        foreach (glob(Hyde::path($model::qualifyBasename('{*,**/*}')), GLOB_BRACE) as $filepath) {
143
            if (! str_starts_with(basename($filepath), '_')) {
144
                $files[] = self::formatSlugForModel($model, $filepath);
145
            }
146
        }
147
148
        return $files;
149
    }
150
151
    public static function formatSlugForModel(string $model, string $filepath): string
152
    {
153
        /** @var AbstractPage $model */
154
        $slug = str_replace(Hyde::path($model::$sourceDirectory), '', $filepath);
155
156
        if (str_ends_with($slug, $model::$fileExtension)) {
157
            $slug = substr($slug, 0, -strlen($model::$fileExtension));
158
        }
159
160
        $slug = unslash($slug);
161
162
        return $slug;
163
    }
164
165
    /**
166
     * Get all the Markdown files in the _pages directory.
167
     *
168
     * @return array
169
     */
170
    public static function getMarkdownPageFiles(): array
171
    {
172
        return self::getSourceFileListForModel(MarkdownPage::class);
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::getSourceFi...es\MarkdownPage::class) could return the type false which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
173
    }
174
175
    /**
176
     * Get all the Media asset file paths.
177
     * Returns a full file path, unlike the other get*List methods.
178
     */
179
    public static function getMediaAssetFiles(): array
180
    {
181
        return glob(Hyde::path('_media/*.{'.str_replace(
182
                ' ',
183
                '',
184
                config('hyde.media_extensions', 'png,svg,jpg,jpeg,gif,ico,css,js')
185
            ).'}'), GLOB_BRACE);
186
    }
187
188
    /**
189
     * Get all the Blade files in the _pages directory.
190
     *
191
     * @return array
192
     */
193
    public static function getBladePageFiles(): array
194
    {
195
        return self::getSourceFileListForModel(BladePage::class);
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::getSourceFi...Pages\BladePage::class) could return the type false which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
196
    }
197
198
    /**
199
     * Get all the Markdown files in the _posts directory.
200
     *
201
     * @return array
202
     */
203
    public static function getMarkdownPostFiles(): array
204
    {
205
        return self::getSourceFileListForModel(MarkdownPost::class);
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::getSourceFi...es\MarkdownPost::class) could return the type false which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
206
    }
207
}
208