Commit 04252c05 authored by Taddeus Kroes's avatar Taddeus Kroes

Added root namespace functionality to autoloader.

parent ba02966d
<?php <?php
/** /**
* * A tool for autoloading PHP classes within a root directory and namespace.
* *
* @author Taddeus Kroes * @author Taddeus Kroes
* @version 1.0 * @version 1.0
...@@ -65,12 +65,11 @@ class Autoloader extends Base { ...@@ -65,12 +65,11 @@ class Autoloader extends Base {
/** /**
* The namespace classes in the root directory are expected to be in. * 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 * @var string
* @todo implement this
*/ */
private $root_namespace = ''; private $root_namespace = '\\';
/** /**
* Whether to throw an exception when a class file does not exist. * Whether to throw an exception when a class file does not exist.
...@@ -85,7 +84,7 @@ class Autoloader extends Base { ...@@ -85,7 +84,7 @@ class Autoloader extends Base {
* @param string $directory Root directory of the autoloader. * @param string $directory Root directory of the autoloader.
* @param bool $throw Whether to throw an exception when a class file does not exist. * @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_root_directory($directory);
$this->set_throw_errors($throw); $this->set_throw_errors($throw);
} }
...@@ -126,6 +125,28 @@ class Autoloader extends Base { ...@@ -126,6 +125,28 @@ class Autoloader extends Base {
return $this->root_directory; 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. * Append a slash ('/') to the given directory name, if it is not already there.
* *
...@@ -149,6 +170,21 @@ class Autoloader extends Base { ...@@ -149,6 +170,21 @@ class Autoloader extends Base {
return strtolower(preg_replace('/(?<=.)([A-Z])/', '_\\1', $classname)); 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. * Create the path to a class file.
* *
...@@ -180,14 +216,15 @@ class Autoloader extends Base { ...@@ -180,14 +216,15 @@ class Autoloader extends Base {
* @return bool * @return bool
* @throws FileNotFoundError If the class file does not exist. * @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); $path = $this->create_path($classname);
if( !file_exists($path) ) { if( !file_exists($path) ) {
if( !$throw || !$this->throw_errors ) if( $throw || ($throw === null && $this->throw_errors) )
return false;
throw new FileNotFoundError($path); throw new FileNotFoundError($path);
return false;
} }
require_once $path; require_once $path;
......
...@@ -10,6 +10,34 @@ class AutoloaderTest extends PHPUnit_Framework_TestCase { ...@@ -10,6 +10,34 @@ class AutoloaderTest extends PHPUnit_Framework_TestCase {
$this->autoloader = new Autoloader(PATH); $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() { function test_path_with_slash() {
$this->assertEquals(Autoloader::path_with_slash('dirname'), 'dirname/'); $this->assertEquals(Autoloader::path_with_slash('dirname'), 'dirname/');
$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 { ...@@ -41,15 +69,47 @@ class AutoloaderTest extends PHPUnit_Framework_TestCase {
$this->assertEquals($this->autoloader->create_path('FooBar\Baz'), PATH.'foo_bar/baz.php'); $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_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 * @expectedException BasicWeb\FileNotFoundError
* @expectedExceptionMessage File "tests/_files/foobar.php" does not exist. * @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'); $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 * @depends test_load_class_not_found
*/ */
...@@ -60,6 +120,17 @@ class AutoloaderTest extends PHPUnit_Framework_TestCase { ...@@ -60,6 +120,17 @@ class AutoloaderTest extends PHPUnit_Framework_TestCase {
$this->assertTrue(class_exists('Foo\Bar', false)); $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 * @depends test_load_class
*/ */
...@@ -68,12 +139,6 @@ class AutoloaderTest extends PHPUnit_Framework_TestCase { ...@@ -68,12 +139,6 @@ class AutoloaderTest extends PHPUnit_Framework_TestCase {
$this->assertTrue(class_exists('Baz')); $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_register
* @depends test_throw_errors * @depends test_throw_errors
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment