Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
33.33% |
1 / 3 |
|
38.89% |
7 / 18 |
CRAP | |
56.25% |
63 / 112 |
Api | |
0.00% |
0 / 1 |
|
43.75% |
7 / 16 |
121.04 | |
63.00% |
63 / 100 |
__construct( Router $router, DependencyResolverInterface $dependencyResolver, SerializerInterface $serializer, CryptographyInterface $encrypter = null, Loggable $logger = null) | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
anonymous function($errno, $errstr, $errfile, $errline, array $errcontext) | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
setControllerEnding($string) | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
run() | |
0.00% |
0 / 1 |
5.15 | |
81.82% |
18 / 22 |
|||
_getApplicationResponse($apiRequest) | |
0.00% |
0 / 1 |
2.09 | |
71.43% |
5 / 7 |
|||
_getActionDependencies($controller, $action) | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
_logError($e) | |
100.00% |
1 / 1 |
2 | |
100.00% |
2 / 2 |
|||
_logDebug($message) | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 2 |
|||
_getControllerName($controllerName) | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
_getTemplateControllerName($controllerName) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
_getFactory() | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
_injectAdditionalDependencies($controller) | |
0.00% |
0 / 1 |
2.86 | |
40.00% |
2 / 5 |
|||
_getController($controllerName) | |
0.00% |
0 / 1 |
6.33 | |
47.37% |
9 / 19 |
|||
setTemplateDependencyName($dependcyName) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
_getFullActionName($controller, $action) | |
0.00% |
0 / 1 |
7.91 | |
37.50% |
3 / 8 |
|||
_callControllerAction($controller, $action, $args) | |
0.00% |
0 / 1 |
17.44 | |
52.94% |
9 / 17 |
|||
DynamicResolutionException | |
100.00% |
1 / 1 |
0 | ||||||
DynamicResolver | |
0.00% |
0 / 1 |
|
0.00% |
0 / 2 |
20 | |
0.00% |
0 / 12 |
getControllerName() | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 9 |
|||
resolve($controller) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
<?php | |
/** | |
* | |
*/ | |
namespace aae\dispatch { | |
use \aae\dispatch\Router as Router; | |
use \aae\serialize\SerializerInterface as SerializerInterface; | |
use \aae\encrypt\CryptographyInterface as CryptographyInterface; | |
use \aae\log\Loggable as Loggable; | |
use \aae\di\DependencyResolverInterface as DependencyResolverInterface; | |
use \aae\ui\Markdown as Markdown; | |
/** | |
* @author Axel Ancona Esselmann | |
* @package aae\dispatch | |
* | |
* Exposes all public methods on all classes as the API. | |
*/ | |
class Api /*implements \aae\dispatch\ApiInterface */{ | |
use \aae\log\LoggableTrait; | |
protected $_controllerAppend = "", $_actionAppend = "", $_controller; | |
private $_router, $_dependencyResolver, $_serializer = null, $_encrypter = null, $_response = null, $_templateDependencyName = null; | |
public $headers = null; | |
public function __construct( | |
Router $router, | |
DependencyResolverInterface $dependencyResolver, | |
SerializerInterface $serializer, | |
CryptographyInterface $encrypter = null, | |
Loggable $logger = null) | |
{ | |
$this->setLogger($logger); | |
$this->_router = $router; | |
$this->_dependencyResolver = $dependencyResolver; | |
$this->_serializer = $serializer; | |
$this->_encrypter = $encrypter; | |
set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) { | |
if (0 === error_reporting()) return false; | |
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); | |
}); | |
} | |
public function setControllerEnding($string) { | |
$this->_controllerAppend = $string; | |
} | |
public function run() { | |
$apiCallResult = array('response' => false, 'errorCode' => 0); | |
try { | |
$apiRequest = $this->_router->getCall(); | |
$response = $this->_getApplicationResponse($apiRequest); | |
$apiCallResult['response'] = $response; | |
$apiCallResult['errorCode'] = $this->_controller->getErrorCode(); | |
} catch (\Exception $e) { | |
$apiCallResult["errorCode"] = $e->getCode(); | |
$apiCallResult["errorMessage"] = $e->getMessage(); | |
$this->_logError($e); | |
// TODO who provides the default error? also remove from applicaiton! | |
try { | |
$apiRequest = new \aae\api\APIRequest('\aae\ui\DefaultError', '', [$e->getMessage(), $e->getCode()]); | |
$response = $this->_getApplicationResponse($apiRequest); | |
} catch (\Exception $e) { | |
$response = "View controller error ".$e->getCode()." with message: ".$e->getMessage(); | |
} | |
$apiCallResult['response'] = $response; | |
} | |
$response = $this->_serializer->serialize($apiCallResult); | |
if ($this->_encrypter) { | |
$response = $this->_encrypter->encrypt($response); | |
} | |
if (!is_null($this->headers)) { | |
$this->headers->send(); | |
} | |
return $response; | |
} | |
protected function _getApplicationResponse($apiRequest) { | |
$actionName = $apiRequest->getAction(); | |
$controller = $this->_getController($apiRequest->getController()); | |
$actionReturn = $this->_callControllerAction($controller, $actionName, $apiRequest->getArgs()); | |
if ($actionReturn === NULL) { | |
# The action did not explicitly return anything | |
# TODO: this is going to be changed once controllers do not interact directly with templates any more | |
$actionReturn = call_user_func(array($controller,"getView")); | |
} | |
return $actionReturn; | |
} | |
protected function _getActionDependencies($controller, $action) { | |
$dependencyResolver = new \aae\di\ArgNameDependencyResolver($this->_router->getRequestArray()); | |
return $dependencyResolver->resolveAllowNoMatch(get_class($controller), $action); | |
} | |
protected function _logError($e) { | |
if ($this->_logger) $this->_logger->logError($e); | |
} | |
protected function _logDebug($message) { | |
if ($this->_logger) $this->_logger->logDebug($message); | |
} | |
protected function _getControllerName($controllerName) { | |
return $controllerName.$this->_controllerAppend; | |
} | |
protected function _getTemplateControllerName($controllerName) { | |
return $controllerName."TemplateController"; | |
} | |
protected function _getFactory() { | |
return new \aae\std\SimpleFactory($this->_dependencyResolver); | |
} | |
protected function _injectAdditionalDependencies($controller) { | |
if (method_exists($controller, "dependencies")) { | |
$dependencies = $this->_dependencyResolver->resolve(get_class($controller), "dependencies"); | |
call_user_func_array(array($controller, "dependencies"), $dependencies); | |
} | |
} | |
protected function _getController($controllerName) { | |
$controllerFactory = $this->_getFactory(); | |
$substituteDependencyNames = (is_null($this->_templateDependencyName)) ? [] : ["template" => $this->_templateDependencyName]; | |
try { | |
$controller = $controllerFactory->buildWithResolvedDependencies( | |
$this->_getControllerName($controllerName), | |
$substituteDependencyNames | |
); | |
} catch (\aae\di\ClassNotDefinedException $e) { | |
// TODO: Allow settings to disallow automatic template controller loading when no specific view controller is present | |
try { | |
$controller = $controllerFactory->buildWithResolvedDependencies( | |
$this->_getTemplateControllerName($controllerName), | |
$substituteDependencyNames | |
); | |
} | |
catch (\aae\di\ClassNotDefinedException $e){ | |
$dynamicresolver = new DynamicResolver(); | |
$dynamicControllerName = $dynamicresolver->getControllerName($controllerName); | |
$controller = $controllerFactory->buildWithResolvedDependencies( | |
$dynamicControllerName, | |
$substituteDependencyNames | |
); | |
$dynamicresolver->resolve($controller); | |
} | |
} | |
$this->_injectAdditionalDependencies($controller); | |
$this->_controller = $controller; | |
return $controller; | |
} | |
public function setTemplateDependencyName($dependcyName) { | |
$this->_templateDependencyName = $dependcyName; | |
} | |
protected function _getFullActionName($controller, $action) { | |
$actionEndings = $controller->getActionEndings(); | |
if (is_array($actionEndings)) { | |
foreach ($actionEndings as $ending) { | |
$fullActionName = $action.$ending; | |
if (method_exists($controller, $fullActionName)) return $fullActionName; | |
} | |
throw new \Exception("The method ".get_class($controller)."->$fullActionName does not exist.", 214141546); | |
} else { | |
return $action.$actionEndings; | |
} | |
} | |
protected function _callControllerAction($controller, $action, $args) { | |
if (is_null($action) || strlen($action) < 1) $action = "default"; | |
$fullActionName = $this->_getFullActionName($controller, $action); | |
$actionArgs = $this->_getActionDependencies($controller, $fullActionName); | |
# arguments in URI part have precedence over query string variables | |
for ($i=0; $i < count($args); $i++) { | |
if (!array_key_exists($i, $actionArgs) || | |
(is_null($actionArgs[$i]) && !is_null($args[$i]))) | |
{ | |
$actionArgs[$i] = $args[$i]; | |
} | |
} | |
$controllerReturn = (count($actionArgs) > 0) | |
? call_user_func_array(array($controller, $action), $actionArgs) | |
: call_user_func( array($controller, $action)); | |
if (property_exists($controller, "headers")) { | |
$this->headers = $controller->headers; | |
} | |
return $controllerReturn; | |
} | |
} | |
class DynamicResolutionException extends \Exception {} | |
class DynamicResolver { | |
private $_directories = ["anconaesselmann/content", "anconaesselmann/content/projects"]; | |
private $_extension = ".md"; | |
private $_validDir = false; | |
public function getControllerName() { | |
$args = func_get_args(); | |
$fileName = \aae\std\std::classFromNSClassName(strtolower($args[0])).$this->_extension; | |
foreach ($this->_directories as $dir) { | |
$fullDir = $_SERVER["DOCUMENT_ROOT"].DIRECTORY_SEPARATOR.$dir.DIRECTORY_SEPARATOR.$fileName; | |
if (file_exists($fullDir)) { | |
$this->_validDir = $fullDir; | |
return "aae\ui\MarkdownViewController";; | |
} | |
} | |
throw new DynamicResolutionException("Could not resolve dynamically", 627161632); | |
} | |
public function resolve($controller) { | |
$controller->markdownFileName = $this->_validDir; | |
$controller->markdownSettings = Markdown::ALLOW_HTML | Markdown::DISPLAY_ATTRIBUTION; | |
return $controller; | |
} | |
} | |
} |