Completed
Push — master ( df309f...9e12f0 )
by Rafael
08:32
created

FilterUtil::createEnumFilter()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 26
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 3.0105

Importance

Changes 0
Metric Value
eloc 20
dl 0
loc 26
c 0
b 0
f 0
ccs 17
cts 19
cp 0.8947
rs 9.6
cc 3
nc 3
nop 4
crap 3.0105
1
<?php
2
/*******************************************************************************
3
 *  This file is part of the GraphQL Bundle package.
4
 *
5
 *  (c) YnloUltratech <[email protected]>
6
 *
7
 *  For the full copyright and license information, please view the LICENSE
8
 *  file that was distributed with this source code.
9
 ******************************************************************************/
10
11
namespace Ynlo\GraphQLBundle\Filter\Resolver;
12
13
use GraphQL\Type\Definition\EnumType;
14
use Ynlo\GraphQLBundle\Annotation\Filter;
15
use Ynlo\GraphQLBundle\Definition\ClassAwareDefinitionInterface;
16
use Ynlo\GraphQLBundle\Definition\EnumDefinition;
17
use Ynlo\GraphQLBundle\Definition\FieldDefinition;
18
use Ynlo\GraphQLBundle\Definition\InputObjectDefinition;
19
use Ynlo\GraphQLBundle\Definition\Registry\Endpoint;
20
use Ynlo\GraphQLBundle\Filter\Common\ArrayFilter;
21
use Ynlo\GraphQLBundle\Filter\Common\BooleanFilter;
22
use Ynlo\GraphQLBundle\Filter\Common\DateFilter;
23
use Ynlo\GraphQLBundle\Filter\Common\EnumFilter;
24
use Ynlo\GraphQLBundle\Filter\Common\NodeFilter;
25
use Ynlo\GraphQLBundle\Filter\Common\NumberFilter;
26
use Ynlo\GraphQLBundle\Filter\Common\StringFilter;
27
use Ynlo\GraphQLBundle\Model\Filter\ArrayComparisonExpression;
28
use Ynlo\GraphQLBundle\Model\Filter\DateComparisonExpression;
29
use Ynlo\GraphQLBundle\Model\Filter\DateTimeComparisonExpression;
30
use Ynlo\GraphQLBundle\Model\Filter\EnumComparisonExpression;
31
use Ynlo\GraphQLBundle\Model\Filter\FloatComparisonExpression;
32
use Ynlo\GraphQLBundle\Model\Filter\IntegerComparisonExpression;
33
use Ynlo\GraphQLBundle\Model\Filter\NodeComparisonExpression;
34
use Ynlo\GraphQLBundle\Model\Filter\StringComparisonExpression;
35
use Ynlo\GraphQLBundle\Model\NodeInterface;
36
use Ynlo\GraphQLBundle\Type\Registry\TypeRegistry;
37
use Ynlo\GraphQLBundle\Type\Types;
38
use Ynlo\GraphQLBundle\Util\TypeUtil;
39
40
/**
41
 * Util to work with filters
42
 */
