use zend router
[GitHub/Stricted/Domain-Control-Panel.git] / vendor / Zend / Mvc / DispatchListener.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;
11
12 use ArrayObject;
13 use Zend\EventManager\AbstractListenerAggregate;
14 use Zend\EventManager\EventManagerInterface;
15 use Zend\ServiceManager\Exception\InvalidServiceException;
16 use Zend\Stdlib\ArrayUtils;
17
18 /**
19 * Default dispatch listener
20 *
21 * Pulls controllers from the service manager's "ControllerManager" service.
22 *
23 * If the controller cannot be found a "404" result is set up. Otherwise it
24 * will continue to try to load the controller.
25 *
26 * If the controller is not dispatchable it sets up a "404" result. In case
27 * of any other exceptions it trigger the "dispatch.error" event in an attempt
28 * to return a 500 status.
29 *
30 * If the controller subscribes to InjectApplicationEventInterface, it injects
31 * the current MvcEvent into the controller.
32 *
33 * It then calls the controller's "dispatch" method, passing it the request and
34 * response. If an exception occurs, it triggers the "dispatch.error" event,
35 * in an attempt to return a 500 status.
36 *
37 * The return value of dispatching the controller is placed into the result
38 * property of the MvcEvent, and returned.
39 */
40 class DispatchListener extends AbstractListenerAggregate
41 {
42 /**
43 * @var Controller\ControllerManager
44 */
45 private $controllerManager;
46
47 /**
48 * @param Controller\ControllerManager $controllerManager
49 */
50 public function __construct(Controller\ControllerManager $controllerManager)
51 {
52 $this->controllerManager = $controllerManager;
53 }
54
55 /**
56 * Attach listeners to an event manager
57 *
58 * @param EventManagerInterface $events
59 * @param int $priority
60 * @return void
61 */
62 public function attach(EventManagerInterface $events, $priority = 1)
63 {
64 $this->listeners[] = $events->attach(MvcEvent::EVENT_DISPATCH, [$this, 'onDispatch']);
65 if (function_exists('zend_monitor_custom_event_ex')) {
66 $this->listeners[] = $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, [$this, 'reportMonitorEvent']);
67 }
68 }
69
70 /**
71 * Listen to the "dispatch" event
72 *
73 * @param MvcEvent $e
74 * @return mixed
75 */
76 public function onDispatch(MvcEvent $e)
77 {
78 $routeMatch = $e->getRouteMatch();
79 $controllerName = $routeMatch instanceof Router\RouteMatch
80 ? $routeMatch->getParam('controller', 'not-found')
81 : 'not-found';
82 $application = $e->getApplication();
83 $events = $application->getEventManager();
84 $controllerManager = $this->controllerManager;
85
86
87 // Query abstract controllers, too!
88 if (! $controllerManager->has($controllerName)) {
89 $return = $this->marshalControllerNotFoundEvent($application::ERROR_CONTROLLER_NOT_FOUND, $controllerName, $e, $application);
90 return $this->complete($return, $e);
91 }
92
93 try {
94 $controller = $controllerManager->get($controllerName);
95 } catch (Exception\InvalidControllerException $exception) {
96 $return = $this->marshalControllerNotFoundEvent($application::ERROR_CONTROLLER_INVALID, $controllerName, $e, $application, $exception);
97 return $this->complete($return, $e);
98 } catch (InvalidServiceException $exception) {
99 $return = $this->marshalControllerNotFoundEvent($application::ERROR_CONTROLLER_INVALID, $controllerName, $e, $application, $exception);
100 return $this->complete($return, $e);
101 } catch (\Throwable $exception) {
102 $return = $this->marshalBadControllerEvent($controllerName, $e, $application, $exception);
103 return $this->complete($return, $e);
104 } catch (\Exception $exception) { // @TODO clean up once PHP 7 requirement is enforced
105 $return = $this->marshalBadControllerEvent($controllerName, $e, $application, $exception);
106 return $this->complete($return, $e);
107 }
108
109 if ($controller instanceof InjectApplicationEventInterface) {
110 $controller->setEvent($e);
111 }
112
113 $request = $e->getRequest();
114 $response = $application->getResponse();
115 $caughtException = null;
116
117 try {
118 $return = $controller->dispatch($request, $response);
119 } catch (\Throwable $ex) {
120 $caughtException = $ex;
121 } catch (\Exception $ex) { // @TODO clean up once PHP 7 requirement is enforced
122 $caughtException = $ex;
123 }
124
125 if ($caughtException !== null) {
126 $e->setName(MvcEvent::EVENT_DISPATCH_ERROR);
127 $e->setError($application::ERROR_EXCEPTION);
128 $e->setController($controllerName);
129 $e->setControllerClass(get_class($controller));
130 $e->setParam('exception', $caughtException);
131
132 $return = $application->getEventManager()->triggerEvent($e)->last();
133 if (! $return) {
134 $return = $e->getResult();
135 }
136 }
137
138 return $this->complete($return, $e);
139 }
140
141 /**
142 * @param MvcEvent $e
143 */
144 public function reportMonitorEvent(MvcEvent $e)
145 {
146 $error = $e->getError();
147 $exception = $e->getParam('exception');
148 if ($exception instanceof \Exception || $exception instanceof \Throwable) { // @TODO clean up once PHP 7 requirement is enforced
149 zend_monitor_custom_event_ex($error, $exception->getMessage(), 'Zend Framework Exception', ['code' => $exception->getCode(), 'trace' => $exception->getTraceAsString()]);
150 }
151 }
152
153 /**
154 * Complete the dispatch
155 *
156 * @param mixed $return
157 * @param MvcEvent $event
158 * @return mixed
159 */
160 protected function complete($return, MvcEvent $event)
161 {
162 if (!is_object($return)) {
163 if (ArrayUtils::hasStringKeys($return)) {
164 $return = new ArrayObject($return, ArrayObject::ARRAY_AS_PROPS);
165 }
166 }
167 $event->setResult($return);
168 return $return;
169 }
170
171 /**
172 * Marshal a controller not found exception event
173 *
174 * @param string $type
175 * @param string $controllerName
176 * @param MvcEvent $event
177 * @param Application $application
178 * @param \Exception $exception
179 * @return mixed
180 */
181 protected function marshalControllerNotFoundEvent(
182 $type,
183 $controllerName,
184 MvcEvent $event,
185 Application $application,
186 \Exception $exception = null
187 ) {
188 $event->setName(MvcEvent::EVENT_DISPATCH_ERROR);
189 $event->setError($type);
190 $event->setController($controllerName);
191 $event->setControllerClass('invalid controller class or alias: ' . $controllerName);
192 if ($exception !== null) {
193 $event->setParam('exception', $exception);
194 }
195
196 $events = $application->getEventManager();
197 $results = $events->triggerEvent($event);
198 $return = $results->last();
199 if (! $return) {
200 $return = $event->getResult();
201 }
202 return $return;
203 }
204
205 /**
206 * Marshal a controller not found exception event
207 *
208 * @deprecated Use marshalControllerNotFoundEvent() instead
209 * @param string $type
210 * @param string $controllerName
211 * @param MvcEvent $event
212 * @param Application $application
213 * @param \Exception $exception
214 * @return mixed
215 */
216 protected function marshallControllerNotFoundEvent(
217 $type,
218 $controllerName,
219 MvcEvent $event,
220 Application $application,
221 \Exception $exception = null
222 ) {
223 trigger_error(sprintf(
224 '%s is deprecated; please use %s::marshalControllerNotFoundEvent instead',
225 __METHOD__,
226 __CLASS__
227 ), E_USER_DEPRECATED);
228
229 return $this->marshalControllerNotFoundEvent($type, $controllerName, $event, $application, $exception);
230 }
231
232 /**
233 * Marshal a bad controller exception event
234 *
235 * @todo Update $exception typehint to "Throwable" once PHP 7 requirement
236 * is enforced
237 * @param string $controllerName
238 * @param MvcEvent $event
239 * @param Application $application
240 * @param \Exception|\Throwable $exception
241 * @return mixed
242 */
243 protected function marshalBadControllerEvent($controllerName, MvcEvent $event, Application $application, $exception)
244 {
245 $event->setName(MvcEvent::EVENT_DISPATCH_ERROR);
246 $event->setError($application::ERROR_EXCEPTION);
247 $event->setController($controllerName);
248 $event->setParam('exception', $exception);
249
250 $events = $application->getEventManager();
251 $results = $events->triggerEvent($event);
252 $return = $results->last();
253 if (! $return) {
254 return $event->getResult();
255 }
256
257 return $return;
258 }
259 }