3 * This class loads class include files with a specific prefix and suffix
5 * @author Roland Haeder <webmaster@ship-simu.org>
7 * @copyright Copyright(c) 2007, 2008 Roland Haeder, this is free software
8 * @license GNU GPL 3.0 or any newer version
9 * @link http://www.ship-simu.org
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * ----------------------------------
26 * - ClassLoader rewritten to PHP SPL's own RecursiveIteratorIterator class
28 * - loadClasses rewritten to fix some notices
31 * ----------------------------------
37 private $cfg = array();
40 * Array with all classes
42 private $classes = array();
45 * Suffix with extension for all class files
47 private $prefix = "class_";
50 * Suffix with extension for all class files
52 private $suffix = ".php";
55 * Length of the suffix. Will be overwritten later.
57 private $suffixLen = 0;
60 * Length of the prefix. Will be overwritten later.
62 private $prefixLen = 0;
65 * A list for directory names (no leading/trailing slashes!) which not be scanned by the path scanner
68 private $ignoreList = array();
71 * Debug this class loader? (true = yes, false = no)
73 private $debug = false;
76 * Instance of this class
78 private static $selfInstance = null;
81 * The *public* constructor
83 * @param $cfgInstance Configuration class instance
86 public function __construct (FrameworkConfiguration $cfgInstance) {
87 // Set suffix and prefix from configuration
88 $this->suffix = $cfgInstance->readConfig('class_suffix');
89 $this->prefix = $cfgInstance->readConfig('class_prefix');
91 // Estimate length of prefix and suffix for substr() function (cache)
92 $this->suffixLen = strlen($this->suffix);
93 $this->prefixLen = strlen($this->prefix);
95 // Set configuration instance
96 $this->cfgInstance = $cfgInstance;
99 self::$selfInstance = $this;
103 * Getter for an instance of this class
105 * @return $selfInstance An instance of this class
107 public final static function getInstance () {
108 // Is the instance there?
109 if (is_null(self::$selfInstance)) {
111 self::$selfInstance = new ClassLoader(FrameworkConfiguration::getInstance());
114 // Return the instance
115 return self::$selfInstance;
119 * Scans recursively a local path for class files which must have a prefix and a suffix as given by $this->suffix and $this->prefix
121 * @param $basePath The relative base path to PATH constant for all classes
122 * @param $ignoreList An optional list (array or string) of directory names which shall be ignored
125 public function loadClasses ($basePath, $ignoreList = array() ) {
126 // Convert string to array
127 if (!is_array($ignoreList)) $ignoreList = array($ignoreList);
129 // Directories which our class loader ignores by default while
130 // deep-scanning the directory structure. See scanLocalPath() for
133 $ignoreList[] = "..";
134 $ignoreList[] = ".htaccess";
135 $ignoreList[] = ".svn";
137 // Keep it in class for later usage
138 $this->ignoreList = $ignoreList;
140 // Set base directory which holds all our classes, we should use an
141 // absolute path here so is_dir(), is_file() and so on will always
142 // find the correct files and dirs.
143 $basePath2 = realpath($basePath);
145 // If the basePath is false it is invalid
146 if ($basePath2 === false) {
147 // TODO: Do not die here.
148 die("Cannot read {$basePath} !");
151 $basePath = $basePath2;
154 // Get a new iterator
155 //* DEBUG: */ echo "<strong>Base path: {$basePath}</strong><br />\n";
156 $iterator = new RecursiveDirectoryIterator($basePath);
157 $recursive = new RecursiveIteratorIterator($iterator);
158 foreach ($recursive as $entry) {
159 // Get filename from iterator
160 $fileName = $entry->getFileName();
162 // Is this file wanted?
163 //* DEBUG: */ echo "FOUND:{$fileName}<br />\n";
164 if ((!in_array($fileName, $this->ignoreList)) && (substr($fileName, 0, $this->prefixLen) == $this->prefix) && (substr($fileName, -$this->suffixLen, $this->suffixLen) == $this->suffix)) {
165 // Get the FQFN and add it to our class list
166 $fqfn = $entry->getRealPath();
167 //* DEBUG: */ echo "ADD: {$fileName}<br />\n";
168 $this->classes[$fileName] = $fqfn;
174 * Load extra config files
178 public function loadExtraConfigs () {
180 $oldPrefix = $this->prefix;
182 // Set new prefix (temporary!)
183 $this->prefix = "config-";
184 $this->prefixLen = strlen($this->prefix);
186 // Set base directory
187 $basePath = sprintf("%sinc/config/", PATH);
189 // Load all classes from the config directory
190 $this->loadClasses($basePath);
192 // Set the prefix back
193 $this->prefix = $oldPrefix;
194 $this->prefixLen = strlen($this->prefix);
198 * Tries to find the given class in our list. This method ignores silently
199 * missing classes or interfaces. So if you use class_exists() this method
200 * does not interrupt your program.
202 * @param $className The class we shall load
205 public function includeClass ($className) {
206 // Create a name with prefix and suffix
207 $fileName = $this->prefix . $className . $this->suffix;
209 // Now look it up in our index
210 if (isset($this->classes[$fileName])) {
211 if ($this->classes[$fileName] != "loaded") {
212 // File is found so load it only once
213 require($this->classes[$fileName]);
216 $this->classes[$fileName] = "loaded";