QueryCompiler::compile()   C
last analyzed

Complexity

Conditions 14
Paths 32

Size

Total Lines 54
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 39
CRAP Score 14

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 14
eloc 37
c 1
b 0
f 0
nc 32
nop 1
dl 0
loc 54
ccs 39
cts 39
cp 1
crap 14
rs 6.2666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
// ---------------------------------------------------------------------
4
//
5
//  Copyright (C) 2018-2024 Artem Rodygin
6
//
7
//  You should have received a copy of the MIT License along with
8
//  this file. If not, see <https://opensource.org/licenses/MIT>.
9
//
10
// ---------------------------------------------------------------------
11
12
namespace Linode\Internal;
13
14
use Symfony\Component\ExpressionLanguage\Node\Node;
15
16
/**
17
 * @internal A query compiler.
18
 */
19
final class QueryCompiler
20
{
21
    /**
22
     * Applies specified parameters to the query.
23
     *
24
     * @param string $query      Query string.
25
     * @param array  $parameters Query parameters.
26
     *
27
     * @throws \Exception
28
     */
29 2
    public function apply(string $query, array $parameters = []): string
30
    {
31 2
        $patterns     = [];
32 2
        $replacements = [];
33
34 2
        foreach ($parameters as $key => $value) {
35 2
            if (!is_scalar($value)) {
36 1
                throw new \Exception(sprintf('Parameter "%s" contains non-scalar value', $key));
37
            }
38
39 1
            if (is_string($value)) {
40 1
                $value = '"' . $value . '"';
41 1
            } elseif (is_bool($value)) {
42 1
                $value = $value ? 'true' : 'false';
43
            }
44
45 1
            $patterns[]     = '/(\s|\=|\<|\>|\~)(\:' . $key . ')([^A-Za-z_0-9]|$)/';
46 1
            $replacements[] = '${1}' . preg_quote($value) . '${3}';
47
        }
48
49 1
        return preg_replace($patterns, $replacements, $query);
50
    }
51
52
    /**
53
     * Compiles specified AST node of the query into Linode API filter.
54
     *
55
     * @return array Filters generated for the node.
56
     *
57
     * @throws \Exception
58
     */
59 14
    public function compile(Node $node): array
60
    {
61 14
        $operator = $node->attributes['operator'] ?? null;
62
63 14
        if (null === $operator) {
64 1
            throw new \Exception('Invalid expression');
65
        }
66
67
        switch ($operator) {
68 13
            case 'and':
69 2
                return ['+and' => [
70 2
                    $this->compile($node->nodes['left']),
71 2
                    $this->compile($node->nodes['right']),
72 2
                ]];
73
74 13
            case 'or':
75 2
                return ['+or' => [
76 2
                    $this->compile($node->nodes['left']),
77 2
                    $this->compile($node->nodes['right']),
78 2
                ]];
79
80 13
            case '==':
81 8
            case '!=':
82 7
            case '<':
83 6
            case '<=':
84 5
            case '>':
85 4
            case '>=':
86 2
            case '~':
87 12
                $name  = $node->nodes['left']->attributes['name']   ?? null;
88 12
                $value = $node->nodes['right']->attributes['value'] ?? null;
89
90 12
                if (null === $name) {
91 1
                    throw new \Exception(sprintf('Left operand for the "%s" operator must be a field name', $operator));
92
                }
93
94 11
                if (null === $value) {
95 1
                    throw new \Exception(sprintf('Right operand for the "%s" operator must be a constant value', $operator));
96
                }
97
98 10
                $operators = [
99 10
                    '!=' => '+neq',
100 10
                    '<'  => '+lt',
101 10
                    '<=' => '+lte',
102 10
                    '>'  => '+gt',
103 10
                    '>=' => '+gte',
104 10
                    '~'  => '+contains',
105 10
                ];
106
107 10
                return ('==' === $operator)
108 4
                    ? [$name => $value]
109 10
                    : [$name => [$operators[$operator] => $value]];
110
111
            default:
112 1
                throw new \Exception(sprintf('Unknown operator "%s"', $operator));
113
        }
114
    }
115
}
116