/** * Render an action from a controller and render it's associated template * @param string $expr * @param array $attributes * @param array $options * @return string */ public function renderAction($expr, $attributes, $options) { $application = Module::getApplication(); //parse the name of the controller, action and template directory that should be used if (strpos($expr, '/') > 0) { $params = explode('/', $expr); $controllerName = $params[0]; $actionName = $params[1]; $templateDir = $controllerName . '/'; } else { $params = explode(':', $expr); $moduleName = $params[0]; $controllerName = $params[1]; $actionName = $params[2]; $actionName = lcfirst($actionName); $actionName = strtolower(preg_replace('/([A-Z])/', '-$1', $actionName)); $templateDir = lcfirst($moduleName) . '-' . lcfirst($controllerName) . '/'; $controllerName = $moduleName . '\\Controller\\' . $controllerName . 'Controller'; } //instantiate the controller based on the given name $controller = $application->getLocator()->get($controllerName); //inject the locator if ($controller instanceof LocatorAware) { $controller->setLocator($application->getLocator()); } //clone the MvcEvent and route and update them with the provided parameters $event = $application->getMvcEvent(); $routeMatch = clone $event->getRouteMatch(); $event = clone $event; foreach ($attributes as $key => $value) { $routeMatch->setParam($key, $value); } $event->setRouteMatch($routeMatch); //inject the new event into the controller if ($controller instanceof InjectApplicationEventInterface) { $controller->setEvent($event); } //test if the action exists in the controller and change it to not-found if missing $method = ActionController::getMethodFromAction($actionName); if (!method_exists($controller, $method)) { $method = 'notFoundAction'; $actionName = 'not-found'; } //call the method on the controller $response = $controller->{$method}(); //if the result is an instance of the Response class return it if ($response instanceof Response) { return $response->getBody(); } //if the response is an instance of ViewModel then render that one if ($response instanceof ModelInterface) { $viewModel = $response; } elseif (is_array($response) || $response instanceof \ArrayAccess || $response instanceof \Traversable) { $viewModel = new ViewModel($response); $viewModel->setTemplate($templateDir . $actionName); } else { return ''; } $viewModel->terminate(); $viewModel->setOption('has_parent', true); $view = $application->getLocator()->get('Zend\\View\\View'); $output = $view->render($viewModel); return $output; }