Completed
Push — master ( 1a67d2...dfab50 )
by Neomerx
11:35 queued 22s
created

JsonApiQueryRulesSerializer   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 240
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 29
lcom 1
cbo 3
dl 0
loc 240
rs 10
c 0
b 0
f 0
ccs 67
cts 67
cp 1

17 Methods

Rating   Name   Duplication   Size   Complexity  
A addRulesFromClass() 0 18 1
F addQueryRules() 0 34 11
A getData() 0 7 1
A readBlocks() 0 4 1
A hasRules() 0 7 2
A readRules() 0 6 1
A readFilterRulesIndexes() 0 4 1
A readFieldSetRulesIndexes() 0 4 1
A readSortsRuleIndexes() 0 4 1
A readIncludesRuleIndexes() 0 4 1
A readPageOffsetRuleIndexes() 0 4 1
A readPageLimitRuleIndexes() 0 4 1
A readRuleMainIndexes() 0 4 1
A readRuleMainIndex() 0 7 1
A readRuleStartIndexes() 0 4 1
A readRuleEndIndexes() 0 4 1
A isRulesClass() 0 6 2
1
<?php namespace Limoncello\Flute\Validation\JsonApi\Execution;
2
3
/**
4
 * Copyright 2015-2017 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use Limoncello\Flute\Contracts\Validation\JsonApiQueryRulesInterface;
20
use Limoncello\Flute\Contracts\Validation\JsonApiQueryRulesSerializerInterface;
21
use Limoncello\Flute\Validation\Serialize\RulesSerializer;
22
use Limoncello\Validation\Contracts\Rules\RuleInterface;
23
use Neomerx\JsonApi\Contracts\Http\Query\BaseQueryParserInterface;
24
25
/**
26
 * @package Limoncello\Flute
27
 *
28
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
29
 */
