Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
44 / 44
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
FileTreeDirectoriesDataSrc
100.00% covered (success)
100.00%
44 / 44
100.00% covered (success)
100.00%
8 / 8
12
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTreeId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setTreeId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTreenodeValueObjects
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createValueObjects
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
2
 filePathRecurse
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3/**
4 * @author: Doug Wilbourne (dougwilbourne@gmail.com)
5 */
6
7declare(strict_types=1);
8
9namespace pvc\file\filesys;
10
11use pvc\file\err\DirectoryDoesNotExistException;
12use pvc\file\err\ScanDirException;
13use pvc\interfaces\struct\treeId\node_value_object\TreenodeValueObjectDataSrcInterface;
14
15/**
16 * Class FileTreeDirectoriesDataSrc
17 */
18class FileTreeDirectoriesDataSrc implements TreenodeValueObjectDataSrcInterface
19{
20    /**
21     * @var array<DirectoryEntryValueObject>
22     */
23    protected array $treenodeValueObjects = [];
24
25    protected DirectoryEntryValueObjectFactory $factory;
26
27    protected int $treeId;
28
29    public function __construct(
30        DirectoryEntryValueObjectFactory $factory,
31        int $treeId)
32    {
33        $this->setFactory($factory);
34        $this->setTreeId($treeId);
35    }
36
37    public function getFactory(): DirectoryEntryValueObjectFactory
38    {
39        return $this->factory;
40    }
41
42    public function setFactory(DirectoryEntryValueObjectFactory $factory): void
43    {
44        $this->factory = $factory;
45    }
46
47    public function getTreeId(): int
48    {
49        return $this->treeId;
50    }
51
52    public function setTreeId(int $treeId): void
53    {
54        $this->treeId = $treeId;
55    }
56
57    /**
58     * getTreenodeValueObjects
59     * @return DirectoryEntryValueObject[]
60     */
61    public function getTreenodeValueObjects(): array
62    {
63        return $this->treenodeValueObjects;
64    }
65
66    /**
67     * createValueObjects
68     * @param string $filePath
69     * @throws DirectoryDoesNotExistException
70     * @throws ScanDirException
71     */
72    public function createValueObjects(string $filePath): void
73    {
74        if (!is_dir($filePath)) {
75            throw new DirectoryDoesNotExistException($filePath);
76        }
77
78        /**
79         * the $filePath argument is the root node in the treeId
80         */
81        $nodeId = 0;
82        $parentId = null;
83        $treeId = $this->getTreeId();
84        $index = 0;
85
86        /**
87         * the hasSubDirs property will be set in the recursive method
88         */
89        $entry = new DirectoryEntry();
90        $entry->setFilePath($filePath);
91        $entry->setLevel(0);
92
93        $valueObject = $this->factory->makeDirectoryEntryValueObject();
94        $valueObject->hydrateFromNumericArray([$nodeId, $parentId, $treeId, $entry, $index]);
95
96        $this->treenodeValueObjects =  $this->filePathRecurse($valueObject);
97    }
98
99    /**
100     * filePathRecurse
101     * @param DirectoryEntryValueObject $parentValueObject
102     * @return DirectoryEntryValueObject[]
103     * @throws ScanDirException
104     */
105    protected function filePathRecurse(DirectoryEntryValueObject $parentValueObject): array
106    {
107        $resultArray = [$parentValueObject];
108
109        $nextNodeId = $parentValueObject->getNodeId() + 1;
110        $nextLevel = $parentValueObject->getValue()->getLevel() + 1;
111
112        $index = 0;
113
114        $filePath = $parentValueObject->getValue()->getFilePath();
115        if (!$files = scandir($filePath, SCANDIR_SORT_ASCENDING)) {
116            throw new ScanDirException($filePath);
117        }
118        /**
119         * remove the dot files or you get an infinite loop
120         */
121        $files = array_diff($files, ['.', '..']);
122
123        foreach ($files as $file) {
124
125            $file = $filePath . '/' . $file;
126
127            if (is_dir($file)) {
128                /**
129                 * now we know the parent dir has subdirectories
130                 */
131                $parentValueObject->getValue()->setHasSubDirs(true);
132
133                /**
134                 * the hasSubDirs attribute will be set as we recurse through the file system
135                 */
136                $entry = new DirectoryEntry();
137                $entry->setFilePath($file);
138                $entry->setLevel($nextLevel);
139
140                $valueObject = $this->factory->makeDirectoryEntryValueObject();
141                $valueObject->hydrateFromNumericArray([
142                                                          $nextNodeId++,
143                                                          $parentValueObject->getNodeId(),
144                                                          $parentValueObject->getTreeId(),
145                                                          $entry,
146                                                          $index
147                                                      ]);
148                $resultArray = array_merge($resultArray, $this->filePathRecurse($valueObject));
149            }
150        }
151        return $resultArray;
152    }
153}