3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Loader
;
14 // Grab SplAutoloader interface
15 require_once __DIR__
. '/SplAutoloader.php';
18 * Class-map autoloader
20 * Utilizes class-map files to lookup classfile locations.
22 class ClassMapAutoloader
implements SplAutoloader
25 * Registry of map files that have already been loaded
28 protected $mapsLoaded = array();
31 * Class name/filename map
34 protected $map = array();
39 * Create a new instance, and optionally configure the autoloader.
41 * @param null|array|Traversable $options
43 public function __construct($options = null)
45 if (null !== $options) {
46 $this->setOptions($options);
51 * Configure the autoloader
53 * Proxies to {@link registerAutoloadMaps()}.
55 * @param array|Traversable $options
56 * @return ClassMapAutoloader
58 public function setOptions($options)
60 $this->registerAutoloadMaps($options);
65 * Register an autoload map
67 * An autoload map may be either an associative array, or a file returning
68 * an associative array.
70 * An autoload map should be an associative array containing
71 * classname/file pairs.
73 * @param string|array $map
74 * @throws Exception\InvalidArgumentException
75 * @return ClassMapAutoloader
77 public function registerAutoloadMap($map)
79 if (is_string($map)) {
81 if ($this === ($map = $this->loadMapFromFile($location))) {
86 if (!is_array($map)) {
87 require_once __DIR__
. '/Exception/InvalidArgumentException.php';
88 throw new Exception\
InvalidArgumentException(sprintf(
89 'Map file provided does not return a map. Map file: "%s"',
90 (isset($location) && is_string($location) ?
$location : 'unexpected type: ' . gettype($map))
94 $this->map
= array_merge($this->map
, $map);
96 if (isset($location)) {
97 $this->mapsLoaded
[] = $location;
104 * Register many autoload maps at once
106 * @param array $locations
107 * @throws Exception\InvalidArgumentException
108 * @return ClassMapAutoloader
110 public function registerAutoloadMaps($locations)
112 if (!is_array($locations) && !($locations instanceof Traversable
)) {
113 require_once __DIR__
. '/Exception/InvalidArgumentException.php';
114 throw new Exception\
InvalidArgumentException('Map list must be an array or implement Traversable');
116 foreach ($locations as $location) {
117 $this->registerAutoloadMap($location);
123 * Retrieve current autoload map
127 public function getAutoloadMap()
135 public function autoload($class)
137 if (isset($this->map
[$class])) {
138 require_once $this->map
[$class];
147 * Register the autoloader with spl_autoload registry
151 public function register()
153 spl_autoload_register(array($this, 'autoload'), true, true);
157 * Load a map from a file
159 * If the map has been previously loaded, returns the current instance;
160 * otherwise, returns whatever was returned by calling include() on the
163 * @param string $location
164 * @return ClassMapAutoloader|mixed
165 * @throws Exception\InvalidArgumentException for nonexistent locations
167 protected function loadMapFromFile($location)
169 if (!file_exists($location)) {
170 require_once __DIR__
. '/Exception/InvalidArgumentException.php';
171 throw new Exception\
InvalidArgumentException(sprintf(
172 'Map file provided does not exist. Map file: "%s"',
173 (is_string($location) ?
$location : 'unexpected type: ' . gettype($location))
177 if (!$path = static::realPharPath($location)) {
178 $path = realpath($location);
181 if (in_array($path, $this->mapsLoaded
)) {
182 // Already loaded this map
186 $map = include $path;
192 * Resolve the real_path() to a file within a phar.
194 * @see https://bugs.php.net/bug.php?id=52769
195 * @param string $path
198 public static function realPharPath($path)
200 if (strpos($path, 'phar:///') !== 0) {
204 $parts = explode('/', str_replace(array('/', '\\'), '/', substr($path, 8)));
205 $parts = array_values(array_filter($parts, function ($p) {
206 return ($p !== '' && $p !== '.');
209 array_walk($parts, function ($value, $key) use (&$parts) {
210 if ($value === '..') {
211 unset($parts[$key], $parts[$key-1]);
212 $parts = array_values($parts);
216 if (file_exists($realPath = 'phar:///' . implode('/', $parts))) {