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

Commit

Permalink
Merge branch 'fix-ZF2-307-hydrator-from-class_methods' of https://git…
Browse files Browse the repository at this point in the history
…hub.com/blanchonvincent/zf2 into feature/zf2-307
  • Loading branch information
Show file tree
Hide file tree
Showing 5 changed files with 319 additions and 0 deletions.
126 changes: 126 additions & 0 deletions src/Hydrator/ClassMethods.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Stdlib
* @subpackage Hydrator
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\Stdlib\Hydrator;

use Zend\Stdlib\Exception;

/**
* @category Zend
* @package Zend_Stdlib
* @subpackage Hydrator
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class ClassMethods implements HydratorInterface
{
/**
* CameCase usage to extract attribute with getter/setter method name
* @var boolean
*/
protected $useCamelCase;

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

/**
* Extract values from an object with class methods
*
* Extracts the getter/setter of the given $object.
*
* @param object $object
* @return array
* @throws Exception\BadMethodCallException for a non-object $object
*/
public function extract($object)
{
if (!is_object($object)) {
throw new Exception\BadMethodCallException(sprintf(
'%s expects the provided $object to be a PHP object)',
__METHOD__
));
}

$transform = function($letters)
{
$letter = array_shift($letters);
return '_' . strtolower($letter);
};
$attributes = array();
$methods = get_class_methods($object);
foreach($methods as $method) {
if(preg_match('/^get[A-Z]\w*/', $method)) {
// setter verification
$setter = preg_replace('/^get/', 'set', $method);
if(!in_array($setter, $methods)) {
continue;
}
$attribute = substr($method, 3);
$attribute = lcfirst($attribute);
if (!$this->useCamelCase) {
$attribute = preg_replace_callback('/([A-Z])/', $transform, $attribute);
}
$attributes[$attribute] = $object->$method();
}
}

return $attributes;
}

/**
* Hydrate an object by populating getter/setter methods
*
* Hydrates an object by getter/setter methods of the object.
*
* @param array $data
* @param object $object
* @return void
* @throws Exception\BadMethodCallException for a non-object $object
*/
public function hydrate(array $data, $object)
{
if (!is_object($object)) {
throw new Exception\BadMethodCallException(sprintf(
'%s expects the provided $object to be a PHP object)',
__METHOD__
));
}

$transform = function($letters)
{
$letter = substr(array_shift($letters), 1, 1);
return ucfirst($letter);
};
foreach ($data as $property => $value) {
if (!$this->useCamelCase) {
$property = preg_replace_callback('/(_[a-z])/', $transform, $property);
}
$method = 'set' . ucfirst($property);
$object->$method($value);
}
}
}
93 changes: 93 additions & 0 deletions test/HydratorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Stdlib
* @subpackage UnitTests
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id:$
*/

namespace ZendTest\Stdlib;

use Zend\Stdlib\Hydrator\ClassMethods;
use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCase,
ZendTest\Stdlib\TestAsset\ClassMethodsUnderscore,
ZendTest\Stdlib\TestAsset\ClassMethodsCamelCaseMissing;

