PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/library/Zend/Mvc/Controller/ActionController.php

https://github.com/farrelley/zf2
PHP | 316 lines | 171 code | 29 blank | 116 comment | 15 complexity | d5c98ec63b967bb511ecc5c806201821 MD5 | raw file
  1. <?php
  2. namespace Zend\Mvc\Controller;
  3. use ArrayObject,
  4. Zend\Di\Locator,
  5. Zend\EventManager\EventCollection,
  6. Zend\EventManager\EventDescription as Event,
  7. Zend\EventManager\EventManager,
  8. Zend\Http\Response as HttpResponse,
  9. Zend\Loader\Broker,
  10. Zend\Loader\Pluggable,
  11. Zend\Stdlib\Dispatchable,
  12. Zend\Stdlib\IsAssocArray,
  13. Zend\Stdlib\RequestDescription as Request,
  14. Zend\Stdlib\ResponseDescription as Response,
  15. Zend\Mvc\InjectApplicationEvent,
  16. Zend\Mvc\LocatorAware,
  17. Zend\Mvc\MvcEvent;
  18. /**
  19. * Basic action controller
  20. */
  21. abstract class ActionController implements Dispatchable, InjectApplicationEvent, LocatorAware, Pluggable
  22. {
  23. protected $broker;
  24. protected $event;
  25. protected $events;
  26. protected $locator;
  27. protected $request;
  28. protected $response;
  29. /**
  30. * Default action if none provided
  31. *
  32. * @return array
  33. */
  34. public function indexAction()
  35. {
  36. return array('content' => 'Placeholder page');
  37. }
  38. /**
  39. * Action called if matched action does not exist
  40. *
  41. * @return array
  42. */
  43. public function notFoundAction()
  44. {
  45. $this->response->setStatusCode(404);
  46. return array('content' => 'Page not found');
  47. }
  48. /**
  49. * Dispatch a request
  50. *
  51. * @events dispatch.pre, dispatch.post
  52. * @param Request $request
  53. * @param null|Response $response
  54. * @return Response|mixed
  55. */
  56. public function dispatch(Request $request, Response $response = null)
  57. {
  58. $this->request = $request;
  59. if (!$response) {
  60. $response = new HttpResponse();
  61. }
  62. $this->response = $response;
  63. $e = $this->getEvent();
  64. $e->setRequest($request)
  65. ->setResponse($response)
  66. ->setTarget($this);
  67. $result = $this->events()->trigger('dispatch', $e, function($test) {
  68. return ($test instanceof Response);
  69. });
  70. if ($result->stopped()) {
  71. return $result->last();
  72. }
  73. return $e->getResult();
  74. }
  75. /**
  76. * Execute the request
  77. *
  78. * @param MvcEvent $e
  79. * @return mixed
  80. */
  81. public function execute(MvcEvent $e)
  82. {
  83. $routeMatch = $e->getRouteMatch();
  84. if (!$routeMatch) {
  85. /**
  86. * @todo Determine requirements for when route match is missing.
  87. * Potentially allow pulling directly from request metadata?
  88. */
  89. throw new \DomainException('Missing route matches; unsure how to retrieve action');
  90. }
  91. $action = $routeMatch->getParam('action', 'index');
  92. $method = static::getMethodFromAction($action);
  93. if (!method_exists($this, $method)) {
  94. $method = 'notFoundAction';
  95. }
  96. $actionResponse = $this->$method();
  97. if (!is_object($actionResponse)) {
  98. if (IsAssocArray::test($actionResponse)) {
  99. $actionResponse = new ArrayObject($actionResponse, ArrayObject::ARRAY_AS_PROPS);
  100. }
  101. }
  102. $e->setResult($actionResponse);
  103. return $actionResponse;
  104. }
  105. /**
  106. * Get the request object
  107. *
  108. * @return Request
  109. */
  110. public function getRequest()
  111. {
  112. return $this->request;
  113. }
  114. /**
  115. * Get the response object
  116. *
  117. * @return Response
  118. */
  119. public function getResponse()
  120. {
  121. if (null === $this->response) {
  122. $this->response = new HttpResponse();
  123. }
  124. return $this->response;
  125. }
  126. /**
  127. * Set the event manager instance used by this context
  128. *
  129. * @param EventCollection $events
  130. * @return AppContext
  131. */
  132. public function setEventManager(EventCollection $events)
  133. {
  134. $this->events = $events;
  135. return $this;
  136. }
  137. /**
  138. * Retrieve the event manager
  139. *
  140. * Lazy-loads an EventManager instance if none registered.
  141. *
  142. * @return EventCollection
  143. */
  144. public function events()
  145. {
  146. if (!$this->events instanceof EventCollection) {
  147. $this->setEventManager(new EventManager(array(
  148. 'Zend\Stdlib\Dispatchable',
  149. __CLASS__,
  150. get_called_class()
  151. )));
  152. $this->attachDefaultListeners();
  153. }
  154. return $this->events;
  155. }
  156. /**
  157. * Set an event to use during dispatch
  158. *
  159. * By default, will re-cast to MvcEvent if another event type is provided.
  160. *
  161. * @param Event $e
  162. * @return void
  163. */
  164. public function setEvent(Event $e)
  165. {
  166. if ($e instanceof Event && !$e instanceof MvcEvent) {
  167. $eventParams = $e->getParams();
  168. $e = new MvcEvent();
  169. $e->setParams($eventParams);
  170. unset($eventParams);
  171. }
  172. $this->event = $e;
  173. }
  174. /**
  175. * Get the attached event
  176. *
  177. * Will create a new MvcEvent if none provided.
  178. *
  179. * @return Event
  180. */
  181. public function getEvent()
  182. {
  183. if (!$this->event) {
  184. $this->setEvent(new MvcEvent());
  185. }
  186. return $this->event;
  187. }
  188. /**
  189. * Set locator instance
  190. *
  191. * @param Locator $locator
  192. * @return void
  193. */
  194. public function setLocator(Locator $locator)
  195. {
  196. $this->locator = $locator;
  197. }
  198. /**
  199. * Retrieve locator instance
  200. *
  201. * @return Locator
  202. */
  203. public function getLocator()
  204. {
  205. return $this->locator;
  206. }
  207. /**
  208. * Get plugin broker instance
  209. *
  210. * @return Zend\Loader\Broker
  211. */
  212. public function getBroker()
  213. {
  214. if (!$this->broker) {
  215. $this->setBroker(new PluginBroker());
  216. }
  217. return $this->broker;
  218. }
  219. /**
  220. * Set plugin broker instance
  221. *
  222. * @param string|Broker $broker Plugin broker to load plugins
  223. * @return Zend\Loader\Pluggable
  224. */
  225. public function setBroker($broker)
  226. {
  227. if (!$broker instanceof Broker) {
  228. throw new Exception\InvalidArgumentException('Broker must implement Zend\Loader\Broker');
  229. }
  230. $this->broker = $broker;
  231. if (method_exists($broker, 'setController')) {
  232. $this->broker->setController($this);
  233. }
  234. return $this;
  235. }
  236. /**
  237. * Get plugin instance
  238. *
  239. * @param string $plugin Name of plugin to return
  240. * @param null|array $options Options to pass to plugin constructor (if not already instantiated)
  241. * @return mixed
  242. */
  243. public function plugin($name, array $options = null)
  244. {
  245. return $this->getBroker()->load($name, $options);
  246. }
  247. /**
  248. * Method overloading: return plugins
  249. *
  250. * @param mixed $method
  251. * @param mixed $params
  252. * @return void
  253. */
  254. public function __call($method, $params)
  255. {
  256. $options = null;
  257. if (0 < count($params)) {
  258. $options = array_shift($params);
  259. }
  260. return $this->plugin($method, $options);
  261. }
  262. /**
  263. * Register the default events for this controller
  264. *
  265. * @return void
  266. */
  267. protected function attachDefaultListeners()
  268. {
  269. $events = $this->events();
  270. $events->attach('dispatch', array($this, 'execute'));
  271. }
  272. /**
  273. * Transform an action name into a method name
  274. *
  275. * @param string $action
  276. * @return string
  277. */
  278. public static function getMethodFromAction($action)
  279. {
  280. $method = str_replace(array('.', '-', '_'), ' ', $action);
  281. $method = ucwords($method);
  282. $method = str_replace(' ', '', $method);
  283. $method = lcfirst($method);
  284. $method .= 'Action';
  285. return $method;
  286. }
  287. }