Completed
Push — master ( eab519...be8cc6 )
by Sebastian
05:27
created

Path   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 260
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 98.44%

Importance

Changes 0
Metric Value
wmc 33
lcom 1
cbo 0
dl 0
loc 260
ccs 63
cts 64
cp 0.9844
rs 9.76
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A replaceDatePlaceholders() 0 11 2
A isContainingPlaceholder() 0 4 1
A replaceTargetPlaceholders() 0 7 1
A datePlaceholdersToRegex() 0 21 1
A hasTrailingSlash() 0 4 1
A withTrailingSlash() 0 4 2
A withoutTrailingSlash() 0 4 3
A hasLeadingSlash() 0 4 1
A withLeadingSlash() 0 4 2
A withoutLeadingSlash() 0 4 1
A withoutLeadingOrTrailingSlash() 0 4 1
A isAbsolutePath() 0 26 5
A isAbsoluteWindowsPath() 0 4 3
A toAbsolutePath() 0 16 5
A getDirectoryListFromPath() 0 6 1
A getDirectoryListFromAbsolutePath() 0 8 2
A getPathDepth() 0 4 1
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       http://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  integer|null $time
23
     * @return string
24
     */
25 89
    public static function replaceDatePlaceholders(string $string, $time = null) : string
26
    {
27 89
        $time = $time === null ? time() : $time;
28 89
        return preg_replace_callback(
29 89
            '#%([a-zA-Z])#',
30 89
            function($match) use ($time) {
31 54
                return date($match[1], $time);
32 89
            },
33 89
            $string
34
        );
35
    }
36
37
    /**
38
     * Does a given string contain a date placeholder.
39
     *
40
     * @param  string $string
41
     * @return bool
42
     */
43 78
    public static function isContainingPlaceholder(string $string) : bool
44
    {
45 78
        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 26
    public static function datePlaceholdersToRegex(string $stringWithDatePlaceholders) : string
70
    {
71
        $dateRegex = [
72 26
            '%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 26
        $regex = preg_quote($stringWithDatePlaceholders, '#');
87 26
        $regex = str_replace(array_keys($dateRegex), array_values($dateRegex), $regex);
88 26
        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 92
    public static function hasTrailingSlash(string $string) : bool
98
    {
99 92
        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 23
    public static function withTrailingSlash(string $string) : string
109
    {
110 23
        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 89
    public static function withoutTrailingSlash(string $string) : string
120
    {
121 89
        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 81
    public static function hasLeadingSlash(string $string) : bool
131
    {
132 81
        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 9
    public static function withLeadingSlash(string $string) : string
142
    {
143 9
        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 19
    public static function withoutLeadingSlash(string $string) : string
153
    {
154 19
        return ltrim($string, '/');
155
    }
156
157
    /**
158
     * Removes trailing and leading sl
159
     * @param string $string
160
     * @return string
161
     */
162 1
    public static function withoutLeadingOrTrailingSlash(string $string) : string
163
    {
164 1
        return trim($string, '/');
165
    }
166
167
    /**
168
     * Is given path absolute.
169
     *
170
     * @param  string $path
171
     * @return bool
172
     */
173 79
    public static function isAbsolutePath(string $path) : bool
174
    {
175
        // path already absolute?
176 79
        if (substr($path, 0, 1) === '/') {
177 41
            return true;
178
        }
179
180
        // Matches the following on Windows:
181
        //  - \\NetworkComputer\Path
182
        //  - \\.\D:
183
        //  - \\.\c:
184
        //  - C:\Windows
185
        //  - C:\windows
186
        //  - C:/windows
187
        //  - c:/windows
188 39
        if (defined('PHP_WINDOWS_VERSION_BUILD') && self::isAbsoluteWindowsPath($path)) {
189
            return true;
190
        }
191
192
        // Stream
193 39
        if (strpos($path, '://') !== false) {
194 1
            return true;
195
        }
196
197 38
        return false;
198
    }
199
200
    /**
201
     * Is given path an absolute windows path.
202
     *
203
     * @param  string $path
204
     * @return bool
205
     */
206 3
    public static function isAbsoluteWindowsPath(string $path) : bool
207
    {
208 3
        return ($path[0] === '\\' || (strlen($path) >= 3 && preg_match('#^[A-Z]\:[/\\\]#i', substr($path, 0, 3))));
209
    }
210
211
    /**
212
     * Converts a path to an absolute one if necessary relative to a given base path.
213
     *
214
     * @param  string  $path
215
     * @param  string  $base
216
     * @param  boolean $useIncludePath
217
     * @return string
218
     */
219 72
    public static function toAbsolutePath(string $path, string $base, bool $useIncludePath = false) : string
220
    {
221 72
        if (self::isAbsolutePath($path)) {
222 37
            return $path;
223
        }
224
225 36
        $file = $base . DIRECTORY_SEPARATOR . $path;
226
227 36
        if ($useIncludePath && !file_exists($file)) {
228 1
            $includePathFile = stream_resolve_include_path($path);
229 1
            if ($includePathFile) {
230 1
                $file = $includePathFile;
231
            }
232
        }
233 36
        return $file;
234
    }
235
236
    /**
237
     * Return list of directories in a given path without absolute root element
238
     *
239
     * @param  string $path
240
     * @return array
241
     */
242 77
    public static function getDirectoryListFromPath(string $path) : array
243
    {
244 77
        $path = trim($path, '/');
245 77
        $dirs = explode('/', $path);
246 77
        return array_filter($dirs);
247
    }
248
249
    /**
250
     * Return list of directories in a given path with absolute root element.
251
     *
252
     * @param  string $path
253
     * @return array
254
     */
255 77
    public static function getDirectoryListFromAbsolutePath(string $path) : array
256
    {
257 77
        $dirs = static::getDirectoryListFromPath($path);
258 77
        if (self::hasLeadingSlash($path)) {
259 68
            array_unshift($dirs, '/');
260
        }
261 77
        return $dirs;
262
    }
263
264
    /**
265
     * Returns directory depth of a given path.
266
     *
267
     * @param  string $path
268
     * @return int
269
     */
270 12
    public static function getPathDepth(string $path) : int
271
    {
272 12
        return count(self::getDirectoryListFromAbsolutePath($path));
273
    }
274
}
275