ENHANCEMENT Added $exclusive flag to SS_ClassLoader->pushManifest() to allow for multiple manifests co-existing (useful for tests which rely on core classes but also want to test their own manifests)

This commit is contained in:
Ingo Schommer 2011-11-27 10:49:42 +01:00
parent a3e74bb2ef
commit 0a0be63ee2
4 changed files with 107 additions and 7 deletions

View File

@ -14,7 +14,7 @@ class SS_ClassLoader {
private static $instance;
/**
* @var SS_ClassManifest[]
* @var array Map of 'instance' (SS_ClassManifest) and other options.
*/
protected $manifests = array();
@ -32,7 +32,7 @@ class SS_ClassLoader {
* @return SS_ClassManifest
*/
public function getManifest() {
return $this->manifests[count($this->manifests) - 1];
return $this->manifests[count($this->manifests) - 1]['instance'];
}
/**
@ -47,16 +47,23 @@ class SS_ClassLoader {
* also include any module configuration files at the same time.
*
* @param SS_ClassManifest $manifest
* @param Boolean Marks the manifest as exclusive. If set to FALSE, will
* look for classes in earlier manifests as well.
*/
public function pushManifest(SS_ClassManifest $manifest) {
$this->manifests[] = $manifest;
public function pushManifest(SS_ClassManifest $manifest, $exclusive = true) {
$this->manifests[] = array('exclusive' => $exclusive, 'instance' => $manifest);
foreach ($manifest->getConfigs() as $config) {
require_once $config;
}
}
/**
* @return SS_ClassManifest
*/
public function popManifest() {
return array_pop($this->manifests);
$manifest = array_pop($this->manifests);
return $manifest['instance'];
}
public function registerAutoloader() {
@ -68,11 +75,28 @@ class SS_ClassLoader {
* manifest.
*
* @param string $class
* @return String
*/
public function loadClass($class) {
if ($path = $this->getManifest()->getItemPath($class)) {
if ($path = $this->getItemPath($class)) {
require_once $path;
}
return $path;
}
/**
* Returns the path for a class or interface in the currently active manifest,
* or any previous ones if later manifests aren't set to "exclusive".
*
* @return String
*/
public function getItemPath($class) {
foreach(array_reverse($this->manifests) as $manifest) {
$manifestInst = $manifest['instance'];
if ($path = $manifestInst->getItemPath($class)) return $path;
if($manifest['exclusive']) break;
}
return false;
}
/**
@ -82,7 +106,7 @@ class SS_ClassLoader {
* @return bool
*/
public function classExists($class) {
return class_exists($class, false) || $this->getManifest()->getItemPath($class);
return class_exists($class, false) || $this->getItemPath($class);
}
}

View File

@ -0,0 +1,71 @@
<?php
/**
* Tests for the {@link SS_ClassManifest} class.
*
* @package sapphire
* @subpackage tests
*/
class ClassLoaderTest extends SapphireTest {
protected $base;
protected $manifest;
function setUp() {
parent::setUp();
$this->baseManifest1 = dirname(__FILE__) . '/fixtures/classmanifest';
$this->baseManifest2 = dirname(__FILE__) . '/fixtures/classmanifest_other';
$this->testManifest1 = new SS_ClassManifest($this->baseManifest1, false, true, false);
$this->testManifest2 = new SS_ClassManifest($this->baseManifest2, false, true, false);
}
function testExclusive() {
$loader = new SS_ClassLoader();
$loader->pushManifest($this->testManifest1);
$this->assertTrue((bool)$loader->getItemPath('ClassA'));
$this->assertFalse((bool)$loader->getItemPath('OtherClassA'));
$loader->pushManifest($this->testManifest2);
$this->assertFalse((bool)$loader->getItemPath('ClassA'));
$this->assertTrue((bool)$loader->getItemPath('OtherClassA'));
$loader->popManifest();
$loader->pushManifest($this->testManifest2, false);
$this->assertTrue((bool)$loader->getItemPath('ClassA'));
$this->assertTrue((bool)$loader->getItemPath('OtherClassA'));
}
function testGetItemPath() {
$ds = DIRECTORY_SEPARATOR;
$loader = new SS_ClassLoader();
$loader->pushManifest($this->testManifest1);
$this->assertEquals(
$this->baseManifest1 . $ds . 'module' . $ds . 'classes' . $ds . 'ClassA.php',
$loader->getItemPath('ClassA')
);
$this->assertEquals(
false,
$loader->getItemPath('UnknownClass')
);
$this->assertEquals(
false,
$loader->getItemPath('OtherClassA')
);
$loader->pushManifest($this->testManifest2);
$this->assertEquals(
false,
$loader->getItemPath('ClassA')
);
$this->assertEquals(
false,
$loader->getItemPath('UnknownClass')
);
$this->assertEquals(
$this->baseManifest2 . $ds . 'module' . $ds . 'classes' . $ds . 'OtherClassA.php',
$loader->getItemPath('OtherClassA')
);
}
}

View File

@ -0,0 +1,5 @@
<?php
/**
* @ignore
*/
class OtherClassA { }