43
class FilterUtil
44
{
45
    /**
46
     * Create filter metadata for given field definition
47
     *
48
     * @param Endpoint        $endpoint
49
     * @param FieldDefinition $field
50
     *
51
     * @return Filter
52
     */
53 1
    public static function createFilter(Endpoint $endpoint, FieldDefinition $field): Filter
54
    {
55 1
        $filter = new Filter();
56 1
        $filter->name = $filter->field = $field->getName();
57
58 1
        switch (TypeUtil::normalize($field->getType())) {
59 1
            case Types::STRING:
60 1
                $filter->resolver = StringFilter::class;
61 1
                $filter->type = StringComparisonExpression::class;
62 1
                if ($field->isList()) {
63 1
                    $filter->resolver = ArrayFilter::class;
64 1
                    $filter->type = ArrayComparisonExpression::class;
65
                }
66 1
                break;
67 1
            case Types::BOOLEAN:
68 1
                $filter->resolver = BooleanFilter::class;
69 1
                $filter->type = Types::BOOLEAN;
70 1
                break;
71 1
            case Types::DATE:
72
                $filter->resolver = DateFilter::class;
73
                $filter->type = DateComparisonExpression::class;
74
                break;
75 1
            case Types::DATETIME:
76 1
                $filter->resolver = DateFilter::class;
77 1
                $filter->type = DateTimeComparisonExpression::class;
78 1
                break;
79 1
            case Types::INT:
80 1
                $filter->resolver = NumberFilter::class;
81 1
                $filter->type = IntegerComparisonExpression::class;
82 1
                break;
83 1
            case Types::FLOAT:
84 1
                $filter->resolver = NumberFilter::class;
85 1
                $filter->type = FloatComparisonExpression::class;
86 1
                break;
87
        }
88
89
        //enums
90 1
        if (!$filter->resolver
91 1
            && $endpoint->hasType($field->getType())
92 1
            && $endpoint->getType($field->getType()) instanceof EnumDefinition) {
93
            /** @var EnumDefinition $relatedNode */
94 1
            $relatedNode = $endpoint->getType($field->getType());
95
            //enum registered using enum definition
96 1
            $enumName = $relatedNode->getName();
97 1
            foreach ($relatedNode->getValues() as $value) {
98 1
                $enumValues[] = $value->getName();
99
            }
100 1
            $filter = self::createEnumFilter($endpoint, $field, $enumName, $enumValues);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $enumValues seems to be defined by a foreach iteration on line 97. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
101 1
            $filter->field = $field->getName();
102
        }
103
104
        //enum registered as internal GraphQL type
105 1
        if (!$filter->resolver && TypeRegistry::has($field->getType())
106 1
            && ($enumType = TypeRegistry::get($field->getType()))
107 1
            && $enumType instanceof EnumType) {
108 1
            $enumName = $enumType->name;
109 1
            foreach ($enumType->getValues() as $value) {
110 1
                $enumValues[] = $value->name;
111
            }
112 1
            $filter = self::createEnumFilter($endpoint, $field, $enumName, $enumValues);
113
        }
114
115
        //relations and enums
116 1
        if (!$filter->resolver
117 1
            && $endpoint->hasType($field->getType())
118 1
            && $endpoint->getType($field->getType()) instanceof ClassAwareDefinitionInterface) {
119
            /** @var ClassAwareDefinitionInterface $relatedNode */
120 1
            $relatedNode = $endpoint->getType($field->getType());
121 1
            $relatedEntity = $relatedNode->getClass();
122
            try {
123 1
                $ref = new \ReflectionClass($relatedEntity);
124 1
                if ($ref->implementsInterface(NodeInterface::class)) {
125 1
                    $filter->resolver = NodeFilter::class;
126 1
                    $filter->type = NodeComparisonExpression::class;
127
                }
128
            } catch (\ReflectionException $exception) {
129
                //ignore invalid class or empty
130
            }
131
        }
132
133 1
        return $filter;
134
    }
135
136
    /**
137
     * @param Endpoint        $endpoint
138
     * @param FieldDefinition $field
139
     * @param string          $enumName
140
     * @param array           $enumValues
141
     *
142
     * @return Filter
143
     */
144 1
    private static function createEnumFilter(Endpoint $endpoint, FieldDefinition $field, string $enumName, array $enumValues): Filter
145
    {
146 1
        $name = "{$enumName}ComparisonExpression";
147 1
        if ($endpoint->hasType($name)) {
148
            $condition = $endpoint->getType($name);
149
        } else {
150
            /** @var InputObjectDefinition $condition */
151 1
            $condition = unserialize(serialize($endpoint->getType(EnumComparisonExpression::class)), ['allowed_classes' => true]);
152 1
            $condition->setName($name);
153 1
            $condition->getField('values')->setType($enumName)->setList(true);
154 1
            $description = $condition->getDescription();
155 1
            $description = str_replace('\'{VALUE_1}\'', array_values($enumValues)[0], $description);
156 1
            if (isset(array_values($enumValues)[1])) {
157 1
                $description = str_replace('\'{VALUE_2}\'', array_values($enumValues)[1], $description);
158
            } else {
159
                $description = str_replace(', \'{VALUE_2}\'', null, $description);
160
            }
161 1
            $condition->setDescription($description);
162 1
            $endpoint->add($condition);
163
        }
164 1
        $filter = new Filter();
165 1
        $filter->name = $filter->field = $field->getName();
166 1
        $filter->resolver = EnumFilter::class;
167 1
        $filter->type = $condition->getName();
168
169 1
        return $filter;
170
    }
171
}