Passed
Push — test ( 0895d9...6e4feb )
by Tom
02:26
created

LibFs::symlink()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
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 7
    public static function mkDir($path, $mode = 0777)
106
    {
107 7
        if (!is_dir($path)) {
108
            /** @noinspection NestedPositiveIfStatementsInspection */
109 6
            if (!mkdir($path, $mode, true) && !is_dir($path)) {
110
                // @codeCoverageIgnoreStart
111
                throw new \RuntimeException(
112
                    sprintf('Directory "%s" was not created', $path)
113
                );
114
                // @codeCoverageIgnoreEnd
115
            }
116
        }
117
118 7
        return $path;
119
    }
120
121
    /**
122
     * rename a file
123
     *
124
     * @param string $old
125
     * @param string $new
126
     *
127
     * @return string new file-name
128
     */
129 1
    public static function rename($old, $new)
130
    {
131 1
        if (!@rename($old, $new)) {
132 1
            throw new \RuntimeException(sprintf('Failed to rename "%s" to "%s"', $old, $new));
133
        }
134
135 1
        return $new;
136
    }
137
138
    /**
139
     * @param string $file
140
     *
141
     * @return string
142
     */
143 5
    public static function rm($file)
144
    {
145 5
        if (self::isReadableFile($file)) {
146 5
            unlink($file);
147
        }
148
149 5
        return $file;
150
    }
151
152
    /**
153
     * @param string $dir
154
     *
155
     * @throws UnexpectedValueException
156
     *
157
     * @return void
158
     */
159 3
    public static function rmDir($dir)
160
    {
161 3
        $result = @lstat($dir);
162 3
        if (false === $result) {
163 1
            return;
164
        }
165
166 3
        $dirs = array();
167 3
        $dirs[] = $dir;
168 3
        for ($i = 0; isset($dirs[$i]); $i++) {
169 3
            $current = $dirs[$i];
170 3
            $result = @scandir($current);
171 3
            if (false === $result) {
172 1
                throw new UnexpectedValueException(sprintf('Failed to open directory: %s', $current));
173
            }
174 2
            $files = array_diff($result, array('.', '..'));
175 2
            foreach ($files as $file) {
176 1
                $path = "${current}/${file}";
177 1
                if (is_dir($path)) {
178 1
                    $dirs[] = $path;
179 1
                } elseif (is_file($path)) {
180 1
                    self::rm($path);
181
                }
182
            }
183
        }
184
185 2
        while (null !== ($pop = array_pop($dirs))) {
186
            /* @scrutinizer ignore-unhandled */
187 2
            @rmdir($pop);
188
        }
189 2
    }
190
191
    /**
192
     * create symbolic link, recreate if it exists
193
     *
194
     * @param string $target
195
     * @param string $link
196
     *
197
     * @return void
198
     */
199
    public static function symlink($target, $link)
200
    {
201 1
        self::unlink($link);
202 1
        symlink($target, $link);
203 1
    }
204
205
    /**
206
     * @param string $link
207
     *
208
     * @return void
209
     */
210
    public static function unlink($link)
211
    {
212 1
        if (is_link($link)) {
213 1
            unlink($link);
214
        }
215 1
    }
216
}
217