Skip to content

Commit

Permalink
[HttpFoundation] added a directory fallback for when the class is not…
Browse files Browse the repository at this point in the history
… found in registered namespaces and class prefixes
  • Loading branch information
fabpot committed Jan 20, 2011
1 parent e414e06 commit 24ff22a
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 33 deletions.
66 changes: 66 additions & 0 deletions src/Symfony/Component/HttpFoundation/UniversalClassLoader.php
Expand Up @@ -55,17 +55,69 @@ class UniversalClassLoader
{
protected $namespaces = array();
protected $prefixes = array();
protected $namespaceFallback;
protected $prefixFallback;

/**
* Gets the configured namespaces.
*
* @return array A hash with namespaces as keys and directories as values
*/
public function getNamespaces()
{
return $this->namespaces;
}

/**
* Gets the configured class prefixes.
*
* @return array A hash with class prefixes as keys and directories as values
*/
public function getPrefixes()
{
return $this->prefixes;
}

/**
* Gets the directory to use as a fallback for namespaces.
*
* @return string A directory path
*/
public function getNamespaceFallback()
{
return $this->namespaceFallback;
}

/**
* Gets the directory to use as a fallback for class prefixes.
*
* @return string A directory path
*/
public function getPrefixFallback()
{
return $this->prefixFallback;
}

/**
* Registers the directory to use as a fallback for namespaces.
*
* @return string $dir A directory path
*/
public function registerNamespaceFallback($dir)
{
$this->namespaceFallback = $dir;
}

/**
* Registers the directory to use as a fallback for class prefixes.
*
* @param string $dir A directory path
*/
public function registerPrefixFallback($dir)
{
$this->prefixFallback = $dir;
}

/**
* Registers an array of namespaces
*
Expand Down Expand Up @@ -140,6 +192,13 @@ public function loadClass($class)
}
}
}

if (null !== $this->namespaceFallback) {
$file = $this->namespaceFallback.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
if (file_exists($file)) {
require $file;
}
}
} else {
// PEAR-like class name
foreach ($this->prefixes as $prefix => $dir) {
Expand All @@ -151,6 +210,13 @@ public function loadClass($class)
}
}
}

if (null !== $this->prefixFallback) {
$file = $this->prefixFallback.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
if (file_exists($file)) {
require $file;
}
}
}
}
}
Expand Up @@ -2,6 +2,7 @@

namespace Namespaced;

class Bar {
class Bar
{
public static $loaded = true;
}
}
@@ -0,0 +1,8 @@
<?php

namespace Namespaced;

class Baz
{
public static $loaded = true;
}
Expand Up @@ -2,6 +2,7 @@

namespace Namespaced;

class Foo {
class Foo
{
public static $loaded = true;
}
}
@@ -1,5 +1,6 @@
<?php

class Pearlike_Bar {
class Pearlike_Bar
{
public static $loaded = true;
}
}
@@ -0,0 +1,6 @@
<?php

class Pearlike_Baz
{
public static $loaded = true;
}
@@ -1,5 +1,6 @@
<?php

class Pearlike_Foo {
class Pearlike_Foo
{
public static $loaded = true;
}
}
@@ -0,0 +1,8 @@
<?php

namespace Namespaced;

class FooBar
{
public static $loaded = true;
}
@@ -0,0 +1,6 @@
<?php

class Pearlike_FooBar
{
public static $loaded = true;
}
Expand Up @@ -16,19 +16,18 @@
class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
{
/**
* @covers Symfony\Component\HttpFoundation\UniversalClassLoader::loadClass
* @dataProvider testClassProvider
* @dataProvider getLoadClassTests
*/
public function testLoadClass($className, $testClassName, $message)
{
$loader = new UniversalClassLoader();
$loader->registerNamespace('Namespaced', __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures');
$loader->registerPrefix('Pearlike_', __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures');
$loader->registerNamespace('Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
$loader->registerPrefix('Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
$loader->loadClass($testClassName);
$this->assertTrue(class_exists($className), $message);
}

public static function testClassProvider()
public function getLoadClassTests()
{
return array(
array('\\Namespaced\\Foo', 'Namespaced\\Foo', '->loadClass() loads Namespaced\Foo class'),
Expand All @@ -39,7 +38,31 @@ public static function testClassProvider()
}

/**
* @dataProvider namespaceCollisionClassProvider
* @dataProvider getLoadClassFromFallbackTests
*/
public function testLoadClassFromFallback($className, $testClassName, $message)
{
$loader = new UniversalClassLoader();
$loader->registerNamespace('Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
$loader->registerPrefix('Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
$loader->registerNamespaceFallback(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback');
$loader->registerPrefixFallback(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback');
$loader->loadClass($testClassName);
$this->assertTrue(class_exists($className), $message);
}

public function getLoadClassFromFallbackTests()
{
return array(
array('\\Namespaced\\Baz', 'Namespaced\\Baz', '->loadClass() loads Namespaced\Baz class'),
array('\\Pearlike_Baz', 'Pearlike_Baz', '->loadClass() loads Pearlike_Baz class'),
array('\\Namespaced\\FooBar', 'Namespaced\\FooBar', '->loadClass() loads Namespaced\Baz class from fallback dir'),
array('\\Pearlike_FooBar', 'Pearlike_FooBar', '->loadClass() loads Pearlike_Baz class from fallback dir'),
);
}

/**
* @dataProvider getLoadClassNamespaceCollisionTests
*/
public function testLoadClassNamespaceCollision($namespaces, $className, $message)
{
Expand All @@ -50,37 +73,37 @@ public function testLoadClassNamespaceCollision($namespaces, $className, $messag
$this->assertTrue(class_exists($className), $message);
}

public static function namespaceCollisionClassProvider()
public function getLoadClassNamespaceCollisionTests()
{
return array(
array(
array(
'NamespaceCollision\\A' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/alpha',
'NamespaceCollision\\A\\B' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/beta',
'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
),
'NamespaceCollision\A\Foo',
'->loadClass() loads NamespaceCollision\A\Foo from alpha.',
),
array(
array(
'NamespaceCollision\\A\\B' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/beta',
'NamespaceCollision\\A' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/alpha',
'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
),
'NamespaceCollision\A\Bar',
'->loadClass() loads NamespaceCollision\A\Bar from alpha.',
),
array(
array(
'NamespaceCollision\\A' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/alpha',
'NamespaceCollision\\A\\B' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/beta',
'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
),
'NamespaceCollision\A\B\Foo',
'->loadClass() loads NamespaceCollision\A\B\Foo from beta.',
),
array(
array(
'NamespaceCollision\\A\\B' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/beta',
'NamespaceCollision\\A' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/alpha',
'NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
'NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
),
'NamespaceCollision\A\B\Bar',
'->loadClass() loads NamespaceCollision\A\B\Bar from beta.',
Expand All @@ -89,7 +112,7 @@ public static function namespaceCollisionClassProvider()
}

/**
* @dataProvider prefixCollisionClassProvider
* @dataProvider getLoadClassPrefixCollisionTests
*/
public function testLoadClassPrefixCollision($prefixes, $className, $message)
{
Expand All @@ -100,37 +123,37 @@ public function testLoadClassPrefixCollision($prefixes, $className, $message)
$this->assertTrue(class_exists($className), $message);
}

public static function prefixCollisionClassProvider()
public function getLoadClassPrefixCollisionTests()
{
return array(
array(
array(
'PrefixCollision_A_' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/alpha',
'PrefixCollision_A_B_' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/beta',
'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
),
'PrefixCollision_A_Foo',
'->loadClass() loads PrefixCollision_A_Foo from alpha.',
),
array(
array(
'PrefixCollision_A_B_' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/beta',
'PrefixCollision_A_' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/alpha',
'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
),
'PrefixCollision_A_Bar',
'->loadClass() loads PrefixCollision_A_Bar from alpha.',
),
array(
array(
'PrefixCollision_A_' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/alpha',
'PrefixCollision_A_B_' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/beta',
'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
),
'PrefixCollision_A_B_Foo',
'->loadClass() loads PrefixCollision_A_B_Foo from beta.',
),
array(
array(
'PrefixCollision_A_B_' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/beta',
'PrefixCollision_A_' => __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures/alpha',
'PrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta',
'PrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha',
),
'PrefixCollision_A_B_Bar',
'->loadClass() loads PrefixCollision_A_B_Bar from beta.',
Expand Down

0 comments on commit 24ff22a

Please sign in to comment.