ProcessDir::deleteDir()   A
last analyzed

Complexity

Conditions 5
Paths 9

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 12
c 1
b 0
f 0
nc 9
nop 2
dl 0
loc 16
ccs 11
cts 11
cp 1
crap 5
rs 9.5555
1
<?php
2
3
namespace kalanis\kw_files_mapper\Processing\MapperNoRoot;
4
5
6
use kalanis\kw_files\FilesException;
7
use kalanis\kw_files\Interfaces\IFLTranslations;
8
use kalanis\kw_files\Interfaces\IProcessDirs;
9
use kalanis\kw_files\Interfaces\IProcessNodes;
10
use kalanis\kw_files\Interfaces\ITypes;
11
use kalanis\kw_files\Node;
12
use kalanis\kw_files\Traits\TLang;
13
use kalanis\kw_files\Traits\TSubPart;
14
use kalanis\kw_files_mapper\Support\Process;
15
use kalanis\kw_files_mapper\Support\TDir;
16
use kalanis\kw_mapper\MapperException;
17
use kalanis\kw_mapper\Records\ARecord;
18
use kalanis\kw_mapper\Search\Search;
19
use kalanis\kw_paths\ArrayPath;
20
use kalanis\kw_paths\Stuff;
21
22
23
/**
24
 * Class ProcessDir
25
 * @package kalanis\kw_files_mapper\Processing\MapperNoRoot
26
 * Process dirs in basic ways
27
 */
