Passed
Pull Request — master (#2)
by Alex
02:27
created

AbstractFilter   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 118
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 9
eloc 35
c 1
b 0
f 0
dl 0
loc 118
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A getOptions() 0 3 1
A resolveFieldName() 0 25 4
A createParamName() 0 3 1
A formatValue() 0 19 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arp\DoctrineQueryFilter\Filter;
6
7
use Arp\DoctrineQueryFilter\Filter\Exception\FilterException;
8
use Arp\DoctrineQueryFilter\Filter\Exception\InvalidArgumentException;
9
use Arp\DoctrineQueryFilter\Filter\Exception\TypecastException;
10
use Arp\DoctrineQueryFilter\Metadata\MetadataInterface;
11
use Arp\DoctrineQueryFilter\QueryFilterManagerInterface;
12
13
/**
14
 * @author  Alex Patterson <[email protected]>
15
 * @package Arp\DoctrineQueryFilter\Filter
16
 */
17
abstract class AbstractFilter implements FilterInterface
18
{
19
    /**
20
     * @var QueryFilterManagerInterface
21
     */
22
    protected QueryFilterManagerInterface $queryFilterManager;
23
24
    /**
25
     * @var TypecasterInterface
26
     */
27
    protected TypecasterInterface $typecaster;
28
29
    /**
30
     * @var array
31
     */
32
    protected array $options = [];
33
34
    /**
35
     * @param QueryFilterManagerInterface $queryFilterManager
36
     * @param TypecasterInterface         $typecaster
37
     * @param array                       $options
38
     */
39
    public function __construct(
40
        QueryFilterManagerInterface $queryFilterManager,
41
        TypecasterInterface $typecaster,
42
        array $options = []
43
    ) {
44
        $this->queryFilterManager = $queryFilterManager;
45
        $this->typecaster = $typecaster;
46
        $this->options = $options;
47
    }
48
49
    /**
50
     * @return array
51
     */
52
    public function getOptions(): array
53
    {
54
        return $this->options;
55
    }
56
57
    /**
58
     * Create a new unique parameter name
59
     *
60
     * @param string $prefix
61
     *
62
     * @return string
63
     */
64
    protected function createParamName(string $prefix = ''): string
65
    {
66
        return uniqid($prefix, false);
67
    }
68
69
    /**
70
     * @param MetadataInterface $metadata
71
     * @param array             $criteria
72
     * @param string            $key
73
     *
74
     * @return string
75
     *
76
     * @throws InvalidArgumentException
77
     */
78
    protected function resolveFieldName(MetadataInterface $metadata, array $criteria, string $key = 'field'): string
79
    {
80
        if (empty($criteria[$key])) {
81
            throw new InvalidArgumentException(
82
                sprintf(
83
                    'The required \'%s\' criteria value is missing for filter \'%s\'',
84
                    $key,
85
                    static::class
86
                )
87
            );
88
        }
89
90
        if (!$metadata->hasField($criteria[$key]) && !$metadata->hasAssociation($criteria[$key])) {
91
            throw new InvalidArgumentException(
92
                sprintf(
93
                    'Unable to apply query filter \'%s\': '
94
                    . 'The entity class \'%s\' has no field or association named \'%s\'',
95
                    static::class,
96
                    $metadata->getName(),
97
                    $criteria[$key]
98
                )
99
            );
100
        }
101
102
        return $criteria[$key];
103
    }
104
105
    /**
106
     * @param MetadataInterface $metadata
107
     * @param string            $fieldName
108
     * @param mixed             $value
109
     * @param string|null       $type
110
     * @param array             $options
111
     *
112
     * @return mixed
113
     *
114
     * @throws FilterException
115
     */
116
    protected function formatValue(
117
        MetadataInterface $metadata,
118
        string $fieldName,
119
        $value,
120
        ?string $type = null,
121
        array $options = []
122
    ) {
123
        try {
124
            return $this->typecaster->typecast($metadata, $fieldName, $value, $type, $options);
125
        } catch (TypecastException $e) {
126
            throw new FilterException(
127
                sprintf(
128
                    'Failed to format the value for field \'%s::%s\': %s',
129
                    $metadata->getName(),
130
                    $fieldName,
131
                    $e->getMessage()
132
                ),
133
                $e->getCode(),
134
                $e
135
            );
136
        }
137
    }
138
}
139