LibFs::rename()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
3
/* this file is part of pipelines */
4
5
namespace Ktomk\Pipelines;
6
7
use UnexpectedValueException;
8
9
/**
10
 * Class LibFs - Low level file-system utility functions
11
 *
12
 * @covers \Ktomk\Pipelines\LibFs
13
 */
14
class LibFs
15
{
16
    /**
17
     * @param string $path
18
     * @param string $mode [optional]
19
     *
20
     * @return bool
21
     */
22 2
    public static function canFopen($path, $mode = null)
23
    {
24 2
        if (null === $mode) {
25 1
            $mode = 'rb';
26
        }
27
28 2
        $handle = @fopen($path, $mode);
29 2
        if (false === $handle) {
30 1
            return false;
31
        }
32
33
        /** @scrutinizer ignore-unhandled */
34 1
        @fclose($handle);
35
36 1
        return true;
37
    }
38
39
    /**
40
     * locate (readable) file by basename upward all parent directories
41
     *
42
     * @param string $basename
43
     * @param string $directory [optional] directory to operate from, defaults
44
     *               to "." (relative path of present working directory)
45
     *
46
     * @return null|string
47
     */
48 4
    public static function fileLookUp($basename, $directory = null)
49
    {
50 4
        if ('' === $directory || null === $directory) {
51 1
            $directory = '.';
52
        }
53
54
        for (
55 4
            $dirName = $directory, $old = null;
56 4
            $old !== $dirName;
57 2
            $old = $dirName, $dirName = dirname($dirName)
58
        ) {
59 4
            $test = $dirName . '/' . $basename;
60 4
            if (self::isReadableFile($test)) {
61 3
                return $test;
62
            }
63
        }
64
65 1
        return null;
66
    }
67
68
    /**
69
     * see 2.2 Standards permit the exclusion of bad filenames / POSIX.1-2008
70
     *
71
     * @link https://dwheeler.com/essays/fixing-unix-linux-filenames.html
72
     *
73
     * @param string $filename
74
     *
75
     * @return bool
76
     */
77 11
    public static function isPortableFilename($filename)
78
    {
79
        # A-Z, a-z, 0-9, <period>, <underscore>, and <hyphen>
80 11
        return 1 === Preg::match('(^(?!-)[A-Za-z0-9._-]+$)', $filename);
81
    }
82
83
    /**
84
     * @param string $path
85
     *
86
     * @return bool
87
     */
88 11
    public static function isReadableFile($path)
89
    {
90 11
        if (!is_file($path)) {
91 4
            return false;
92
        }
93
94 9
        return is_readable($path) ?: self::canFopen($path, 'rb');
95
    }
96
97
    /**
98
     * create directory if not yet exists
99
     *
100
     * @param string $path
101
     * @param int $mode [optional]
102
     *
103
     * @return string
104
     */
105 8
    public static function mkDir($path, $mode = 0777)
106
    {
107 8
        if (!is_dir($path) && !mkdir($path, $mode, true) && !is_dir($path)) {
108
            // @codeCoverageIgnoreStart
109
            throw new \RuntimeException(
110
                sprintf('Directory "%s" was not created', $path)
111
            );
112
            // @codeCoverageIgnoreEnd
113
        }
114
115 8
        return $path;
116
    }
117
118
    /**
119
     * create symbolic link to a directory with parents
120
     *
121
     * do not create if link pathname is already a
122
     * directory or targeting one (even if not the target).
123
     *
124
     * create parent directory/ies of link if necessary.
125
     *
126
     * @param string $target pathname of target directory
127
     * @param string $link pathname of link
128
     *
129
     * @return void
130
     */
131 1
    public static function symlinkWithParents($target, $link)
132
    {
133 1
        self::mkDir(dirname($link));
134 1
        if (!is_dir($link)) {
135 1
            self::symlink($target, $link);
136 1
            if (!is_link($link)) {
137
                // @codeCoverageIgnoreStart
138
                throw new \RuntimeException(
139
                    sprintf('Link "%s" was not created', $link)
140
                );
141
                // @codeCoverageIgnoreEnd
142
            }
143
        }
144
    }
145
146
    /**
147
     * rename a file
148
     *
149
     * @param string $old
150
     * @param string $new
151
     *
152
     * @return string new file-name
153
     */
154 1
    public static function rename($old, $new)
155
    {
156 1
        if (!@rename($old, $new)) {
157 1
            throw new \RuntimeException(sprintf('Failed to rename "%s" to "%s"', $old, $new));
158
        }
159
160 1
        return $new;
161
    }
162
163
    /**
164
     * @param string $file
165
     *
166
     * @return string
167
     */
168 5
    public static function rm($file)
169
    {
170 5
        if (self::isReadableFile($file)) {
171 5
            unlink($file);
172
        }
173
174 5
        return $file;
175
    }
176
177
    /**
178
     * @param string $dir
179
     *
180
     * @throws UnexpectedValueException
181
     *
182
     * @return void
183
     */
184 4
    public static function rmDir($dir)
185
    {
186 4
        $result = @lstat($dir);
187 4
        if (false === $result) {
188 1
            return;
189
        }
190
191 4
        $stack = array();
192 4
        $stack[] = $dir;
193
194 4
        for ($i = 0; isset($stack[$i]); $i++) {
195 4
            $current = $stack[$i];
196 4
            $result = @scandir($current);
197 4
            if (false === $result) {
198 1
                throw new UnexpectedValueException(sprintf('Failed to open directory: %s', $current));
199
            }
200 3
            foreach (array_diff($result, array('.', '..')) as $file) {
201 2
                $path = "{$current}/{$file}";
202 2
                if (is_link($path)) {
203 1
                    self::unlink($path);
204 2
                } elseif (is_dir($path)) {
205 2
                    $stack[] = $path;
206 1
                } elseif (is_file($path)) {
207 1
                    self::rm($path);
208
                }
209
            }
210
        }
211
212 3
        for ($i = count($stack); isset($stack[--$i]);) {
213
            /* @scrutinizer ignore-unhandled */
214 3
            @rmdir($stack[$i]);
215
        }
216
    }
217
218
    /**
219
     * create symbolic link, recreate if it exists
220
     *
221
     * @param string $target
222
     * @param string $link
223
     *
224
     * @return void
225
     */
226 2
    public static function symlink($target, $link)
227
    {
228 2
        self::unlink($link);
229 2
        symlink($target, $link);
230
    }
231
232
    /**
233
     * @param string $link
234
     *
235
     * @return void
236
     */
237 2
    public static function unlink($link)
238
    {
239 2
        if (is_link($link)) {
240 2
            unlink($link);
241
        }
242
    }
243
}
244