Skip to content
This repository was archived by the owner on Jan 21, 2020. It is now read-only.

Commit 06c27db

Browse files
committed
Merge pull request #4 from weierophinney/feature/view-models
Allow rendering view models via render()
2 parents 047f562 + aa6fd32 commit 06c27db

File tree

2 files changed

+101
-41
lines changed

2 files changed

+101
-41
lines changed

src/ZendViewRenderer.php

Lines changed: 71 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public function __construct(RendererInterface $renderer = null, $layout = null)
109109
*
110110
* If a layout was specified during construction, it will be used;
111111
* alternately, you can specify a layout to use via the "layout"
112-
* parameter, using either:
112+
* parameter/variable, using either:
113113
*
114114
* - a string layout template name
115115
* - a Zend\View\Model\ModelInterface instance
@@ -118,16 +118,18 @@ public function __construct(RendererInterface $renderer = null, $layout = null)
118118
* the constructor.
119119
*
120120
* @param string $name
121-
* @param array|object $params
121+
* @param array|ModelInterface|object $params
122122
* @return string
123123
*/
124124
public function render($name, $params = [])
125125
{
126-
$params = $this->mergeParams($name, $this->normalizeParams($params));
127-
return $this->renderModel(
128-
$this->createModel($name, $params),
129-
$this->renderer
130-
);
126+
$viewModel = ($params instanceof ModelInterface)
127+
? $this->mergeViewModel($name, $params)
128+
: $this->createModel($name, $params);
129+
130+
$viewModel = $this->prepareLayout($viewModel);
131+
132+
return $this->renderModel($viewModel, $this->renderer);
131133
}
132134

133135
/**
@@ -169,43 +171,15 @@ public function getPaths()
169171
/**
170172
* Create a view model from the template and parameters.
171173
*
172-
* Injects the created model in the layout view model, if present.
173-
*
174-
* If the $params contains a non-empty 'layout' key, that value will
175-
* be used to seed a layout view model, if:
176-
*
177-
* - it is a string layout template name
178-
* - it is a ModelInterface instance
179-
*
180-
* If a layout is discovered in this way, it will override the one set in
181-
* the constructor, if any.
182-
*
183174
* @param string $name
184-
* @param array $params
175+
* @param mixed $params
185176
* @return ModelInterface
186177
*/
187-
private function createModel($name, array $params)
178+
private function createModel($name, $params)
188179
{
189-
$layout = $this->layout ? clone $this->layout : null;
190-
if (array_key_exists('layout', $params) && $params['layout']) {
191-
if (is_string($params['layout'])) {
192-
$layout = new ViewModel();
193-
$layout->setTemplate($params['layout']);
194-
unset($params['layout']);
195-
} elseif ($params['layout'] instanceof ModelInterface) {
196-
$layout = $params['layout'];
197-
unset($params['layout']);
198-
}
199-
}
200-
201-
$model = new ViewModel($params);
180+
$params = $this->mergeParams($name, $this->normalizeParams($params));
181+
$model = new ViewModel($params);
202182
$model->setTemplate($name);
203-
204-
if ($layout) {
205-
$layout->addChild($model);
206-
$model = $layout;
207-
}
208-
209183
return $model;
210184
}
211185

@@ -306,4 +280,62 @@ private function getNamespacedResolver(AggregateResolver $aggregate)
306280
}
307281
}
308282
}
283+
284+
/**
285+
* Merge global/template parameters with provided view model.
286+
*
287+
* @param string $name Template name.
288+
* @param ModelInterface $model
289+
* @return ModelInterface
290+
*/
291+
private function mergeViewModel($name, ModelInterface $model)
292+
{
293+
$params = $this->mergeParams($name, $model->getVariables());
294+
$model->setVariables($params);
295+
$model->setTemplate($name);
296+
return $model;
297+
}
298+
299+
/**
300+
* Prepare the layout, if any.
301+
*
302+
* Injects the view model in the layout view model, if present.
303+
*
304+
* If the view model contains a non-empty 'layout' variable, that value
305+
* will be used to seed a layout view model, if:
306+
*
307+
* - it is a string layout template name
308+
* - it is a ModelInterface instance
309+
*
310+
* If a layout is discovered in this way, it will override the one set in
311+
* the constructor, if any.
312+
*
313+
* Returns the provided $viewModel unchanged if no layout is discovered;
314+
* otherwise, a view model representing the layout, with the provided
315+
* view model as a child, is returned.
316+
*
317+
* @param ModelInterface $viewModel
318+
* @return ModelInterface
319+
*/
320+
private function prepareLayout(ModelInterface $viewModel)
321+
{
322+
$layout = $this->layout ? clone $this->layout : null;
323+
324+
$providedLayout = $viewModel->getVariable('layout', false);
325+
if (is_string($providedLayout) && ! empty($providedLayout)) {
326+
$layout = new ViewModel();
327+
$layout->setTemplate($providedLayout);
328+
$viewModel->setVariable('layout', null);
329+
} elseif ($providedLayout instanceof ModelInterface) {
330+
$layout = $providedLayout;
331+
$viewModel->setVariable('layout', null);
332+
}
333+
334+
if ($layout) {
335+
$layout->addChild($viewModel);
336+
$viewModel = $layout;
337+
}
338+
339+
return $viewModel;
340+
}
309341
}

test/ZendViewRendererTest.php

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,16 +338,44 @@ public function testOverrideSharedParametersPerTemplate()
338338
$this->assertEquals($content, $result);
339339
}
340340

341-
public function testOverrideSharedParametersAtRender()
341+
public function useArrayOrViewModel()
342+
{
343+
return [
344+
'array' => [false],
345+
'view-model' => [true],
346+
];
347+
}
348+
349+
/**
350+
* @dataProvider useArrayOrViewModel
351+
*/
352+
public function testOverrideSharedParametersAtRender($viewAsModel)
342353
{
343354
$renderer = new ZendViewRenderer();
344355
$renderer->addPath(__DIR__ . '/TestAsset');
345356
$name = 'Zend';
346357
$name2 = 'View';
347358
$renderer->addDefaultParam($renderer::TEMPLATE_ALL, 'name', $name);
348-
$result = $renderer->render('zendview', ['name' => $name2]);
359+
360+
$viewModel = ['name' => $name2];
361+
$viewModel = $viewAsModel ? new ViewModel($viewModel) : $viewModel;
362+
363+
$result = $renderer->render('zendview', $viewModel);
349364
$content = file_get_contents(__DIR__ . '/TestAsset/zendview.phtml');
350365
$content = str_replace('<?php echo $name ?>', $name2, $content);
351366
$this->assertEquals($content, $result);
352367
}
368+
369+
public function testWillRenderAViewModel()
370+
{
371+
$renderer = new ZendViewRenderer();
372+
$renderer->addPath(__DIR__ . '/TestAsset');
373+
374+
$viewModel = new ViewModel(['name' => 'Zend']);
375+
$result = $renderer->render('zendview', $viewModel);
376+
377+
$content = file_get_contents(__DIR__ . '/TestAsset/zendview.phtml');
378+
$content = str_replace('<?php echo $name ?>', 'Zend', $content);
379+
$this->assertEquals($content, $result);
380+
}
353381
}

0 commit comments

Comments
 (0)