Source for file loader.php

Documentation is available at loader.php

  1. <?php
  2. /**
  3.  * @package    Joomla.Platform
  4.  *
  5.  * @copyright  Copyright (C) 2005 - 2013 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.             foreach ($iterator as $file)
  88.             {
  89.                 $fileName $file->getFilename();
  90.  
  91.                 // Only load for php files.
  92.                 // Note: DirectoryIterator::getExtension only available PHP >= 5.3.6
  93.                 if ($file->isFile(&& substr($fileNamestrrpos($fileName'.'1== '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($classfalse))
  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[$prefixarray($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[$namespacearray($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($class1);
  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_SEPARATORsubstr($class0$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($classfalse))
  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($class1);
  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($prefixstrlen($class$class[strlen($prefix)0;
  504.  
  505.             if (strpos($class$prefix=== && ($chr === strtoupper($chr)))
  506.             {
  507.                 return self::_load(substr($classstrlen($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=== 1array($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. }

Documentation generated on Tue, 19 Nov 2013 15:07:23 +0100 by phpDocumentor 1.4.3