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