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