Path::isAbsolutePath()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 25
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5.0488

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 7
nc 4
nop 1
dl 0
loc 25
ccs 7
cts 8
cp 0.875
crap 5.0488
rs 9.6111
c 1
b 0
f 0
1
<?php
2
namespace phpbu\App\Util;
3
4
/**
5
 * Path utility class
6
 *
7
 * @package    phpbu
8
 * @subpackage Util
9
 * @author     Sebastian Feldmann <[email protected]>
10
 * @copyright  Sebastian Feldmann <[email protected]>
11
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
12
 * @link       https://phpbu.de/
13
 * @since      Class available since Release 5.1.0
14
 */
15
class Path
16
{
17
    /**
18
     * Date placeholder replacement
19
     * Replaces %{somevalue} with date({somevalue})
20
     *
21
     * @param  string   $string
22
     * @param  int|null $time
23
     * @return string
24
     */
25 99
    public static function replaceDatePlaceholders(string $string, $time = null) : string
26
    {
27 99
        $time = $time === null ? time() : $time;
28 99
        return preg_replace_callback(
29 99
            '#%([a-zA-Z])#',
30
            function ($match) use ($time) {
31 58
                return date($match[1], $time);
32 99
            },
33
            $string
34
        );
35
    }
36
37
    /**
38
     * Does a given string contain a date placeholder
39
     *
40
     * @param  string $string
41
     * @return bool
42
     */
43 88
    public static function isContainingPlaceholder(string $string) : bool
44
    {
45 88
        return false !== strpos($string, '%');
46
    }
47
48
    /**
49
     * Replaces %TARGET_DIR% and %TARGET_FILE% in given string
50
     *
51
     * @param  string $string
52
     * @param  string $target
53
     * @return string
54
     */
55 4
    public static function replaceTargetPlaceholders(string $string, string $target) : string
56
    {
57 4
        $targetDir  = dirname($target);
58 4
        $search     = ['%TARGET_DIR%', '%TARGET_FILE%'];
59 4
        $replace    = [$targetDir, $target];
60 4
        return str_replace($search, $replace, $string);
61
    }
62
63
    /**
64
     * Create a regex that matches the raw path considering possible date placeholders
65
     *
66
     * @param  string $stringWithDatePlaceholders
67
     * @return string
68
     */
69 31
    public static function datePlaceholdersToRegex(string $stringWithDatePlaceholders) : string
70
    {
71
        $dateRegex = [
72 31
            '%Y' => '[0-9]{4}',
73
            '%y' => '[0-9]{2}',
74
            '%m' => '[0-9]{2}',
75
            '%M' => '[a-z]{3}',
76
            '%d' => '[0-9]{2}',
77
            '%D' => '[a-z]{3}',
78
            '%j' => '[1-9]{1,2}',
79
            '%H' => '[0-9]{2}',
80
            '%s' => '[0-9]{2}',
81
            '%i' => '[0-9]{2}',
82
            '%N' => '[1-7]{1}',
83
            '%w' => '[0-6]{1}',
84
            '%z' => '[0-9]{1,3}',
85
        ];
86 31
        $regex = preg_quote($stringWithDatePlaceholders, '#');
87 31
        $regex = str_replace(array_keys($dateRegex), array_values($dateRegex), $regex);
88 31
        return preg_replace('#%[a-z]#i', '[0-9a-z]+', $regex);
89
    }
90
91
    /**
92
     * Determine if the path has a trailing slash
93
     *
94
     * @param  string $string
95
     * @return bool
96
     */
97 100
    public static function hasTrailingSlash(string $string) : bool
98
    {
99 100
        return substr($string, -1) === '/';
100
    }
101
102
    /**
103
     * Adds trailing slash to a string/path if not already there
104
     *
105
     * @param  string $string
106
     * @return string
107
     */
108 26
    public static function withTrailingSlash(string $string) : string
109
    {
110 26
        return $string . (self::hasTrailingSlash($string) ? '' : '/');
111
    }
112
113
    /**
114
     * Removes the trailing slash from a string/path
115
     *
116
     * @param  string $string
117
     * @return string
118
     */
119 105
    public static function withoutTrailingSlash(string $string) : string
120
    {
121 105
        return strlen($string) > 1 && self::hasTrailingSlash($string) ? substr($string, 0, -1) : $string;
122
    }
123
124
    /**
125
     * Determine if the path has a leading slash
126
     *
127
     * @param  string $string
128
     * @return bool
129
     */
130 91
    public static function hasLeadingSlash(string $string) : bool
131
    {
132 91
        return substr($string, 0, 1) === '/';
133
    }
134
135
    /**
136
     * Adds leading slash to a string/path if not already there.
137
     *
138
     * @param  string $string
139
     * @return string
140
     */
141 15
    public static function withLeadingSlash(string $string) : string
142
    {
143 15
        return (self::hasLeadingSlash($string) ? '' : '/') . $string;
144
    }
145
146
    /**
147
     * Removes the leading slash from a string/path
148
     *
149
     * @param  string $string
150
     * @return string
151
     */
152 30
    public static function withoutLeadingSlash(string $string) : string
153
    {
154 30
        return ltrim($string, '/');
155
    }
156
157
    /**
158
     * Removes trailing and leading sl
159
     *
160
     * @param string $string
161
     * @return string
162
     */
163 1
    public static function withoutLeadingOrTrailingSlash(string $string) : string
164
    {
165 1
        return trim($string, '/');
166
    }
167
168
    /**
169
     * Is given path absolute
170
     *
171
     * @param  string $path
172
     * @return bool
173
     */
174 85
    public static function isAbsolutePath(string $path) : bool
175
    {
176
        // path already absolute?
177 85
        if (substr($path, 0, 1) === '/') {
178 42
            return true;
179
        }
180
181
        // Matches the following on Windows:
182
        //  - \\NetworkComputer\Path
183
        //  - \\.\D:
184
        //  - \\.\c:
185
        //  - C:\Windows
186
        //  - C:\windows
187
        //  - C:/windows
188
        //  - c:/windows
189 44
        if (defined('PHP_WINDOWS_VERSION_BUILD') && self::isAbsoluteWindowsPath($path)) {
190
            return true;
191
        }
192
193
        // Stream
194 44
        if (strpos($path, '://') !== false) {
195 1
            return true;
196
        }
197
198 43
        return false;
199
    }
200
201
    /**
202
     * Is given path an absolute windows path
203
     *
204
     * @param  string $path
205
     * @return bool
206
     */
207 3
    public static function isAbsoluteWindowsPath(string $path) : bool
208
    {
209 3
        return ($path[0] === '\\' || (strlen($path) >= 3 && preg_match('#^[A-Z]\:[/\\\]#i', substr($path, 0, 3))));
210
    }
211
212
    /**
213
     * Converts a path to an absolute one if necessary relative to a given base path
214
     *
215
     * @param  string  $path
216
     * @param  string  $base
217
     * @param  boolean $useIncludePath
218
     * @return string
219
     */
220 78
    public static function toAbsolutePath(string $path, string $base, bool $useIncludePath = false) : string
221
    {
222 78
        if (self::isAbsolutePath($path)) {
223 38
            return $path;
224
        }
225
226 41
        $file = $base . DIRECTORY_SEPARATOR . $path;
227
228 41
        if ($useIncludePath && !file_exists($file)) {
229 1
            $includePathFile = stream_resolve_include_path($path);
230 1
            if ($includePathFile) {
231 1
                $file = $includePathFile;
232
            }
233
        }
234 41
        return $file;
235
    }
236
237
    /**
238
     * Return list of directories in a given path without absolute root element
239
     *
240
     * @param  string $path
241
     * @return array
242
     */
243 87
    public static function getDirectoryListFromPath(string $path) : array
244
    {
245 87
        $path = trim($path, '/');
246 87
        $dirs = explode('/', $path);
247 87
        return array_filter($dirs);
248
    }
249
250
    /**
251
     * Return list of directories in a given path with absolute root element
252
     *
253
     * @param  string $path
254
     * @return array
255
     */
256 87
    public static function getDirectoryListFromAbsolutePath(string $path) : array
257
    {
258 87
        $dirs = static::getDirectoryListFromPath($path);
259 87
        if (self::hasLeadingSlash($path)) {
260 76
            array_unshift($dirs, '/');
261
        }
262 87
        return $dirs;
263
    }
264
265
    /**
266
     * Returns directory depth of a given path
267
     *
268
     * @param  string $path
269
     * @return int
270
     */
271 12
    public static function getPathDepth(string $path) : int
272
    {
273 12
        return count(self::getDirectoryListFromAbsolutePath($path));
274
    }
275
}
276