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