Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Added Namespacing. Merge from platform commits (1739 & 1591) #677

Closed
wants to merge 2 commits into from

3 participants

@davidhurley

Added Namespacing. Merged platform commits (1739 & 1591)

joomla/joomla-platform#1739
joomla/joomla-platform#1591

David Hurley added some commits
David Hurley Added Namespacing. Merge from platform commits (#1739 & #1591)
p Added Ncmespacing. Merged platform commits (#1739 & #1591)
54bcb31
David Hurley Merge platform commit #1742 a5d4ea9
@nicksavov

Looks like there's a combined PR in JoomlaCode. Thanks for coding this, David! :)

Closing.

@nicksavov nicksavov closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 22, 2013
  1. Added Namespacing. Merge from platform commits (#1739 & #1591)

    David Hurley authored
    p Added Ncmespacing. Merged platform commits (#1739 & #1591)
  2. Merge platform commit #1742

    David Hurley authored
This page is out of date. Refresh to see the latest.
Showing with 284 additions and 18 deletions.
  1. +3 −3 libraries/joomla/language/language.php
  2. +281 −15 libraries/loader.php
View
6 libraries/joomla/language/language.php
@@ -761,19 +761,19 @@ protected function loadLanguage($filename, $extension = 'unknown')
if (file_exists($filename))
{
- $strings = $this->parse($filename);
+ $strings = ksort($this->parse($filename),SORT_STRING);
}
if ($strings)
{
if (is_array($strings))
{
- $this->strings = array_merge($this->strings, $strings);
+ $this->strings = ksort(array_merge($this->strings, $strings),SORT_STRING);
}
if (is_array($strings) && count($strings))
{
- $this->strings = array_merge($this->strings, $this->override);
+ $this->strings = ksort(array_merge($this->strings, $this->override),SORT_STRING);
$result = true;
}
}
View
296 libraries/loader.php
@@ -16,6 +16,10 @@
*/
abstract class JLoader
{
+ const LOWER_CASE = 1;
+ const NATURAL_CASE = 2;
+ const MIXED_CASE = 3;
+
/**
* Container for already imported library paths.
*
@@ -41,6 +45,14 @@
protected static $prefixes = array();
/**
+ * Container for namespace => path map.
+ *
+ * @var array
+ * @since 12.3
+ */
+ protected static $namespaces = array();
+
+ /**
* Method to discover classes of a given type in a given path.
*
* @param string $classPrefix The class name prefix to use for discovery.
@@ -106,6 +118,18 @@ public static function getClassList()
}
/**
+ * Method to get the list of registered namespaces.
+ *
+ * @return array The array of namespace => path values for the autoloader.
+ *
+ * @since 12.3
+ */
+ public static function getNamespaces()
+ {
+ return self::$namespaces;
+ }
+
+ /**
* Loads a class from specified directories.
*
* @param string $key The class name to look for (dot notation).
@@ -195,9 +219,165 @@ public static function load($class)
if (isset(self::$classes[$class]))
{
include_once self::$classes[$class];
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Load a class based on namespace using the Lower Case strategy.
+ * This loader might be used when the namespace is lower case or camel case
+ * and the path lower case.
+ *
+ * @param string $class The class (including namespace) to load.
+ *
+ * @return boolean True on success, false otherwise.
+ *
+ * @since 12.3
+ */
+ public static function loadByNamespaceLowerCase($class)
+ {
+ // If the class already exists do nothing.
+ if (class_exists($class, false))
+ {
+ return true;
+ }
+
+ // Get the root namespace name.
+ $namespace = strstr($class, '\\', true);
+
+ // If we find the namespace in the stack.
+ if (isset(self::$namespaces[$namespace]))
+ {
+ // Remove the namespace name from the class.
+ $class = str_replace($namespace, '', $class);
+
+ // Create a lower case relative path.
+ $relativePath = strtolower(str_replace('\\', '/', $class));
+
+ // Iterate the registered root paths.
+ foreach (self::$namespaces[$namespace] as $rootPath)
+ {
+ // Create the full path.
+ $path = $rootPath . '/' . $relativePath . '.php';
+
+ // Include the file if it exists.
+ if (file_exists($path))
+ {
+ return (bool) include_once $path;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Load a class based on namespace using the Natural Case strategy.
+ * This loader might be used when the namespace case matches the path case.
+ *
+ * @param string $class The class (including namespace) to load.
+ *
+ * @return boolean True on success, false otherwise.
+ *
+ * @since 12.3
+ */
+ public static function loadByNamespaceNaturalCase($class)
+ {
+ // If the class already exists do nothing.
+ if (class_exists($class, false))
+ {
+ return true;
+ }
+
+ // Get the root namespace name.
+ $namespace = strstr($class, '\\', true);
+
+ // If we find the namespace in the stack.
+ if (isset(self::$namespaces[$namespace]))
+ {
+ // Remove the namespace name from the class.
+ $class = str_replace($namespace, '', $class);
+
+ // Create a relative path.
+ $relativePath = str_replace('\\', '/', $class);
+
+ // Iterate the registered root paths.
+ foreach (self::$namespaces[$namespace] as $rootPath)
+ {
+ // Create the full path.
+ $path = $rootPath . '/' . $relativePath . '.php';
+
+ // Include the file if it exists.
+ if (file_exists($path))
+ {
+ return (bool) include_once $path;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Load a class based on namespace using the Mixed Case strategy.
+ * This loader might be used when the namespace case matches the path case,
+ * or when the namespace is camel case and the path lower case.
+ *
+ * @param string $class The class (including namespace) to load.
+ *
+ * @return boolean True on success, false otherwise.
+ *
+ * @since 12.3
+ */
+ public static function loadByNamespaceMixedCase($class)
+ {
+ // If the class already exists do nothing.
+ if (class_exists($class, false))
+ {
return true;
}
+ // Get the root namespace name.
+ $namespace = strstr($class, '\\', true);
+
+ // If we find the namespace in the stack.
+ if (isset(self::$namespaces[$namespace]))
+ {
+ // Remove the namespace name from the class.
+ $class = str_replace($namespace, '', $class);
+
+ // Create a relative path.
+ $relativePath = str_replace('\\', '/', $class);
+
+ // Create a relative lower case path.
+ $relativeLowPath = strtolower($relativePath);
+
+ // Iterate the registered root paths.
+ foreach (self::$namespaces[$namespace] as $rootPath)
+ {
+ // Create the full lower case path.
+ $lowerPath = $rootPath . '/' . $relativeLowPath . '.php';
+
+ // Include the file if it exists.
+ if (file_exists($lowerPath))
+ {
+ return (bool) include_once $lowerPath;
+ }
+
+ // Create the full natural case path.
+ $naturalPath = $rootPath . '/' . $relativePath . '.php';
+
+ // Include the file if it exists.
+ if (file_exists($naturalPath))
+ {
+ return (bool) include_once $naturalPath;
+ }
+ }
+ }
+
return false;
}
@@ -233,7 +413,7 @@ public static function register($class, $path, $force = true)
* packages with different class prefixes to the system autoloader. More than one lookup path
* may be registered for the same class prefix, but if this method is called with the reset flag
* set to true then any registered lookups for the given prefix will be overwritten with the current
- * lookup path.
+ * lookup path. When loaded, prefix paths are searched in a "last in, first out" order.
*
* @param string $prefix The class prefix to register.
* @param string $path Absolute file path to the library root where classes with the given prefix can be found.
@@ -241,6 +421,8 @@ public static function register($class, $path, $force = true)
*
* @return void
*
+ * @throws RuntimeException
+ *
* @since 12.1
*/
public static function registerPrefix($prefix, $path, $reset = false)
@@ -259,28 +441,107 @@ public static function registerPrefix($prefix, $path, $reset = false)
// Otherwise we want to simply add the path to the prefix.
else
{
- self::$prefixes[$prefix][] = $path;
+ array_unshift(self::$prefixes[$prefix], $path);
}
}
/**
- * Method to setup the autoloaders for the Joomla Platform. Since the SPL autoloaders are
- * called in a queue we will add our explicit, class-registration based loader first, then
- * fall back on the autoloader based on conventions. This will allow people to register a
- * class in a specific location and override platform libraries as was previously possible.
+ * Register a namespace to the autoloader. When loaded, namespace paths are searched in a "last in, first out" order.
+ *
+ * @param string $namespace A case sensitive Namespace to register.
+ * @param string $path A case sensitive absolute file path to the library root where classes of the given namespace can be found.
+ * @param boolean $reset True to reset the namespace with only the given lookup path.
*
* @return void
*
- * @since 11.3
+ * @throws RuntimeException
+ *
+ * @since 12.3
*/
- public static function setup()
+ public static function registerNamespace($namespace, $path, $reset = false)
{
- // Register the base path for Joomla platform libraries.
- self::registerPrefix('J', JPATH_PLATFORM . '/joomla');
+ // Verify the library path exists.
+ if (!file_exists($path))
+ {
+ throw new RuntimeException('Library path ' . $path . ' cannot be found.', 500);
+ }
+
+ // If the namespace is not yet registered or we have an explicit reset flag then set the path.
+ if (!isset(self::$namespaces[$namespace]) || $reset)
+ {
+ self::$namespaces[$namespace] = array($path);
+ }
- // Register the autoloader functions.
- spl_autoload_register(array('JLoader', 'load'));
- spl_autoload_register(array('JLoader', '_autoload'));
+ // Otherwise we want to simply add the path to the namespace.
+ else
+ {
+ array_unshift(self::$namespaces[$namespace], $path);
+ }
+ }
+
+ /**
+ * Method to setup the autoloaders for the Joomla Platform.
+ * Since the SPL autoloaders are called in a queue we will add our explicit
+ * class-registration based loader first, then fall back on the autoloader based on conventions.
+ * This will allow people to register a class in a specific location and override platform libraries
+ * as was previously possible.
+ *
+ * @param integer $caseStrategy An option to define the class finding strategy for the namespace loader
+ * depending on the namespace and class path case.
+ * The possible values are :
+ * JLoader::LOWER_CASE : The namespace can be either lower case or camel case and the path lower case.
+ * JLoader::NATURAL_CASE : The namespace case matches the path case.
+ * JLoader::MIXED_CASE : It regroups option 1 and option 2.
+ * @param boolean $enableNamespaces True to enable PHP namespace based class autoloading.
+ * @param boolean $enablePrefixes True to enable prefix based class loading (needed to auto load the Joomla core).
+ * @param boolean $enableClasses True to enable class map based class loading (needed to auto load the Joomla core).
+ *
+ * @return boolean True if the class was loaded, false otherwise.
+ *
+ * @since 12.3
+ */
+ public static function setup($caseStrategy = self::LOWER_CASE, $enableNamespaces = false, $enablePrefixes = true, $enableClasses = true)
+ {
+ if ($enableClasses)
+ {
+ // Register the class map based autoloader.
+ spl_autoload_register(array('JLoader', 'load'));
+ }
+
+ if ($enablePrefixes)
+ {
+ // Register the J prefix and base path for Joomla platform libraries.
+ self::registerPrefix('J', JPATH_PLATFORM . '/joomla');
+
+ // Register the prefix autoloader.
+ spl_autoload_register(array('JLoader', '_autoload'));
+ }
+
+ if ($enableNamespaces)
+ {
+ switch ($caseStrategy)
+ {
+ // Register the lower case namespace loader.
+ case self::LOWER_CASE:
+ spl_autoload_register(array('JLoader', 'loadByNamespaceLowerCase'));
+ break;
+
+ // Register the natural case namespace loader.
+ case self::NATURAL_CASE:
+ spl_autoload_register(array('JLoader', 'loadByNamespaceNaturalCase'));
+ break;
+
+ // Register the mixed case namespace loader.
+ case self::MIXED_CASE:
+ spl_autoload_register(array('JLoader', 'loadByNamespaceMixedCase'));
+ break;
+
+ // Default to the lower case namespace loader.
+ default:
+ spl_autoload_register(array('JLoader', 'loadByNamespaceLowerCase'));
+ break;
+ }
+ }
}
/**
@@ -288,7 +549,7 @@ public static function setup()
*
* @param string $class The class to be loaded.
*
- * @return void
+ * @return boolean True if the class was loaded, false otherwise.
*
* @since 11.3
*/
@@ -297,11 +558,14 @@ private static function _autoload($class)
foreach (self::$prefixes as $prefix => $lookup)
{
$chr = strlen($prefix) < strlen($class) ? $class[strlen($prefix)] : 0;
+
if (strpos($class, $prefix) === 0 && ($chr === strtoupper($chr)))
{
return self::_load(substr($class, strlen($prefix)), $lookup);
}
}
+
+ return false;
}
/**
@@ -333,6 +597,8 @@ private static function _load($class, $lookup)
return include $path;
}
}
+
+ return false;
}
}
@@ -365,4 +631,4 @@ function jexit($message = 0)
function jimport($path)
{
return JLoader::import($path);
-}
+}
Something went wrong with that request. Please try again.