[ Index ] |
PHP Cross Reference of Automap |
[Summary view] [Print] [Text view]
1 <?php 2 //============================================================================= 3 // 4 // Copyright Francois Laupretre <automap@tekwire.net> 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); 7 // you may not use this file except in compliance with the License. 8 // You may obtain a copy of the License at 9 // 10 // http://www.apache.org/licenses/LICENSE-2.0 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 // 18 //============================================================================= 19 /** 20 * @copyright Francois Laupretre <automap@tekwire.net> 21 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, V 2.0 22 * @category Automap 23 * @package Automap 24 *///========================================================================== 25 26 //============================================================================= 27 /** 28 * The Automap (PHP) manager. 29 * 30 * Methods use map IDs. A map ID is a non null positive number, uniquely 31 * identifying a loaded map. 32 * 33 * Static-only 34 * API status: Public 35 * Included in the PHK PHP runtime: Yes 36 * Implemented in the extension: Yes 37 *///========================================================================== 38 39 namespace Automap { 40 41 if (!class_exists('Automap\Mgr',false)) 42 { 43 class Mgr 44 { 45 /** Symbol types */ 46 47 const T_FUNCTION='F'; 48 const T_CONSTANT='C'; 49 const T_CLASS='L'; 50 const T_EXTENSION='E'; 51 52 /** Target types */ 53 54 const F_SCRIPT='S'; 55 const F_EXTENSION='X'; 56 const F_PACKAGE='P'; 57 58 /* Load flags */ 59 60 /** Autoloader ignores maps loaded with this flag */ 61 62 const NO_AUTOLOAD=1; 63 64 /** Check CRC */ 65 66 const CRC_CHECK=2; 67 68 /** Load is done by the PECL extension - Reserved for internal use */ 69 70 const PECL_LOAD=4; 71 72 /** @var array Fixed value array containing a readable string for each 73 * symbol/target type 74 */ 75 76 private static $type_strings=array( 77 self::T_FUNCTION => 'function', 78 self::T_CONSTANT => 'constant', 79 self::T_CLASS => 'class', 80 self::T_EXTENSION => 'extension', 81 self::F_SCRIPT => 'script', 82 self::F_EXTENSION => 'extension file', 83 self::F_PACKAGE => 'package' 84 ); 85 86 /** @var array(callables) Registered failure handlers */ 87 88 private static $failureHandlers=array(); 89 90 /** @var array(callables) Registered success handlers */ 91 92 private static $successHandlers=array(); 93 94 /** @var bool Whether the PHP engine is able to autoload constants */ 95 96 private static $supportConstantAutoload; // 97 98 /** @var bool Whether the PHP engine is able to autoload functions */ 99 100 private static $supportFunctionAutoload; // 101 102 /** @var array(<map ID> => <\Automap\Map>) Array of active maps */ 103 104 private static $maps=array(); 105 106 /** @var integer The map ID of the next map load */ 107 108 private static $load_index=1; 109 110 //================== Map manager (static methods) ======================= 111 112 //-------------- 113 /** 114 * Undocumented - Internal use only 115 */ 116 117 public static function init() 118 { 119 // Determines if function/constant autoloading is supported 120 121 $f=new \ReflectionFunction('function_exists'); 122 self::$supportFunctionAutoload=($f->getNumberOfParameters()==2); 123 124 $f=new \ReflectionFunction('defined'); 125 self::$supportConstantAutoload=($f->getNumberOfParameters()==2); 126 } 127 128 //=============== User handlers =============== 129 130 /** 131 * Register a failure handler 132 * 133 * Once registered, the failure handler is called each time a symbol resolution 134 * fails. 135 * 136 * There is no limit on the number of failure handlers that can be registered. 137 * 138 * Handlers cannot be unregistered. 139 * 140 * @param callable $callable 141 * @return null 142 */ 143 144 public static function registerFailureHandler($callable) 145 { 146 self::$failureHandlers[]=$callable; 147 } 148 149 //-------------- 150 /** 151 * Call every registered failure handlers 152 * 153 * Call provides two arguments : the symbol type (one of the 'T_' constants) 154 * and the symbol name. 155 * 156 * Handlers are called in registration order. 157 * 158 * @param string $type one of the 'T_' constants 159 * @param string $name The symbol name 160 * @return null 161 */ 162 163 private static function callFailureHandlers($type,$name) 164 { 165 foreach (self::$failureHandlers as $callable) $callable($type,$name); 166 } 167 168 //-------------- 169 /** 170 * Register a success handler 171 * 172 * Once registered, the success handler is called each time a symbol resolution 173 * succeeds. 174 * 175 * The success handler receives two arguments : An array as returned by the 176 * getSymbol() method, and the ID of the map where the symbol was found. 177 * 178 * There is no limit on the number of success handlers that can be registered. 179 * 180 * Handlers cannot be unregistered. 181 * 182 * @param callable $callable 183 * @return null 184 */ 185 186 public static function registerSuccessHandler($callable) 187 { 188 self::$successHandlers[]=$callable; 189 } 190 191 //--- 192 193 private static function callSuccessHandlers($entry,$id) 194 { 195 foreach (self::$successHandlers as $callable) 196 $callable($entry,$id); 197 } 198 199 //-------- Key management ----------- 200 /** 201 * Combines a type and a symbol in a 'key' 202 * 203 * Starting with version 3.0, Automap is fully case-sensitive. This allows for 204 * higher performance and cleaner code. 205 * 206 * Do not use: access reserved for Automap classes 207 * 208 * @param string $type one of the 'T_' constants 209 * @param string $name The symbol value (case sensitive) 210 * @return string Symbol key 211 */ 212 213 public static function key($type,$name) 214 { 215 return $type.trim($name,'\\'); 216 } 217 218 //--------- 219 220 public static function typeToString($type) 221 { 222 if (!isset(self::$type_strings[$type])) 223 throw new \Exception("$type: Invalid type"); 224 225 return self::$type_strings[$type]; 226 } 227 228 //--------- 229 230 public static function stringToType($string) 231 { 232 $type=array_search($string,self::$type_strings,true); 233 234 if ($type===false) throw new \Exception("$type: Invalid type"); 235 236 return $type; 237 } 238 239 //-------- Map loading/unloading ----------- 240 241 /** 242 * Checks if a map ID is active (if it corresponds to a loaded map) 243 * 244 * @param integer $id ID to check 245 * @return boolean 246 */ 247 248 public static function isActiveID($id) 249 { 250 return isset(self::$maps[$id]); 251 } 252 253 //----- 254 /** 255 * Same as isActiveID() but throws an exception if the map ID is invalid 256 * 257 * Returns the map ID so that it can be embedded in a call string. 258 * 259 * @param integer $id ID to check 260 * @return integer ID (not modified) 261 * @throws \Exception if the ID is invalid (not loaded) 262 */ 263 264 private static function validate($id) 265 { 266 if (!self::isActiveID($id)) throw new \Exception($id.': Invalid map ID'); 267 268 return $id; 269 } 270 271 //----- 272 /** 273 * Returns the \Automap\Map object corresponding to an active map ID 274 * 275 * @param string $id The map ID 276 * @return \Automap\Map instance 277 * @throws \Exception if map ID is invalid 278 */ 279 280 public static function map($id) 281 { 282 self::validate($id); 283 284 return self::$maps[$id]; 285 } 286 287 //----- 288 /** 289 * Returns the list of currently active IDs. 290 * 291 * @return array 292 */ 293 294 public static function activeIDs() 295 { 296 return array_keys(self::$maps); 297 } 298 299 //--------- 300 /** 301 * Loads a map file and returns its ID. 302 * 303 * @param string $path The path of the map file to load 304 * @param integer $flags Load flags 305 * @param string $_bp Reserved for internal operations. Never set this param. 306 * @return int the map ID 307 */ 308 309 public static function load($path,$flags=0,$_bp=null) 310 { 311 $map=new \Automap\Map($path,$flags,$_bp); 312 313 $id=self::$load_index++; 314 self::$maps[$id]=$map; 315 // \Phool\Display::info("Loaded $path as ID $id");//TRACE 316 return $id; 317 } 318 319 //--------------------------------- 320 /** 321 * Unloads a map 322 * 323 * We dont use __destruct because : 324 * 1. We don't want this to be called on script shutdown 325 * 2. Exceptions cannot be caught when sent from a destructor. 326 * 327 * If the input ID is invalid, it is silently ignored. 328 * 329 * @param string $id The map ID to unload 330 * @return null 331 */ 332 333 public static function unload($id) 334 { 335 self::validate($id); 336 337 unset(self::$maps[$id]); 338 // \Phool\Display::info("Unloaded ID $id");//TRACE 339 } 340 341 //--------------------------------- 342 343 public static function usingAccelerator() 344 { 345 return false; 346 } 347 348 //-------- Symbol resolution ----------- 349 350 private static function symbolIsDefined($type,$name) 351 { 352 switch($type) 353 { 354 case self::T_CONSTANT: return (self::$supportConstantAutoload ? 355 defined($name,false) : defined($name)); 356 357 case self::T_FUNCTION: return (self::$supportFunctionAutoload ? 358 function_exists($name,false) : function_exists($name)); 359 360 case self::T_CLASS: return class_exists($name,false) 361 || interface_exists($name,false) 362 || (function_exists('trait_exists') && trait_exists($name,false)); 363 364 case self::T_EXTENSION: return extension_loaded($name); 365 } 366 } 367 368 //--------- 369 /** 370 * The autoload handler 371 * 372 * Reserved for internal use 373 * 374 * @param string $name Symbol name 375 * @param string Symbol type. One of the T_xxx constants. The default type is 'class', 376 * and cannot be anything else as long as PHP does not support function/constant 377 * autoloading. 378 */ 379 380 public static function autoloadHook($name,$type=self::T_CLASS) 381 { 382 self::resolve($type,$name,true,false); 383 } 384 385 //--------- 386 /** 387 * Resolve a symbol 388 * 389 * , i.e. load what needs to be loaded for the symbol to be 390 * defined. 391 * 392 * In order to optimize the PHK case, maps are searched in reverse order 393 * (newest first). 394 * 395 * Warning: Autoload mechanism is not reentrant. This function cannot reference 396 * an unknow class (like \Phool\Display). 397 * 398 * @param string $type Symbol type 399 * @param string $name Symbol name 400 * @param bool $autoloading Whether this was called by the PHP autoloader 401 * @param bool $exception Whether we must throw an exception if the resolution fails 402 * @return true on success / false if unable to resolve symbol 403 * @throw \Exception 404 */ 405 406 private static function resolve($type,$name,$autoloading=false 407 ,$exception=false) 408 { 409 //echo "Resolving $type$name\n";//TRACE 410 411 if ((!$autoloading)&&(self::symbolIsDefined($type,$name))) return true; 412 413 foreach(array_reverse(self::$maps,true) as $id => $map) 414 { 415 if (($entry=$map->resolve($type,$name,$id))===false) continue; 416 //echo "Symbol $name was resolved from ID $id\n"; 417 self::callSuccessHandlers($entry,$id); 418 return true; 419 } 420 421 // Failure 422 423 self::callFailureHandlers($type,$name); 424 if ($exception) throw new \Exception('Automap: Unknown ' 425 .self::typeToString($type).': '.$name); 426 return false; 427 } 428 429 //--------- 430 // Methods for explicit resolutions 431 432 public static function getFunction($name) 433 { return self::resolve(self::T_FUNCTION,$name,false,false); } 434 435 public static function getConstant($name) 436 { return self::resolve(self::T_CONSTANT,$name,false,false); } 437 438 public static function getClass($name) 439 { return self::resolve(self::T_CLASS,$name,false,false); } 440 441 public static function getExtension($name) 442 { return self::resolve(self::T_EXTENSION,$name,false,false); } 443 444 //--------- 445 446 public static function requireFunction($name) 447 { return self::resolve(self::T_FUNCTION,$name,false,true); } 448 449 public static function requireConstant($name) 450 { return self::resolve(self::T_CONSTANT,$name,false,true); } 451 452 public static function requireClass($name) 453 { return self::resolve(self::T_CLASS,$name,false,true); } 454 455 public static function requireExtension($name) 456 { return self::resolve(self::T_EXTENSION,$name,false,true); } 457 458 //--- 459 } // End of class 460 //=========================================================================== 461 462 // Registers the automap callback (append) 463 464 if (!defined('_AUTOMAP_DISABLE_REGISTER')) 465 { 466 if (!extension_loaded('spl')) 467 throw new \Exception("Automap requires the SPL extension"); 468 469 spl_autoload_register('\Automap\Mgr::autoloadHook'); 470 } 471 472 Mgr::init(); 473 474 //--- 475 } // End of class_exists 476 //=========================================================================== 477 } // End of namespace 478 //=========================================================================== 479 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Jun 4 18:32:29 2015 | Cross-referenced by PHPXref 0.7.1 |