Passed
Push — master ( c70df2...3b77f2 )
by Caen
03:41 queued 11s
created

HydeKernel::getMarkdownPagePath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 2
b 0
f 0
1
<?php
2
3
namespace Hyde\Framework;
4
5
use Composer\InstalledVersions;
6
use Hyde\Framework\Contracts\HydeKernelContract;
7
use Hyde\Framework\Contracts\RouteContract;
8
use Hyde\Framework\Helpers\Features;
9
use Hyde\Framework\Models\Pages\BladePage;
10
use Hyde\Framework\Models\Pages\DocumentationPage;
11
use Hyde\Framework\Models\Pages\MarkdownPage;
12
use Hyde\Framework\Models\Pages\MarkdownPost;
13
use Hyde\Framework\Services\DiscoveryService;
14
use Illuminate\Support\Facades\View;
15
use Illuminate\Support\Str;
16
use Illuminate\Support\Traits\Macroable;
17
18
/**
19
 * Encapsulates a HydePHP project, providing helpful methods for interacting with it.
20
 *
21
 * @see \Hyde\Framework\Hyde
22
 *
23
 * @author  Caen De Silva <[email protected]>
24
 * @copyright 2022 Caen De Silva
25
 * @license MIT License
26
 *
27
 * @link https://hydephp.com/
28
 */
