use zend router
[GitHub/Stricted/Domain-Control-Panel.git] / vendor / Zend / Mvc / View / Console / ExceptionStrategy.php
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
4 *
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
8 */
9
10 namespace Zend\Mvc\View\Console;
11
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;
18
19 class ExceptionStrategy extends AbstractListenerAggregate
20 {
21 /**
22 * Display exceptions?
23 * @var bool
24 */
25 protected $displayExceptions = true;
26
27 /**
28 * A template for message to show in console when an exception has occurred.
29 * @var string|callable
30 */
31 protected $message = <<<EOT
32 ======================================================================
33 The application has thrown an exception!
34 ======================================================================
35 :className
36 :message
37 ----------------------------------------------------------------------
38 :file::line
39 :stack
40 ======================================================================
41 Previous Exception(s):
42 :previous
43
44 EOT;
45
46 /**
47 * A template for message to show in console when an exception has previous exceptions.
48 * @var string
49 */
50 protected $previousMessage = <<<EOT
51 ======================================================================
52 :className
53 :message
54 ----------------------------------------------------------------------
55 :file::line
56 :stack
57
58 EOT;
59
60 /**
61 * {@inheritDoc}
62 */
63 public function attach(EventManagerInterface $events, $priority = 1)
64 {
65 $this->listeners[] = $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, [$this, 'prepareExceptionViewModel']);
66 $this->listeners[] = $events->attach(MvcEvent::EVENT_RENDER_ERROR, [$this, 'prepareExceptionViewModel']);
67 }
68
69 /**
70 * Flag: display exceptions in error pages?
71 *
72 * @param bool $displayExceptions
73 * @return ExceptionStrategy
74 */
75 public function setDisplayExceptions($displayExceptions)
76 {
77 $this->displayExceptions = (bool) $displayExceptions;
78 return $this;
79 }
80
81 /**
82 * Should we display exceptions in error pages?
83 *
84 * @return bool
85 */
86 public function displayExceptions()
87 {
88 return $this->displayExceptions;
89 }
90
91 /**
92 * Get current template for message that will be shown in Console.
93 *
94 * @return string
95 */
96 public function getMessage()
97 {
98 return $this->message;
99 }
100
101 /**
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).
104 *
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
108 *
109 * If the message is a string, one can use the following template params:
110 *
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
117 *
118 * @param string|callable $message
119 * @return ExceptionStrategy
120 */
121 public function setMessage($message)
122 {
123 $this->message = $message;
124 return $this;
125 }
126
127 /**
128 * Sets template for previous message that will be shown in Console.
129 *
130 * @param string $previousMessage
131 * @return ExceptionStrategy
132 */
133 public function setPreviousMessage($previousMessage)
134 {
135 $this->previousMessage = $previousMessage;
136 return $this;
137 }
138
139 /**
140 * @return callable|string
141 */
142 public function getPreviousMessage()
143 {
144 return $this->previousMessage;
145 }
146
147 /**
148 * Create an exception view model, and set the HTTP status code
149 *
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
154 * expected.
155 * @param MvcEvent $e
156 * @return void
157 */
158 public function prepareExceptionViewModel(MvcEvent $e)
159 {
160 // Do nothing if no error in the event
161 $error = $e->getError();
162 if (empty($error)) {
163 return;
164 }
165
166 // Do nothing if the result is a response object
167 $result = $e->getResult();
168 if ($result instanceof Response) {
169 return;
170 }
171
172 switch ($error) {
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
177 return;
178
179 case Application::ERROR_EXCEPTION:
180 default:
181 // Prepare error message
182 $exception = $e->getParam('exception');
183
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)
190 ) {
191 $previous = '';
192 $previousException = $exception->getPrevious();
193 while ($previousException) {
194 $previous .= str_replace(
195 [
196 ':className',
197 ':message',
198 ':code',
199 ':file',
200 ':line',
201 ':stack',
202 ],
203 [
204 get_class($previousException),
205 $previousException->getMessage(),
206 $previousException->getCode(),
207 $previousException->getFile(),
208 $previousException->getLine(),
209 $exception->getTraceAsString(),
210 ],
211 $this->previousMessage
212 );
213 $previousException = $previousException->getPrevious();
214 }
215
216 /* @var $exception \Exception */
217 $message = str_replace(
218 [
219 ':className',
220 ':message',
221 ':code',
222 ':file',
223 ':line',
224 ':stack',
225 ':previous',
226 ],
227 [
228 get_class($exception),
229 $exception->getMessage(),
230 $exception->getCode(),
231 $exception->getFile(),
232 $exception->getLine(),
233 $exception->getTraceAsString(),
234 $previous
235 ],
236 $this->message
237 );
238 } else {
239 $message = str_replace(
240 [
241 ':className',
242 ':message',
243 ':code',
244 ':file',
245 ':line',
246 ':stack',
247 ':previous',
248 ],
249 [
250 '',
251 '',
252 '',
253 '',
254 '',
255 '',
256 '',
257 ],
258 $this->message
259 );
260 }
261
262 // Prepare view model
263 $model = new ConsoleModel();
264 $model->setResult($message);
265 $model->setErrorLevel(1);
266
267 // Inject it into MvcEvent
268 $e->setResult($model);
269
270 break;
271 }
272 }
273 }