Skip to content

Commit 02793df

Browse files
Merge pull request #5 from netiul/feature/extract-type-casting
Extract type cast behaviour
2 parents 74736f9 + 97eb983 commit 02793df

File tree

91 files changed

+1867
-758
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+1867
-758
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
/.phpcs-cache
2+
/.phpunit.result.cache
13
/clover.xml
24
/composer.lock
35
/coveralls-upload.json
46
/phpunit.xml
57
/vendor/
6-
.phpunit.result.cache

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file, in reverse
66

77
### Added
88

9+
- [#5](https://github.com/laminas-api-tools/api-tools-doctrine-querybuilder/pull/5) adds the interface `Laminas\ApiTools\Doctrine\QueryBuilder\Filter\TypeCastInterface` and the default implementations `Laminas\ApiTools\Doctrine\QueryBuilder\Filter\ODM\TypeCaster` and `Laminas\ApiTools\Doctrine\QueryBuilder\ORM\TypeCaster`, extracted from logic originally present in the ORM and ODM `AbstractFilter` implementations. Users can supply their own implementation by aliasing the `Laminas\ApiTools\Doctrine\QueryBuilder\Filter\TypeCastInterface` service to their own implementation. This ability allows users to supply their own type casting rules for their projects.
10+
911
- [#12](https://github.com/laminas-api-tools/api-tools-doctrine-querybuilder/pull/12) adds support for PHP 7.3, 7.4, and 8.0.
1012

1113
### Changed

README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,3 +442,46 @@ Field:
442442
```php
443443
['type' => 'field', 'field' => 'fieldName', 'direction' => 'desc']
444444
```
445+
446+
Custom MappingTypes
447+
-------------------
448+
449+
In case you have [custom mapping types](https://www.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/custom-mapping-types.html)
450+
configured, you can substitute the supplied `Laminas\ApiTools\Doctrine\QueryBuilder\Filter\TypeCastInterface`
451+
implementation with your own implementation.
452+
453+
As an example, given a custom type caster implentation as follows:
454+
455+
```php
456+
namespace My\Custom;
457+
458+
class TypeCaster implements \Laminas\ApiTools\Doctrine\QueryBuilder\Filter\TypeCastInterface
459+
{
460+
public function typeCastField($metadata, $field, $value, $format = null, $doNotTypecastDatetime = false)
461+
{
462+
// implement your type casting logic
463+
}
464+
}
465+
```
466+
467+
You will then provide a factory for your implementation, and alias the package `TypeCastInterface` to it:
468+
469+
```php
470+
// config/autoload/api-tools-doctrine-querybuilder-global.php
471+
472+
use Laminas\ApiTools\Doctrine\QueryBuilder\Filter\TypeCastInterface;
473+
use Laminas\ServiceManager\Factory\InvokableFactory;
474+
use My\Custom\TypeCaster;
475+
476+
return [
477+
'service_manager => [
478+
'aliases' => [
479+
TypeCastInterface::class => TypeCaster::class,
480+
],
481+
'factories' => [
482+
TypeCaster::class => InvokableFactory::class,
483+
],
484+
],
485+
];
486+
```
487+

config/module.config.php

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,37 @@
88

99
namespace Laminas\ApiTools\Doctrine\QueryBuilder;
1010

11+
use Laminas\ServiceManager\Factory\InvokableFactory;
12+
use ZF\Doctrine\QueryBuilder\Filter\Service\ODMFilterManager;
13+
use ZF\Doctrine\QueryBuilder\Filter\Service\ORMFilterManager;
14+
use ZF\Doctrine\QueryBuilder\OrderBy\Service\ODMOrderByManager;
15+
use ZF\Doctrine\QueryBuilder\OrderBy\Service\ORMOrderByManager;
16+
1117
return [
1218
'service_manager' => [
13-
'aliases' => [
14-
'LaminasDoctrineQueryBuilderFilterManagerOrm' => Filter\Service\ORMFilterManager::class,
15-
'LaminasDoctrineQueryBuilderFilterManagerOdm' => Filter\Service\ODMFilterManager::class,
19+
'aliases' => [
20+
'LaminasDoctrineQueryBuilderFilterManagerOrm' => Filter\Service\ORMFilterManager::class,
21+
'LaminasDoctrineQueryBuilderFilterManagerOdm' => Filter\Service\ODMFilterManager::class,
1622
'LaminasDoctrineQueryBuilderOrderByManagerOrm' => OrderBy\Service\ORMOrderByManager::class,
1723
'LaminasDoctrineQueryBuilderOrderByManagerOdm' => OrderBy\Service\ODMOrderByManager::class,
1824

1925
// Legacy Zend Framework aliases
20-
'ZfDoctrineQueryBuilderFilterManagerOrm' => 'LaminasDoctrineQueryBuilderFilterManagerOrm',
21-
'ZfDoctrineQueryBuilderFilterManagerOdm' => 'LaminasDoctrineQueryBuilderFilterManagerOdm',
26+
'ZfDoctrineQueryBuilderFilterManagerOrm' => 'LaminasDoctrineQueryBuilderFilterManagerOrm',
27+
'ZfDoctrineQueryBuilderFilterManagerOdm' => 'LaminasDoctrineQueryBuilderFilterManagerOdm',
2228
'ZfDoctrineQueryBuilderOrderByManagerOrm' => 'LaminasDoctrineQueryBuilderOrderByManagerOrm',
2329
'ZfDoctrineQueryBuilderOrderByManagerOdm' => 'LaminasDoctrineQueryBuilderOrderByManagerOdm',
24-
\ZF\Doctrine\QueryBuilder\Filter\Service\ORMFilterManager::class => Filter\Service\ORMFilterManager::class,
25-
\ZF\Doctrine\QueryBuilder\Filter\Service\ODMFilterManager::class => Filter\Service\ODMFilterManager::class,
26-
\ZF\Doctrine\QueryBuilder\OrderBy\Service\ORMOrderByManager::class => OrderBy\Service\ORMOrderByManager::class,
27-
\ZF\Doctrine\QueryBuilder\OrderBy\Service\ODMOrderByManager::class => OrderBy\Service\ODMOrderByManager::class,
30+
ORMFilterManager::class => Filter\Service\ORMFilterManager::class,
31+
ODMFilterManager::class => Filter\Service\ODMFilterManager::class,
32+
ORMOrderByManager::class => OrderBy\Service\ORMOrderByManager::class,
33+
ODMOrderByManager::class => OrderBy\Service\ODMOrderByManager::class,
2834
],
2935
'factories' => [
30-
Filter\Service\ORMFilterManager::class => Filter\Service\ORMFilterManagerFactory::class,
31-
Filter\Service\ODMFilterManager::class => Filter\Service\ODMFilterManagerFactory::class,
36+
Filter\Service\ORMFilterManager::class => Filter\Service\ORMFilterManagerFactory::class,
37+
Filter\Service\ODMFilterManager::class => Filter\Service\ODMFilterManagerFactory::class,
3238
OrderBy\Service\ORMOrderByManager::class => OrderBy\Service\ORMOrderByManagerFactory::class,
3339
OrderBy\Service\ODMOrderByManager::class => OrderBy\Service\ODMOrderByManagerFactory::class,
40+
Filter\ORM\TypeCaster::class => InvokableFactory::class,
41+
Filter\ODM\TypeCaster::class => InvokableFactory::class,
3442
],
3543
],
3644
];

phpcs.xml

Lines changed: 0 additions & 10 deletions
This file was deleted.

phpcs.xml.dist

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0"?>
2+
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
4+
5+
<arg name="basepath" value="."/>
6+
<arg name="cache" value=".phpcs-cache"/>
7+
<arg name="colors"/>
8+
<arg name="extensions" value="php"/>
9+
<arg name="parallel" value="80"/>
10+
11+
<!-- Show progress -->
12+
<arg value="p"/>
13+
14+
<!-- Paths to check -->
15+
<file>config</file>
16+
<file>config/api-tools-doctrine-querybuilder.global.php.dist</file>
17+
<file>src</file>
18+
<file>test</file>
19+
20+
<!-- Include all rules from the Laminas Coding Standard -->
21+
<rule ref="LaminasCodingStandard"/>
22+
23+
<rule ref="Generic.Files.LineLength">
24+
<properties>
25+
<property name="lineLimit" value="121"/>
26+
</properties>
27+
</rule>
28+
</ruleset>

src/Filter/FilterInterface.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,16 @@
88

99
namespace Laminas\ApiTools\Doctrine\QueryBuilder\Filter;
1010

11+
use Doctrine\ODM\MongoDB\Query\Builder;
12+
use Doctrine\ORM\QueryBuilder;
13+
1114
interface FilterInterface
1215
{
16+
/**
17+
* @param QueryBuilder|Builder $queryBuilder
18+
* @param object $metadata
19+
* @param array $option
20+
* @return void
21+
*/
1322
public function filter($queryBuilder, $metadata, $option);
1423
}

src/Filter/ODM/AbstractFilter.php

Lines changed: 43 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,74 +8,57 @@
88

99
namespace Laminas\ApiTools\Doctrine\QueryBuilder\Filter\ODM;
1010

11-
use DateTime;
11+
use Doctrine\ODM\MongoDB\Query\Builder;
1212
use Laminas\ApiTools\Doctrine\QueryBuilder\Filter\FilterInterface;
13+
use Laminas\ApiTools\Doctrine\QueryBuilder\Filter\TypeCastInterface;
1314

1415
abstract class AbstractFilter implements FilterInterface
1516
{
17+
/**
18+
* @param Builder $queryBuilder
19+
* @param object $metadata
20+
* @param array $option
21+
* @return void
22+
*/
1623
abstract public function filter($queryBuilder, $metadata, $option);
1724

18-
protected function typeCastField($metadata, $field, $value, $format = null, $doNotTypecastDatetime = false)
25+
/** @var TypeCastInterface */
26+
protected $typeCaster;
27+
28+
public function __construct(array $params = [])
1929
{
20-
if (! isset($metadata->fieldMappings[$field])) {
21-
return $value;
22-
}
30+
$this->setTypeCaster($params['type_caster'] ?? new TypeCaster());
31+
}
2332

24-
switch ($metadata->fieldMappings[$field]['type']) {
25-
case 'int':
26-
settype($value, 'integer');
27-
break;
28-
case 'boolean':
29-
settype($value, 'boolean');
30-
break;
31-
case 'float':
32-
settype($value, 'float');
33-
break;
34-
case 'string':
35-
settype($value, 'string');
36-
break;
37-
case 'bin_data_custom':
38-
break;
39-
case 'bin_data_func':
40-
break;
41-
case 'bin_data_md5':
42-
break;
43-
case 'bin_data':
44-
break;
45-
case 'bin_data_uuid':
46-
break;
47-
case 'collection':
48-
break;
49-
case 'custom_id':
50-
break;
51-
case 'date':
52-
if ($value && ! $doNotTypecastDatetime) {
53-
if (! $format) {
54-
$format = 'Y-m-d H:i:s';
55-
}
56-
$value = DateTime::createFromFormat($format, $value);
57-
}
58-
break;
59-
case 'file':
60-
break;
61-
case 'hash':
62-
break;
63-
case 'id':
64-
break;
65-
case 'increment':
66-
break;
67-
case 'key':
68-
break;
69-
case 'object_id':
70-
break;
71-
case 'raw_type':
72-
break;
73-
case 'timestamp':
74-
break;
75-
default:
76-
break;
77-
}
33+
/**
34+
* @return $this
35+
*/
36+
public function setTypeCaster(TypeCastInterface $typeCaster)
37+
{
38+
$this->typeCaster = $typeCaster;
39+
return $this;
40+
}
41+
42+
/**
43+
* @return TypeCastInterface
44+
*/
45+
protected function getTypeCaster()
46+
{
47+
return $this->typeCaster;
48+
}
7849

79-
return $value;
50+
/**
51+
* @param object $metadata
52+
* @param string|int|float $value
53+
* @return mixed
54+
*/
55+
protected function typeCastField(
56+
$metadata,
57+
string $field,
58+
$value,
59+
?string $format = null,
60+
bool $doNotTypecastDatetime = false
61+
) {
62+
return $this->getTypeCaster()->typeCastField($metadata, $field, $value, $format, $doNotTypecastDatetime);
8063
}
8164
}

src/Filter/ODM/Between.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
class Between extends AbstractFilter
1212
{
13+
/**
14+
* {@inheritDoc}
15+
*/
1316
public function filter($queryBuilder, $metadata, $option)
1417
{
1518
$queryType = 'addAnd';
@@ -22,7 +25,7 @@ public function filter($queryBuilder, $metadata, $option)
2225
}
2326
}
2427

25-
$format = isset($option['format']) ? $option['format'] : null;
28+
$format = $option['format'] ?? null;
2629

2730
$from = $this->typeCastField($metadata, $option['field'], $option['from'], $format);
2831
$to = $this->typeCastField($metadata, $option['field'], $option['to'], $format);

src/Filter/ODM/Equals.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
class Equals extends AbstractFilter
1212
{
13+
/**
14+
* {@inheritDoc}
15+
*/
1316
public function filter($queryBuilder, $metadata, $option)
1417
{
1518
$queryType = 'addAnd';
@@ -22,7 +25,7 @@ public function filter($queryBuilder, $metadata, $option)
2225
}
2326
}
2427

25-
$format = isset($option['format']) ? $option['format'] : null;
28+
$format = $option['format'] ?? null;
2629

2730
$value = $this->typeCastField($metadata, $option['field'], $option['value'], $format);
2831

0 commit comments

Comments
 (0)