Skip to content

Commit

Permalink
ClassLoader and Event documentation complete.
Browse files Browse the repository at this point in the history
  • Loading branch information
KrisJordan committed Feb 8, 2010
1 parent 3bda740 commit d1eec84
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 111 deletions.
6 changes: 3 additions & 3 deletions lib/Recess/Core/Callable.php
Expand Up @@ -2,7 +2,7 @@
namespace Recess\Core; /** @addtogroup Core *//** @{ */

/**
* Turns any PHP value which is_callable into an invocable object/closure with call() and apply() methods.
* Turns any PHP value which is_callable() into an invocable object/closure with call() and apply() methods.
*
* Note: Callable does not support passing arguments by-reference.
*
Expand All @@ -13,7 +13,7 @@
*
* @author Kris Jordan <http://www.krisjordan.com>
* @author Copyright &copy; RecessFramework.org 2008-2010 (MIT License)
* @since Recess 5.3
* @since Recess PHP Framework 5.3
*/
class Callable implements ICallable {
/** @} */
Expand Down Expand Up @@ -73,7 +73,7 @@ function apply($arguments = array()) {
}

/**
* An alias of __invoke().
* An alias of __invoke().
*
* @code $add->call(1,2); @endcode
*
Expand Down
83 changes: 43 additions & 40 deletions lib/Recess/Core/ClassLoader.php
@@ -1,6 +1,5 @@
<?php
namespace Recess\Core;
/** @addtogroup Core *//** @{ */
namespace Recess\Core; /** @addtogroup Core *//** @{ */

DEFINE('NAMESPACE_SEPARATOR','\\');

Expand All @@ -10,17 +9,21 @@
require __DIR__.'/Wrappable.php';

/**
* ClassLoader is a simple autoloader for including class files. Class files
* end with a '.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.
* An SPL class loader for automatically including class and interface files.
*
* ClassLoader implements http://groups.google.com/group/php-standards/web/psr-0-final-proposal
* for painless interoperability with other PHP libraries.
*
* Usage:
* Class files end with a '.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 wrapped with wrapLoad(). After successfully loading
* a class or interface it will trigger the onLoad event.
*
* Example usage:
*
* @code
* spl_autoload_register(array('recess\core\ClassLoader','load'));
* use recess\core\ClassLoader;
* // Register a call back with the onLoad Event
Expand All @@ -40,46 +43,28 @@
* use some\Class;
* $someClass = new Class;
* // Output: Before load some\Class! some\Class loaded! After load some\Class!
* @endcode
*
* @author Kris Jordan <http://krisjordan.com>
* @copyright RecessFramework.org 2008-2010
* @license MIT
* @since Recess 5.3
* @author Kris Jordan <http://www.krisjordan.com>
* @author Copyright &copy; RecessFramework.org 2008-2010 (MIT License)
* @since Recess PHP Framework 5.3
*/
abstract class ClassLoader {
/** @} */

/**
* @var string
*/
public static $extension = '.php';
/** @var string */
private static $extension = '.php';

/**
* @var recess\core\Event
*/
/** @var Recess\Core\Event */
private static $onLoad = null;

/**
* @var recess\core\Wrappable or \Closure
*/
/** @var Recess\Core\Wrappable 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
* @return boolean
*/
static public function load($class) {
if(self::$loader === null) {
Expand All @@ -88,13 +73,31 @@ static public function load($class) {
$loader = self::$loader;
}
return $loader($class);
}

/**
* Returns a reference to the onLoad Event that callbacks can be registered on.
*
* @code
* ClassLoader::onLoad()->callback(function($class){echo "$class loaded!";});
* @endcode
*
* @return Event
*/
static public function onLoad() {
if(self::$onLoad === null) {
self::$onLoad = new Event();
}
return self::$onLoad;
}

/**
* Load is candied and can be wrapped by passing a wrapper to this method.
* Load is wrappable by passing a wrapper to this method.
* The wrapper should have two parameters: $load and $class. Usage:
*
* @code
* ClassLoader::wrapLoad(function($load,$class) { echo "loading $class"; $load($class); });
* @endcode
*
* @param $wrapper
* @return recess\core\Wrappable
Expand Down Expand Up @@ -146,9 +149,9 @@ static private function loader() {
if($found === false) return false;

$onLoad($fullyQualifiedClass);
return true;
if(class_exists($fullyQualifiedClass, false)
|| interface_exists($fullyQualifiedClass, false)) {
|| interface_exists($fullyQualifiedClass, false)) {
return true;
} else {
throw new \Exception("'$classFile' does not contain a definition of $class.");
}
Expand Down
109 changes: 41 additions & 68 deletions lib/Recess/Core/Event.php
@@ -1,76 +1,25 @@
<?php
namespace Recess\Core;
/** @addtogroup Core *//** @{ */
namespace Recess\Core; /** @addtogroup Core *//** @{ */

/**
* When something important happens, let others know with an Event.
* A lightweight, functional variation on the delegate/observable pattern.
* Events pass their arguments to any callables registered with callback()
* when the Event is triggered.
*
* Events are a variation on the delegate/observable pattern. Events pass
* their arguments to any callables who register to be called back when the
* event is triggered.
* @include examples/Recess/Core/Event.php
*
* One Callback, With No Arguments
* @code
* $onLoad = new Event();
* $onLoad->callback(function() { echo 'Event triggered!'; });
* echo 'Calling onLoad...';
* $onLoad();
* // Output: Calling onLoad... Event triggered!
* @endcode
* To run the example code from the command line:
* @code php lib/Recess/examples/Recess/Core/Event.php @endcode
*
* Many Callbacks
* @code
* $onLoad = new Event();
* $onLoad->callback(function() { echo 'First callback. '; })
* ->callback(function() { echo 'Second callback.'; });
* $onLoad();
* // Output: First callback. Second callback.
* // Note: Though callables are called FIFO, this is not a behavior that
* // should be relied upon.
* @endcode
*
* Using Arguments
* @code
* $onSavePerson = new Event();
* $onSavePerson->callback(function($person) { echo 'Saving '.$person->name.'!'; });
* $aPerson = new Person('Kris');
* $onSavePerson($aPerson);
* // Output: Saving Kris!
* @endcode
*
* @author Kris Jordan <krisjordan@gmail.com>
* @since Recess 5.3
* @copyright RecessFramework.org 2009, 2010
* @license MIT
* @author Kris Jordan <http://www.krisjordan.com>
* @author Copyright &copy; RecessFramework.org 2008-2010 (MIT License)
* @since Recess PHP Framework 5.3
*/
class Event implements ICallable {
/** @} */

protected $callbacks = array();

/**
* Register a callback with an event.
*
* @param $callable Callable to be called when event occurs.
* @return Event
*/
function callback($callback) {
if(!is_callable($callback)) {
throw new \Exception("Event's constructor requires an is_callable value.");
}
$this->callbacks[] = $callback;
return $this;
}

/**
* Return the array of registered callbacks.
*
* @return array of callables
*/
function callbacks() {
return $this->callbacks;
}

/**
* Call each callback with arguments passed to __invoke
*/
Expand All @@ -85,22 +34,46 @@ function __invoke() {
}

/**
* Helper method alias for __invoke() that can be chained.
* An alias of __invoke() called with an array of arguments.
*
* @param array $arguments
* @return mixed
*/
function apply($arguments = array()) {
return call_user_func_array(array($this,'__invoke'), $arguments);
}

/**
* An alias of __invoke().
*
* @see Event::__invoke
* @return any
* @return mixed
*/
function call() {
return call_user_func_array(array($this,'__invoke'), func_get_args());
}

/**
* Call with an array of arguments rather than an argument list.
* Register a callback with the event.
*
* @param array $arguments
* @return any
* @param is_callable $callback to be called when the event is triggered.
* @return Event
*/
function apply($arguments = array()) {
return call_user_func_array(array($this,'__invoke'), $arguments);
function callback($callback) {
if(!is_callable($callback)) {
throw new \Exception("Event's constructor requires an is_callable value.");
}
$this->callbacks[] = $callback;
return $this;
}

/**
* Return the array of registered callbacks.
*
* @return array
*/
function callbacks() {
return $this->callbacks;
}

}
21 changes: 21 additions & 0 deletions lib/Recess/examples/Recess/Core/Event.php
@@ -0,0 +1,21 @@
<?php include "lib/Recess/Recess.php"; use Recess\Core\Event;

// ==== One Callback, With No Arguments
$onLoad = new Event();
$onLoad->callback(function() { echo "Event triggered!\n"; });
echo 'Calling onLoad...';
$onLoad();
//> Calling onLoad... Event triggered!

// ==== Many Callbacks
$onLoad = new Event();
$onLoad->callback(function() { echo "First callback. "; })
->callback(function() { echo "Second callback.\n"; });
$onLoad();
//> First callback. Second callback.

// ==== Passing Arguments
$onSaveFile = new Event();
$onSaveFile->callback(function($file) { echo "Saving $file!\n"; });
$onSaveFile('example.txt');
//> Saving example.txt!

0 comments on commit d1eec84

Please sign in to comment.