/** * Add a child model * * @param Model $child * @param null|string $captureTo Optional; if specified, the "capture to" value to set on the child * @return ViewModel */ public function addChild(Model $child, $captureTo = null) { $this->children[] = $child; if (null !== $captureTo) { $child->setCaptureTo($captureTo); } return $this; }
/** * Loop through children, rendering each * * @param Model $model * @return void */ protected function renderChildren(Model $model) { foreach ($model as $child) { if ($child->terminate()) { throw new Exception\DomainException('Inconsistent state; child view model is marked as terminal'); } $child->setOption('has_parent', true); $result = $this->render($child); $child->setOption('has_parent', null); $capture = $child->captureTo(); if (!empty($capture)) { $model->setVariable($capture, $result); } } }
/** * Inject the controller and controller class into the model * * If either $displayExceptions or $displayNotFoundReason are enabled, * injects the controllerClass from the MvcEvent. It checks to see if a * controller is present in the MvcEvent, and, if not, grabs it from * the route match if present; if a controller is found, it injects it into * the model. * * @param ViewModel $model * @param MvcEvent $e * @return void */ protected function injectController($model, $e) { if (!$this->displayExceptions() && !$this->displayNotFoundReason()) { return; } $controller = $e->getController(); if (empty($controller)) { $routeMatch = $e->getRouteMatch(); if (empty($routeMatch)) { return; } $controller = $routeMatch->getParam('controller', false); if (!$controller) { return; } } $controllerClass = $e->getControllerClass(); $model->setVariable('controller', $controller); $model->setVariable('controller_class', $controllerClass); }
/** * Recursively processes all ViewModels and returns output. * * @param string|Model $model A ViewModel instance. * @param null|array|Traversable $values Values to use when rendering. If none * provided, uses those in the composed * variables container. * @return string Console output. */ public function render($model, $values = null) { if (!$model instanceof Model) { return ''; } $result = ''; $options = $model->getOptions(); foreach ($options as $setting => $value) { $method = 'set' . $setting; if (method_exists($this, $method)) { $this->{$method}($value); } unset($method, $setting, $value); } unset($options); $values = $model->getVariables(); if (isset($values['result'])) { // filter and append the result $result .= $this->getFilterChain()->filter($values['result']); } if ($model->hasChildren()) { // recursively render all children foreach ($model->getChildren() as $child) { $result .= $this->render($child, $values); } } return $result; }
/** * Retrieve values from a model and recurse its children to build a data structure * * @param Model $model * @return array */ protected function recurseModel(Model $model) { $values = $model->getVariables(); if (!$model->hasChildren()) { return $values; } $mergeChildren = $this->mergeUnnamedChildren(); foreach ($model as $child) { $captureTo = $child->captureTo(); if (!$captureTo && !$mergeChildren) { // We don't want to do anything with this child continue; } $childValues = $this->recurseModel($child); if ($captureTo) { // Capturing to a specific key $values[$captureTo] = $childValues; } elseif ($mergeChildren) { // Merging values with parent $values = array_replace_recursive($values, $childValues); } } return $values; }