Basic::readDir()   B
last analyzed

Complexity

Conditions 10
Paths 58

Size

Total Lines 48
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 37
CRAP Score 10

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 32
nc 58
nop 3
dl 0
loc 48
ccs 37
cts 37
cp 1
crap 10
rs 7.6666
c 1
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace kalanis\kw_files\Processing\Storage\Dirs;
4
5
6
use kalanis\kw_files\FilesException;
7
use kalanis\kw_files\Interfaces\IFLTranslations;
8
use kalanis\kw_files\Interfaces\IProcessNodes;
9
use kalanis\kw_files\Interfaces\ITypes;
10
use kalanis\kw_files\Node;
11
use kalanis\kw_paths\ArrayPath;
12
use kalanis\kw_storage\Interfaces\IStorage;
13
use kalanis\kw_storage\StorageException;
14
15
16
/**
17
 * Class Basic
18
 * @package kalanis\kw_files\Processing\Storage\Dirs
19
 * Process dirs via lookup
20
 */
21
class Basic extends ADirs
22
{
23
    protected IStorage $storage;
24
25 33
    public function __construct(IStorage $storage, ?IFLTranslations $lang = null)
26
    {
27 33
        $this->storage = $storage;
28 33
        $this->setFlLang($lang);
29
    }
30
31 10
    public function createDir(array $entry, bool $deep = false): bool
32
    {
33 10
        $full = array_merge([''], $entry);
34 10
        $entryPath = $this->compactName($full, $this->getStorageSeparator());
35
        try {
36 10
            if ($this->storage->exists($entryPath)) {
37 2
                return false;
38
            }
39 9
            $total = count($full);
40 9
            for ($i = 1; $i < $total; $i++) {
41 9
                $subNodeName = $this->compactName(array_slice($full, 0, $i), $this->getStorageSeparator());
42 9
                $exists = $this->storage->exists($subNodeName);
43 9
                if ($exists) {
44 5
                    if (!$this->isNode($subNodeName)) {
45
                        // current node is file/data
46 5
                        return false;
47
                    }
48
                } else {
49 8
                    if ($deep) {
50
                        // create deep tree
51 8
                        $this->storage->write($subNodeName, IProcessNodes::STORAGE_NODE_KEY);
52
                    } else {
53
                        // cannot create in shallow tree
54 1
                        return false;
55
                    }
56
                }
57
            }
58 9
            return $this->storage->write($entryPath, IProcessNodes::STORAGE_NODE_KEY);
59 1
        } catch (StorageException $ex) {
60 1
            throw new FilesException($this->getFlLang()->flCannotCreateDir($entryPath), $ex->getCode(), $ex);
61
        }
62
    }
63
64 7
    public function readDir(array $entry, bool $loadRecursive = false, bool $wantSize = false): array
65
    {
66 7
        $entryPath = $this->removeSeparator($this->compactName(array_filter($entry), $this->getStorageSeparator()));
67 7
        $entryPath = empty($entryPath) ? '' : $this->getStorageSeparator() . $entryPath;
68
        try {
69 7
            if (!$this->isNode($entryPath)) {
70 1
                throw new FilesException($this->getFlLang()->flCannotReadDir($entryPath));
71
            }
72
            /** @var array<string, Node> */
73 5
            $files = [];
74 5
            $sepLen = mb_strlen($this->getStorageSeparator());
75 5
            foreach ($this->storage->lookup($entryPath) as $item) {
76 5
                $usePath = mb_substr($item, $sepLen);
77 5
                if (!$loadRecursive && (false !== mb_strpos($usePath, $this->getStorageSeparator()))) {
78
                    // pass sub when not need
79 3
                    continue;
80
                }
81
82 5
                $sub = new Node();
83 5
                $currentPath = $this->removeSeparator($this->compactName(array_merge(
84 5
                    $entry,
85 5
                    $this->expandName($usePath, $this->getStorageSeparator())
86 5
                ), $this->getStorageSeparator()));
87 5
                if (empty($item)) {
88 5
                    $sub->setData(
89 5
                        [],
90 5
                        0,
91 5
                        ITypes::TYPE_DIR
92 5
                    );
93 5
                } elseif ($this->isNode($this->getStorageSeparator() . $currentPath)) {
94 4
                    $sub->setData(
95 4
                        $this->expandName($usePath),
96 4
                        0,
97 4
                        ITypes::TYPE_DIR
98 4
                    );
99
                } else {
100
                    // normal node - file
101 4
                    $sub->setData(
102 4
                        $this->expandName($usePath),
103 4
                        $wantSize ? $this->getSize($this->getStorageSeparator() . $currentPath) : 0,
104 4
                        ITypes::TYPE_FILE
105 4
                    );
106
                }
107 5
                $files[] = $sub;
108
            }
109 5
            return $files;
110 2
        } catch (StorageException $ex) {
111 1
            throw new FilesException($this->getFlLang()->flCannotReadDir($entryPath), $ex->getCode(), $ex);
112
        }
113
    }
114
115 7
    protected function removeSeparator(string $path): string
116
    {
117 7
        $sepLen = mb_strlen($this->getStorageSeparator());
118 7
        $first = mb_substr($path, 0, $sepLen);
119 7
        return $this->getStorageSeparator() == $first ? mb_substr($path, $sepLen) : $path;
120
    }
121
122 6
    public function copyDir(array $source, array $dest): bool
123
    {
124 6
        $src = $this->getStorageSeparator() . $this->compactName($source, $this->getStorageSeparator());
125 6
        $dst = $this->getStorageSeparator() . $this->compactName($dest, $this->getStorageSeparator());
126
        try {
127 6
            if ($this->isSubPart($dest, $source)) {
128 1
                return false;
129
            }
130
131 5
            if (!$this->isNode($src)) {
132 1
                return false;
133
            }
134 3
            if ($this->storage->exists($dst)) {
135 1
                return false;
136
            }
137 2
            $dstArr = new ArrayPath();
138 2
            $dstArr->setArray($dest);
139 2
            $tgt = $this->compactName($dstArr->getArrayDirectory(), $this->getStorageSeparator());
140 2
            if (!empty($tgt) && !$this->storage->exists($this->getStorageSeparator() . $tgt)) {
141 1
                return false;
142
            }
143
144 1
            $paths = $this->storage->lookup($src);
145 1
            $this->storage->write($dst, IProcessNodes::STORAGE_NODE_KEY);
146 1
            foreach ($paths as $path) {
147 1
                if (empty($path)) {
148
                    // skip current
149 1
                    continue;
150
                }
151 1
                $this->storage->write($dst . $path, $this->storage->read($src . $path));
152
            }
153 1
            return true;
154 1
        } catch (StorageException $ex) {
155 1
            throw new FilesException($this->getFlLang()->flCannotCopyDir($src, $dst), $ex->getCode(), $ex);
156
        }
157
    }
158
159 6
    public function moveDir(array $source, array $dest): bool
160
    {
161 6
        $src = $this->getStorageSeparator() . $this->compactName($source, $this->getStorageSeparator());
162 6
        $dst = $this->getStorageSeparator() . $this->compactName($dest, $this->getStorageSeparator());
163
        try {
164 6
            if ($this->isSubPart($dest, $source)) {
165 1
                return false;
166
            }
167
168 5
            if (!$this->isNode($src)) {
169 1
                return false;
170
            }
171 3
            if ($this->storage->exists($dst)) {
172 1
                return false;
173
            }
174 2
            $dstArr = new ArrayPath();
175 2
            $dstArr->setArray($dest);
176 2
            $tgt = $this->compactName($dstArr->getArrayDirectory(), $this->getStorageSeparator());
177 2
            if (!empty($tgt) && !$this->storage->exists($this->getStorageSeparator() . $tgt)) {
178 1
                return false;
179
            }
180
181 1
            $paths = $this->storage->lookup($src);
182 1
            $this->storage->write($dst, IProcessNodes::STORAGE_NODE_KEY);
183 1
            foreach ($paths as $path) {
184 1
                if (empty($path)) {
185
                    // skip current
186 1
                    continue;
187
                }
188 1
                $this->storage->write($dst . $path, $this->storage->read($src . $path));
189 1
                $this->storage->remove($src . $path);
190
            }
191 1
            return $this->storage->remove($src);
192 1
        } catch (StorageException $ex) {
193 1
            throw new FilesException($this->getFlLang()->flCannotMoveDir($src, $dst), $ex->getCode(), $ex);
194
        }
195
    }
196
197 8
    public function deleteDir(array $entry, bool $deep = false): bool
198
    {
199 8
        $path = $this->getStorageSeparator() . $this->compactName($entry, $this->getStorageSeparator());
200
        try {
201 8
            if (!$this->storage->exists($path)) {
202 1
                return false;
203
            }
204 7
            if (!$this->isNode($path)) {
205 1
                return false;
206
            }
207 6
            $paths = $this->storage->lookup($path);
208 6
            foreach ($paths as $item) {
209 6
                if ('' != $item) {
210
                    // found something
211 4
                    if (!$deep) {
212 2
                        return false;
213
                    }
214 3
                    $this->storage->remove($path . $item);
215
                }
216
            }
217 5
            return $this->storage->remove($path);
218 1
        } catch (StorageException $ex) {
219 1
            throw new FilesException($this->getFlLang()->flCannotRemoveDir($path), $ex->getCode(), $ex);
220
        }
221
    }
222
223
    /**
224
     * @param string $entry
225
     * @throws StorageException
226
     * @return bool
227
     */
228 23
    protected function isNode(string $entry): bool
229
    {
230 23
        return $this->storage->exists($entry) ? (IProcessNodes::STORAGE_NODE_KEY === $this->storage->read($entry)) : false;
231
    }
232
233
    /**
234
     * @param string $file
235
     * @throws StorageException
236
     * @return int
237
     */
238 1
    protected function getSize(string $file): int
239
    {
240 1
        return strlen($this->storage->read($file));
241
    }
242
243
    /**
244
     * @return string
245
     * @codeCoverageIgnore only when path fails
246
     */
247
    protected function noDirectoryDelimiterSet(): string
248
    {
249
        return $this->getFlLang()->flNoDirectoryDelimiterSet();
250
    }
251
}
252