28
class ProcessDir implements IProcessDirs
29
{
30
    use TDir;
31
    use TEntryLookup;
32
    use TLang;
33
    use TSubPart;
34
35
    protected ARecord $record;
36
37 25
    public function __construct(ARecord $record, ?Process\Translate $translate = null, ?IFLTranslations $lang = null)
38
    {
39 25
        $this->setFlLang($lang);
40 25
        $this->record = $record;
41 25
        $this->setTranslation($translate);
42 25
    }
43
44 5
    public function createDir(array $entry, bool $deep = false): bool
45
    {
46
        try {
47 5
            $parentNode = $this->getEntry([]);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $parentNode is correct as $this->getEntry(array()) targeting kalanis\kw_files_mapper\...\ProcessDir::getEntry() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
48
49 5
            $maxPos = count($entry) - 1;
50 5
            foreach (array_values($entry) as $pos => $levelKey) {
51
52 5
                $all = $this->getChildrenRecords(strval($levelKey), $parentNode);
53 4
                if (!empty($all)) {
54 1
                    if ($pos == $maxPos) {
55
                        // wanted one already exists
56 1
                        return false;
57
                    }
58 1
                    $parentNode = reset($all);
59 4
                } elseif ($pos == $maxPos) {
60
                    // create wanted one
61 4
                    $parentNode = $this->createRecord(strval($levelKey), $parentNode);
62 3
                } elseif ($deep) {
63
                    // create on lower level
64 3
                    $parentNode = $this->createRecord(strval($levelKey), $parentNode);
65
                } else {
66 1
                    return false;
67
                }
68
            }
69
70 4
            return $parentNode ? $this->isDir($parentNode) : false;
71 1
        } catch (MapperException $ex) {
72 1
            throw new FilesException($this->getFlLang()->flCannotCreateDir(Stuff::arrayToPath($entry)), $ex->getCode(), $ex);
73
        }
74
    }
75
76
    /**
77
     * @param string $currentName
78
     * @param ARecord|null $parentNode
79
     * @throws MapperException
80
     * @return ARecord[]
81
     */
82 5
    protected function getChildrenRecords(string $currentName, ?ARecord $parentNode): array
83
    {
84 5
        $search = new Search($this->getLookupRecord());
85 4
        $search->exact($this->getTranslation()->getCurrentKey(), $currentName);
86 4
        if ($parentNode) {
87 3
            $search->exact(
88 3
                $this->getTranslation()->getParentKey(),
89 3
                strval($parentNode->__get($this->getTranslation()->getPrimaryKey()))
90
            );
91
        } else {
92
            // no root node?
93 4
            $search->null($this->getTranslation()->getParentKey());
94
        }
95 4
        return $search->getResults();
96
    }
97
98
    /**
99
     * @param string $name
100
     * @param ARecord|null $parentNode
101
     * @throws MapperException
102
     * @return ARecord
103
     */
104 4
    protected function createRecord(string $name, ?ARecord $parentNode): ARecord
105
    {
106 4
        $record = $this->getLookupRecord();
107 4
        if (!is_null($parentNode)) {
108 3
            $record->__set(
109 3
                $this->getTranslation()->getParentKey(),
110 3
                strval($parentNode->__get($this->getTranslation()->getPrimaryKey()))
111
            );
112
        }
113 4
        $record->__set(
114 4
            $this->getTranslation()->getCurrentKey(),
115
            $name
116
        );
117 4
        $record->__set(
118 4
            $this->getTranslation()->getContentKey(),
119 4
            IProcessNodes::STORAGE_NODE_KEY
120
        );
121 4
        $record->save();
122 4
        $record->load();
123 4
        return $record;
124
    }
125
126 6
    public function readDir(array $entry, bool $loadRecursive = false, bool $wantSize = false): array
127
    {
128 6
        $entryPath = Stuff::arrayToPath($entry);
129
        try {
130 6
            $node = $this->getEntry($entry);
131
132 5
            if (!is_null($node) && !$this->isDir($node)) {
133 1
                throw new FilesException($this->getFlLang()->flCannotReadDir($entryPath));
134
            }
135
            /** @var array<string, Node> */
136 4
            $files = [];
137 4
            $startSub = new Node();
138 4
            $startSub->setData(
139 4
                [],
140 4
                0,
141 4
                ITypes::TYPE_DIR
142
            );
143 4
            $files[] = $startSub;
144
145 4
            return array_merge($files, $this->subNodes($node, $loadRecursive, $wantSize));
146 2
        } catch (MapperException $ex) {
147 1
            throw new FilesException($this->getFlLang()->flCannotReadDir($entryPath), $ex->getCode(), $ex);
148
        }
149
    }
150
151
    /**
152
     * @param ARecord|null $node
153
     * @param bool $loadRecursive
154
     * @param bool $wantSize
155
     * @param string[] $upper
156
     * @throws MapperException
157
     * @return Node[]
158
     */
159 4
    protected function subNodes(?ARecord $node, bool $loadRecursive = false, bool $wantSize = false, array $upper = []): array
160
    {
161 4
        $search = new Search($this->getLookupRecord());
162 4
        if ($node) {
163 3
            $search->exact(
164 3
                $this->getTranslation()->getParentKey(),
165 3
                strval($node->__get($this->getTranslation()->getPrimaryKey()))
166
            );
167
        } else {
168 2
            $search->null($this->getTranslation()->getParentKey());
169
        }
170
171
        /** @var Node[] $files */
172 4
        $files = [];
173 4
        foreach ($search->getResults() as $item) {
174 4
            $path = array_merge($upper, [strval($item->__get($this->getTranslation()->getCurrentKey()))]);
175 4
            if ($this->isDir($item)) {
176 3
                $sub = new Node();
177 3
                $files[] = $sub->setData(
178 3
                    $path,
179 3
                    0,
180 3
                    ITypes::TYPE_DIR
181
                );
182 3
                if ($loadRecursive) {
183 3
                    $files = array_merge($files, $this->subNodes($item, $loadRecursive, $wantSize, $path));
184
                }
185
            } else {
186
                // normal node - file
187 4
                $sub = new Node();
188 4
                $files[] = $sub->setData(
189 4
                    $path,
190 4
                    $wantSize ? $this->getSize($item) : 0,
191 4
                    ITypes::TYPE_FILE
192
                );
193
            }
194
        }
195 4
        return $files;
196
    }
197
198 6
    public function copyDir(array $source, array $dest): bool
199
    {
200
        try {
201 6
            if ($this->isSubPart($dest, $source)) {
202 1
                return false;
203
            }
204
205 5
            $ptDst = new ArrayPath();
206 5
            $ptDst->setArray($dest);
207
208 5
            $src = $this->getEntry($source);
209 4
            if (!$src) {
210 1
                return false;
211
            }
212
213 3
            $dst = $this->getEntry($ptDst->getArrayDirectory());
214
215 3
            $tgt = $this->getEntry([$ptDst->getFileName()], $dst);
216 3
            if ($tgt) {
0 ignored issues
show
introduced by
$tgt is of type kalanis\kw_mapper\Records\ARecord, thus it always evaluated to true.
Loading history...
217 2
                return false;
218
            }
219
220 1
            $new = $this->getLookupRecord();
221 1
            $new->__set($this->getTranslation()->getCurrentKey(), $ptDst->getFileName());
222 1
            if ($dst) {
223 1
                $new->__set($this->getTranslation()->getParentKey(), $dst->__get($this->getTranslation()->getPrimaryKey()));
224
            }
225 1
            $new->__set($this->getTranslation()->getContentKey(), IProcessNodes::STORAGE_NODE_KEY);
226 1
            $new->save();
227
228 1
            return $this->copyCycle($src, $new);
229
230 1
        } catch (MapperException $ex) {
231 1
            throw new FilesException($this->getFlLang()->flCannotCopyDir(
232 1
                Stuff::arrayToPath($source),
233 1
                Stuff::arrayToPath($dest)
234 1
            ), $ex->getCode(), $ex);
235
        }
236
    }
237
238 6
    public function moveDir(array $source, array $dest): bool
239
    {
240
        try {
241 6
            if ($this->isSubPart($dest, $source)) {
242 1
                return false;
243
            }
244
245 5
            $ptDst = new ArrayPath();
246 5
            $ptDst->setArray($dest);
247
248 5
            $src = $this->getEntry($source);
249 4
            if (!$src) {
250 1
                return false;
251
            }
252
253 3
            $dst = $this->getEntry($ptDst->getArrayDirectory());
254
255 3
            $tgt = $this->getEntry([$ptDst->getFileName()], $dst);
256 3
            if ($tgt) {
0 ignored issues
show
introduced by
$tgt is of type kalanis\kw_mapper\Records\ARecord, thus it always evaluated to true.
Loading history...
257 2
                return false;
258
            }
259
260 1
            $src->__set($this->getTranslation()->getCurrentKey(), $ptDst->getFileName());
261 1
            $src->__set($this->getTranslation()->getParentKey(), $dst ? $dst->__get($this->getTranslation()->getPrimaryKey()) : null);
262 1
            return $src->save();
263
264 1
        } catch (MapperException $ex) {
265 1
            throw new FilesException($this->getFlLang()->flCannotMoveDir(
266 1
                Stuff::arrayToPath($source),
267 1
                Stuff::arrayToPath($dest)
268 1
            ), $ex->getCode(), $ex);
269
        }
270
    }
271
272 7
    public function deleteDir(array $entry, bool $deep = false): bool
273
    {
274
        try {
275 7
            $start = $this->getEntry($entry);
276 6
            if (is_null($start)) {
277 1
                return false;
278
            }
279 6
            if ($deep) {
280 3
                return $this->removeCycle($start);
281 4
            } elseif ($this->isDir($start)) {
282 3
                return $this->removeSingleDir($start);
283
            } else {
284 1
                return false;
285
            }
286 1
        } catch (MapperException $ex) {
287 1
            throw new FilesException($this->getFlLang()->flCannotRemoveDir(Stuff::arrayToPath($entry)), $ex->getCode(), $ex);
288
        }
289
    }
290
291
    /**
292
     * Copy a file, or recursively copy a folder and its contents - version for db storage
293
     * @param ARecord $source Source node
294
     * @param ARecord $dest Destination node
295
     * @throws MapperException
296
     * @return bool
297
     */
298 1
    protected function copyCycle(ARecord $source, ARecord $dest): bool
299
    {
300 1
        $stat = 0;
301
302 1
        $search = new Search($this->getLookupRecord());
303 1
        $search->exact($this->getTranslation()->getParentKey(), strval($source->__get($this->getTranslation()->getPrimaryKey())));
304 1
        $src = $search->getResults();
305
306 1
        foreach ($src as $item) {
307 1
            $newNode = $this->getLookupRecord();
308 1
            $newNode->__set($this->getTranslation()->getCurrentKey(), $item->__get($this->getTranslation()->getCurrentKey()));
309 1
            $newNode->__set($this->getTranslation()->getParentKey(), $dest->__get($this->getTranslation()->getPrimaryKey()));
310 1
            $newNode->__set($this->getTranslation()->getContentKey(), $item->__get($this->getTranslation()->getContentKey()));
311 1
            $stat += intval(!$newNode->save());
312
313 1
            if ($this->isDir($newNode)) {
314 1
                $stat += intval(!$this->copyCycle($item, $newNode));
315
            }
316
        }
317
318 1
        return !boolval($stat);
319
    }
320
321
    /**
322
     * @param ARecord $entry
323
     * @throws MapperException
324
     * @return bool
325
     */
326 3
    protected function removeCycle(ARecord $entry): bool
327
    {
328 3
        if ($this->isDir($entry)) {
329 3
            $search = new Search($this->getLookupRecord());
330 3
            $search->exact(
331 3
                $this->getTranslation()->getParentKey(),
332 3
                strval($entry->__get($this->getTranslation()->getPrimaryKey()))
333
            );
334 3
            $fileListing = $search->getResults();
335 3
            foreach ($fileListing as $fileRecord) {
336 3
                $this->removeCycle($fileRecord);
337
            }
338
        }
339 3
        return $entry->delete();
340
    }
341
342
    /**
343
     * @param ARecord $entry
344
     * @throws MapperException
345
     * @return bool
346
     */
347 3
    protected function removeSingleDir(ARecord $entry): bool
348
    {
349 3
        $subs = new Search($this->getLookupRecord());
350 3
        $subs->exact(
351 3
            $this->getTranslation()->getParentKey(),
352 3
            strval($entry->__get($this->getTranslation()->getPrimaryKey()))
353
        );
354 3
        if (1 > $subs->getCount()) {
355 1
            return $entry->delete();
356
        } else {
357 2
            return false;
358
        }
359
    }
360
361 18
    protected function getLookupRecord(): ARecord
362
    {
363 18
        return clone $this->record;
364
    }
365
}
366