File indexing completed on 2024-12-22 05:37:17
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Loader 0017 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0018 * @license http://framework.zend.com/license/new-bsd New BSD License 0019 * @version $Id$ 0020 */ 0021 0022 /** 0023 * Static methods for loading classes and files. 0024 * 0025 * @category Zend 0026 * @package Zend_Loader 0027 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0028 * @license http://framework.zend.com/license/new-bsd New BSD License 0029 */ 0030 class Zend_Loader 0031 { 0032 /** 0033 * Loads a class from a PHP file. The filename must be formatted 0034 * as "$class.php". 0035 * 0036 * If $dirs is a string or an array, it will search the directories 0037 * in the order supplied, and attempt to load the first matching file. 0038 * 0039 * If $dirs is null, it will split the class name at underscores to 0040 * generate a path hierarchy (e.g., "Zend_Example_Class" will map 0041 * to "Zend/Example/Class.php"). 0042 * 0043 * If the file was not found in the $dirs, or if no $dirs were specified, 0044 * it will attempt to load it from PHP's include_path. 0045 * 0046 * @param string $class - The full class name of a Zend component. 0047 * @param string|array $dirs - OPTIONAL Either a path or an array of paths 0048 * to search. 0049 * @return void 0050 * @throws Zend_Exception 0051 */ 0052 public static function loadClass($class, $dirs = null) 0053 { 0054 if (class_exists($class, false) || interface_exists($class, false)) { 0055 return; 0056 } 0057 0058 if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) { 0059 // require_once 'Zend/Exception.php'; 0060 throw new Zend_Exception('Directory argument must be a string or an array'); 0061 } 0062 0063 $file = self::standardiseFile($class); 0064 0065 if (!empty($dirs)) { 0066 // use the autodiscovered path 0067 $dirPath = dirname($file); 0068 if (is_string($dirs)) { 0069 $dirs = explode(PATH_SEPARATOR, $dirs); 0070 } 0071 foreach ($dirs as $key => $dir) { 0072 if ($dir == '.') { 0073 $dirs[$key] = $dirPath; 0074 } else { 0075 $dir = rtrim($dir, '\\/'); 0076 $dirs[$key] = $dir . DIRECTORY_SEPARATOR . $dirPath; 0077 } 0078 } 0079 $file = basename($file); 0080 self::loadFile($file, $dirs, true); 0081 } else { 0082 self::loadFile($file, null, true); 0083 } 0084 0085 if (!class_exists($class, false) && !interface_exists($class, false)) { 0086 // require_once 'Zend/Exception.php'; 0087 throw new Zend_Exception("File \"$file\" does not exist or class \"$class\" was not found in the file"); 0088 } 0089 } 0090 0091 /** 0092 * Loads a PHP file. This is a wrapper for PHP's include() function. 0093 * 0094 * $filename must be the complete filename, including any 0095 * extension such as ".php". Note that a security check is performed that 0096 * does not permit extended characters in the filename. This method is 0097 * intended for loading Zend Framework files. 0098 * 0099 * If $dirs is a string or an array, it will search the directories 0100 * in the order supplied, and attempt to load the first matching file. 0101 * 0102 * If the file was not found in the $dirs, or if no $dirs were specified, 0103 * it will attempt to load it from PHP's include_path. 0104 * 0105 * If $once is TRUE, it will use include_once() instead of include(). 0106 * 0107 * @param string $filename 0108 * @param string|array $dirs - OPTIONAL either a path or array of paths 0109 * to search. 0110 * @param boolean $once 0111 * @return boolean 0112 * @throws Zend_Exception 0113 */ 0114 public static function loadFile($filename, $dirs = null, $once = false) 0115 { 0116 self::_securityCheck($filename); 0117 0118 /** 0119 * Search in provided directories, as well as include_path 0120 */ 0121 $incPath = false; 0122 if (!empty($dirs) && (is_array($dirs) || is_string($dirs))) { 0123 if (is_array($dirs)) { 0124 $dirs = implode(PATH_SEPARATOR, $dirs); 0125 } 0126 $incPath = get_include_path(); 0127 set_include_path($dirs . PATH_SEPARATOR . $incPath); 0128 } 0129 0130 /** 0131 * Try finding for the plain filename in the include_path. 0132 */ 0133 if ($once) { 0134 include_once $filename; 0135 } else { 0136 include $filename; 0137 } 0138 0139 /** 0140 * If searching in directories, reset include_path 0141 */ 0142 if ($incPath) { 0143 set_include_path($incPath); 0144 } 0145 0146 return true; 0147 } 0148 0149 /** 0150 * Returns TRUE if the $filename is readable, or FALSE otherwise. 0151 * This function uses the PHP include_path, where PHP's is_readable() 0152 * does not. 0153 * 0154 * Note from ZF-2900: 0155 * If you use custom error handler, please check whether return value 0156 * from error_reporting() is zero or not. 0157 * At mark of fopen() can not suppress warning if the handler is used. 0158 * 0159 * @param string $filename 0160 * @return boolean 0161 */ 0162 public static function isReadable($filename) 0163 { 0164 if (is_readable($filename)) { 0165 // Return early if the filename is readable without needing the 0166 // include_path 0167 return true; 0168 } 0169 0170 if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' 0171 && preg_match('/^[a-z]:/i', $filename) 0172 ) { 0173 // If on windows, and path provided is clearly an absolute path, 0174 // return false immediately 0175 return false; 0176 } 0177 0178 foreach (self::explodeIncludePath() as $path) { 0179 if ($path == '.') { 0180 if (is_readable($filename)) { 0181 return true; 0182 } 0183 continue; 0184 } 0185 $file = $path . '/' . $filename; 0186 if (is_readable($file)) { 0187 return true; 0188 } 0189 } 0190 return false; 0191 } 0192 0193 /** 0194 * Explode an include path into an array 0195 * 0196 * If no path provided, uses current include_path. Works around issues that 0197 * occur when the path includes stream schemas. 0198 * 0199 * @param string|null $path 0200 * @return array 0201 */ 0202 public static function explodeIncludePath($path = null) 0203 { 0204 if (null === $path) { 0205 $path = get_include_path(); 0206 } 0207 0208 if (PATH_SEPARATOR == ':') { 0209 // On *nix systems, include_paths which include paths with a stream 0210 // schema cannot be safely explode'd, so we have to be a bit more 0211 // intelligent in the approach. 0212 $paths = preg_split('#:(?!//)#', $path); 0213 } else { 0214 $paths = explode(PATH_SEPARATOR, $path); 0215 } 0216 return $paths; 0217 } 0218 0219 /** 0220 * spl_autoload() suitable implementation for supporting class autoloading. 0221 * 0222 * Attach to spl_autoload() using the following: 0223 * <code> 0224 * spl_autoload_register(array('Zend_Loader', 'autoload')); 0225 * </code> 0226 * 0227 * @deprecated Since 1.8.0 0228 * @param string $class 0229 * @return string|false Class name on success; false on failure 0230 */ 0231 public static function autoload($class) 0232 { 0233 trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated as of 1.8.0 and will be removed with 2.0.0; use Zend_Loader_Autoloader instead', E_USER_NOTICE); 0234 try { 0235 @self::loadClass($class); 0236 return $class; 0237 } catch (Exception $e) { 0238 return false; 0239 } 0240 } 0241 0242 /** 0243 * Register {@link autoload()} with spl_autoload() 0244 * 0245 * @deprecated Since 1.8.0 0246 * @param string $class (optional) 0247 * @param boolean $enabled (optional) 0248 * @return void 0249 * @throws Zend_Exception if spl_autoload() is not found 0250 * or if the specified class does not have an autoload() method. 0251 */ 0252 public static function registerAutoload($class = 'Zend_Loader', $enabled = true) 0253 { 0254 trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated as of 1.8.0 and will be removed with 2.0.0; use Zend_Loader_Autoloader instead', E_USER_NOTICE); 0255 // require_once 'Zend/Loader/Autoloader.php'; 0256 $autoloader = Zend_Loader_Autoloader::getInstance(); 0257 $autoloader->setFallbackAutoloader(true); 0258 0259 if ('Zend_Loader' != $class) { 0260 self::loadClass($class); 0261 $methods = get_class_methods($class); 0262 if (!in_array('autoload', (array) $methods)) { 0263 // require_once 'Zend/Exception.php'; 0264 throw new Zend_Exception("The class \"$class\" does not have an autoload() method"); 0265 } 0266 0267 $callback = array($class, 'autoload'); 0268 0269 if ($enabled) { 0270 $autoloader->pushAutoloader($callback); 0271 } else { 0272 $autoloader->removeAutoloader($callback); 0273 } 0274 } 0275 } 0276 0277 /** 0278 * Ensure that filename does not contain exploits 0279 * 0280 * @param string $filename 0281 * @return void 0282 * @throws Zend_Exception 0283 */ 0284 protected static function _securityCheck($filename) 0285 { 0286 /** 0287 * Security check 0288 */ 0289 if (preg_match('/[^a-z0-9\\/\\\\_.:-]/i', $filename)) { 0290 // require_once 'Zend/Exception.php'; 0291 throw new Zend_Exception('Security check: Illegal character in filename'); 0292 } 0293 } 0294 0295 /** 0296 * Attempt to include() the file. 0297 * 0298 * include() is not prefixed with the @ operator because if 0299 * the file is loaded and contains a parse error, execution 0300 * will halt silently and this is difficult to debug. 0301 * 0302 * Always set display_errors = Off on production servers! 0303 * 0304 * @param string $filespec 0305 * @param boolean $once 0306 * @return boolean 0307 * @deprecated Since 1.5.0; use loadFile() instead 0308 */ 0309 protected static function _includeFile($filespec, $once = false) 0310 { 0311 if ($once) { 0312 return include_once $filespec; 0313 } else { 0314 return include $filespec ; 0315 } 0316 } 0317 0318 /** 0319 * Standardise the filename. 0320 * 0321 * Convert the supplied filename into the namespace-aware standard, 0322 * based on the Framework Interop Group reference implementation: 0323 * http://groups.google.com/group/php-standards/web/psr-0-final-proposal 0324 * 0325 * The filename must be formatted as "$file.php". 0326 * 0327 * @param string $file - The file name to be loaded. 0328 * @return string 0329 */ 0330 public static function standardiseFile($file) 0331 { 0332 $fileName = ltrim($file, '\\'); 0333 $file = ''; 0334 $namespace = ''; 0335 if ($lastNsPos = strripos($fileName, '\\')) { 0336 $namespace = substr($fileName, 0, $lastNsPos); 0337 $fileName = substr($fileName, $lastNsPos + 1); 0338 $file = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; 0339 } 0340 $file .= str_replace('_', DIRECTORY_SEPARATOR, $fileName) . '.php'; 0341 return $file; 0342 } 0343 }