@ 2016-01-12T11:14:19Z <?php
namespace Magnus;
class ObjectDispatch {
public function routeIterator(&$path) {
while (!empty($path)) {
yield end($path);
array_pop($path);
/* This prevents having to put back a value in the event of a
* readjustment in the dispatch path.
* Testing indicates that it's better to do array maninpulation than it is
* to implement SplDoublyLinkedList for deque behavior. Likewise,
* simply tracking the index is a bit slower and can add complexity
* when dealing with reorients/redispatches.
*/
}
}
public function __invoke($context, $root) {
$log = $context->getLogger();
$path = $context->getRequestPath();
$last = '';
$parent = null;
$current = $root;
if ($context->getAppMode() === 'DEBUG' && $log !== null) {
$log->addDebug('Starting Object Dispatch', [
'request' => $context->getRequestURI(),
'path' => var_export($path, true),
'root' => var_export($root, true)
]);
}
foreach ($this->routeIterator($path) as $chunk) {
if ($context->getAppMode() === 'DEBUG' && $log !== null) {
$log->addDebug('Beginning dispatch step.', [
'chunk' => $chunk,
'path' => var_export($path, true),
'current' => var_export($current, true)
]);
}
if (!is_object($current) || class_exists($context->getControllerPrefix() . $current)) {
if ($context->getAppMode() === 'DEBUG' && $log !== null) {
$log->addDebug('Instantiating current class', [
'request' => $context->getRequestURI(),
'current' => $current
]);
}
$current = $context->getControllerPrefix() . $current($context);
}
if (is_object($current)) {
$parent = $current;
}
if (in_array($chunk, get_class_methods($parent))) {
if ($context->getAppMode() === 'DEBUG' && $log !== null) {
$log->addDebug('Found an endpoint', [
'request' => $context->getRequestURI(),
'isEndpoint' => true,
'parent' => var_export($parent, true),
'handler' => $chunk,
'arguments' => var_export($path, true)
]);
}
yield array($parent, $chunk, $path, true);
} elseif (in_array($chunk, get_object_vars($parent))) {
if ($context->getAppMode() === 'DEBUG' && $log !== null) {
$log->addDebug('Found a property', [
'request' => $context->getRequestURI(),
'property' => $chunk,
'parent' => var_export($parent, true)
]);
}
$current = $parent->chunk;
} elseif (method_exists($parent, 'lookup')) {
try {
list($current, $consumed) = $parent->lookup($path);
$chunk = implode('/', $consumed);
$path = array_slice($path, 0, count($path) - count($consumed));
} catch (Exception $e) {
throw new HTTPNotFound();
}
} else {
throw new HTTPNotFound();
}
yield array(explode('/', $last), $parent, false);
$last = $chunk;
}
if ($context->getAppMode() === 'DEBUG' && $log !== null) {
$log->addDebug('No endpoint found', [
'request' => $context->getRequestURI(),
'current' => var_export($current),
'parent' => var_export($parent)
]);
}
if (!is_object($current) && class_exists($context->getControllerPrefix() . $current)) {
$current = new $current($context);
}
if (is_callable($current)) {
yield array($current, $chunk, $path, true);
} elseif (is_callable($parent)) {
yield array($parent, $chunk, $path, true);
}
}
}
class Context {
protected $requestURI;
protected $requestPath;
protected $appMode;
protected $logger;
protected $controllerPrefix;
public function __construct(Array $config) {
$this->requestURI = isset($config['requestURI']) ? $config['requestURI'] : '/';
$this->appMode = isset($config['appMode']) ? $config['appMode'] : 'DEVELOPMENT';
$this->logger = isset($config['logger']) ? $config['logger'] : null;
$this->controllerPrefix = isset($config['controllerPrefix']) ? $config['controllerPrefix'] : __NAMESPACE__ . '\';
$this->requestPath = explode('/', str_replace('\\', '/', $this->requestURI));
if (end($this->requestPath) === '') {
array_pop($this->requestPath);
}
$this->requestPath = array_reverse($this->requestPath);
if (end($this->requestPath) === '') {
array_pop($this->requestPath);
}
}
public function getRequestURI() {
return $this->requestURI;
}
public function getRequestPath() {
return $this->requestPath;
}
public function getAppMode() {
return $this->appMode;
}
public function getLogger() {
return $this->logger;
}
public function getControllerPrefix() {
return $this->controllerPrefix;
}
}
class ScreenLog {
public function __call($methodName, $args) {
echo var_export($args, true) . "\n";
}
}
class RootController {
public $home = 'homeController';
public function __invoke($args = array()) {
return "Root controller index";
}
}
$context = new Context([
'requestURI' => '/',
'logger' => new ScreenLog()
]);
$dispatch = new ObjectDispatch();
foreach ($dispatch($context, 'RootController') as $signal) {
list($object, $chunk, $path, $isEndpoint) = $signal;
if ($isEndpoint) {
echo $object->$chunk($path);
}
}
Enable javascript to submit You have javascript disabled. You will not be able to edit any code.
Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).
Version System time (s) User time (s) Memory (MiB) 7.0.2 0.033 0.073 20.16 7.0.1 0.013 0.047 20.23 7.0.0 0.010 0.067 20.19 5.6.17 0.023 0.053 20.51 5.6.16 0.010 0.040 20.55 5.6.15 0.010 0.077 18.20 5.6.14 0.010 0.077 18.23 5.6.13 0.013 0.033 18.30 5.6.12 0.000 0.070 21.16 5.6.11 0.007 0.077 21.15 5.6.10 0.017 0.060 21.02 5.6.9 0.007 0.093 21.05 5.6.8 0.000 0.043 20.42 5.5.31 0.020 0.043 20.51 5.5.30 0.007 0.080 17.98 5.5.29 0.000 0.070 18.01 5.5.28 0.000 0.047 20.78 5.5.27 0.007 0.083 20.91 5.5.26 0.013 0.053 21.02 5.5.25 0.010 0.037 20.63 5.5.24 0.027 0.073 20.20
preferences:dark mode live preview
138.64 ms | 1394 KiB | 7 Q