3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Mvc\View\Console
;
12 use Zend\EventManager\AbstractListenerAggregate
;
13 use Zend\EventManager\EventManagerInterface
;
14 use Zend\Mvc\Application
;
15 use Zend\Mvc\MvcEvent
;
16 use Zend\Stdlib\ResponseInterface
as Response
;
17 use Zend\View\Model\ConsoleModel
;
19 class ExceptionStrategy
extends AbstractListenerAggregate
25 protected $displayExceptions = true;
28 * A template for message to show in console when an exception has occurred.
29 * @var string|callable
31 protected $message = <<<EOT
32 ======================================================================
33 The application has thrown an exception!
34 ======================================================================
37 ----------------------------------------------------------------------
40 ======================================================================
41 Previous Exception(s):
47 * A template for message to show in console when an exception has previous exceptions.
50 protected $previousMessage = <<<EOT
51 ======================================================================
54 ----------------------------------------------------------------------
63 public function attach(EventManagerInterface
$events, $priority = 1)
65 $this->listeners
[] = $events->attach(MvcEvent
::EVENT_DISPATCH_ERROR
, [$this, 'prepareExceptionViewModel']);
66 $this->listeners
[] = $events->attach(MvcEvent
::EVENT_RENDER_ERROR
, [$this, 'prepareExceptionViewModel']);
70 * Flag: display exceptions in error pages?
72 * @param bool $displayExceptions
73 * @return ExceptionStrategy
75 public function setDisplayExceptions($displayExceptions)
77 $this->displayExceptions
= (bool) $displayExceptions;
82 * Should we display exceptions in error pages?
86 public function displayExceptions()
88 return $this->displayExceptions
;
92 * Get current template for message that will be shown in Console.
96 public function getMessage()
98 return $this->message
;
102 * Set template for message that will be shown in Console.
103 * The message can be a string (template) or a callable (i.e. a closure).
105 * The closure is expected to return a string and will be called with 2 parameters:
106 * Exception $exception - the exception being thrown
107 * boolean $displayExceptions - whether to display exceptions or not
109 * If the message is a string, one can use the following template params:
111 * :className - full class name of exception instance
112 * :message - exception message
113 * :code - exception code
114 * :file - the file where the exception has been thrown
115 * :line - the line where the exception has been thrown
116 * :stack - full exception stack
118 * @param string|callable $message
119 * @return ExceptionStrategy
121 public function setMessage($message)
123 $this->message
= $message;
128 * Sets template for previous message that will be shown in Console.
130 * @param string $previousMessage
131 * @return ExceptionStrategy
133 public function setPreviousMessage($previousMessage)
135 $this->previousMessage
= $previousMessage;
140 * @return callable|string
142 public function getPreviousMessage()
144 return $this->previousMessage
;
148 * Create an exception view model, and set the HTTP status code
150 * @todo dispatch.error does not halt dispatch unless a response is
151 * returned. As such, we likely need to trigger rendering as a low
152 * priority dispatch.error event (or goto a render event) to ensure
153 * rendering occurs, and that munging of view models occurs when
158 public function prepareExceptionViewModel(MvcEvent
$e)
160 // Do nothing if no error in the event
161 $error = $e->getError();
166 // Do nothing if the result is a response object
167 $result = $e->getResult();
168 if ($result instanceof Response
) {
173 case Application
::ERROR_CONTROLLER_NOT_FOUND
:
174 case Application
::ERROR_CONTROLLER_INVALID
:
175 case Application
::ERROR_ROUTER_NO_MATCH
:
176 // Specifically not handling these because they are handled by routeNotFound strategy
179 case Application
::ERROR_EXCEPTION
:
181 // Prepare error message
182 $exception = $e->getParam('exception');
184 if (is_callable($this->message
)) {
185 $callback = $this->message
;
186 $message = (string) $callback($exception, $this->displayExceptions
);
187 } elseif ($this->displayExceptions
188 // @TODO clean up once PHP 7 requirement is enforced
189 && ($exception instanceof \Exception ||
$exception instanceof \Throwable
)
192 $previousException = $exception->getPrevious();
193 while ($previousException) {
194 $previous .= str_replace(
204 get_class($previousException),
205 $previousException->getMessage(),
206 $previousException->getCode(),
207 $previousException->getFile(),
208 $previousException->getLine(),
209 $exception->getTraceAsString(),
211 $this->previousMessage
213 $previousException = $previousException->getPrevious();
216 /* @var $exception \Exception */
217 $message = str_replace(
228 get_class($exception),
229 $exception->getMessage(),
230 $exception->getCode(),
231 $exception->getFile(),
232 $exception->getLine(),
233 $exception->getTraceAsString(),
239 $message = str_replace(
262 // Prepare view model
263 $model = new ConsoleModel();
264 $model->setResult($message);
265 $model->setErrorLevel(1);
267 // Inject it into MvcEvent
268 $e->setResult($model);