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 10namespace Zend\Mvc\Controller; 11 12use Zend\EventManager\EventInterface as Event; 13use Zend\EventManager\EventManager; 14use Zend\EventManager\EventManagerAwareInterface; 15use Zend\EventManager\EventManagerInterface; 16use Zend\Http\PhpEnvironment\Response as HttpResponse; 17use Zend\Http\Request as HttpRequest; 18use Zend\Mvc\InjectApplicationEventInterface; 19use Zend\Mvc\MvcEvent; 20use Zend\ServiceManager\ServiceLocatorAwareInterface; 21use Zend\ServiceManager\ServiceLocatorInterface; 22use Zend\Stdlib\DispatchableInterface as Dispatchable; 23use Zend\Stdlib\RequestInterface as Request; 24use Zend\Stdlib\ResponseInterface as Response; 25 26/** 27 * Abstract controller 28 * 29 * Convenience methods for pre-built plugins (@see __call): 30 * 31 * @method \Zend\View\Model\ModelInterface acceptableViewModelSelector(array $matchAgainst = null, bool $returnDefault = true, \Zend\Http\Header\Accept\FieldValuePart\AbstractFieldValuePart $resultReference = null) 32 * @method bool|array|\Zend\Http\Response fileprg(\Zend\Form\FormInterface $form, $redirect = null, $redirectToUrl = false) 33 * @method bool|array|\Zend\Http\Response filePostRedirectGet(\Zend\Form\FormInterface $form, $redirect = null, $redirectToUrl = false) 34 * @method \Zend\Mvc\Controller\Plugin\FlashMessenger flashMessenger() 35 * @method \Zend\Mvc\Controller\Plugin\Forward forward() 36 * @method mixed|null identity() 37 * @method \Zend\Mvc\Controller\Plugin\Layout|\Zend\View\Model\ModelInterface layout(string $template = null) 38 * @method \Zend\Mvc\Controller\Plugin\Params|mixed params(string $param = null, mixed $default = null) 39 * @method \Zend\Http\Response|array prg(string $redirect = null, bool $redirectToUrl = false) 40 * @method \Zend\Http\Response|array postRedirectGet(string $redirect = null, bool $redirectToUrl = false) 41 * @method \Zend\Mvc\Controller\Plugin\Redirect redirect() 42 * @method \Zend\Mvc\Controller\Plugin\Url url() 43 * @method \Zend\View\Model\ConsoleModel createConsoleNotFoundModel() 44 * @method \Zend\View\Model\ViewModel createHttpNotFoundModel() 45 */ 46abstract class AbstractController implements 47 Dispatchable, 48 EventManagerAwareInterface, 49 InjectApplicationEventInterface, 50 ServiceLocatorAwareInterface 51{ 52 /** 53 * @var PluginManager 54 */ 55 protected $plugins; 56 57 /** 58 * @var Request 59 */ 60 protected $request; 61 62 /** 63 * @var Response 64 */ 65 protected $response; 66 67 /** 68 * @var Event 69 */ 70 protected $event; 71 72 /** 73 * @var EventManagerInterface 74 */ 75 protected $events; 76 77 /** 78 * @var ServiceLocatorInterface 79 */ 80 protected $serviceLocator; 81 82 /** 83 * @var null|string|string[] 84 */ 85 protected $eventIdentifier; 86 87 /** 88 * Execute the request 89 * 90 * @param MvcEvent $e 91 * @return mixed 92 */ 93 abstract public function onDispatch(MvcEvent $e); 94 95 /** 96 * Dispatch a request 97 * 98 * @events dispatch.pre, dispatch.post 99 * @param Request $request 100 * @param null|Response $response 101 * @return Response|mixed 102 */ 103 public function dispatch(Request $request, Response $response = null) 104 { 105 $this->request = $request; 106 if (!$response) { 107 $response = new HttpResponse(); 108 } 109 $this->response = $response; 110 111 $e = $this->getEvent(); 112 $e->setRequest($request) 113 ->setResponse($response) 114 ->setTarget($this); 115 116 $result = $this->getEventManager()->trigger(MvcEvent::EVENT_DISPATCH, $e, function ($test) { 117 return ($test instanceof Response); 118 }); 119 120 if ($result->stopped()) { 121 return $result->last(); 122 } 123 124 return $e->getResult(); 125 } 126 127 /** 128 * Get request object 129 * 130 * @return Request 131 */ 132 public function getRequest() 133 { 134 if (!$this->request) { 135 $this->request = new HttpRequest(); 136 } 137 138 return $this->request; 139 } 140 141 /** 142 * Get response object 143 * 144 * @return Response 145 */ 146 public function getResponse() 147 { 148 if (!$this->response) { 149 $this->response = new HttpResponse(); 150 } 151 152 return $this->response; 153 } 154 155 /** 156 * Set the event manager instance used by this context 157 * 158 * @param EventManagerInterface $events 159 * @return AbstractController 160 */ 161 public function setEventManager(EventManagerInterface $events) 162 { 163 $className = get_class($this); 164 165 $nsPos = strpos($className, '\\') ?: 0; 166 $events->setIdentifiers(array_merge( 167 array( 168 __CLASS__, 169 $className, 170 substr($className, 0, $nsPos) 171 ), 172 array_values(class_implements($className)), 173 (array) $this->eventIdentifier 174 )); 175 176 $this->events = $events; 177 $this->attachDefaultListeners(); 178 179 return $this; 180 } 181 182 /** 183 * Retrieve the event manager 184 * 185 * Lazy-loads an EventManager instance if none registered. 186 * 187 * @return EventManagerInterface 188 */ 189 public function getEventManager() 190 { 191 if (!$this->events) { 192 $this->setEventManager(new EventManager()); 193 } 194 195 return $this->events; 196 } 197 198 /** 199 * Set an event to use during dispatch 200 * 201 * By default, will re-cast to MvcEvent if another event type is provided. 202 * 203 * @param Event $e 204 * @return void 205 */ 206 public function setEvent(Event $e) 207 { 208 if (!$e instanceof MvcEvent) { 209 $eventParams = $e->getParams(); 210 $e = new MvcEvent(); 211 $e->setParams($eventParams); 212 unset($eventParams); 213 } 214 $this->event = $e; 215 } 216 217 /** 218 * Get the attached event 219 * 220 * Will create a new MvcEvent if none provided. 221 * 222 * @return MvcEvent 223 */ 224 public function getEvent() 225 { 226 if (!$this->event) { 227 $this->setEvent(new MvcEvent()); 228 } 229 230 return $this->event; 231 } 232 233 /** 234 * Set serviceManager instance 235 * 236 * @param ServiceLocatorInterface $serviceLocator 237 * @return void 238 */ 239 public function setServiceLocator(ServiceLocatorInterface $serviceLocator) 240 { 241 $this->serviceLocator = $serviceLocator; 242 } 243 244 /** 245 * Retrieve serviceManager instance 246 * 247 * @return ServiceLocatorInterface 248 */ 249 public function getServiceLocator() 250 { 251 return $this->serviceLocator; 252 } 253 254 /** 255 * Get plugin manager 256 * 257 * @return PluginManager 258 */ 259 public function getPluginManager() 260 { 261 if (!$this->plugins) { 262 $this->setPluginManager(new PluginManager()); 263 } 264 265 $this->plugins->setController($this); 266 return $this->plugins; 267 } 268 269 /** 270 * Set plugin manager 271 * 272 * @param PluginManager $plugins 273 * @return AbstractController 274 */ 275 public function setPluginManager(PluginManager $plugins) 276 { 277 $this->plugins = $plugins; 278 $this->plugins->setController($this); 279 280 return $this; 281 } 282 283 /** 284 * Get plugin instance 285 * 286 * @param string $name Name of plugin to return 287 * @param null|array $options Options to pass to plugin constructor (if not already instantiated) 288 * @return mixed 289 */ 290 public function plugin($name, array $options = null) 291 { 292 return $this->getPluginManager()->get($name, $options); 293 } 294 295 /** 296 * Method overloading: return/call plugins 297 * 298 * If the plugin is a functor, call it, passing the parameters provided. 299 * Otherwise, return the plugin instance. 300 * 301 * @param string $method 302 * @param array $params 303 * @return mixed 304 */ 305 public function __call($method, $params) 306 { 307 $plugin = $this->plugin($method); 308 if (is_callable($plugin)) { 309 return call_user_func_array($plugin, $params); 310 } 311 312 return $plugin; 313 } 314 315 /** 316 * Register the default events for this controller 317 * 318 * @return void 319 */ 320 protected function attachDefaultListeners() 321 { 322 $events = $this->getEventManager(); 323 $events->attach(MvcEvent::EVENT_DISPATCH, array($this, 'onDispatch')); 324 } 325 326 /** 327 * Transform an "action" token into a method name 328 * 329 * @param string $action 330 * @return string 331 */ 332 public static function getMethodFromAction($action) 333 { 334 $method = str_replace(array('.', '-', '_'), ' ', $action); 335 $method = ucwords($method); 336 $method = str_replace(' ', '', $method); 337 $method = lcfirst($method); 338 $method .= 'Action'; 339 340 return $method; 341 } 342} 343