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

ZF2-417 Form Annotation Hydrator options support #2378

Closed
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
43 changes: 43 additions & 0 deletions library/Zend/Form/Annotation/AbstractArrayOrStringAnnotation.php
@@ -0,0 +1,43 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @package Zend_Form
*/

namespace Zend\Form\Annotation;

use Zend\Form\Exception;

/**
* @package Zend_Form
* @subpackage Annotation
*/
abstract class AbstractArrayOrStringAnnotation
{
/**
* @var array|string
*/
protected $value;

/**
* Receive and process the contents of an annotation
*
* @param array $data
* @throws Exception\DomainException if a 'value' key is missing, or its value is not an array or string
*/
public function __construct(array $data)
{
if (!isset($data['value']) || (!is_array($data['value']) && !is_string($data['value']))) {
throw new Exception\DomainException(sprintf(
'%s expects the annotation to define an array or string; received "%s"',
get_class($this),
isset($data['value']) ? gettype($data['value']) : 'null'
));
}
$this->value = $data['value'];
}
}
4 changes: 2 additions & 2 deletions library/Zend/Form/Annotation/Hydrator.php
Expand Up @@ -21,12 +21,12 @@
* @package Zend_Form
* @subpackage Annotation
*/
class Hydrator extends AbstractStringAnnotation
class Hydrator extends AbstractArrayOrStringAnnotation
{
/**
* Retrieve the hydrator class
*
* @return null|string
* @return null|string|array
*/
public function getHydrator()
{
Expand Down
26 changes: 21 additions & 5 deletions library/Zend/Form/Factory.php
Expand Up @@ -351,9 +351,9 @@ protected function prepareAndInjectObject($objectName, FieldsetInterface $fields
* Takes a string indicating a hydrator class name (or a concrete instance), instantiates the class
* by that name, and injects the hydrator instance into the form.
*
* @param string $hydratorOrName
* @param FieldsetInterface $fieldset
* @param string $method
* @param string|array|Hydrator\HydratorInterface $hydratorOrName
* @param FieldsetInterface $fieldset
* @param string $method
* @return void
* @throws Exception\DomainException If $hydratorOrName is not a string, does not resolve to a known class, or
* the class does not implement Hydrator\HydratorInterface
Expand All @@ -365,14 +365,27 @@ protected function prepareAndInjectHydrator($hydratorOrName, FieldsetInterface $
return;
}

if (!is_string($hydratorOrName)) {
if (!is_string($hydratorOrName) && !is_array($hydratorOrName)) {
throw new Exception\DomainException(sprintf(
'%s expects string hydrator class name; received "%s"',
'%s expects string hydrator class name or an array specification; received "%s"',
$method,
(is_object($hydratorOrName) ? get_class($hydratorOrName) : gettype($hydratorOrName))
));
}

if (is_array($hydratorOrName)) {
if (!isset($hydratorOrName['type'])) {
throw new Exception\DomainException(sprintf(
'%s expects array specification to have a type value',
$method
));
}
$hydratorOptions = (isset($hydratorOrName['options'])) ? $hydratorOrName['options'] : array();
$hydratorOrName = $hydratorOrName['type'];
} else {
$hydratorOptions = array();
}

if (!class_exists($hydratorOrName)) {
throw new Exception\DomainException(sprintf(
'%s expects string hydrator name to be a valid class name; received "%s"',
Expand All @@ -389,6 +402,9 @@ protected function prepareAndInjectHydrator($hydratorOrName, FieldsetInterface $
$hydratorOrName
));
}
if (!empty($hydratorOptions) && $hydrator instanceof Hydrator\HydratorOptionsInterface) {
$hydrator->setOptions($hydratorOptions);
}

$fieldset->setHydrator($hydrator);
}
Expand Down
2 changes: 1 addition & 1 deletion library/Zend/Stdlib/Hydrator/AbstractHydrator.php
Expand Up @@ -56,7 +56,7 @@ public function getStrategy($name)
$name
));
}

return $this->strategies['*'];
}

Expand Down
45 changes: 42 additions & 3 deletions library/Zend/Stdlib/Hydrator/ClassMethods.php
Expand Up @@ -17,22 +17,61 @@
* @package Zend_Stdlib
* @subpackage Hydrator
*/
class ClassMethods extends AbstractHydrator
class ClassMethods extends AbstractHydrator implements HydratorOptionsInterface
{
/**
* Flag defining whether array keys are underscore-separated (true) or camel case (false)
* @var boolean
*/
protected $underscoreSeparatedKeys;
protected $underscoreSeparatedKeys = true;

/**
* Define if extract values will use camel case or name with underscore
* @param boolean $underscoreSeparatedKeys
* @param boolean|array $underscoreSeparatedKeys
*/
public function __construct($underscoreSeparatedKeys = true)
{
parent::__construct();
$this->setUnderscoreSeparatedKeys($underscoreSeparatedKeys);
}

/**
* @param array|\Traversable $options
* @return ClassMethods
* @throws Exception\InvalidArgumentException
*/
public function setOptions($options)
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif (!is_array($options)) {
throw new Exception\InvalidArgumentException(
'The options parameter must be an array or a Traversable'
);
}
if (isset($options['underscoreSeparatedKeys'])) {
$this->setUnderscoreSeparatedKeys($options['underscoreSeparatedKeys']);
}

return $this;
}

