]> 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 - 2023 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                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('FRAMEWORK-DIRECTORY-POINTER: DESTRUCTED!');
65                 if ($this->getDirectoryIteratorInstance() instanceof DirectoryIterator) {
66                         // Try to close a directory
67                         $this->closeDirectory();
68                 }
69
70                 // Call the parent destructor
71                 parent::__destruct();
72
73                 // Trace message
74                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('FRAMEWORK-DIRECTORY-POINTER: EXIT!');
75         }
76
77         /**
78          * Create a directory pointer based on the given path. The path will also
79          * be verified here.
80          *
81          * @param       $pathName               The path name we shall pass to opendir()
82          * @return      $pointerInstance        A prepared instance of FrameworkDirectoryPointer
83          * @throws      NullPointerException    If the provided path name is null
84          * @throws      InvalidPathStringException      If the provided path name is not a string
85          * @throws      PathIsNoDirectoryException      If the provided path name is not valid
86          * @throws      PathReadProtectedException      If the provided path name is read-protected
87          */
88         public static final function createFrameworkDirectoryPointer (string $pathName) {
89                 // Some pre-sanity checks...
90                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('FRAMEWORK-DIRECTORY-POINTER: pathName=%s - CALLED!', $pathName));
91                 if (empty($pathName)) {
92                         // Throw IAE
93                         throw new InvalidArgumentException('Parameter "pathName" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
94                 } elseif (!is_dir($pathName)) {
95                         // Not a directory
96                         throw new PathIsNoDirectoryException($pathName, self::EXCEPTION_INVALID_PATH_NAME);
97                 } elseif (!is_readable($pathName)) {
98                         // Not readable
99                         throw new PathReadProtectedException($pathName, self::EXCEPTION_READ_PROTECED_PATH);
100                 }
101
102                 // Create new instance
103                 $pointerInstance = new FrameworkDirectoryPointer();
104
105                 // Get an iterator for the directory
106                 $iteratorInstance = new DirectoryIterator($pathName);
107
108                 // ... and rewind back
109                 $iteratorInstance->rewind();
110
111                 // Set directory pointer and path name
112                 $pointerInstance->setDirectoryIteratorInstance($iteratorInstance);
113                 $pointerInstance->setPathName($pathName);
114
115                 // Return the instance
116                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('DIRECTORY-POINTER: pointerInstance=%s - EXIT!', $pointerInstance->__toString()));
117                 return $pointerInstance;
118         }
119
120         /**
121          * Read raw lines of data from a directory pointer and return the data
122          *
123          * @return      $currentEntry   Current entry from encapsulated iterator
124          */
125         public function readRawDirectory () {
126                 // Can the next entry be read?
127                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('DIRECTORY-POINTER: CALLED!');
128                 assert($this->getDirectoryIteratorInstance()->valid());
129
130                 // Read data from the directory pointer and return it
131                 $currentEntry = $this->getDirectoryIteratorInstance()->current();
132
133                 // Return found entry
134                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('DIRECTORY-POINTER: currentEntry[%s]=%s - EXIT!', gettype($currentEntry), $currentEntry));
135                 return $currentEntry;
136         }
137
138         /**
139          * Read lines from the current directory pointer except some parts
140          *
141          * @param       $except         Some parts of a directory we want to ignore. Valid: directory and file names, other values will be silently ignored
142          * @return      SplFileInfo             An instance of a SplFileInfo class
143          * @throws      InvalidArgumentException        If a parameter has an invalid value
144          */
145         public function readDirectoryExcept (array $except = []) {
146                 // No exceptions given?
147                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('DIRECTORY-POINTER: except()=%d - CALLED!', count($except)));
148                 if (count($except) == 0) {
149                         // No exception given, so read all files and directories, but not recursive
150                         throw new InvalidArgumentException('Parameter "except" is an empty array', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
151                 } elseif (!$this->getDirectoryIteratorInstance()->valid()) {
152                         // No more left to read
153                         /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('DIRECTORY-POINTER: EOD reached - EXIT!');
154                         return NULL;
155                 }
156
157                 // Init raw line
158                 $fileInfoInstance = NULL;
159
160                 // Read a raw line...
161                 $currentEntry = $this->readRawDirectory();
162
163                 // Shall we exclude directories?
164                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('DIRECTORY-POINTER: currentEntry[]=%s', gettype($currentEntry)));
165                 if (is_object($currentEntry)) {
166                         // Get file name
167                         $fileInfoInstance = $currentEntry;
168
169                         // Is it a dot-directory or excluded?
170                         /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('DIRECTORY-POINTER: fileInfoInstance->filename=%s,isDot=%d', $fileInfoInstance->getFilename(), intval($this->getDirectoryIteratorInstance()->isDot())));
171                         while ($this->getDirectoryIteratorInstance()->valid() && ($this->getDirectoryIteratorInstance()->isDot() || in_array($fileInfoInstance->getFilename(), $except))) {
172                                 // Update current instance
173                                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('DIRECTORY-POINTER: fileInfoInstance->filename=%s,isDot=%d', $fileInfoInstance->getFilename(), intval($this->getDirectoryIteratorInstance()->isDot())));
174                                 $fileInfoInstance = $this->readRawDirectory();
175
176                                 // To next entry
177                                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage('DIRECTORY-POINTER: Invoking directoryIteratorInstance->next() ...');
178                                 $this->getDirectoryIteratorInstance()->next();
179                         }
180                 }
181
182                 // Return read line
183                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('DIRECTORY-POINTER: fileInfoInstance[%s]=%s - EXIT!', gettype($fileInfoInstance), $fileInfoInstance));
184                 return $fileInfoInstance;
185         }
186
187         /**
188          * Close a directory source and set it's instance to null and the path name
189          * to empty
190          *
191          * @return      void
192          */
193         public function closeDirectory () {
194                 // Close the directory by unsetting it
195                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('DIRECTORY-POINTER: CALLED!');
196                 $this->unsetDirectoryIteratorInstance();
197                 $this->setPathName('');
198
199                 // Trace message
200                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('DIRECTORY-POINTER: CALLED!');
201         }
202
203         /**
204          * Setter for the directory pointer
205          *
206          * @param       $iteratorInstance       An instanceof a DirectoryIterator class
207          * @return      void
208          */
209         protected final function setDirectoryIteratorInstance (DirectoryIterator $iteratorInstance) {
210                 // Set instance
211                 $this->iteratorInstance = $iteratorInstance;
212         }
213
214         /**
215          * Getter for the directory pointer
216          *
217          * @return      $iteratorInstance       The directory pointer which shall be a valid directory resource
218          */
219         public final function getDirectoryIteratorInstance () {
220                 return $this->iteratorInstance;
221         }
222
223         /**
224          * Remove directory iterator instance (effectively closing it) by setting
225          * it to NULL. This will trigger a call on the destructor which will then
226          * "close" the iterator.
227          *
228          * @param       $iteratorInstance       An instanceof a DirectoryIterator class
229          * @return      void
230          */
231         protected final function unsetDirectoryIteratorInstance () {
232                 // "Unset" the instance
233                 $this->iteratorInstance = NULL;
234         }
235
236         /**
237          * Setter for path name
238          *
239          * @param       $pathName       The new path name
240          * @return      void
241          */
242         protected final function setPathName (string $pathName) {
243                 $this->pathName = $pathName;
244         }
245
246         /**
247          * Getter for path name
248          *
249          * @return      $pathName       The current path name
250          */
251         public final function getPathName () {
252                 return $this->pathName;
253         }
254
255 }