Passed
Push — master ( 95ec1e...702df7 )
by Petr
02:32
created

ProcessDir::noDirectoryDelimiterSet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace kalanis\kw_files\Processing\Volume;
4
5
6
use FilesystemIterator;
7
use kalanis\kw_files\FilesException;
8
use kalanis\kw_files\Interfaces\IFLTranslations;
9
use kalanis\kw_files\Interfaces\IProcessDirs;
10
use kalanis\kw_files\Interfaces\ITypes;
11
use kalanis\kw_files\Node;
12
use kalanis\kw_files\Processing\TPath;
13
use kalanis\kw_files\Translations;
14
use kalanis\kw_paths\Extras\TPathTransform;
15
use kalanis\kw_paths\PathsException;
16
use kalanis\kw_storage\Extras\TRemoveCycle;
17
use kalanis\kw_storage\Extras\TVolumeCopy;
18
use RecursiveDirectoryIterator;
19
use RecursiveIteratorIterator;
20
use SplFileInfo;
21
use Throwable;
22
23
24
/**
25
 * Class ProcessDir
26
 * @package kalanis\kw_files\Processing\Volume
27
 * Process dirs in basic ways
28
 */
29
class ProcessDir implements IProcessDirs
30
{
31
    use TPath;
32
    use TPathTransform;
33
    use TRemoveCycle;
34
    use TVolumeCopy;
35
36
    /** @var IFLTranslations */
37
    protected $lang = null;
38
    /** @var int */
39
    protected $sliceStartParts = 0;
40
    /** @var int */
41
    protected $sliceCustomParts = 0;
42
43
    /**
44
     * @param string $path
45
     * @param IFLTranslations|null $lang
46
     * @throws PathsException
47
     */
48 10
    public function __construct(string $path = '', ?IFLTranslations $lang = null)
49
    {
50 10
        $this->lang = $lang ?? new Translations();
51 10
        $this->setPath($path);
52 10
    }
53
54
    /**
55
     * @param string $path
56
     * @throws PathsException
57
     */
58 10
    public function setPath(string $path = ''): void
59
    {
60 10
        $used = realpath($path);
61 10
        if (false !== $used) {
62 9
            $this->path = $used;
63 9
            $this->sliceStartParts = count($this->expandName($used));
64
        }
65 10
    }
66
67 1
    public function createDir(array $entry, bool $deep = false): bool
68
    {
69 1
        $path = $this->fullPath($entry);
70
        try {
71 1
            return @mkdir($path, 0777, $deep);
72
            // @codeCoverageIgnoreStart
73
        } catch (Throwable $ex) {
74
            throw new FilesException($this->lang->flCannotCreateDir($path), $ex->getCode(), $ex);
75
        }
76
        // @codeCoverageIgnoreEnd
77
    }
78
79 4
    public function readDir(array $entry, bool $loadRecursive = false, bool $wantSize = false): array
80
    {
81 4
        $path = $this->fullPath($entry);
82 4
        $this->sliceCustomParts = count($entry);
83
        try {
84 4
            $iter = $loadRecursive
85 1
                ? new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path))
86 4
                : new FilesystemIterator($path, 0)
87
            ;
88 3
            return array_values(
89 3
                array_map(
90 3
                    [$this, 'intoNode'],
91 3
                    array_filter(
92 3
                        array_filter(
93 3
                            array_filter(
94 3
                                ($loadRecursive ? [] : [$this->addRootNode($path)]) + iterator_to_array($iter)
95
                            ),
96 3
                            [$this, 'filterFilesAndDirsOnly']
97
                        ),
98 3
                        [$this, 'filterDots']
99
                    )
100
                )
101
            );
102
            // @codeCoverageIgnoreStart
103 1
        } catch (Throwable $ex) {
104 1
            throw new FilesException($this->lang->flCannotReadDir($path), $ex->getCode(), $ex);
105
        }
106
        // @codeCoverageIgnoreEnd
107
    }
108
109 2
    protected function addRootNode(string $path): SplFileInfo
110
    {
111 2
        return new SplFileInfo($path);
112
    }
113
114 3
    public function filterFilesAndDirsOnly(SplFileInfo $file): bool
115
    {
116 3
        return in_array($file->getType(), [ITypes::TYPE_DIR, ITypes::TYPE_FILE]);
117
    }
118
119 3
    public function filterDots(SplFileInfo $file): bool
120
    {
121 3
        return '..' !== $file->getFilename();
122
    }
123
124
    /**
125
     * @param SplFileInfo $file
126
     * @throws PathsException
127
     * @return Node
128
     */
129 3
    public function intoNode(SplFileInfo $file): Node
130
    {
131 3
        $node = new Node();
132 3
        return $node->setData(
133 3
            array_slice($this->expandName($file->getRealPath()), $this->sliceStartParts + $this->sliceCustomParts),
134 3
            $file->getSize(),
135 3
            $file->getType()
136
        );
137
    }
138
139 1
    public function copyDir(array $source, array $dest): bool
140
    {
141 1
        $src = $this->fullPath($source);
142 1
        $dst = $this->fullPath($dest);
143
        try {
144 1
            return $this->xcopy($src, $dst);
145
            // @codeCoverageIgnoreStart
146
        } catch (Throwable $ex) {
147
            throw new FilesException($this->lang->flCannotCopyDir($src, $dst), $ex->getCode(), $ex);
148
        }
149
        // @codeCoverageIgnoreEnd
150
    }
151
152 1
    public function moveDir(array $source, array $dest): bool
153
    {
154 1
        $src = $this->fullPath($source);
155 1
        $dst = $this->fullPath($dest);
156
        try {
157
            // original call with doomed sub-calls chmod and chown - see
158
            // @link https://www.php.net/manual/en/function.rename.php#117590
159
            // return @rename($src, $dst);
160
161
            // to avoid that internal bug...
162 1
            $v1 = $this->copyDir($source, $dest);
163 1
            $v2 = $this->deleteDir($source, true);
164 1
            return $v1 && $v2;
165
            // @codeCoverageIgnoreStart
166
        } catch (Throwable $ex) {
167
            throw new FilesException($this->lang->flCannotMoveDir($src, $dst), $ex->getCode(), $ex);
168
        }
169
        // @codeCoverageIgnoreEnd
170
    }
171
172 1
    public function deleteDir(array $entry, bool $deep = false): bool
173
    {
174 1
        $path = $this->fullPath($entry);
175
        try {
176 1
            if ($deep) {
177 1
                return $this->removeCycle($path);
178
            } else {
179 1
                return @rmdir($path);
180
            }
181
            // @codeCoverageIgnoreStart
182
        } catch (Throwable $ex) {
183
            throw new FilesException($this->lang->flCannotRemoveDir($path), $ex->getCode(), $ex);
184
        }
185
        // @codeCoverageIgnoreEnd
186
    }
187
188
    /**
189
     * @param array<string> $path
190
     * @throws PathsException
191
     * @return string
192
     */
193 6
    protected function fullPath(array $path): string
194
    {
195 6
        return $this->getPath() . DIRECTORY_SEPARATOR . $this->compactName($path);
196
    }
197
198
    /**
199
     * @return string
200
     * @codeCoverageIgnore only when path fails
201
     */
202
    protected function noDirectoryDelimiterSet(): string
203
    {
204
        return $this->lang->flNoDirectoryDelimiterSet();
205
    }
206
}
207