29
class HydeKernel implements HydeKernelContract
30
{
31
    use Macroable;
1 ignored issue
show
Bug introduced by
The trait Illuminate\Support\Traits\Macroable requires the property $name which is not provided by Hyde\Framework\HydeKernel.
Loading history...
32
33
    protected string $basePath;
34
35
    public function __construct(?string $basePath = null)
36
    {
37
        $this->setBasePath($basePath ?? getcwd());
38
    }
39
40
    public static function getInstance(): static
41
    {
42
        return app(HydeKernelContract::class);
0 ignored issues
show
Bug Best Practice introduced by
The expression return app(Hyde\Framewor...eKernelContract::class) returns the type Hyde\Framework\Contracts\HydeKernelContract which includes types incompatible with the type-hinted return Hyde\Framework\HydeKernel.
Loading history...
43
    }
44
45
    public static function version(): string
46
    {
47
        return InstalledVersions::getPrettyVersion('hyde/framework') ?: 'unreleased';
48
    }
49
50
    public function getBasePath(): string
51
    {
52
        return $this->basePath;
53
    }
54
55
    public function setBasePath($basePath)
56
    {
57
        $this->basePath = rtrim($basePath, '/\\');
58
    }
59
60
    // HydeHelperFacade
61
62
    public function features(): Features
63
    {
64
        return new Features;
65
    }
66
67
    public function hasFeature(string $feature): bool
68
    {
69
        return Features::enabled($feature);
70
    }
71
72
    public function makeTitle(string $slug): string
73
    {
74
        $alwaysLowercase = ['a', 'an', 'the', 'in', 'on', 'by', 'with', 'of', 'and', 'or', 'but'];
75
76
        return ucfirst(str_ireplace(
0 ignored issues
show
Bug introduced by
It seems like str_ireplace($alwaysLowe...t\Str::headline($slug)) can also be of type array; however, parameter $string of ucfirst() 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

76
        return ucfirst(/** @scrutinizer ignore-type */ str_ireplace(
Loading history...
77
            $alwaysLowercase,
78
            $alwaysLowercase,
79
            Str::headline($slug)
80
        ));
81
    }
82
83
    /**
84
     * File helper methods.
85
     *
86
     * If a method uses the name `path` it refers to an internal file path.
87
     * if a method uses the name `link` it refers to a web link used in Blade templates.
88
     */
89
90
    /**
91
     * Get an absolute file path from a supplied relative path.
92
     *
93
     * The function returns the fully qualified path to your site's root directory.
94
     *
95
     * You may also use the function to generate a fully qualified path to a given file
96
     * relative to the project root directory when supplying the path argument.
97
     *
98
     * @param  string  $path
99
     * @return string
100
     */
101
    public function path(string $path = ''): string
102
    {
103
        if (empty($path)) {
104
            return static::getBasePath();
0 ignored issues
show
Bug Best Practice introduced by
The method Hyde\Framework\HydeKernel::getBasePath() 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

104
            return static::/** @scrutinizer ignore-call */ getBasePath();
Loading history...
105
        }
106
107
        $path = unslash($path);
108
109
        return static::getBasePath().DIRECTORY_SEPARATOR.$path;
110
    }
111
112
    /**
113
     * Works similarly to the path() function, but returns a file in the Framework package.
114
     *
115
     * @param  string  $path
116
     * @return string
117
     */
118
    public function vendorPath(string $path = ''): string
119
    {
120
        return $this->path('vendor/hyde/framework/'.unslash($path));
121
    }
122
123
    /**
124
     * Format a link to an HTML file, allowing for pretty URLs, if enabled.
125
     *
126
     * @see \Hyde\Framework\Testing\Unit\FileHelperPageLinkPrettyUrlTest
127
     */
128
    public function pageLink(string $destination): string
129
    {
130
        if (config('site.pretty_urls', false) === true) {
131
            if (str_ends_with($destination, '.html')) {
132
                if ($destination === 'index.html') {
133
                    return '/';
134
                }
135
                if ($destination === DocumentationPage::getOutputDirectory().'/index.html') {
136
                    return DocumentationPage::getOutputDirectory().'/';
137
                }
138
139
                return substr($destination, 0, -5);
140
            }
141
        }
142
143
        return $destination;
144
    }
145
146
    /**
147
     * Inject the proper number of `../` before the links in Blade templates.
148
     *
149
     * Since v0.50.x you no longer have to supply a current page as it will be automatically retrieved from the View.
150
     *
151
     * @param  string  $destination  relative to output directory on compiled site
152
     * @param  string|null  $current  the current URI path relative to the site root
153
     * @return string
154
     *
155
     * @see \Hyde\Framework\Testing\Unit\FileHelperRelativeLinkTest
156
     */
157
    public function relativeLink(string $destination, ?string $current = null): string
158
    {
159
        if (str_starts_with($destination, '../')) {
160
            return $destination;
161
        }
162
163
        if ($current === null) {
164
            $current = static::currentPage();
0 ignored issues
show
Bug Best Practice introduced by
The method Hyde\Framework\HydeKernel::currentPage() 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

164
            /** @scrutinizer ignore-call */ 
165
            $current = static::currentPage();
Loading history...
165
        }
166
167
        $nestCount = substr_count($current, '/');
168
        $route = '';
169
        if ($nestCount > 0) {
170
            $route .= str_repeat('../', $nestCount);
171
        }
172
        $route .= static::pageLink($destination);
0 ignored issues
show
Bug Best Practice introduced by
The method Hyde\Framework\HydeKernel::pageLink() 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

172
        $route .= static::/** @scrutinizer ignore-call */ pageLink($destination);
Loading history...
173
174
        return str_replace('//', '/', $route);
175
    }
176
177
    /**
178
     * Get the current page path, or fall back to the root path.
179
     */
180
    public function currentPage(): string
181
    {
182
        return View::shared('currentPage', '');
183
    }
184
185
    /**
186
     * Get the current page route, or fall back to null.
187
     */
188
    public function currentRoute(): ?RouteContract
189
    {
190
        return View::shared('currentRoute');
191
    }
192
193
    /**
194
     * Gets a relative web link to the given image stored in the _site/media folder.
195
     * Since v0.50.x you no longer have to supply a current page as it will be automatically retrieved from the View.
196
     */
197
    public function image(string $name, string $current = null): string
198
    {
199
        if ($current === null) {
200
            $current = static::currentPage();
0 ignored issues
show
Bug Best Practice introduced by
The method Hyde\Framework\HydeKernel::currentPage() 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

200
            /** @scrutinizer ignore-call */ 
201
            $current = static::currentPage();
Loading history...
201
        }
202
203
        if (str_starts_with($name, 'http')) {
204
            return $name;
205
        }
206
207
        return static::relativeLink('media/'.basename($name), $current);
0 ignored issues
show
Bug Best Practice introduced by
The method Hyde\Framework\HydeKernel::relativeLink() 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

207
        return static::/** @scrutinizer ignore-call */ relativeLink('media/'.basename($name), $current);
Loading history...
208
    }
209
210
    /**
211
     * Return a qualified URI path, if SITE_URL is set in .env, else return false.
212
     *
213
     * @param  string|null  $path  optional relative path suffix. Omit to return base url.
214
     * @return string|false
215
     */
216
    public function uriPath(?string $path = ''): string|false
217
    {
218
        if (config('site.url', false)) {
219
            return rtrim(config('site.url'), '/').'/'.(trim($path, '/') ?? '');
0 ignored issues
show
Bug introduced by
It seems like $path can also be of type null; however, parameter $string of trim() 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

219
            return rtrim(config('site.url'), '/').'/'.(trim(/** @scrutinizer ignore-type */ $path, '/') ?? '');
Loading history...
220
        }
221
222
        return false;
223
    }
224
225
    /**
226
     * Wrapper for the copy function, but allows choosing if files may be overwritten.
227
     *
228
     * @param  string  $from  The source file path.
229
     * @param  string  $to  The destination file path.
230
     * @param  bool  $force  If true, existing files will be overwritten.
231
     * @return bool|int Returns true|false on copy() success|failure, or an error code on failure
232
     */
233
    public function copy(string $from, string $to, bool $force = false): bool|int
234
    {
235
        if (! file_exists($from)) {
236
            return 404;
237
        }
238
239
        if (file_exists($to) && ! $force) {
240
            return 409;
241
        }
242
243
        return copy($from, $to);
244
    }
245
246
    /**
247
     * Fluent file helper methods.
248
     *
249
     * Provides a more fluent way of getting either the absolute path
250
     * to a model's source directory, or an absolute path to a file within it.
251
     *
252
     * These are intended to be used as a dynamic alternative to legacy code
253
     * Hyde::path('_pages/foo') becomes Hyde::getBladePagePath('foo')
254
     */
255
    public function getModelSourcePath(string $model, string $path = ''): string
256
    {
257
        if (empty($path)) {
258
            return $this->path(DiscoveryService::getFilePathForModelClassFiles($model));
259
        }
260
261
        $path = unslash($path);
262
263
        return $this->path(DiscoveryService::getFilePathForModelClassFiles($model).DIRECTORY_SEPARATOR.$path);
264
    }
265
266
    public function getBladePagePath(string $path = ''): string
267
    {
268
        return static::getModelSourcePath(BladePage::class, $path);
0 ignored issues
show
Bug Best Practice introduced by
The method Hyde\Framework\HydeKernel::getModelSourcePath() 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

268
        return static::/** @scrutinizer ignore-call */ getModelSourcePath(BladePage::class, $path);
Loading history...
269
    }
270
271
    public function getMarkdownPagePath(string $path = ''): string
272
    {
273
        return static::getModelSourcePath(MarkdownPage::class, $path);
0 ignored issues
show
Bug Best Practice introduced by
The method Hyde\Framework\HydeKernel::getModelSourcePath() 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

273
        return static::/** @scrutinizer ignore-call */ getModelSourcePath(MarkdownPage::class, $path);
Loading history...
274
    }
275
276
    public function getMarkdownPostPath(string $path = ''): string
277
    {
278
        return static::getModelSourcePath(MarkdownPost::class, $path);
0 ignored issues
show
Bug Best Practice introduced by
The method Hyde\Framework\HydeKernel::getModelSourcePath() 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

278
        return static::/** @scrutinizer ignore-call */ getModelSourcePath(MarkdownPost::class, $path);
Loading history...
279
    }
280
281
    public function getDocumentationPagePath(string $path = ''): string
282
    {
283
        return static::getModelSourcePath(DocumentationPage::class, $path);
0 ignored issues
show
Bug Best Practice introduced by
The method Hyde\Framework\HydeKernel::getModelSourcePath() 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

283
        return static::/** @scrutinizer ignore-call */ getModelSourcePath(DocumentationPage::class, $path);
Loading history...
284
    }
285
286
    /**
287
     * Get the absolute path to the compiled site directory, or a file within it.
288
     */
289
    public function getSiteOutputPath(string $path = ''): string
290
    {
291
        if (empty($path)) {
292
            return StaticPageBuilder::$outputPath;
293
        }
294
295
        $path = unslash($path);
296
297
        return StaticPageBuilder::$outputPath.DIRECTORY_SEPARATOR.$path;
298
    }
299
300
    /**
301
     * Decode an absolute path created with a Hyde::path() helper into its relative counterpart.
302
     */
303
    public function pathToRelative(string $path): string
304
    {
305
        return str_starts_with($path, $this->path()) ? unslash(str_replace(
306
            $this->path(),
307
            '',
308
            $path
309
        )) : $path;
310
    }
311
}
312