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

Make Partial proxy to view render function #2957

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
90 changes: 12 additions & 78 deletions library/Zend/View/Helper/Partial.php
Expand Up @@ -10,6 +10,7 @@

namespace Zend\View\Helper;

use Traversable;
use Zend\View\Exception;

/**
Expand All @@ -20,98 +21,31 @@
*/
class Partial extends AbstractHelper
{
/**
* Variable to which object will be assigned
* @var string
*/
protected $objectKey;

/**
* Renders a template fragment within a variable scope distinct from the
* calling View object.
*
* If no arguments are passed, returns the helper instance.
*
* If the $model is an array, it is passed to the view object's assign()
* method.
*
* If the $model is an object, it first checks to see if the object
* implements a 'toArray' method; if so, it passes the result of that
* method to to the view object's assign() method. Otherwise, the result of
* get_object_vars() is passed.
* calling View object. It proxies to view's render function
*
* @param string $name Name of view script
* @param array $model Variables to populate in the view
* @param array $values Variables to populate in the view
* @return string|Partial
* @throws Exception\RuntimeException
*/
public function __invoke($name = null, $model = null)
public function __invoke($name = null, $values = null)
{
if (0 == func_num_args()) {
return $this;
}

$view = $this->cloneView();
if (isset($this->partialCounter)) {
$view->partialCounter = $this->partialCounter;
}

if (!empty($model)) {
if (is_array($model)) {
$view->vars()->assign($model);
} elseif (is_object($model)) {
if (null !== ($objectKey = $this->getObjectKey())) {
$view->vars()->offsetSet($objectKey, $model);
} elseif (method_exists($model, 'toArray')) {
$view->vars()->assign($model->toArray());
} else {
$view->vars()->assign(get_object_vars($model));
}
if (is_scalar($values)) {
$values = array();
} elseif (is_object($values)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this:

} elseif ($values instanceof \Zend\View\Model\ModelInterface) {
    $values = $values->getVariables();
} elseif (is_object($values)) {
   ... 

(importing ModelInterface, of course). The reason being that we can't count on a View Model implementation implementing the various bits that the next conditional looks at, but we can count on getVariables().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, we should probably check if $name is a View Model -- that could simplify things, too. :)

if (method_exists($values, 'toArray')) {
$values = $values->toArray();
} else {
$values = get_object_vars($values);
}
}

return $view->render($name);
}

/**
* Clone the current View
*
* @return \Zend\View\Renderer\RendererInterface
*/
public function cloneView()
{
$view = clone $this->view;
$view->setVars(array());
return $view;
}

/**
* Set object key
*
* @param string $key
* @return Partial
*/
public function setObjectKey($key)
{
if (null === $key) {
$this->objectKey = null;
} else {
$this->objectKey = (string) $key;
}

return $this;
}

/**
* Retrieve object key
*
* The objectKey is the variable to which an object in the iterator will be
* assigned.
*
* @return null|string
*/
public function getObjectKey()
{
return $this->objectKey;
return $this->getView()->render($name, $values);
}
}
43 changes: 29 additions & 14 deletions library/Zend/View/Helper/PartialLoop.php
Expand Up @@ -10,7 +10,9 @@

namespace Zend\View\Helper;

use Iterator;
use Traversable;
use Zend\Stdlib\ArrayUtils;
use Zend\View\Exception;

/**
Expand All @@ -22,9 +24,9 @@
*/
class PartialLoop extends Partial
{

/**
* Marker to where the pointer is at in the loop
*
* @var integer
*/
protected $partialCounter = 0;
Expand All @@ -36,40 +38,53 @@ class PartialLoop extends Partial
* If no arguments are provided, returns object instance.
*
* @param string $name Name of view script
* @param array $model Variables to populate in the view
* @param array $values Variables to populate in the view
* @return string
* @throws Exception\InvalidArgumentException
*/
public function __invoke($name = null, $model = null)
public function __invoke($name = null, $values = null)
{
if (0 == func_num_args()) {
return $this;
}

if (!is_array($model)
&& (!$model instanceof Traversable)
&& (is_object($model) && !method_exists($model, 'toArray'))
if (!is_array($values)
&& (!$values instanceof Traversable)
&& (is_object($values) && !method_exists($values, 'toArray'))
) {
throw new Exception\InvalidArgumentException('PartialLoop helper requires iterable data');
}

if (is_object($model)
&& (!$model instanceof Traversable)
&& method_exists($model, 'toArray')
if (is_object($values)
&& (!$values instanceof Traversable)
&& method_exists($values, 'toArray')
) {
$model = $model->toArray();
$values = $values->toArray();
}

if ($values instanceof Iterator) {
$values = ArrayUtils::iteratorToArray($values);
}

$content = '';
// reset the counter if it's called again
$this->partialCounter = 0;
foreach ($model as $item) {
// increment the counter variable
$this->partialCounter++;
$content = '';

foreach ($values as $item) {
$this->partialCounter++;
$content .= parent::__invoke($name, $item);
}

return $content;
}

/**
* Get the partial counter
*
* @return int
*/
public function getPartialCounter()
{
return $this->partialCounter;
}
}
28 changes: 7 additions & 21 deletions tests/ZendTest/View/Helper/PartialLoopTest.php
Expand Up @@ -221,7 +221,6 @@ public function testShouldNotCastToArrayIfObjectIsTraversable()
$view = new View();
$view->resolver()->addPath($this->basePath . '/application/views/scripts');
$this->helper->setView($view);
$this->helper->setObjectKey('obj');

$result = $this->helper->__invoke('partialLoopObject.phtml', $o);
foreach ($data as $item) {
Expand All @@ -245,7 +244,7 @@ public function testEmptyArrayPassedToPartialLoopShouldNotThrowException()
/**
* @group ZF-2737
*/
public function testPartialLoopIncramentsPartialCounter()
public function testPartialLoopIncrementsPartialCounter()
{
$data = array(
array('message' => 'foo'),
Expand All @@ -258,15 +257,8 @@ public function testPartialLoopIncramentsPartialCounter()
$view->resolver()->addPath($this->basePath . '/application/views/scripts');
$this->helper->setView($view);

$result = $this->helper->__invoke('partialLoopCouter.phtml', $data);
foreach ($data as $key => $item) {
$string = sprintf(
'This is an iteration: %s, pointer at %d',
$item['message'],
$key + 1
);
$this->assertContains($string, $result, $result);
}
$this->helper->__invoke('partialLoopCouter.phtml', $data);
$this->assertEquals(4, $this->helper->getPartialCounter());
}

/**
Expand All @@ -285,17 +277,11 @@ public function testPartialLoopPartialCounterResets()
$view->resolver()->addPath($this->basePath . '/application/views/scripts');
$this->helper->setView($view);

$result = $this->helper->__invoke('partialLoopCouter.phtml', $data);
foreach ($data as $key=>$item) {
$string = 'This is an iteration: ' . $item['message'] . ', pointer at ' . ($key+1);
$this->assertContains($string, $result);
}
$this->helper->__invoke('partialLoopCouter.phtml', $data);
$this->assertEquals(4, $this->helper->getPartialCounter());

$result = $this->helper->__invoke('partialLoopCouter.phtml', $data);
foreach ($data as $key=>$item) {
$string = 'This is an iteration: ' . $item['message'] . ', pointer at ' . ($key+1);
$this->assertContains($string, $result);
}
$this->helper->__invoke('partialLoopCouter.phtml', $data);
$this->assertEquals(4, $this->helper->getPartialCounter());
}
}

Expand Down
73 changes: 0 additions & 73 deletions tests/ZendTest/View/Helper/PartialTest.php
Expand Up @@ -94,34 +94,6 @@ public function testSetViewSetsViewProperty()
$this->assertSame($view, $this->helper->getView());
}

/**
* @return void
*/
public function testCloneViewReturnsDifferentViewInstance()
{
$view = new View();
$this->helper->setView($view);
$clone = $this->helper->cloneView();
$this->assertNotSame($view, $clone);
$this->assertTrue($clone instanceof View);
}

/**
* @return void
*/
public function testCloneViewClearsViewVariables()
{
$view = new View();
$view->foo = 'bar';
$this->helper->setView($view);

$clone = $this->helper->cloneView();
$clonedVars = $clone->vars();

$this->assertEquals(0, count($clonedVars));
$this->assertNull($clone->vars()->foo);
}

public function testObjectModelWithPublicPropertiesSetsViewVariables()
{
$model = new \stdClass();
Expand Down Expand Up @@ -154,56 +126,11 @@ public function testObjectModelWithToArraySetsViewVariables()
}
}

public function testObjectModelSetInObjectKeyWhenKeyPresent()
{
$this->helper->setObjectKey('foo');
$model = new \stdClass();
$model->footest = 'bar';
$model->bartest = 'baz';

$view = new View;
$view->resolver()->addPath($this->basePath . '/application/views/scripts');
$this->helper->setView($view);
$return = $this->helper->__invoke('partialObj.phtml', $model);

$this->assertNotContains('No object model passed', $return);

foreach (get_object_vars($model) as $key => $value) {
$string = sprintf('%s: %s', $key, $value);
$this->assertContains($string, $return, "Checking for '$return' containing '$string'");
}
}

public function testPassingNoArgsReturnsHelperInstance()
{
$test = $this->helper->__invoke();
$this->assertSame($this->helper, $test);
}

public function testObjectKeyIsNullByDefault()
{
$this->assertNull($this->helper->getObjectKey());
}

public function testCanSetObjectKey()
{
$this->testObjectKeyIsNullByDefault();
$this->helper->setObjectKey('foo');
$this->assertEquals('foo', $this->helper->getObjectKey());
}

public function testCanSetObjectKeyToNullValue()
{
$this->testCanSetObjectKey();
$this->helper->setObjectKey(null);
$this->assertNull($this->helper->getObjectKey());
}

public function testSetObjectKeyImplementsFluentInterface()
{
$test = $this->helper->setObjectKey('foo');
$this->assertSame($this->helper, $test);
}
}

class Aggregate
Expand Down