[ Index ]

PHP Cross Reference of Joomla 3.3.0

title

Body

[close]

/libraries/ -> loader.php (source)

   1  <?php
   2  /**
   3   * @package    Joomla.Platform
   4   *
   5   * @copyright  Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
   6   * @license    GNU General Public License version 2 or later; see LICENSE
   7   */
   8  
   9  defined('JPATH_PLATFORM') or die;
  10  
  11  /**
  12   * Static class to handle loading of libraries.
  13   *
  14   * @package  Joomla.Platform
  15   * @since    11.1
  16   */
  17  abstract class JLoader
  18  {
  19      /**
  20       * Container for already imported library paths.
  21       *
  22       * @var    array
  23       * @since  11.1
  24       */
  25      protected static $classes = array();
  26  
  27      /**
  28       * Container for already imported library paths.
  29       *
  30       * @var    array
  31       * @since  11.1
  32       */
  33      protected static $imported = array();
  34  
  35      /**
  36       * Container for registered library class prefixes and path lookups.
  37       *
  38       * @var    array
  39       * @since  12.1
  40       */
  41      protected static $prefixes = array();
  42  
  43      /**
  44       * Holds proxy classes and the class names the proxy.
  45       *
  46       * @var    array
  47       * @since  3.2
  48       */
  49      protected static $classAliases = array();
  50  
  51      /**
  52       * Container for namespace => path map.
  53       *
  54       * @var    array
  55       * @since  12.3
  56       */
  57      protected static $namespaces = array();
  58  
  59      /**
  60       * Method to discover classes of a given type in a given path.
  61       *
  62       * @param   string   $classPrefix  The class name prefix to use for discovery.
  63       * @param   string   $parentPath   Full path to the parent folder for the classes to discover.
  64       * @param   boolean  $force        True to overwrite the autoload path value for the class if it already exists.
  65       * @param   boolean  $recurse      Recurse through all child directories as well as the parent path.
  66       *
  67       * @return  void
  68       *
  69       * @since   11.1
  70       */
  71  	public static function discover($classPrefix, $parentPath, $force = true, $recurse = false)
  72      {
  73          try
  74          {
  75              if ($recurse)
  76              {
  77                  $iterator = new RecursiveIteratorIterator(
  78                      new RecursiveDirectoryIterator($parentPath),
  79                      RecursiveIteratorIterator::SELF_FIRST
  80                  );
  81              }
  82              else
  83              {
  84                  $iterator = new DirectoryIterator($parentPath);
  85              }
  86  
  87              /* @type  $file  DirectoryIterator */
  88              foreach ($iterator as $file)
  89              {
  90                  $fileName = $file->getFilename();
  91  
  92                  // Only load for php files.
  93                  if ($file->isFile() && $file->getExtension() == 'php')
  94                  {
  95                      // Get the class name and full path for each file.
  96                      $class = strtolower($classPrefix . preg_replace('#\.php$#', '', $fileName));
  97  
  98                      // Register the class with the autoloader if not already registered or the force flag is set.
  99                      if (empty(self::$classes[$class]) || $force)
 100                      {
 101                          self::register($class, $file->getPath() . '/' . $fileName);
 102                      }
 103                  }
 104              }
 105          }
 106          catch (UnexpectedValueException $e)
 107          {
 108              // Exception will be thrown if the path is not a directory. Ignore it.
 109          }
 110      }
 111  
 112      /**
 113       * Method to get the list of registered classes and their respective file paths for the autoloader.
 114       *
 115       * @return  array  The array of class => path values for the autoloader.
 116       *
 117       * @since   11.1
 118       */
 119  	public static function getClassList()
 120      {
 121          return self::$classes;
 122      }
 123  
 124      /**
 125       * Method to get the list of registered namespaces.
 126       *
 127       * @return  array  The array of namespace => path values for the autoloader.
 128       *
 129       * @since   12.3
 130       */
 131  	public static function getNamespaces()
 132      {
 133          return self::$namespaces;
 134      }
 135  
 136      /**
 137       * Loads a class from specified directories.
 138       *
 139       * @param   string  $key   The class name to look for (dot notation).
 140       * @param   string  $base  Search this directory for the class.
 141       *
 142       * @return  boolean  True on success.
 143       *
 144       * @since   11.1
 145       */
 146  	public static function import($key, $base = null)
 147      {
 148          // Only import the library if not already attempted.
 149          if (!isset(self::$imported[$key]))
 150          {
 151              // Setup some variables.
 152              $success = false;
 153              $parts = explode('.', $key);
 154              $class = array_pop($parts);
 155              $base = (!empty($base)) ? $base : __DIR__;
 156              $path = str_replace('.', DIRECTORY_SEPARATOR, $key);
 157  
 158              // Handle special case for helper classes.
 159              if ($class == 'helper')
 160              {
 161                  $class = ucfirst(array_pop($parts)) . ucfirst($class);
 162              }
 163              // Standard class.
 164              else
 165              {
 166                  $class = ucfirst($class);
 167              }
 168  
 169              // If we are importing a library from the Joomla namespace set the class to autoload.
 170              if (strpos($path, 'joomla') === 0)
 171              {
 172                  // Since we are in the Joomla namespace prepend the classname with J.
 173                  $class = 'J' . $class;
 174  
 175                  // Only register the class for autoloading if the file exists.
 176                  if (is_file($base . '/' . $path . '.php'))
 177                  {
 178                      self::$classes[strtolower($class)] = $base . '/' . $path . '.php';
 179                      $success = true;
 180                  }
 181              }
 182              /*
 183               * If we are not importing a library from the Joomla namespace directly include the
 184               * file since we cannot assert the file/folder naming conventions.
 185               */
 186              else
 187              {
 188                  // If the file exists attempt to include it.
 189                  if (is_file($base . '/' . $path . '.php'))
 190                  {
 191                      $success = (bool) include_once $base . '/' . $path . '.php';
 192                  }
 193              }
 194  
 195              // Add the import key to the memory cache container.
 196              self::$imported[$key] = $success;
 197          }
 198  
 199          return self::$imported[$key];
 200      }
 201  
 202      /**
 203       * Load the file for a class.
 204       *
 205       * @param   string  $class  The class to be loaded.
 206       *
 207       * @return  boolean  True on success
 208       *
 209       * @since   11.1
 210       */
 211  	public static function load($class)
 212      {
 213          // Sanitize class name.
 214          $class = strtolower($class);
 215  
 216          // If the class already exists do nothing.
 217          if (class_exists($class, false))
 218          {
 219              return true;
 220          }
 221  
 222          // If the class is registered include the file.
 223          if (isset(self::$classes[$class]))
 224          {
 225              include_once self::$classes[$class];
 226  
 227              return true;
 228          }
 229  
 230          return false;
 231      }
 232  
 233      /**
 234       * Directly register a class to the autoload list.
 235       *
 236       * @param   string   $class  The class name to register.
 237       * @param   string   $path   Full path to the file that holds the class to register.
 238       * @param   boolean  $force  True to overwrite the autoload path value for the class if it already exists.
 239       *
 240       * @return  void
 241       *
 242       * @since   11.1
 243       */
 244  	public static function register($class, $path, $force = true)
 245      {
 246          // Sanitize class name.
 247          $class = strtolower($class);
 248  
 249          // Only attempt to register the class if the name and file exist.
 250          if (!empty($class) && is_file($path))
 251          {
 252              // Register the class with the autoloader if not already registered or the force flag is set.
 253              if (empty(self::$classes[$class]) || $force)
 254              {
 255                  self::$classes[$class] = $path;
 256              }
 257          }
 258      }
 259  
 260      /**
 261       * Register a class prefix with lookup path.  This will allow developers to register library
 262       * packages with different class prefixes to the system autoloader.  More than one lookup path
 263       * may be registered for the same class prefix, but if this method is called with the reset flag
 264       * set to true then any registered lookups for the given prefix will be overwritten with the current
 265       * lookup path. When loaded, prefix paths are searched in a "last in, first out" order.
 266       *
 267       * @param   string   $prefix   The class prefix to register.
 268       * @param   string   $path     Absolute file path to the library root where classes with the given prefix can be found.
 269       * @param   boolean  $reset    True to reset the prefix with only the given lookup path.
 270       * @param   boolean  $prepend  If true, push the path to the beginning of the prefix lookup paths array.
 271       *
 272       * @return  void
 273       *
 274       * @throws  RuntimeException
 275       *
 276       * @since   12.1
 277       */
 278  	public static function registerPrefix($prefix, $path, $reset = false, $prepend = false)
 279      {
 280          // Verify the library path exists.
 281          if (!file_exists($path))
 282          {
 283              throw new RuntimeException('Library path ' . $path . ' cannot be found.', 500);
 284          }
 285  
 286          // If the prefix is not yet registered or we have an explicit reset flag then set set the path.
 287          if (!isset(self::$prefixes[$prefix]) || $reset)
 288          {
 289              self::$prefixes[$prefix] = array($path);
 290          }
 291          // Otherwise we want to simply add the path to the prefix.
 292          else
 293          {
 294              if ($prepend)
 295              {
 296                  array_unshift(self::$prefixes[$prefix], $path);
 297              }
 298              else
 299              {
 300                  self::$prefixes[$prefix][] = $path;
 301              }
 302          }
 303      }
 304  
 305      /**
 306       * Offers the ability for "just in time" usage of `class_alias()`.
 307       * You cannot overwrite an existing alias.
 308       *
 309       * @param   string  $alias     The alias name to register.
 310       * @param   string  $original  The original class to alias.
 311       *
 312       * @return  boolean  True if registration was successful. False if the alias already exists.
 313       *
 314       * @since   3.2
 315       */
 316  	public static function registerAlias($alias, $original)
 317      {
 318          if (!isset(self::$classAliases[$alias]))
 319          {
 320              self::$classAliases[$alias] = $original;
 321  
 322              return true;
 323          }
 324  
 325          return false;
 326      }
 327  
 328      /**
 329       * Register a namespace to the autoloader. When loaded, namespace paths are searched in a "last in, first out" order.
 330       *
 331       * @param   string   $namespace  A case sensitive Namespace to register.
 332       * @param   string   $path       A case sensitive absolute file path to the library root where classes of the given namespace can be found.
 333       * @param   boolean  $reset      True to reset the namespace with only the given lookup path.
 334       * @param   boolean  $prepend    If true, push the path to the beginning of the namespace lookup paths array.
 335       *
 336       * @return  void
 337       *
 338       * @throws  RuntimeException
 339       *
 340       * @since   12.3
 341       */
 342  	public static function registerNamespace($namespace, $path, $reset = false, $prepend = false)
 343      {
 344          // Verify the library path exists.
 345          if (!file_exists($path))
 346          {
 347              throw new RuntimeException('Library path ' . $path . ' cannot be found.', 500);
 348          }
 349  
 350          // If the namespace is not yet registered or we have an explicit reset flag then set the path.
 351          if (!isset(self::$namespaces[$namespace]) || $reset)
 352          {
 353              self::$namespaces[$namespace] = array($path);
 354          }
 355  
 356          // Otherwise we want to simply add the path to the namespace.
 357          else
 358          {
 359              if ($prepend)
 360              {
 361                  array_unshift(self::$namespaces[$namespace], $path);
 362              }
 363              else
 364              {
 365                  self::$namespaces[$namespace][] = $path;
 366              }
 367          }
 368      }
 369  
 370      /**
 371       * Method to setup the autoloaders for the Joomla Platform.
 372       * Since the SPL autoloaders are called in a queue we will add our explicit
 373       * class-registration based loader first, then fall back on the autoloader based on conventions.
 374       * This will allow people to register a class in a specific location and override platform libraries
 375       * as was previously possible.
 376       *
 377       * @param   boolean  $enablePsr       True to enable autoloading based on PSR-0.
 378       * @param   boolean  $enablePrefixes  True to enable prefix based class loading (needed to auto load the Joomla core).
 379       * @param   boolean  $enableClasses   True to enable class map based class loading (needed to auto load the Joomla core).
 380       *
 381       * @return  void
 382       *
 383       * @since   12.3
 384       */
 385  	public static function setup($enablePsr = true, $enablePrefixes = true, $enableClasses = true)
 386      {
 387          if ($enableClasses)
 388          {
 389              // Register the class map based autoloader.
 390              spl_autoload_register(array('JLoader', 'load'));
 391          }
 392  
 393          if ($enablePrefixes)
 394          {
 395              // Register the J prefix and base path for Joomla platform libraries.
 396              self::registerPrefix('J', JPATH_PLATFORM . '/joomla');
 397  
 398              // Register the prefix autoloader.
 399              spl_autoload_register(array('JLoader', '_autoload'));
 400          }
 401  
 402          if ($enablePsr)
 403          {
 404              // Register the PSR-0 based autoloader.
 405              spl_autoload_register(array('JLoader', 'loadByPsr0'));
 406              spl_autoload_register(array('JLoader', 'loadByAlias'));
 407          }
 408      }
 409  
 410      /**
 411       * Method to autoload classes that are namespaced to the PSR-0 standard.
 412       *
 413       * @param   string  $class  The fully qualified class name to autoload.
 414       *
 415       * @return  boolean  True on success, false otherwise.
 416       *
 417       * @since   13.1
 418       */
 419  	public static function loadByPsr0($class)
 420      {
 421          // Remove the root backslash if present.
 422          if ($class[0] == '\\')
 423          {
 424              $class = substr($class, 1);
 425          }
 426  
 427          // Find the location of the last NS separator.
 428          $pos = strrpos($class, '\\');
 429  
 430          // If one is found, we're dealing with a NS'd class.
 431          if ($pos !== false)
 432          {
 433              $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)) . DIRECTORY_SEPARATOR;
 434              $className = substr($class, $pos + 1);
 435          }
 436          // If not, no need to parse path.
 437          else
 438          {
 439              $classPath = null;
 440              $className = $class;
 441          }
 442  
 443          $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
 444  
 445          // Loop through registered namespaces until we find a match.
 446          foreach (self::$namespaces as $ns => $paths)
 447          {
 448              if (strpos($class, $ns) === 0)
 449              {
 450                  // Loop through paths registered to this namespace until we find a match.
 451                  foreach ($paths as $path)
 452                  {
 453                      $classFilePath = $path . DIRECTORY_SEPARATOR . $classPath;
 454  
 455                      // We check for class_exists to handle case-sensitive file systems
 456                      if (file_exists($classFilePath) && !class_exists($class, false))
 457                      {
 458                          return (bool) include_once $classFilePath;
 459                      }
 460                  }
 461              }
 462          }
 463  
 464          return false;
 465      }
 466  
 467      /**
 468       * Method to autoload classes that have been aliased using the registerAlias method.
 469       *
 470       * @param   string  $class  The fully qualified class name to autoload.
 471       *
 472       * @return  boolean  True on success, false otherwise.
 473       *
 474       * @since   3.2
 475       */
 476  	public static function loadByAlias($class)
 477      {
 478          // Remove the root backslash if present.
 479          if ($class[0] == '\\')
 480          {
 481              $class = substr($class, 1);
 482          }
 483  
 484          if (isset(self::$classAliases[$class]))
 485          {
 486              class_alias(self::$classAliases[$class], $class);
 487          }
 488      }
 489  
 490      /**
 491       * Autoload a class based on name.
 492       *
 493       * @param   string  $class  The class to be loaded.
 494       *
 495       * @return  boolean  True if the class was loaded, false otherwise.
 496       *
 497       * @since   11.3
 498       */
 499  	private static function _autoload($class)
 500      {
 501          foreach (self::$prefixes as $prefix => $lookup)
 502          {
 503              $chr = strlen($prefix) < strlen($class) ? $class[strlen($prefix)] : 0;
 504  
 505              if (strpos($class, $prefix) === 0 && ($chr === strtoupper($chr)))
 506              {
 507                  return self::_load(substr($class, strlen($prefix)), $lookup);
 508              }
 509          }
 510  
 511          return false;
 512      }
 513  
 514      /**
 515       * Load a class based on name and lookup array.
 516       *
 517       * @param   string  $class   The class to be loaded (wihtout prefix).
 518       * @param   array   $lookup  The array of base paths to use for finding the class file.
 519       *
 520       * @return  boolean  True if the class was loaded, false otherwise.
 521       *
 522       * @since   12.1
 523       */
 524  	private static function _load($class, $lookup)
 525      {
 526          // Split the class name into parts separated by camelCase.
 527          $parts = preg_split('/(?<=[a-z0-9])(?=[A-Z])/x', $class);
 528  
 529          // If there is only one part we want to duplicate that part for generating the path.
 530          $parts = (count($parts) === 1) ? array($parts[0], $parts[0]) : $parts;
 531  
 532          foreach ($lookup as $base)
 533          {
 534              // Generate the path based on the class name parts.
 535              $path = $base . '/' . implode('/', array_map('strtolower', $parts)) . '.php';
 536  
 537              // Load the file if it exists.
 538              if (file_exists($path))
 539              {
 540                  return include $path;
 541              }
 542          }
 543  
 544          return false;
 545      }
 546  }
 547  
 548  /**
 549   * Global application exit.
 550   *
 551   * This function provides a single exit point for the platform.
 552   *
 553   * @param   mixed  $message  Exit code or string. Defaults to zero.
 554   *
 555   * @return  void
 556   *
 557   * @codeCoverageIgnore
 558   * @since   11.1
 559   */
 560  function jexit($message = 0)
 561  {
 562      exit($message);
 563  }
 564  
 565  /**
 566   * Intelligent file importer.
 567   *
 568   * @param   string  $path  A dot syntax path.
 569   *
 570   * @return  boolean  True on success.
 571   *
 572   * @since   11.1
 573   */
 574  function jimport($path)
 575  {
 576      return JLoader::import($path);
 577  }


Generated: Fri May 2 13:54:24 2014 Cross-referenced by PHPXref 0.7.1