Skip to content

Commit

Permalink
Extract type cast behaviour. Processed review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
zluiten committed Oct 27, 2020
1 parent 3ad862d commit 80ac4b3
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 22 deletions.
8 changes: 1 addition & 7 deletions src/Filter/ODM/AbstractFilter.php
Expand Up @@ -19,9 +19,7 @@ abstract public function filter($queryBuilder, $metadata, $option);

public function __construct($params)
{
if (isset($params[1])) {
$this->setTypeCaster($params[1]);
}
$this->setTypeCaster(isset($params['type_caster']) ? $params['type_caster'] : new TypeCaster());
}

public function setTypeCaster(TypeCastInterface $typeCaster)
Expand All @@ -32,10 +30,6 @@ public function setTypeCaster(TypeCastInterface $typeCaster)

protected function getTypeCaster()
{
if ($this->typeCaster === null) {
$this->typeCaster = new TypeCaster();
}

return $this->typeCaster;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Filter/ODM/TypeCaster.php
Expand Up @@ -13,7 +13,7 @@

class TypeCaster implements TypeCastInterface
{
public function typeCastField($metadata, $field, $value, $format = null, $doNotTypecastDatetime = false)
public function typeCastField($metadata, string $field, $value, string $format = null, bool $doNotTypecastDatetime = false)
{
if (! isset($metadata->fieldMappings[$field])) {
return $value;
Expand Down
24 changes: 16 additions & 8 deletions src/Filter/ORM/AbstractFilter.php
Expand Up @@ -8,6 +8,7 @@

namespace Laminas\ApiTools\Doctrine\QueryBuilder\Filter\ORM;

use InvalidArgumentException;
use Laminas\ApiTools\Doctrine\QueryBuilder\Filter\FilterInterface;
use Laminas\ApiTools\Doctrine\QueryBuilder\Filter\Service\ORMFilterManager;
use Laminas\ApiTools\Doctrine\QueryBuilder\Filter\TypeCastInterface;
Expand All @@ -22,10 +23,8 @@ abstract public function filter($queryBuilder, $metadata, $option);

public function __construct($params)
{
$this->setFilterManager($params[0]);
if (isset($params[1])) {
$this->setTypeCaster($params[1]);
}
$this->setFilterManager($this->extractFilterManagerFromConstructorParams($params));
$this->setTypeCaster(isset($params['type_caster']) ? $params['type_caster'] : new TypeCaster());
}

public function setFilterManager(ORMFilterManager $filterManager)
Expand All @@ -47,15 +46,24 @@ public function setTypeCaster(TypeCastInterface $typeCaster)

public function getTypeCaster()
{
if ($this->typeCaster === null) {
$this->typeCaster = new TypeCaster();
}

return $this->typeCaster;
}

protected function typeCastField($metadata, $field, $value, $format, $doNotTypecastDatetime = false)
{
return $this->getTypeCaster()->typeCastField($metadata, $field, $value, $format, $doNotTypecastDatetime);
}

private function extractFilterManagerFromConstructorParams(array $params)
{
if (isset($params['filter_manager']) && $params['filter_manager'] instanceof ORMFilterManager) {
return $params['filter_manager'];
}

if (isset($params[0]) && $params[0] instanceof ORMFilterManager) {
return $params[0];
}

throw new InvalidArgumentException('Missing or invalid filter manager provided to ' . __CLASS__);
}
}
28 changes: 27 additions & 1 deletion src/Filter/ORM/TypeCaster.php
Expand Up @@ -13,7 +13,7 @@

class TypeCaster implements TypeCastInterface
{
public function typeCastField($metadata, $field, $value, $format = null, $doNotTypecastDatetime = false)
public function typeCastField($metadata, string $field, $value, string $format = null, bool $doNotTypecastDatetime = false)
{
if (! isset($metadata->fieldMappings[$field])) {
return $value;
Expand Down Expand Up @@ -45,6 +45,16 @@ public function typeCastField($metadata, $field, $value, $format = null, $doNotT
$value = DateTime::createFromFormat('Y-m-d H:i:s', $value->format('Y-m-d') . ' 00:00:00');
}
break;
case 'date_immutable':
// For dates set time to midnight
if ($value && !$doNotTypecastDatetime) {
if (!$format) {
$format = 'Y-m-d';
}
$value = \DateTimeImmutable::createFromFormat($format, $value);
$value = \DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $value->format('Y-m-d') . ' 00:00:00');
}
break;
case 'time':
if ($value && ! $doNotTypecastDatetime) {
if (! $format) {
Expand All @@ -53,6 +63,14 @@ public function typeCastField($metadata, $field, $value, $format = null, $doNotT
$value = DateTime::createFromFormat($format, $value);
}
break;
case 'time_immutable':
if ($value && !$doNotTypecastDatetime) {
if (!$format) {
$format = 'H:i:s';
}
$value = \DateTimeImmutable::createFromFormat($format, $value);
}
break;
case 'datetime':
if ($value && ! $doNotTypecastDatetime) {
if (! $format) {
Expand All @@ -61,6 +79,14 @@ public function typeCastField($metadata, $field, $value, $format = null, $doNotT
$value = DateTime::createFromFormat($format, $value);
}
break;
case 'datetime_immutable':
if ($value && !$doNotTypecastDatetime) {
if (!$format) {
$format = 'Y-m-d H:i:s';
}
$value = \DateTimeImmutable::createFromFormat($format, $value);
}
break;
default:
break;
}
Expand Down
6 changes: 5 additions & 1 deletion src/Filter/Service/ODMFilterManager.php
Expand Up @@ -32,7 +32,11 @@ public function filter(QueryBuilder $queryBuilder, Metadata $metadata, $filters)

$typeCaster = $this->resolveTypeCaster();

$filter = $this->get(strtolower($option['type']), [$this, $typeCaster]);
$filter = $this->get(strtolower($option['type']), [
0 => $this,
'filter_manager' => $this,
'type_caster' => $typeCaster,
]);
$filter->filter($queryBuilder, $metadata, $option);
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/Filter/Service/ORMFilterManager.php
Expand Up @@ -31,7 +31,11 @@ public function filter(QueryBuilder $queryBuilder, $metadata, $filters)

$typeCaster = $this->resolveTypeCaster();

$filter = $this->get(strtolower($option['type']), [$this, $typeCaster]);
$filter = $this->get(strtolower($option['type']), [
0 => $this,
'filter_manager' => $this,
'type_caster' => $typeCaster,
]);
$filter->filter($queryBuilder, $metadata, $option);
}
}
Expand Down
10 changes: 9 additions & 1 deletion src/Filter/TypeCastInterface.php
Expand Up @@ -10,5 +10,13 @@

interface TypeCastInterface
{
public function typeCastField($metadata, $field, $value, $format = null, $doNotTypecastDatetime = false);
/**
* @param object $metadata
* @param string $field
* @param string|int|float $value
* @param string|null $format
* @param bool $doNotTypecastDatetime
* @return mixed
*/
public function typeCastField($metadata, string $field, $value, string $format = null, bool $doNotTypecastDatetime = false);
}
39 changes: 38 additions & 1 deletion test/Filter/ODMTypeCasterTest.php
Expand Up @@ -6,7 +6,7 @@
* @license https://github.com/laminas-api-tools/api-tools-doctrine-querybuilder/blob/master/LICENSE.md New BSD License
*/

namespace ZFTest\Doctrine\QueryBuilder\Filter;
namespace LaminasTest\ApiTools\Doctrine\QueryBuilder\Filter;

use PHPUnit\Framework\TestCase;
use Laminas\ApiTools\Doctrine\QueryBuilder\Filter\ODM\TypeCaster;
Expand Down Expand Up @@ -133,4 +133,41 @@ public function testNoTypeCastingToDateWhenFlaggedSo()
$result = $this->typeCaster->typeCastField($metadata, $field, $value, $format, $doNotTypecastDateTime);
$this->assertSame($result, $value);
}

public function testTypeCastingToDateImmutable()
{
$metadata = new \stdClass();
$metadata->fieldMappings = [
'field' => [
'type' => 'date_immutable'
],
];

$field = 'field';
$value = '2019-09-01 12:19:01';
$format = null;
$doNotTypecastDateTime = false;

$result = $this->typeCaster->typeCastField($metadata, $field, $value, $format, $doNotTypecastDateTime);
$this->assertInstanceOf(\DateTimeImmutable::class, $result);
$this->assertEquals($result->format('Y-m-d H:i:s'), '2019-09-01 12:19:01');
}

public function testNoTypeCastingToDateImmutableWhenFlaggedSo()
{
$metadata = new \stdClass();
$metadata->fieldMappings = [
'field' => [
'type' => 'date_immutable'
],
];

$field = 'field';
$value = '2019-09-01 12:19:01';
$format = null;
$doNotTypecastDateTime = true;

$result = $this->typeCaster->typeCastField($metadata, $field, $value, $format, $doNotTypecastDateTime);
$this->assertSame($result, $value);
}
}
115 changes: 114 additions & 1 deletion test/Filter/ORMTypeCasterTest.php
Expand Up @@ -6,7 +6,7 @@
* @license https://github.com/laminas-api-tools/api-tools-doctrine-querybuilder/blob/master/LICENSE.md New BSD License
*/

namespace ZFTest\Doctrine\QueryBuilder\Filter;
namespace LaminasTest\ApiTools\Doctrine\QueryBuilder\Filter;

use PHPUnit\Framework\TestCase;
use Laminas\ApiTools\Doctrine\QueryBuilder\Filter\ORM\TypeCaster;
Expand Down Expand Up @@ -171,6 +171,44 @@ public function testNoTypeCastingToDateWhenFlaggedSo()
$this->assertSame($result, $value);
}

public function testTypeCastingToDateImmutable()
{
$metadata = new \stdClass();
$metadata->fieldMappings = [
'field' => [
'type' => 'date_immutable'
],
];

$field = 'field';
$value = '2019-09-01';
$format = null;
$doNotTypecastDateTime = false;

$result = $this->typeCaster->typeCastField($metadata, $field, $value, $format, $doNotTypecastDateTime);
$this->assertInstanceOf(\DateTimeImmutable::class, $result);
$this->assertEquals($result->format('Y-m-d'), '2019-09-01');
$this->assertEquals($result->format('H:i:s'), '00:00:00');
}

public function testNoTypeCastingToDateImmutableWhenFlaggedSo()
{
$metadata = new \stdClass();
$metadata->fieldMappings = [
'field' => [
'type' => 'date_immutable'
],
];

$field = 'field';
$value = '2019-09-01';
$format = null;
$doNotTypecastDateTime = true;

$result = $this->typeCaster->typeCastField($metadata, $field, $value, $format, $doNotTypecastDateTime);
$this->assertSame($result, $value);
}

public function testTypeCastingToTime()
{
$metadata = new \stdClass();
Expand Down Expand Up @@ -208,6 +246,43 @@ public function testNoTypeCastingToTimeWhenFlaggedSo()
$this->assertSame($result, $value);
}

public function testTypeCastingToTimeImmutable()
{
$metadata = new \stdClass();
$metadata->fieldMappings = [
'field' => [
'type' => 'time_immutable'
],
];

$field = 'field';
$value = '12:01:55';
$format = null;
$doNotTypecastDateTime = false;

$result = $this->typeCaster->typeCastField($metadata, $field, $value, $format, $doNotTypecastDateTime);
$this->assertInstanceOf(\DateTimeImmutable::class, $result);
$this->assertEquals($result->format('H:i:s'), '12:01:55');
}

public function testNoTypeCastingToTimeImmutableWhenFlaggedSo()
{
$metadata = new \stdClass();
$metadata->fieldMappings = [
'field' => [
'type' => 'time_immutable'
],
];

$field = 'field';
$value = '12:01:55';
$format = null;
$doNotTypecastDateTime = true;

$result = $this->typeCaster->typeCastField($metadata, $field, $value, $format, $doNotTypecastDateTime);
$this->assertSame($result, $value);
}

public function testTypeCastingToDateTime()
{
$metadata = new \stdClass();
Expand Down Expand Up @@ -246,6 +321,44 @@ public function testNoTypeCastingToDateTimeWhenFlaggedSo()
$this->assertSame($result, $value);
}

public function testTypeCastingToDateTimeImmutable()
{
$metadata = new \stdClass();
$metadata->fieldMappings = [
'field' => [
'type' => 'datetime_immutable'
],
];

$field = 'field';
$value = '2019-09-01 12:03:44';
$format = null;
$doNotTypecastDateTime = false;

$result = $this->typeCaster->typeCastField($metadata, $field, $value, $format, $doNotTypecastDateTime);
$this->assertInstanceOf(\DateTime::class, $result);
$this->assertEquals($result->format('Y-m-d'), '2019-09-01');
$this->assertEquals($result->format('H:i:s'), '12:03:44');
}

public function testNoTypeCastingToDateTimeImmutableWhenFlaggedSo()
{
$metadata = new \stdClass();
$metadata->fieldMappings = [
'field' => [
'type' => 'datetime_immutable'
],
];

$field = 'field';
$value = '2019-09-01 12:03:44';
$format = null;
$doNotTypecastDateTime = true;

$result = $this->typeCaster->typeCastField($metadata, $field, $value, $format, $doNotTypecastDateTime);
$this->assertSame($result, $value);
}

public function testTypeCastingForUnknownFieldType()
{
$metadata = new \stdClass();
Expand Down

0 comments on commit 80ac4b3

Please sign in to comment.