/**
* @param boolean $underscoreSeparatedKeys
* @return ClassMethods
*/
public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys)
{
$this->underscoreSeparatedKeys = $underscoreSeparatedKeys;
return $this;
}

/**
* @return boolean
*/
public function getUnderscoreSeparatedKeys()
{
return $this->underscoreSeparatedKeys;
}

/**
Expand Down
25 changes: 25 additions & 0 deletions library/Zend/Stdlib/Hydrator/HydratorOptionsInterface.php
@@ -0,0 +1,25 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @package Zend_Stdlib
*/

namespace Zend\Stdlib\Hydrator;

/**
* @category Zend
* @package Zend_Stdlib
* @subpackage Hydrator
*/
interface HydratorOptionsInterface
{
/**
* @param array|\Traversable $options
* @return HydratorOptionsInterface
*/
public function setOptions($options);
}
11 changes: 11 additions & 0 deletions tests/ZendTest/Form/Annotation/AnnotationBuilderTest.php
Expand Up @@ -187,6 +187,17 @@ public function testCanHandleOptionsAnnotation()
$this->assertEquals(array('class' => 'label'), $username->getLabelAttributes());
}

public function testCanHandleHydratorArrayAnnotation()
{
$entity = new TestAsset\Annotation\EntityWithHydratorArray();
$builder = new Annotation\AnnotationBuilder();
$form = $builder->createForm($entity);

$hydrator = $form->getHydrator();
$this->assertInstanceOf('Zend\Stdlib\Hydrator\ClassMethods', $hydrator);
$this->assertFalse($hydrator->getUnderscoreSeparatedKeys());
}

public function testAllowTypeAsElementNameInInputFilter()
{
$entity = new TestAsset\Annotation\EntityWithTypeAsElementName();
Expand Down
16 changes: 16 additions & 0 deletions tests/ZendTest/Form/FactoryTest.php
Expand Up @@ -317,6 +317,22 @@ public function testCanCreateFormsAndSpecifyHydrator()
$this->assertInstanceOf('Zend\Stdlib\Hydrator\ObjectProperty', $hydrator);
}

public function testCanCreateHydratorFromArray()
{
$form = $this->factory->createForm(array(
'name' => 'foo',
'hydrator' => array(
'type' => 'Zend\Stdlib\Hydrator\ClassMethods',
'options' => array('underscoreSeparatedKeys' => false),
),
));

$this->assertInstanceOf('Zend\Form\FormInterface', $form);
$hydrator = $form->getHydrator();
$this->assertInstanceOf('Zend\Stdlib\Hydrator\ClassMethods', $hydrator);
$this->assertFalse($hydrator->getUnderscoreSeparatedKeys());
}

public function testCanCreateHydratorFromConcreteClass()
{
$form = $this->factory->createForm(array(
Expand Down
@@ -0,0 +1,26 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @package Zend_Form
*/

namespace ZendTest\Form\TestAsset\Annotation;

use Zend\Form\Annotation;

/**
* @Annotation\Name("user")
* @Annotation\Attributes({"legend":"Register"})
* @Annotation\Hydrator({"type":"Zend\Stdlib\Hydrator\ClassMethods", "options": {"underscoreSeparatedKeys": false}})
*/
class EntityWithHydratorArray
{
/**
* @Annotation\Options({"label":"Username:", "label_attributes": {"class": "label"}})
*/
public $username;
}
10 changes: 10 additions & 0 deletions tests/ZendTest/Stdlib/HydratorTest.php
Expand Up @@ -179,6 +179,16 @@ public function testHydratorClassMethodsUnderscore()
$this->assertEquals($test->hasBar(), false);
}

public function testHydratorClassMethodsOptions()
{
$hydrator = new ClassMethods();
$this->assertTrue($hydrator->getUnderscoreSeparatedKeys());
$hydrator->setOptions(array('underscoreSeparatedKeys' => false));
$this->assertFalse($hydrator->getUnderscoreSeparatedKeys());
$hydrator->setUnderscoreSeparatedKeys(true);
$this->assertTrue($hydrator->getUnderscoreSeparatedKeys());
}

public function testHydratorClassMethodsIgnoresInvalidValues()
{
$hydrator = new ClassMethods(true);
Expand Down