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