]> git.mxchange.org Git - core.git/blob - framework/main/classes/file_directories/directory/class_FrameworkDirectoryPointer.php
Continued:
[core.git] / framework / main / classes / file_directories / directory / class_FrameworkDirectoryPointer.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Filesytem\Pointer;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Filesystem\FrameworkDirectory;
7 use Org\Mxchange\CoreFramework\Generic\FrameworkInterface;
8 use Org\Mxchange\CoreFramework\Generic\NullPointerException;
9 use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem;
10
11 // Deprecated imports
12 use Org\Mxchange\CoreFramework\Deprecated\PathIsNoDirectoryException;
13
14 // Import SPL stuff
15 use \DirectoryIterator;
16 use \InvalidArgumentException;
17
18 /**
19  * A class for directory reading and getting its contents, no recursion!
20  *
21  * @author              Roland Haeder <webmaster@shipsimu.org>
22  * @version             0.0.0
23  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2022 Core Developer Team
24  * @license             GNU GPL 3.0 or any newer version
25  * @link                http://www.shipsimu.org
26  *
27  * This program is free software: you can redistribute it and/or modify
28  * it under the terms of the GNU General Public License as published by
29  * the Free Software Foundation, either version 3 of the License, or
30  * (at your option) any later version.
31  *
32  * This program is distributed in the hope that it will be useful,
33  * but WITHOUT ANY WARRANTY; without even the implied warranty of
34  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35  * GNU General Public License for more details.
36  *
37  * You should have received a copy of the GNU General Public License
38  * along with this program. If not, see <http://www.gnu.org/licenses/>.
39  */
40 class FrameworkDirectoryPointer extends BaseFrameworkSystem implements FrameworkDirectory {
41         /**
42          * The current path we are working in
43          */
44         private $pathName = '';
45
46         /**
47          * The directory iterator instance
48          */
49         private $iteratorInstance = NULL;
50
51         /**
52          * Protected constructor
53          */
54         private function __construct () {
55                 // Call parent constructor
56                 parent::__construct(__CLASS__);
57         }
58
59         /**
60          * Destructor for cleaning purposes, etc
61          */
62         public function __destruct() {
63                 // Is there a resource pointer? Then we have to close the directory here!
64                 if ($this->getDirectoryIteratorInstance() instanceof DirectoryIterator) {
65                         // Try to close a directory
66                         $this->closeDirectory();
67                 }
68
69                 // Call the parent destructor
70                 parent::__destruct();
71         }
72
73         /**
74          * Create a directory pointer based on the given path. The path will also
75          * be verified here.
76          *
77          * @param       $pathName               The path name we shall pass to opendir()
78          * @return      $pointerInstance        A prepared instance of FrameworkDirectoryPointer
79          * @throws      NullPointerException    If the provided path name is null
80          * @throws      InvalidPathStringException      If the provided path name is not a string
81          * @throws      PathIsNoDirectoryException      If the provided path name is not valid
82          * @throws      PathReadProtectedException      If the provided path name is read-protected
83          */
84         public static final function createFrameworkDirectoryPointer (string $pathName) {
85                 // Some pre-sanity checks...
86                 if (empty($pathName)) {
87                         // Throw IAE
88                         throw new InvalidArgumentException('Parameter "pathName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
89                 } elseif (!is_dir($pathName)) {
90                         // Not a directory
91                         throw new PathIsNoDirectoryException($pathName, self::EXCEPTION_INVALID_PATH_NAME);
92                 } elseif (!is_readable($pathName)) {
93                         // Not readable
94                         throw new PathReadProtectedException($pathName, self::EXCEPTION_READ_PROTECED_PATH);
95                 }
96
97                 // Create new instance
98                 $pointerInstance = new FrameworkDirectoryPointer();
99
100                 // Get an iterator for the directory
101                 $iteratorInstance = new DirectoryIterator($pathName);
102
103                 // ... and rewind back
104                 $iteratorInstance->rewind();
105
106                 // Set directory pointer and path name
107                 $pointerInstance->setDirectoryIteratorInstance($iteratorInstance);
108                 $pointerInstance->setPathName($pathName);
109
110                 // Return the instance
111                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY-POINTER: Opened pathName=' . $pathName . ' - EXIT!');
112                 return $pointerInstance;
113         }
114
115         /**
116          * Read raw lines of data from a directory pointer and return the data
117          *
118          * @return      $currentEntry   Current entry from encapsulated iterator
119          */
120         public function readRawDirectory () {
121                 // Can the next entry be read?
122                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY-POINTER: CALLED!');
123                 assert($this->getDirectoryIteratorInstance()->valid());
124
125                 // Read data from the directory pointer and return it
126                 $currentEntry = $this->getDirectoryIteratorInstance()->current();
127
128                 // Return found entry
129                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('DIRECTORY-POINTER: currentEntry[%s]=%s - EXIT!', gettype($currentEntry), $currentEntry));
130                 return $currentEntry;
131         }
132
133         /**
134          * Read lines from the current directory pointer except some parts
135          *
136          * @param       $except         Some parts of a directory we want to ignore. Valid: directory and file names, other values will be silently ignored
137          * @return      SplFileInfo             An instance of a SplFileInfo class
138          */
139         public function readDirectoryExcept (array $except = []) {
140                 // No exceptions given?
141                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('DIRECTORY-POINTER: except()=%d - CALLED!', count($except)));
142                 if (count($except) == 0) {
143                         // No exception given, so read all files and directories, but not recursive
144                         self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY-POINTER: No exceptions given, please use readRawDirectory() instead!');
145                         return $this->readRawDirectory();
146                 } elseif (!$this->getDirectoryIteratorInstance()->valid()) {
147                         // No more left to read
148                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY-POINTER: EOD reached - EXIT!');
149                         return NULL;
150                 }
151
152                 // Init raw line
153                 $fileInfoInstance = NULL;
154
155                 // Read a raw line...
156                 $currentEntry = $this->readRawDirectory();
157
158                 // Shall we exclude directories?
159                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('DIRECTORY-POINTER: currentEntry[]=%s', gettype($currentEntry)));
160                 if (is_object($currentEntry)) {
161                         // Get file name
162                         $fileInfoInstance = $currentEntry;
163
164                         // Is it a dot-directory or excluded?
165                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('DIRECTORY-POINTER: fileInfoInstance->filename=%s,isDot=%d', $fileInfoInstance->getFilename(), intval($this->getDirectoryIteratorInstance()->isDot())));
166                         while ($this->getDirectoryIteratorInstance()->valid() && ($this->getDirectoryIteratorInstance()->isDot() || in_array($fileInfoInstance->getFilename(), $except))) {
167                                 // Update current instance
168                                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('DIRECTORY-POINTER: fileInfoInstance->filename=%s,isDot=%d', $fileInfoInstance->getFilename(), intval($this->getDirectoryIteratorInstance()->isDot())));
169                                 $fileInfoInstance = $this->readRawDirectory();
170
171                                 // To next entry
172                                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY-POINTER: Invoking directoryIteratorInstance->next() ...');
173                                 $this->getDirectoryIteratorInstance()->next();
174                         }
175                 }
176
177                 // Return read line
178                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('DIRECTORY-POINTER: fileInfoInstance[%s]=%s - EXIT!', gettype($fileInfoInstance), $fileInfoInstance));
179                 return $fileInfoInstance;
180         }
181
182         /**
183          * Close a directory source and set it's instance to null and the path name
184          * to empty
185          *
186          * @return      void
187          */
188         public function closeDirectory () {
189                 // Close the directory by unsetting it
190                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY-POINTER: CALLED!');
191                 $this->unsetDirectoryIteratorInstance();
192                 $this->setPathName('');
193         }
194
195         /**
196          * Setter for the directory pointer
197          *
198          * @param       $iteratorInstance       An instanceof a DirectoryIterator class
199          * @return      void
200          */
201         protected final function setDirectoryIteratorInstance (DirectoryIterator $iteratorInstance) {
202                 // Set instance
203                 $this->iteratorInstance = $iteratorInstance;
204         }
205
206         /**
207          * Getter for the directory pointer
208          *
209          * @return      $iteratorInstance       The directory pointer which shall be a valid directory resource
210          */
211         public final function getDirectoryIteratorInstance () {
212                 return $this->iteratorInstance;
213         }
214
215         /**
216          * Remove directory iterator instance (effectively closing it) by setting
217          * it to NULL. This will trigger a call on the destructor which will then
218          * "close" the iterator.
219          *
220          * @param       $iteratorInstance       An instanceof a DirectoryIterator class
221          * @return      void
222          */
223         protected final function unsetDirectoryIteratorInstance () {
224                 // "Unset" the instance
225                 $this->iteratorInstance = NULL;
226         }
227
228         /**
229          * Setter for path name
230          *
231          * @param       $pathName       The new path name
232          * @return      void
233          */
234         protected final function setPathName (string $pathName) {
235                 $this->pathName = $pathName;
236         }
237
238         /**
239          * Getter for path name
240          *
241          * @return      $pathName       The current path name
242          */
243         public final function getPathName () {
244                 return $this->pathName;
245         }
246
247 }