Passed
Push — master ( 39f3e5...c21571 )
by Caen
03:18 queued 12s
created

Filesystem::pathToRelative()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 5
rs 10
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
     * @param  string  $path
56
     * @return string
57
     */
58
    public function path(string $path = ''): string
59
    {
60
        if (empty($path)) {
61
            return $this->getBasePath();
62
        }
63
64
        $path = unslash($path);
65
66
        return $this->implode($this->getBasePath(), $path);
67
    }
68
69
    /**
70
     * Get an absolute file path from a supplied relative path.
71
     *
72
     * Input types are matched, meaning that if the input is a string so will the output be.
73
     */
74
    public function pathToAbsolute(array|string $path): array|string
75
    {
76
        if (is_array($path)) {
0 ignored issues
show
introduced by
The condition is_array($path) is always true.
Loading history...
77
            return array_map(fn (string $path): string => $this->pathToAbsolute($path), $path);
78
        }
79
80
        return $this->path($path);
81
    }
82
83
    /**
84
     * Decode an absolute path created with a Hyde::path() helper into its relative counterpart.
85
     */
86
    public function pathToRelative(string $path): string
87
    {
88
        return str_starts_with($path, $this->path())
89
            ? unslash(str_replace($this->path(), '', $path))
90
            : $path;
91
    }
92
93
    /**
94
     * Get the absolute path to the compiled site directory, or a file within it.
95
     */
96
    public function sitePath(string $path = ''): string
97
    {
98
        if (empty($path)) {
99
            return Hyde::path(Site::$outputPath);
100
        }
101
102
        $path = unslash($path);
103
104
        return Hyde::path(Site::$outputPath.DIRECTORY_SEPARATOR.$path);
105
    }
106
107
    /**
108
     * Works similarly to the path() function, but returns a file in the Framework package.
109
     *
110
     * @param  string  $path
111
     * @return string
112
     */
113
    public function vendorPath(string $path = ''): string
114
    {
115
        return $this->path('vendor/hyde/framework/'.unslash($path));
116
    }
117
118
    /**
119
     * Wrapper for the copy function, but using project relative paths.
120
     */
121
    public function copy(string $from, string $to): bool
122
    {
123
        return copy($this->path($from), $this->path($to));
124
    }
125
126
    /**
127
     * Touch one or more files in the project's directory.
128
     */
129
    public function touch(string|array $path): bool
130
    {
131
        if (is_string($path)) {
0 ignored issues
show
introduced by
The condition is_string($path) is always false.
Loading history...
132
            return touch($this->path($path));
133
        }
134
135
        foreach ($path as $p) {
136
            touch($this->path($p));
137
        }
138
139
        return true;
140
    }
141
142
    /**
143
     * Unlink one or more files in the project's directory.
144
     */
145
    public function unlink(string|array $path): bool
146
    {
147
        if (is_string($path)) {
0 ignored issues
show
introduced by
The condition is_string($path) is always false.
Loading history...
148
            return unlink($this->path($path));
149
        }
150
151
        foreach ($path as $p) {
152
            unlink($this->path($p));
153
        }
154
155
        return true;
156
    }
157
158
    /**
159
     * Unlink a file in the project's directory, but only if it exists.
160
     */
161
    public function unlinkIfExists(string $path): bool
162
    {
163
        if (file_exists($this->path($path))) {
164
            return unlink($this->path($path));
165
        }
166
167
        return false;
168
    }
169
170
    /**
171
     * Fluent file helper methods.
172
     *
173
     * Provides a more fluent way of getting either the absolute path
174
     * to a model's source directory, or an absolute path to a file within it.
175
     *
176
     * These are intended to be used as a dynamic alternative to legacy code
177
     * Hyde::path('_pages/foo') becomes Hyde::getBladePagePath('foo')
178
     */
179
    public function getModelSourcePath(string $model, string $path = ''): string
180
    {
181
        if (empty($path)) {
182
            return $this->path(DiscoveryService::getModelSourceDirectory($model));
183
        }
184
185
        $path = unslash($path);
186
187
        return $this->path($this->implode(DiscoveryService::getModelSourceDirectory($model), $path));
188
    }
189
190
    public function getBladePagePath(string $path = ''): string
191
    {
192
        return $this->getModelSourcePath(BladePage::class, $path);
193
    }
194
195
    public function getMarkdownPagePath(string $path = ''): string
196
    {
197
        return $this->getModelSourcePath(MarkdownPage::class, $path);
198
    }
199
200
    public function getMarkdownPostPath(string $path = ''): string
201
    {
202
        return $this->getModelSourcePath(MarkdownPost::class, $path);
203
    }
204
205
    public function getDocumentationPagePath(string $path = ''): string
206
    {
207
        return $this->getModelSourcePath(DocumentationPage::class, $path);
208
    }
209
210
    public function smartGlob(string $pattern, int $flags = 0): Collection
211
    {
212
        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

212
        return collect(/** @scrutinizer ignore-type */ \Hyde\Facades\Filesystem::glob($pattern, $flags))
Loading history...
213
            ->map(fn (string $path): string => $this->pathToRelative($path));
214
    }
215
216
    /**
217
     * Implode path components into a string with directory separators.
218
     */
219
    public static function implode(string $base, string ...$paths): string
220
    {
221
        return implode(DIRECTORY_SEPARATOR, array_merge([$base], $paths));
222
    }
223
}
224