/** * 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; }
/** * Populate the view model returned by the AcceptableViewModelSelector from the result * * If the result is a ViewModel, we "re-cast" it by copying over all * values/settings/etc from the original. * * If the result is an array, we pass those values as the view model variables. * * @param array|ViewModel $result * @param ViewModelInterface $viewModel * @param MvcEvent $e */ protected function populateViewModel($result, ViewModelInterface $viewModel, MvcEvent $e) { if ($result instanceof ViewModel) { // "Re-cast" content-negotiation view models to the view model type // selected by the AcceptableViewModelSelector $viewModel->setVariables($result->getVariables()); $viewModel->setTemplate($result->getTemplate()); $viewModel->setOptions($result->getOptions()); $viewModel->setCaptureTo($result->captureTo()); $viewModel->setTerminal($result->terminate()); $viewModel->setAppend($result->isAppend()); if ($result->hasChildren()) { foreach ($result->getChildren() as $child) { $viewModel->addChild($child); } } $e->setResult($viewModel); return; } // At this point, the result is an array; use it to populate the view // model variables $viewModel->setVariables($result); $e->setResult($viewModel); }