Преглед на файлове

[Foundation] updated the autoloader, added a new one

Fabien Potencier преди 15 години
родител
ревизия
81340d349b
променени са 2 файла, в които са добавени 165 реда и са изтрити 57 реда
  1. 18 57
      src/Symfony/Foundation/ClassLoader.php
  2. 147 0
      src/Symfony/Foundation/UniversalClassLoader.php

+ 18 - 57
src/Symfony/Foundation/ClassLoader.php

@@ -15,7 +15,7 @@ namespace Symfony\Foundation;
  * ClassLoader implementation that implements the technical interoperability
  * standards for PHP 5.3 namespaces and class names.
  *
- * Based on http://groups.google.com/group/php-standards/web/final-proposal
+ * Based on http://groups.google.com/group/php-standards/web/psr-0-final-proposal
  *
  * Example usage:
  *
@@ -42,19 +42,7 @@ class ClassLoader
    */
   public function registerNamespace($namespace, $includePath = null)
   {
-    if (!isset($this->namespaces[$namespace]))
-    {
-      $this->namespaces[$namespace] = $includePath;
-    }
-    else
-    {
-      if (!is_array($this->namespaces[$namespace]))
-      {
-        $this->namespaces[$namespace] = array($this->namespaces[$namespace]);
-      }
-
-      $this->namespaces[$namespace][] = $includePath;
-    }
+    $this->namespaces[$namespace] = $includePath;
   }
 
   /**
@@ -65,14 +53,6 @@ class ClassLoader
     spl_autoload_register(array($this, 'loadClass'));
   }
 
-  /**
-   * Uninstalls this class loader from the SPL autoloader stack.
-   */
-  public function unregister()
-  {
-    spl_autoload_unregister(array($this, 'loadClass'));
-  }
-
   /**
    * Loads the given class or interface.
    *
@@ -81,43 +61,24 @@ class ClassLoader
   public function loadClass($className)
   {
     $vendor = substr($className, 0, stripos($className, '\\'));
-    if ($vendor || isset($this->namespaces['']))
+    if (!isset($this->namespaces[$vendor]))
     {
-      $fileName = '';
-      $namespace = '';
-      if (false !== ($lastNsPos = strripos($className, '\\')))
-      {
-        $namespace = substr($className, 0, $lastNsPos);
-        $className = substr($className, $lastNsPos + 1);
-        $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR;
-      }
-      $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
-
-      if (null !== $this->namespaces[$vendor])
-      {
-        if (is_array($this->namespaces[$vendor]))
-        {
-          foreach ($this->namespaces[$vendor] as $dir)
-          {
-            if (!file_exists($dir.DIRECTORY_SEPARATOR.$fileName))
-            {
-              continue;
-            }
-
-            require $dir.DIRECTORY_SEPARATOR.$fileName;
+      return;
+    }
 
-            break;
-          }
-        }
-        else
-        {
-          require $this->namespaces[$vendor].DIRECTORY_SEPARATOR.$fileName;
-        }
-      }
-      else
-      {
-        require $fileName;
-      }
+    if (false !== ($lastNsPos = strripos($className, '\\')))
+    {
+      $namespace = substr($className, 0, $lastNsPos);
+      $className = substr($className, $lastNsPos + 1);
+      $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR;
     }
+    else
+    {
+      $namespace = '';
+      $fileName = '';
+    }
+    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
+
+    require $this->namespaces[$vendor].DIRECTORY_SEPARATOR.$fileName;
   }
 }

+ 147 - 0
src/Symfony/Foundation/UniversalClassLoader.php

@@ -0,0 +1,147 @@
+<?php
+
+namespace Symfony\Foundation;
+
+/*
+ * This file is part of the symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * UniversalClassLoader implements a "universal" autoloder for PHP 5.3.
+ *
+ * It is able to load classes that use either:
+ *
+ *  * The technical interoperability standards for PHP 5.3 namespaces and
+ *    class names (http://groups.google.com/group/php-standards/web/final-proposal);
+ *
+ *  * The PEAR naming convention for classes (http://pear.php.net/).
+ *
+ * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be
+ * looked for in a list of locations to ease the vendoring of a sub-set of
+ * classes for large projects.
+ *
+ * Example usage:
+ *
+ *     $loader = new ClassLoader();
+ *
+ *     // register classes with namespaces
+ *     $loader->registerNamespaces(array(
+ *       'Symfony\Components' => __DIR__.'/components',
+ *       'Symfony' => __DIR__.'/framework',
+ *     ));
+ *
+ *     // register a library using the PEAR naming convention
+ *     $loader->registerClasses(array(
+ *       'Swift_' => __DIR__.'/Swift',
+ *     ));
+ *
+ *     // activate the autoloader
+ *     $loader->register();
+ *
+ * In this example, if you try to use a class in the Symfony\Components
+ * namespace or one of its children (Symfony\Components\Console for instance),
+ * the autoloader will first look for the class under the components/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * @package    symfony
+ * @subpackage foundation
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.org>
+ */
+class UniversalClassLoader
+{
+  protected $namespaces = array();
+  protected $prefixes = array();
+
+  /**
+   * Registers an array of namespaces
+   *
+   * @param array $namespaces An array of namespaces (namespaces as keys and locations as values)
+   */
+  public function registerNamespaces(array $namespaces)
+  {
+    $this->namespaces = array_merge($this->namespaces, $namespaces);
+  }
+
+  /**
+   * Registers a namespace.
+   *
+   * @param string $namespace The namespace
+   * @param string $path      The location of the namespace
+   */
+  public function registerNamespace($namespace, $path)
+  {
+    $this->namespaces[$namespace] = $path;
+  }
+
+  /**
+   * Registers an array of classes using the PEAR naming convention.
+   *
+   * @param array $classes An array of classes (prefixes as keys and locations as values)
+   */
+  public function registerPrefixes(array $classes)
+  {
+    $this->prefixes = array_merge($this->prefixes, $classes);
+  }
+
+  /**
+   * Registers a set of classes using the PEAR naming convention.
+   *
+   * @param string $prefix The classes prefix
+   * @param string $path   The location of the classes
+   */
+  public function registerPrefix($prefix, $path)
+  {
+    $this->prefixes[$prefix] = $path;
+  }
+
+  /**
+   * Registers this instance as an autoloader.
+   */
+  public function register()
+  {
+    spl_autoload_register(array($this, 'loadClass'));
+  }
+
+  /**
+   * Loads the given class or interface.
+   *
+   * @param string $class The name of the class
+   */
+  public function loadClass($class)
+  {
+    if (false !== ($pos = strripos($class, '\\')))
+    {
+      // namespaced class name
+      $namespace = substr($class, 0, $pos);
+      foreach ($this->namespaces as $ns => $dir)
+      {
+        if (0 === strpos($namespace, $ns))
+        {
+          $class = substr($class, $pos + 1);
+          require $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
+
+          return;
+        }
+      }
+    }
+    else
+    {
+      // PEAR-like class name
+      foreach ($this->prefixes as $prefix => $dir)
+      {
+        if (0 === strpos($class, $prefix))
+        {
+          require $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
+
+          return;
+        }
+      }
+    }
+  }
+}