/**
* @category Zend
* @package Zend_Stdlib
* @subpackage UnitTests
* @group Zend_Stdlib
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class HydratorTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->classMethodsCamelCase = new ClassMethodsCamelCase();
$this->classMethodsCamelCaseMissing = new ClassMethodsCamelCaseMissing();
$this->classMethodsUnderscore = new ClassMethodsUnderscore();
}

public function testInitiateValues()
{
$this->assertEquals($this->classMethodsCamelCase->getFooBar(), '1');
$this->assertEquals($this->classMethodsCamelCase->getFooBarBaz(), '2');
$this->assertEquals($this->classMethodsUnderscore->getFooBar(), '1');
$this->assertEquals($this->classMethodsUnderscore->getFooBarBaz(), '2');
}

public function testHydratorClassMethodsCamelCase()
{
$hydrator = new ClassMethods(true);
$datas = $hydrator->extract($this->classMethodsCamelCase);
$this->assertTrue(isset($datas['fooBar']));
$this->assertEquals($datas['fooBar'], '1');
$this->assertTrue(isset($datas['fooBarBaz']));
$this->assertFalse(isset($datas['foo_bar']));
$hydrator->hydrate(array('fooBar' => 'foo', 'fooBarBaz' => 'bar'), $this->classMethodsCamelCase);
$this->assertEquals($this->classMethodsCamelCase->getFooBar(), 'foo');
$this->assertEquals($this->classMethodsCamelCase->getFooBarBaz(), 'bar');
}

public function testHydratorClassMethodsCamelCaseWithSetterMissing()
{
$hydrator = new ClassMethods(true);
$datas = $hydrator->extract($this->classMethodsCamelCaseMissing);
$this->assertTrue(isset($datas['fooBar']));
$this->assertEquals($datas['fooBar'], '1');
$this->assertFalse(isset($datas['fooBarBaz']));
$this->assertFalse(isset($datas['foo_bar']));
$hydrator->hydrate(array('fooBar' => 'foo'), $this->classMethodsCamelCaseMissing);
$this->assertEquals($this->classMethodsCamelCaseMissing->getFooBar(), 'foo');
$this->assertEquals($this->classMethodsCamelCaseMissing->getFooBarBaz(), '2');
}

public function testHydratorClassMethodsUnderscore()
{
$hydrator = new ClassMethods(false);
$datas = $hydrator->extract($this->classMethodsUnderscore);
$this->assertTrue(isset($datas['foo_bar']));
$this->assertEquals($datas['foo_bar'], '1');
$this->assertTrue(isset($datas['foo_bar_baz']));
$this->assertFalse(isset($datas['fooBar']));
$hydrator->hydrate(array('foo_bar' => 'foo', 'foo_bar_baz' => 'bar'), $this->classMethodsUnderscore);
$this->assertEquals($this->classMethodsUnderscore->getFooBar(), 'foo');
$this->assertEquals($this->classMethodsUnderscore->getFooBarBaz(), 'bar');
}
}
32 changes: 32 additions & 0 deletions test/TestAsset/ClassMethodsCamelCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace ZendTest\Stdlib\TestAsset;

class ClassMethodsCamelCase
{
protected $fooBar = '1';

protected $fooBarBaz = '2';

public function getFooBar()
{
return $this->fooBar;
}

public function setFooBar($value)
{
$this->fooBar = $value;
return $this;
}

public function getFooBarBaz()
{
return $this->fooBarBaz;
}

public function setFooBarBaz($value)
{
$this->fooBarBaz = $value;
return $this;
}
}
36 changes: 36 additions & 0 deletions test/TestAsset/ClassMethodsCamelCaseMissing.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace ZendTest\Stdlib\TestAsset;

class ClassMethodsCamelCaseMissing
{
protected $fooBar = '1';

protected $fooBarBaz = '2';

public function getFooBar()
{
return $this->fooBar;
}

public function setFooBar($value)
{
$this->fooBar = $value;
return $this;
}

public function getFooBarBaz()
{
return $this->fooBarBaz;
}

/*
* comment to detection verification
*
public function setFooBarBaz($value)
{
$this->fooBarBaz = $value;
return $this;
}
*/
}
32 changes: 32 additions & 0 deletions test/TestAsset/ClassMethodsUnderscore.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace ZendTest\Stdlib\TestAsset;

class ClassMethodsUnderscore
{
protected $foo_bar = '1';

protected $foo_bar_baz = '2';

public function getFooBar()
{
return $this->foo_bar;
}

public function setFooBar($value)
{
$this->foo_bar = $value;
return $this;
}

public function getFooBarBaz()
{
return $this->foo_bar_baz;
}

public function setFooBarBaz($value)
{
$this->foo_bar_baz = $value;
return $this;
}
}

0 comments on commit 94860d1

Please sign in to comment.