30
class JsonApiQueryRulesSerializer extends RulesSerializer implements JsonApiQueryRulesSerializerInterface
31
{
32
    /**
33
     * @var array
34
     */
35
    private $serializedRules = [];
36
37
    /** Index key */
38
    protected const FILTER_RULES = 0;
39
40
    /** Index key */
41
    protected const FIELD_SET_RULES = self::FILTER_RULES + 1;
42
43
    /** Index key */
44
    protected const SORTS_RULE = self::FIELD_SET_RULES + 1;
45
46
    /** Index key */
47
    protected const INCLUDES_RULE = self::SORTS_RULE + 1;
48
49
    /** Index key */
50
    protected const PAGE_OFFSET_RULE = self::INCLUDES_RULE + 1;
51
52
    /** Index key */
53
    protected const PAGE_LIMIT_RULE = self::PAGE_OFFSET_RULE + 1;
54
55
    /** Index key */
56
    protected const SINGLE_RULE_INDEX = 0;
57
58
    /** Serialized indexes key */
59
    protected const SERIALIZED_RULES = 0;
60
61
    /** Serialized rules key */
62
    protected const SERIALIZED_BLOCKS = self::SERIALIZED_RULES + 1;
63
64
    /**
65
     * @inheritdoc
66
     */
67 43
    public function addRulesFromClass(string $rulesClass): JsonApiQueryRulesSerializerInterface
68
    {
69 43
        assert(static::isRulesClass($rulesClass));
0 ignored issues
show
Bug introduced by
Since isRulesClass() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of isRulesClass() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
70
71 43
        $name = $rulesClass;
72
73
        /** @var JsonApiQueryRulesInterface $rulesClass */
74
75 43
        return $this->addQueryRules(
76 43
            $name,
77 43
            $rulesClass::getFilterRules(),
78 43
            $rulesClass::getFieldSetRules(),
79 43
            $rulesClass::getSortsRule(),
80 43
            $rulesClass::getIncludesRule(),
81 43
            $rulesClass::getPageOffsetRule(),
82 43
            $rulesClass::getPageLimitRule()
83
        );
84
    }
85
86
    /**
87
     * @param string               $name
88
     * @param RuleInterface[]|null $filterRules
89
     * @param RuleInterface[]|null $fieldSetRules
90
     * @param RuleInterface|null   $sortsRule
91
     * @param RuleInterface|null   $includesRule
92
     * @param RuleInterface|null   $pageOffsetRule
93
     * @param RuleInterface|null   $pageLimitRule
94
     *
95
     * @return self
96
     *
97
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
98
     * @SuppressWarnings(PHPMD.NPathComplexity)
99
     */
100 43
    public function addQueryRules(
101
        string $name,
102
        ?array $filterRules,
103
        ?array $fieldSetRules,
104
        ?RuleInterface $sortsRule,
105
        ?RuleInterface $includesRule,
106
        ?RuleInterface $pageOffsetRule,
107
        ?RuleInterface $pageLimitRule
108
    ): JsonApiQueryRulesSerializerInterface {
109 43
        assert(!empty($name));
110 43
        assert(static::hasRules($name, $this->serializedRules) === false);
111
112 43
        $sortsRule === null ?: $sortsRule->setName(BaseQueryParserInterface::PARAM_SORT);
113 43
        $includesRule === null ?: $includesRule->setName(BaseQueryParserInterface::PARAM_INCLUDE);
114 43
        $pageOffsetRule === null ?: $pageOffsetRule->setName(BaseQueryParserInterface::PARAM_PAGE);
115 43
        $pageLimitRule === null ?: $pageLimitRule->setName(BaseQueryParserInterface::PARAM_PAGE);
116
117 43
        $this->serializedRules[$name] = [
118 43
            static::FILTER_RULES     =>
119 43
                $filterRules === null ? null : $this->addRules($filterRules),
120 43
            static::FIELD_SET_RULES  =>
121 43
                $fieldSetRules === null ? null : $this->addRules($fieldSetRules),
122 43
            static::SORTS_RULE       =>
123 43
                $sortsRule === null ? null : $this->addRules([static::SINGLE_RULE_INDEX => $sortsRule]),
124 43
            static::INCLUDES_RULE    =>
125 43
                $includesRule === null ? null : $this->addRules([static::SINGLE_RULE_INDEX => $includesRule]),
126 43
            static::PAGE_OFFSET_RULE =>
127 43
                $pageOffsetRule === null ? null : $this->addRules([static::SINGLE_RULE_INDEX => $pageOffsetRule]),
128 43
            static::PAGE_LIMIT_RULE  =>
129 43
                $pageLimitRule === null ? null : $this->addRules([static::SINGLE_RULE_INDEX => $pageLimitRule]),
130
        ];
131
132 43
        return $this;
133
    }
134
135
    /**
136
     * @inheritdoc
137
     */
138 43
    public function getData(): array
139
    {
140
        return [
141 43
            static::SERIALIZED_RULES  => $this->serializedRules,
142 43
            static::SERIALIZED_BLOCKS => $this->getBlocks(),
143
        ];
144
    }
145
146
    /**
147
     * @inheritdoc
148
     */
149 52
    public static function readBlocks(array $serializedData): array
150
    {
151 52
        return $serializedData[static::SERIALIZED_BLOCKS];
152
    }
153
154
    /**
155
     * @inheritdoc
156
     */
157 43
    public static function hasRules(string $name, array $serializedData): bool
158
    {
159
        // the value could be null so we have to check by key existence.
160
        return
161 43
            array_key_exists(static::SERIALIZED_RULES, $serializedData) === true &&
162 43
            array_key_exists($name, $serializedData[static::SERIALIZED_RULES]);
163
    }
164
165
    /**
166
     * @inheritdoc
167
     */
168 32
    public static function readRules(string $name, array $serializedData): array
169
    {
170 32
        assert(static::hasRules($name, $serializedData) === true);
171
172 32
        return $serializedData[static::SERIALIZED_RULES][$name];
173
    }
174
175
    /**
176
     * @inheritdoc
177
     */
178 22
    public static function readFilterRulesIndexes(array $serializedRules): ?array
179
    {
180 22
        return $serializedRules[static::FILTER_RULES];
181
    }
182
183
    /**
184
     * @inheritdoc
185
     */
186 2
    public static function readFieldSetRulesIndexes(array $serializedRules): ?array
187
    {
188 2
        return $serializedRules[static::FIELD_SET_RULES];
189
    }
190
191
    /**
192
     * @inheritdoc
193
     */
194 16
    public static function readSortsRuleIndexes(array $serializedRules): ?array
195
    {
196 16
        return $serializedRules[static::SORTS_RULE];
197
    }
198
199
    /**
200
     * @inheritdoc
201
     */
202 16
    public static function readIncludesRuleIndexes(array $serializedRules): ?array
203
    {
204 16
        return $serializedRules[static::INCLUDES_RULE];
205
    }
206
207
    /**
208
     * @inheritdoc
209
     */
210 31
    public static function readPageOffsetRuleIndexes(array $serializedRules): ?array
211
    {
212 31
        return $serializedRules[static::PAGE_OFFSET_RULE];
213
    }
214
215
    /**
216
     * @inheritdoc
217
     */
218 31
    public static function readPageLimitRuleIndexes(array $serializedRules): ?array
219
    {
220 31
        return $serializedRules[static::PAGE_LIMIT_RULE];
221
    }
222
223
    /**
224
     * @inheritdoc
225
     */
226 22
    public static function readRuleMainIndexes(array $ruleIndexes): ?array
227
    {
228 22
        return parent::getRulesIndexes($ruleIndexes);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getRulesIndexes() instead of readRuleMainIndexes()). Are you sure this is correct? If so, you might want to change this to $this->getRulesIndexes().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
229
    }
230
231
    /**
232
     * @inheritdoc
233
     */
234 30
    public static function readRuleMainIndex(array $ruleIndexes): ?int
235
    {
236
        // if you read main/first/only rule and blocks actually have more then something must be wrong
237 30
        assert(count($ruleIndexes[static::RULES_ARRAY_INDEXES]) === 1);
238
239 30
        return $ruleIndexes[static::RULES_ARRAY_INDEXES][static::SINGLE_RULE_INDEX];
240
    }
241
242
    /**
243
     * @inheritdoc
244
     */
245 30
    public static function readRuleStartIndexes(array $ruleIndexes): array
246
    {
247 30
        return parent::getRulesStartIndexes($ruleIndexes);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getRulesStartIndexes() instead of readRuleStartIndexes()). Are you sure this is correct? If so, you might want to change this to $this->getRulesStartIndexes().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
248
    }
249
250
    /**
251
     * @inheritdoc
252
     */
253 30
    public static function readRuleEndIndexes(array $ruleIndexes): array
254
    {
255 30
        return parent::getRulesEndIndexes($ruleIndexes);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getRulesEndIndexes() instead of readRuleEndIndexes()). Are you sure this is correct? If so, you might want to change this to $this->getRulesEndIndexes().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
256
    }
257
258
    /**
259
     * @param string $rulesClass
260
     *
261
     * @return bool
262
     */
263 43
    private static function isRulesClass(string $rulesClass): bool
264
    {
265
        return
266 43
            class_exists($rulesClass) === true &&
267 43
            in_array(JsonApiQueryRulesInterface::class, class_implements($rulesClass)) === true;
268
    }
269
}
270