Passed
Push — master ( e3b121...219a49 )
by Caen
03:57 queued 14s
created

Filesystem::unlinkIfExists()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Hyde\Foundation;
6
7
use function array_map;
8
use function collect;
9
use function copy;
10
use Hyde\Facades\Site;
11
use Hyde\Framework\Services\DiscoveryService;
12
use Hyde\Hyde;
13
use Hyde\Pages\BladePage;
14
use Hyde\Pages\DocumentationPage;
15
use Hyde\Pages\MarkdownPage;
16
use Hyde\Pages\MarkdownPost;
17
use Illuminate\Support\Collection;
18
use function is_array;
19
use function is_string;
20
use function str_replace;
21
use function touch;
22
use function unlink;
23
use function unslash;
24
25
/**
26
 * File helper methods, bound to the HydeKernel instance, and is an integral part of the framework.
27
 *
28
 * All paths arguments are relative to the root of the application,
29
 * and will be automatically resolved to absolute paths.
30
 *
31
 * @see \Hyde\Framework\Testing\Feature\Foundation\FilesystemTest
32
 */
33
class Filesystem
34
{
35
    protected HydeKernel $kernel;
36
37
    public function __construct(HydeKernel $kernel)
38
    {
39
        $this->kernel = $kernel;
40
    }
41
42
    public function getBasePath(): string
43
    {
44
        return $this->kernel->getBasePath();
45
    }
46
47
    /**
48
     * Get an absolute file path from a supplied relative path.
49
     *
50
     * The function returns the fully qualified path to your site's root directory.
51
     *
52
     * You may also use the function to generate a fully qualified path to a given file
53
     * relative to the project root directory when supplying the path argument.
54
     */
55
    public function path(string $path = ''): string
56
    {
57
        if (empty($path)) {
58
            return $this->getBasePath();
59
        }
60
61
        $path = unslash($path);
62
63
        return $this->implode($this->getBasePath(), $path);
64
    }
65
66
    /**
67
     * Get an absolute file path from a supplied relative path.
68
     *
69
     * Input types are matched, meaning that if the input is a string so will the output be.
70
     */
71
    public function pathToAbsolute(string|array $path): string|array
72
    {
73
        if (is_array($path)) {
0 ignored issues
show
introduced by
The condition is_array($path) is always true.
Loading history...
74
            return array_map(fn (string $path): string => $this->pathToAbsolute($path), $path);
75
        }
76
77
        return $this->path($path);
78
    }
79
80
    /**
81
     * Decode an absolute path created with a Hyde::path() helper into its relative counterpart.
82
     *
83
     * @todo Normalize slashes to forward slashes?
84
     */
85
    public function pathToRelative(string $path): string
86
    {
87
        return str_starts_with($path, $this->path())
88
            ? unslash(str_replace($this->path(), '', $path))
89
            : $path;
90
    }
91
92
    /**
93
     * Get the absolute path to the media source directory, or a file within it.
94
     */
95
    public function mediaPath(string $path = ''): string
96
    {
97
        if (empty($path)) {
98
            return Hyde::path(Hyde::getMediaDirectory());
99
        }
100
101
        $path = unslash($path);
102
103
        return Hyde::path(Hyde::getMediaDirectory().DIRECTORY_SEPARATOR.$path);
104
    }
105
106
    /**
107
     * Get the absolute path to the compiled site directory, or a file within it.
108
     */
109
    public function sitePath(string $path = ''): string
110
    {
111
        if (empty($path)) {
112
            return Hyde::path(Site::getOutputDirectory());
113
        }
114
115
        $path = unslash($path);
116
117
        return Hyde::path(Site::getOutputDirectory().DIRECTORY_SEPARATOR.$path);
118
    }
119
120
    /**
121
     * Get the absolute path to the compiled site's media directory, or a file within it.
122
     */
123
    public function siteMediaPath(string $path = ''): string
124
    {
125
        if (empty($path)) {
126
            return Hyde::sitePath(Hyde::getMediaOutputDirectory());
127
        }
128
129
        $path = unslash($path);
130
131
        return Hyde::sitePath(Hyde::getMediaOutputDirectory().DIRECTORY_SEPARATOR.$path);
132
    }
133
134
    /**
135
     * Works similarly to the path() function, but returns a file in the Framework package.
136
     */
137
    public function vendorPath(string $path = ''): string
138
    {
139
        return $this->path('vendor/hyde/framework/'.unslash($path));
140
    }
141
142
    /**
143
     * Wrapper for the copy function, but using project relative paths.
144
     */
145
    public function copy(string $from, string $to): bool
146
    {
147
        return copy($this->path($from), $this->path($to));
148
    }
149
150
    /**
151
     * Touch one or more files in the project's directory.
152
     */
153
    public function touch(string|array $path): bool
154
    {
155
        if (is_string($path)) {
0 ignored issues
show
introduced by
The condition is_string($path) is always false.
Loading history...
156
            return touch($this->path($path));
157
        }
158
159
        foreach ($path as $p) {
160
            touch($this->path($p));
161
        }
162
163
        return true;
164
    }
165
166
    /**
167
     * Unlink one or more files in the project's directory.
168
     */
169
    public function unlink(string|array $path): bool
170
    {
171
        if (is_string($path)) {
0 ignored issues
show
introduced by
The condition is_string($path) is always false.
Loading history...
172
            return unlink($this->path($path));
173
        }
174
175
        foreach ($path as $p) {
176
            unlink($this->path($p));
177
        }
178
179
        return true;
180
    }
181
182
    /**
183
     * Unlink a file in the project's directory, but only if it exists.
184
     */
185
    public function unlinkIfExists(string $path): bool
186
    {
187
        if (file_exists($this->path($path))) {
188
            return unlink($this->path($path));
189
        }
190
191
        return false;
192
    }
193
194
    /**
195
     * Fluent file helper methods.
196
     *
197
     * Provides a more fluent way of getting either the absolute path
198
     * to a model's source directory, or an absolute path to a file within it.
199
     *
200
     * These are intended to be used as a dynamic alternative to legacy code
201
     * Hyde::path('_pages/foo') becomes Hyde::getBladePagePath('foo')
202
     */
203
    public function getModelSourcePath(string $model, string $path = ''): string
204
    {
205
        if (empty($path)) {
206
            return $this->path(DiscoveryService::getModelSourceDirectory($model));
207
        }
208
209
        $path = unslash($path);
210
211
        return $this->path($this->implode(DiscoveryService::getModelSourceDirectory($model), $path));
212
    }
213
214
    public function getBladePagePath(string $path = ''): string
215
    {
216
        return $this->getModelSourcePath(BladePage::class, $path);
217
    }
218
219
    public function getMarkdownPagePath(string $path = ''): string
220
    {
221
        return $this->getModelSourcePath(MarkdownPage::class, $path);
222
    }
223
224
    public function getMarkdownPostPath(string $path = ''): string
225
    {
226
        return $this->getModelSourcePath(MarkdownPost::class, $path);
227
    }
228
229
    public function getDocumentationPagePath(string $path = ''): string
230
    {
231
        return $this->getModelSourcePath(DocumentationPage::class, $path);
232
    }
233
234
    public function smartGlob(string $pattern, int $flags = 0): Collection
235
    {
236
        return collect(\Hyde\Facades\Filesystem::glob($pattern, $flags))
0 ignored issues
show
Bug introduced by
Hyde\Facades\Filesystem::glob($pattern, $flags) of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

236
        return collect(/** @scrutinizer ignore-type */ \Hyde\Facades\Filesystem::glob($pattern, $flags))
Loading history...
237
            ->map(fn (string $path): string => $this->pathToRelative($path));
238
    }
239
240
    /**
241
     * Implode path components into a string with directory separators.
242
     */
243
    public static function implode(string $base, string ...$paths): string
244
    {
245
        return implode(DIRECTORY_SEPARATOR, array_merge([$base], $paths));
246
    }
247
}
248