Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f47f2f6
commit d5b1810
Showing
4 changed files
with
190 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
<?php | ||
namespace recess\core; | ||
|
||
require __DIR__.'/Event.class.php'; | ||
require __DIR__.'/Candy.class.php'; | ||
|
||
/** | ||
* ClassLoader is a simple autoloader for including class files. Class files | ||
* end with a '.class.php' extension and classes must share the same name as | ||
* their containing class file. ClassLoader can be used in conjunction with | ||
* the SPL autoloader chain. Its load function can be candied and wrapped | ||
* with wrapLoad(). After successfully loading a class it will trigger the | ||
* onLoad event. | ||
* | ||
* Usage: | ||
* spl_autoload_register(array('recess\core\ClassLoader','load')); | ||
* use recess\core\ClassLoader; | ||
* // Register a call back with the onLoad Event | ||
* ClassLoader::onLoad()->call(function($class) { echo "$class loaded! "; }); | ||
* // Wrap the candied loader | ||
* ClassLoader::wrapLoad( | ||
* function($load, $class) { | ||
* echo "Before load $class!"; | ||
* $load($class); | ||
* echo "After load $class!"; | ||
* } | ||
* ); | ||
* // Load a class explicitely | ||
* ClassLoader::load('a\Class'); | ||
* // Output: Before load A\Class! A\Class loaded! After load A\Class! | ||
* // Load a class implicitly | ||
* use some\Class; | ||
* $someClass = new Class; | ||
* // Output: Before load some\Class! some\Class loaded! After load some\Class! | ||
* | ||
* @author Kris Jordan <krisjordan@gmail.com> | ||
* @since Recess 5.3 | ||
* @copyright RecessFramework.org 2009 | ||
* @license MIT | ||
*/ | ||
abstract class ClassLoader { | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public static $extension = '.class.php'; | ||
|
||
/** | ||
* @var recess\core\Event | ||
*/ | ||
private static $onLoad = null; | ||
|
||
/** | ||
* @var recess\core\Candy or \Closure | ||
*/ | ||
private static $loader = null; | ||
|
||
/** | ||
* Returns a reference to the onLoad Event for interested parties | ||
* to register callbacks with. | ||
* @return recess\core\Event | ||
*/ | ||
static public function onLoad() { | ||
if(self::$onLoad === null) { | ||
self::$onLoad = new Event(); | ||
} | ||
return self::$onLoad; | ||
} | ||
|
||
/** | ||
* Load a class by passing a fully qualified classname. | ||
* @param $class string fully qualified classname | ||
* @return bool | ||
*/ | ||
static public function load($class) { | ||
if(self::$loader === null) { | ||
$loader = self::loader(); | ||
} else { | ||
$loader = self::$loader; | ||
} | ||
return $loader($class); | ||
} | ||
|
||
/** | ||
* Load is candied and can be wrapped by passing a wrapper to this method. | ||
* The wrapper should have two parameters: $load and $class. Usage: | ||
* | ||
* ClassLoader::wrapLoad(function($load,$class) { echo "loading $class"; $load($class); }); | ||
* | ||
* @param $wrapper | ||
* @return recess\core\Candy | ||
*/ | ||
static public function wrapLoad($wrapper) { | ||
if(self::$loader === null) { | ||
self::$loader = new Candy(self::loader()); | ||
} | ||
if(!self::$loader instanceof Candy) { | ||
self::$loader = new Candy(self::$loader); | ||
} | ||
return self::$loader->wrap($wrapper); | ||
} | ||
|
||
/** | ||
* Returns a closure for loading class files. | ||
* | ||
* @return \Closure | ||
*/ | ||
static private function loader() { | ||
if(self::$loader === null) { | ||
$onLoad = self::onLoad(); | ||
$extension = self::$extension; | ||
self::$loader = function($class) use (&$onLoad, &$extension) { | ||
if(!class_exists($class)) { | ||
$classFile = str_replace('\\','/',$class).$extension; | ||
include $classFile; | ||
$onLoad($class); | ||
} | ||
return true; | ||
}; | ||
} | ||
return self::$loader; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<?php | ||
require_once 'PHPUnit/Framework.php'; | ||
|
||
include_once __DIR__ . '/../../../recess/core/ClassLoader.class.php'; | ||
use recess\core\ClassLoader; | ||
|
||
class ClassLoaderTest extends PHPUnit_Framework_TestCase { | ||
|
||
function testOnLoad() { | ||
$onLoad = ClassLoader::onLoad(); | ||
$this->assertType('recess\core\Event',$onLoad); | ||
$onLoad2 = ClassLoader::onLoad(); | ||
$this->assertTrue($onLoad === $onLoad2); | ||
$theClass = ''; | ||
ClassLoader::onLoad()->call(function($class) use (&$theClass) { $theClass = $class; }); | ||
ClassLoader::load('recess\core\Dummy'); | ||
$this->assertEquals('recess\core\Dummy',$theClass); | ||
} | ||
|
||
function testWrapLoad() { | ||
$loadedCount = 0; | ||
ClassLoader::wrapLoad( | ||
function($load,$class) use (&$loadedCount) { | ||
if($load($class)) { | ||
$loadedCount += 1; | ||
} else { | ||
$loadedCount -= 1; | ||
} | ||
}); | ||
ClassLoader::load('ClassLoaderTest'); | ||
ClassLoader::load('ClassLoaderTest'); | ||
$this->assertEquals(2,$loadedCount); | ||
} | ||
|
||
function testLoadDummy() { | ||
set_include_path(__DIR__.'/../../'); | ||
ClassLoader::load('recess\core\Dummy'); | ||
$dummy = new recess\core\Dummy; | ||
$this->assertType('recess\core\Dummy',$dummy); | ||
$this->assertEquals('hello world',$dummy->helloWorld()); | ||
} | ||
|
||
function testWrapAfterLoadDummy() { | ||
set_include_path(__DIR__.'/../../'); | ||
ClassLoader::load('recess\core\Dummy'); | ||
$loadedCount = 0; | ||
ClassLoader::wrapLoad( | ||
function($load,$class) use (&$loadedCount) { | ||
if($load($class)) { | ||
$loadedCount += 1; | ||
} else { | ||
$loadedCount -= 1; | ||
} | ||
}); | ||
ClassLoader::load('ClassLoaderTest'); | ||
$this->assertEquals(1,$loadedCount); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?php | ||
namespace recess\core; | ||
|
||
class Dummy { | ||
function helloWorld() { return 'hello world'; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters