Skip to content
This repository has been archived by the owner on Jan 8, 2020. It is now read-only.

Commit

Permalink
[#1] update RouteNotFound model injection
Browse files Browse the repository at this point in the history
- Added displayExceptions flag
- Inject exception, if present and allowed
- Inject controller, if present and allowed
  • Loading branch information
weierophinney committed Feb 28, 2012
1 parent 5d8919a commit 04b5132
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 1 deletion.
109 changes: 108 additions & 1 deletion library/Zend/Mvc/View/RouteNotFoundStrategy.php
Expand Up @@ -43,6 +43,13 @@ class RouteNotFoundStrategy implements ListenerAggregate
*/
protected $listeners = array();

/**
* Whether or not to display exceptions related to the 404 condition
*
* @var bool
*/
protected $displayExceptions = false;

/**
* Whether or not to display the reason for a 404
*
Expand Down Expand Up @@ -77,6 +84,28 @@ public function attach(EventCollection $events)
$this->listeners[] = $events->attach('dispatch.error', array($this, 'prepareNotFoundViewModel'));
}

/**
* Set value indicating whether or not to display exceptions related to a not-found condition
*
* @param bool $displayExceptions
* @return RouteNotFoundStrategy
*/
public function setDisplayExceptions($displayExceptions)
{
$this->displayExceptions = (bool) $displayExceptions;
return $this;
}

/**
* Should we display exceptions related to a not-found condition?
*
* @return bool
*/
public function displayExceptions()
{
return $this->displayExceptions;
}

/**
* Detach aggregate listeners from the specified event manager
*
Expand Down Expand Up @@ -194,11 +223,28 @@ public function prepareNotFoundViewModel(MvcEvent $e)
$model->setTemplate($this->getNotFoundTemplate());

// If displaying reasons, inject the reason
$this->injectNotFoundReason($model);
$this->injectNotFoundReason($model, $e);

// If displaying exceptions, inject
$this->injectException($model, $e);

// Inject controller if we're displaying either the reason or the exception
$this->injectController($model, $e);

$e->setResult($model);
}

/**
* Inject the not-found reason into the model
*
* If $displayNotFoundReason is enabled, checks to see if $reason is set,
* and, if so, injects it into the model. If not, it injects
* Application::ERROR_CONTROLLER_CANNOT_DISPATCH.
*
* @param ViewModel $model
* @param MvcEvent $e
* @return void
*/
protected function injectNotFoundReason($model)
{
if (!$this->displayNotFoundReason()) {
Expand All @@ -215,4 +261,65 @@ protected function injectNotFoundReason($model)
// dispatch itself.
$model->setVariable('reason', Application::ERROR_CONTROLLER_CANNOT_DISPATCH);
}

/**
* Inject the exception message into the model
*
* If $displayExceptions is enabled, and an exception is found in the
* event, inject it into the model.
*
* @param ViewModel $model
* @param MvcEvent $e
* @return void
*/
protected function injectException($model, $e)
{
if (!$this->displayExceptions()) {
return;
}

$exception = $e->getParam('exception', false);
if (!$exception instanceof \Exception) {
return;
}

$model->setVariable('exception', $exception);
}

/**
* Inject the controller and controller class into the model
*
* If either $displayExceptions or $displayNotFoundReason are enabled,
* injects the controllerClass from the MvcEvent. It checks to see if a
* controller is present in the MvcEvent, and, if not, grabs it from
* the route match if present; if a controller is found, it injects it into
* the model.
*
* @param ViewModel $model
* @param MvcEvent $e
* @return void
*/
protected function injectController($model, $e)
{
if (!$this->displayExceptions() && !$this->displayNotFoundReason()) {
return;
}

$controller = $e->getController();
if (empty($controller)) {
$routeMatch = $e->getRouteMatch();
if (empty($routeMatch)) {
return;
}

$controller = $routeMatch->getParam('controller', false);
if (!$controller) {
return;
}
}

$controllerClass = $e->getControllerClass();
$model->setVariable('controller', $controller);
$model->setVariable('controller_class', $controllerClass);
}
}
55 changes: 55 additions & 0 deletions tests/Zend/Mvc/View/RouteNotFoundStrategyTest.php
Expand Up @@ -178,6 +178,61 @@ public function test404ResponsePrepares404ViewModelWithReasonWhenAllowed()
}
}

public function test404ResponsePrepares404ViewModelWithExceptionWhenAllowed()
{
$response = new Response();
$event = new MvcEvent();
$exception = new \Exception();
$event->setParam('exception', $exception);

foreach (array(true, false) as $allow) {
$this->strategy->setDisplayExceptions($allow);
$response->setStatusCode(404);
$event->setResponse($response);
$this->strategy->prepareNotFoundViewModel($event);
$model = $event->getResult();
$this->assertInstanceOf('Zend\View\Model', $model);
$variables = $model->getVariables();
if ($allow) {
$this->assertTrue(isset($variables['exception']));
$this->assertSame($exception, $variables['exception']);
} else {
$this->assertFalse(isset($variables['exception']));
}
}
}

public function test404ResponsePrepares404ViewModelWithControllerWhenAllowed()
{
$response = new Response();
$event = new MvcEvent();
$controller = 'some-or-other';
$controllerClass = 'Some\Controller\OrOtherController';
$event->setController($controller);
$event->setControllerClass($controllerClass);

foreach (array('setDisplayNotFoundReason', 'setDisplayExceptions') as $method) {
foreach (array(true, false) as $allow) {
$this->strategy->$method($allow);
$response->setStatusCode(404);
$event->setResponse($response);
$this->strategy->prepareNotFoundViewModel($event);
$model = $event->getResult();
$this->assertInstanceOf('Zend\View\Model', $model);
$variables = $model->getVariables();
if ($allow) {
$this->assertTrue(isset($variables['controller']));
$this->assertEquals($controller, $variables['controller']);
$this->assertTrue(isset($variables['controller_class']));
$this->assertEquals($controllerClass, $variables['controller_class']);
} else {
$this->assertFalse(isset($variables['controller']));
$this->assertFalse(isset($variables['controller_class']));
}
}
}
}

public function testInjectsHttpResponseIntoEventIfNoneAlreadyPresent()
{
$event = new MvcEvent();
Expand Down

0 comments on commit 04b5132

Please sign in to comment.