Passed
Push — master ( d467ff...321125 )
by Petr
08:04
created

ProcessDir::createDir()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.2559

Importance

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