Sfoglia il codice sorgente

Added root namespace functionality to autoloader.

Taddeus Kroes 13 anni fa
parent
commit
04252c05a5
2 ha cambiato i file con 118 aggiunte e 16 eliminazioni
  1. 46 9
      autoloader.php
  2. 72 7
      tests/test_autoloader.php

+ 46 - 9
autoloader.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * 
+ * A tool for autoloading PHP classes within a root directory and namespace.
  * 
  * @author Taddeus Kroes
  * @version 1.0
@@ -65,12 +65,11 @@ class Autoloader extends Base {
 	/**
 	 * The namespace classes in the root directory are expected to be in.
 	 * 
-	 * This namespace is removed from loaded class names.
+	 * This namespace is removed from the beginning of loaded class names.
 	 * 
 	 * @var string
-	 * @todo implement this
 	 */
-	private $root_namespace = '';
+	private $root_namespace = '\\';
 	
 	/**
 	 * Whether to throw an exception when a class file does not exist.
@@ -85,7 +84,7 @@ class Autoloader extends Base {
 	 * @param string $directory Root directory of the autoloader.
 	 * @param bool $throw Whether to throw an exception when a class file does not exist.
 	 */
-	function __construct($directory, $throw=true) {
+	function __construct($directory, $throw=false) {
 		$this->set_root_directory($directory);
 		$this->set_throw_errors($throw);
 	}
@@ -126,6 +125,28 @@ class Autoloader extends Base {
 		return $this->root_directory;
 	}
 	
+	/**
+	 * Set the root namespace that loaded classes are expected to be in.
+	 * 
+	 * @param string $directory The new root namespace.
+	 */
+	function set_root_namespace($namespace) {
+		// Assert that the namespace ends with a backslash
+		if( $namespace[strlen($namespace) - 1] != '\\' )
+			$namespace .= '\\';
+		
+		$this->root_namespace = $namespace;
+	}
+	
+	/**
+	 * Get the root namespace that loaded classes are expected to be in.
+	 * 
+	 * @return string
+	 */
+	function get_root_namespace() {
+		return $this->root_namespace;
+	}
+	
 	/**
 	 * Append a slash ('/') to the given directory name, if it is not already there.
 	 * 
@@ -149,6 +170,21 @@ class Autoloader extends Base {
 		return strtolower(preg_replace('/(?<=.)([A-Z])/', '_\\1', $classname));
 	}
 	
+	/**
+	 * Strip the root namespace from the beginning of a class name.
+	 * 
+	 * @param string $classname The name of the class to strip the namespace from.
+	 * @return string The stripped class name.
+	 */
+	private function strip_root_namespace($classname) {
+		$begin = substr($classname, 0, strlen($this->root_namespace));
+		
+		if( $begin == $this->root_namespace )
+			$classname = substr($classname, strlen($this->root_namespace));
+		
+		return $classname;
+	}
+	
 	/**
 	 * Create the path to a class file.
 	 * 
@@ -180,14 +216,15 @@ class Autoloader extends Base {
 	 * @return bool
 	 * @throws FileNotFoundError If the class file does not exist.
 	 */
-	function load_class($classname, $throw=true) {
+	function load_class($classname, $throw=null) {
+		$classname = $this->strip_root_namespace($classname);
 		$path = $this->create_path($classname);
 		
 		if( !file_exists($path) ) {
-			if( !$throw || !$this->throw_errors )
-				return false;
+			if( $throw || ($throw === null && $this->throw_errors) )
+				throw new FileNotFoundError($path);
 			
-			throw new FileNotFoundError($path);
+			return false;
 		}
 		
 		require_once $path;

+ 72 - 7
tests/test_autoloader.php

@@ -10,6 +10,34 @@ class AutoloaderTest extends PHPUnit_Framework_TestCase {
 		$this->autoloader = new Autoloader(PATH);
 	}
 	
+	
+	function test_set_root_namespace() {
+		$this->assertAttributeEquals('\\', 'root_namespace', $this->autoloader);
+		$this->autoloader->set_root_namespace('Foo');
+		$this->assertAttributeEquals('Foo\\', 'root_namespace', $this->autoloader);
+		$this->autoloader->set_root_namespace('Foo\\');
+		$this->assertAttributeEquals('Foo\\', 'root_namespace', $this->autoloader);
+	}
+	
+	/**
+	 * @depends test_set_root_namespace
+	 */
+	function test_get_root_namespace() {
+		$this->autoloader->set_root_namespace('Foo');
+		$this->assertEquals($this->autoloader->get_root_namespace(), 'Foo\\');
+	}
+	
+	/**
+	 * @depends test_set_root_namespace
+	 */
+	function test_strip_root_namespace() {
+		$strip = new ReflectionMethod('BasicWeb\Autoloader', 'strip_root_namespace');
+		$strip->setAccessible(true);
+		
+		$this->autoloader->set_root_namespace('Foo');
+		$this->assertEquals($strip->invoke($this->autoloader, 'Foo\Bar'), 'Bar');
+	}
+	
 	function test_path_with_slash() {
 		$this->assertEquals(Autoloader::path_with_slash('dirname'), 'dirname/');
 		$this->assertEquals(Autoloader::path_with_slash('dirname/'), 'dirname/');
@@ -41,15 +69,47 @@ class AutoloaderTest extends PHPUnit_Framework_TestCase {
 		$this->assertEquals($this->autoloader->create_path('FooBar\Baz'), PATH.'foo_bar/baz.php');
 	}
 	
+	function test_throw_errors() {
+		$this->assertFalse($this->autoloader->get_throw_errors());
+		$this->autoloader->set_throw_errors(true);
+		$this->assertTrue($this->autoloader->get_throw_errors());
+	}
+	
 	/**
 	 * @depends test_create_path
+	 * @depends test_throw_errors
+	 */
+	function test_load_class_not_found() {
+		$this->assertFalse($this->autoloader->load_class('foobar'));
+	}
+	
+	/**
+	 * @depends test_load_class_not_found
 	 * @expectedException BasicWeb\FileNotFoundError
 	 * @expectedExceptionMessage File "tests/_files/foobar.php" does not exist.
 	 */
-	function test_load_class_not_found() {
+	function test_load_class_not_found_error() {
+		$this->autoloader->set_throw_errors(true);
 		$this->autoloader->load_class('foobar');
 	}
 	
+	/**
+	 * @depends test_load_class_not_found
+	 * @expectedException BasicWeb\FileNotFoundError
+	 * @expectedExceptionMessage File "tests/_files/foobar.php" does not exist.
+	 */
+	function test_load_class_not_found_noerror_overwrite() {
+		$this->autoloader->load_class('foobar', true);
+	}
+	
+	/**
+	 * @depends test_load_class_not_found
+	 */
+	function test_load_class_not_found_error_overwrite() {
+		$this->autoloader->set_throw_errors(true);
+		$this->assertFalse($this->autoloader->load_class('foobar', false));
+	}
+	
 	/**
 	 * @depends test_load_class_not_found
 	 */
@@ -60,6 +120,17 @@ class AutoloaderTest extends PHPUnit_Framework_TestCase {
 		$this->assertTrue(class_exists('Foo\Bar', false));
 	}
 	
+	/**
+	 * @depends test_load_class
+	 * @depends test_strip_root_namespace
+	 */
+	function test_load_class_root_namespace() {
+		$autoloader = new Autoloader(PATH.'foo');
+		$autoloader->set_root_namespace('Foo');
+		$this->assertTrue($autoloader->load_class('Bar'));
+		$this->assertTrue(class_exists('Foo\Bar', false));
+	}
+	
 	/**
 	 * @depends test_load_class
 	 */
@@ -68,12 +139,6 @@ class AutoloaderTest extends PHPUnit_Framework_TestCase {
 		$this->assertTrue(class_exists('Baz'));
 	}
 	
-	function test_throw_errors() {
-		$this->assertTrue($this->autoloader->get_throw_errors());
-		$this->autoloader->set_throw_errors(false);
-		$this->assertFalse($this->autoloader->get_throw_errors());
-	}
-	
 	/**
 	 * @depends test_register
 	 * @depends test_throw_errors