[ Index ]

PHP Cross Reference of Automap

title

Body

[close]

/Automap/ -> Mgr.php (source)

   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  ?>


Generated: Thu Jun 4 18:32:29 2015 Cross-referenced by PHPXref 0.7.1