3 namespace CoreFramework\Filesytem\Pointer;
5 // Import framework stuff
6 use CoreFramework\Object\BaseFrameworkSystem;
9 * A class for directory reading and getting its contents, no recursion!
11 * @author Roland Haeder <webmaster@shipsimu.org>
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
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.
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.
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/>.
30 class FrameworkDirectoryPointer extends BaseFrameworkSystem implements FrameworkDirectory {
32 * The current path we are working in
34 private $pathName = '';
37 * The directory iterator instance
39 private $iteratorInstance = NULL;
42 * Protected constructor
44 protected function __construct () {
45 // Call parent constructor
46 parent::__construct(__CLASS__);
50 * Destructor for cleaning purposes, etc
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();
59 // Call the parent destructor
64 * Create a directory pointer based on the given path. The path will also
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.
76 public static final function createFrameworkDirectoryPointer ($pathName, $inConstructor = FALSE) {
77 // Some pre-sanity checks...
78 if (is_null($pathName)) {
83 throw new PathIsEmptyException(NULL, self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
85 } elseif (!is_string($pathName)) {
90 throw new InvalidPathStringException(NULL, self::EXCEPTION_INVALID_STRING);
92 } elseif (!is_dir($pathName)) {
97 throw new PathIsNoDirectoryException($pathName, self::EXCEPTION_INVALID_PATH_NAME);
99 } elseif (!is_readable($pathName)) {
101 if ($inConstructor) {
104 throw new PathReadProtectedException($pathName, self::EXCEPTION_READ_PROTECED_PATH);
108 // Create new instance
109 $pointerInstance = new FrameworkDirectoryPointer();
111 // Get an iterator for the directory
112 $iteratorInstance = new DirectoryIterator($pathName);
114 // ... and rewind back
115 $iteratorInstance->rewind();
117 // Set directory pointer and path name
118 $pointerInstance->setDirectoryIteratorInstance($iteratorInstance);
119 $pointerInstance->setPathName($pathName);
121 // Return the instance
122 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: Opened pathName=' . $pathName . ' - EXIT!');
123 return $pointerInstance;
127 * Read raw lines of data from a directory pointer and return the data
129 * @return $currentEntry Current entry from encapsulated iterator
131 public function readRawDirectory () {
132 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . '] - CALLED!');
134 // Can the next entry be read?
135 assert($this->getDirectoryIteratorInstance()->valid());
137 // Read data from the directory pointer and return it
138 $currentEntry = $this->getDirectoryIteratorInstance()->current();
140 // Return found entry
141 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: currentEntry[]=' . gettype($currentEntry) . ' - EXIT!');
142 return $currentEntry;
146 * Read lines from the current directory pointer except some parts
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
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__, __LINE__)->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__, __LINE__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: EOD reached.');
166 // Read a raw line...
167 $currentEntry = $this->readRawDirectory();
168 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: currentEntry[]=' . gettype($currentEntry));
170 // Shall we exclude directories?
171 if (is_object($currentEntry)) {
173 $rawLine = $currentEntry->getFilename();
174 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: rawLine[' . gettype($rawLine) . ']=' . $rawLine . ',isDot=' . intval($this->getDirectoryIteratorInstance()->isDot()));
176 // Is it a dot-directory or excluded?
177 if (($this->getDirectoryIteratorInstance()->isDot()) || (in_array($rawLine, $except))) {
179 $this->getDirectoryIteratorInstance()->next();
182 $rawLine = $this->readDirectoryExcept($except);
183 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: rawline[' . gettype($rawLine) . ']=' . $rawLine . ' - Recursive call!');
188 $this->getDirectoryIteratorInstance()->next();
191 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('DIRECTORY[' . __METHOD__ . ':' . __LINE__ . ']: rawLine[' . gettype($rawLine) . ']=' . $rawLine);
196 * Close a directory source and set it's instance to null and the path name
201 public function closeDirectory () {
202 // Close the directory by unsetting it
203 $this->unsetDirectoryIteratorInstance();
204 $this->setPathName('');
208 * Setter for the directory pointer
210 * @param $iteratorInstance An instanceof a DirectoryIterator class
213 protected final function setDirectoryIteratorInstance (DirectoryIterator $iteratorInstance) {
215 $this->iteratorInstance = $iteratorInstance;
219 * Getter for the directory pointer
221 * @return $iteratorInstance The directory pointer which shall be a valid directory resource
223 public final function getDirectoryIteratorInstance () {
224 return $this->iteratorInstance;
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.
232 * @param $iteratorInstance An instanceof a DirectoryIterator class
235 protected final function unsetDirectoryIteratorInstance () {
236 // "Unset" the instance
237 $this->iteratorInstance = NULL;
241 * Setter for path name
243 * @param $pathName The new path name
246 protected final function setPathName ($pathName) {
247 $pathName = (string) $pathName;
248 $this->pathName = $pathName;
252 * Getter for path name
254 * @return $pathName The current path name
256 public final function getPathName () {
257 return $this->pathName;