Permalink
Browse files

[ClassLoader] A PSR-4 compatible class loader

  • Loading branch information...
1 parent 4ad343b commit 6837df3e144c2e12b38a84f4b7cb847f6f13eefc @derrabus derrabus committed with fabpot Jan 18, 2014
@@ -0,0 +1,94 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\ClassLoader;
+
+/**
+ * A PSR-4 compatible class loader.
+ *
+ * See http://www.php-fig.org/psr/psr-4/
+ *
+ * @author Alexander M. Turek <me@derrabus.de>
+ */
+class Psr4ClassLoader
+{
+ /**
+ * @var array
+ */
+ private $prefixes = array();
+
+ /**
+ * @param string $prefix
+ * @param string $baseDir
+ */
+ public function addPrefix($prefix, $baseDir)
+ {
+ $prefix = trim($prefix, '\\').'\\';
+ $baseDir = rtrim($baseDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
+ $this->prefixes[] = array($prefix, $baseDir);
+ }
+
+ /**
+ * @param string $class
+ *
+ * @return string|null
+ */
+ public function findFile($class)
+ {
+ $class = ltrim($class, '\\');
+
+ foreach ($this->prefixes as $current) {
+ list($currentPrefix, $currentBaseDir) = $current;
+ if (0 === strpos($class, $currentPrefix)) {
+ $classWithoutPrefix = substr($class, strlen($currentPrefix));
+ $file = $currentBaseDir . str_replace('\\', DIRECTORY_SEPARATOR, $classWithoutPrefix) . '.php';
+ if (file_exists($file)) {
+ return $file;
+ }
+ }
+ }
+ }
+
+ /**
+ * @param string $class
+ *
+ * @return Boolean
+ */
+ public function loadClass($class)
+ {
+ $file = $this->findFile($class);
+ if (null !== $file) {
+ require $file;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Registers this instance as an autoloader.
+ *
+ * @param Boolean $prepend
+ */
+ public function register($prepend = false)
+ {
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+ }
+
+ /**
+ * Removes this instance from the registered autoloaders.
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+ }
+}
@@ -0,0 +1,7 @@
+<?php
+
+namespace Acme\DemoLib;
+
+class Class_With_Underscores
+{
+}
@@ -0,0 +1,7 @@
+<?php
+
+namespace Acme\DemoLib;
+
+class Foo
+{
+}
@@ -0,0 +1,7 @@
+<?php
+
+namespace Acme\DemoLib\Lets\Go\Deeper;
+
+class Class_With_Underscores
+{
+}
@@ -0,0 +1,7 @@
+<?php
+
+namespace Acme\DemoLib\Lets\Go\Deeper;
+
+class Foo
+{
+}
@@ -0,0 +1,71 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\ClassLoader\Tests;
+
+use Symfony\Component\ClassLoader\Psr4ClassLoader;
+
+class Psr4ClassLoaderTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @param string $className
+ * @dataProvider getLoadClassTests
+ */
+ public function testLoadClass($className)
+ {
+ $loader = new Psr4ClassLoader();
+ $loader->addPrefix(
+ 'Acme\\DemoLib',
+ __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'psr-4'
+ );
+ $loader->loadClass($className);
+ $this->assertTrue(class_exists($className), sprintf('loadClass() should load %s', $className));
+ }
+
+ /**
+ * @return array
+ */
+ public function getLoadClassTests()
+ {
+ return array(
+ array('Acme\\DemoLib\\Foo'),
+ array('Acme\\DemoLib\\Class_With_Underscores'),
+ array('Acme\\DemoLib\\Lets\\Go\\Deeper\\Foo'),
+ array('Acme\\DemoLib\\Lets\\Go\\Deeper\\Class_With_Underscores')
+ );
+ }
+
+ /**
+ * @param string $className
+ * @dataProvider getLoadNonexistentClassTests
+ */
+ public function testLoadNonexistentClass($className)
+ {
+ $loader = new Psr4ClassLoader();
+ $loader->addPrefix(
+ 'Acme\\DemoLib',
+ __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'psr-4'
+ );
+ $loader->loadClass($className);
+ $this->assertFalse(class_exists($className), sprintf('loadClass() should not load %s', $className));
+ }
+
+ /**
+ * @return array
+ */
+ public function getLoadNonexistentClassTests()
+ {
+ return array(
+ array('Acme\\DemoLib\\I_Do_Not_Exist'),
+ array('UnknownVendor\\SomeLib\\I_Do_Not_Exist')
+ );
+ }
+}

0 comments on commit 6837df3

Please sign in to comment.