Passed
Branch master (950424)
by Christopher
11:06
created

PHPExpressionProvider::onFunctionCallExpression()   D

Complexity

Conditions 27
Paths 27

Size

Total Lines 84
Code Lines 57

Duplication

Lines 11
Ratio 13.1 %

Importance

Changes 0
Metric Value
cc 27
eloc 57
nc 27
nop 2
dl 11
loc 84
rs 4.7908
c 0
b 0
f 0

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
namespace POData\Providers\Expression;
4
5
use POData\Common\ODataConstants;
6
use POData\Providers\Metadata\ResourceType;
7
use POData\Providers\Metadata\Type\IType;
8
use POData\UriProcessor\QueryProcessor\ExpressionParser\Expressions\ExpressionType;
9
use POData\UriProcessor\QueryProcessor\ExpressionParser\Expressions\PropertyAccessExpression;
10
use POData\UriProcessor\QueryProcessor\FunctionDescription;
11
12
/**
13
 * Class PHPExpressionProvider.
14
 */
15
class PHPExpressionProvider implements IExpressionProvider
16
{
17
    const ADD = '+';
18
    const CLOSE_BRACKET = ')';
19
    const COMMA = ',';
20
    const DIVIDE = '/';
21
    const SUBTRACT = '-';
22
    const EQUAL = '==';
23
    const GREATER_THAN = '>';
24
    const GREATER_THAN_OR_EQUAL = '>=';
25
    const LESS_THAN = '<';
26
    const LESS_THAN_OR_EQUAL = '<=';
27
    const LOGICAL_AND = '&&';
28
    const LOGICAL_NOT = '!';
29
    const LOGICAL_OR = '||';
30
    const MEMBER_ACCESS = '->';
31
    const MODULO = '%';
32
    const MULTIPLY = '*';
33
    const NEGATE = '-';
34
    const NOT_EQUAL = '!=';
35
    const OPEN_BRACKET = '(';
36
    const TYPE_NAMESPACE = 'POData\\Providers\\Metadata\\Type\\';
37
38
    /**
39
     * The name of iterator.
40
     *
41
     * @var string
42
     */
43
    private $iteratorName;
44
45
    /**
46
     * The type of the resource pointed by the resource path segment.
47
     *
48
     * @var ResourceType
49
     */
50
    private $resourceType;
51
52
    /**
53
     * @param string $iteratorName The name of the iterator
54
     */
55
    public function __construct($iteratorName)
56
    {
57
        $this->iteratorName = $iteratorName;
58
    }
59
60
    /**
61
     * Get the name of the iterator.
62
     *
63
     * @return string
64
     */
65
    public function getIteratorName()
66
    {
67
        return $this->iteratorName;
68
    }
69
70
    /**
71
     * call-back for setting the resource type.
72
     *
73
     * @param ResourceType $resourceType The resource type on which the filter is going to be applied
74
     *
75
     * @return void
76
     */
77
    public function setResourceType(ResourceType $resourceType)
78
    {
79
        $this->resourceType = $resourceType;
80
    }
81
82
    /**
83
     * Call-back for logical expression.
84
     *
85
     * @param ExpressionType $expressionType The type of logical expression
86
     * @param string         $left           The left expression
87
     * @param string         $right          The left expression
88
     *
89
     * @return string
90
     */
91
    public function onLogicalExpression($expressionType, $left, $right)
92
    {
93
        assert($expressionType instanceof ExpressionType, get_class($expressionType));
94
        switch ($expressionType) {
95
            case ExpressionType::AND_LOGICAL():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...sionType::AND_LOGICAL() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

95
            case ExpressionType::/** @scrutinizer ignore-call */ AND_LOGICAL():
Loading history...
96
                return $this->prepareBinaryExpression(self::LOGICAL_AND, $left, $right);
97
98
            case ExpressionType::OR_LOGICAL():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...ssionType::OR_LOGICAL() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

98
            case ExpressionType::/** @scrutinizer ignore-call */ OR_LOGICAL():
Loading history...
99
                return $this->prepareBinaryExpression(self::LOGICAL_OR, $left, $right);
100
101
            default:
102
                throw new \InvalidArgumentException('onLogicalExpression');
103
        }
104
    }
105
106
    /**
107
     * Call-back for arithmetic expression.
108
     *
109
     * @param ExpressionType $expressionType The type of arithmetic expression
110
     * @param string         $left           The left expression
111
     * @param string         $right          The left expression
112
     *
113
     * @return string
114
     */
115
    public function onArithmeticExpression($expressionType, $left, $right)
116
    {
117
        switch ($expressionType) {
118
            case ExpressionType::MULTIPLY():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...ressionType::MULTIPLY() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

118
            case ExpressionType::/** @scrutinizer ignore-call */ MULTIPLY():
Loading history...
119
                return $this->prepareBinaryExpression(self::MULTIPLY, $left, $right);
120
121
            case ExpressionType::DIVIDE():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...xpressionType::DIVIDE() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

121
            case ExpressionType::/** @scrutinizer ignore-call */ DIVIDE():
Loading history...
122
                return $this->prepareBinaryExpression(self::DIVIDE, $left, $right);
123
124
            case ExpressionType::MODULO():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...xpressionType::MODULO() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

124
            case ExpressionType::/** @scrutinizer ignore-call */ MODULO():
Loading history...
125
                return $this->prepareBinaryExpression(self::MODULO, $left, $right);
126
127
            case ExpressionType::ADD():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...s\ExpressionType::ADD() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

127
            case ExpressionType::/** @scrutinizer ignore-call */ ADD():
Loading history...
128
                return $this->prepareBinaryExpression(self::ADD, $left, $right);
129
130
            case ExpressionType::SUBTRACT():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...ressionType::SUBTRACT() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

130
            case ExpressionType::/** @scrutinizer ignore-call */ SUBTRACT():
Loading history...
131
                return $this->prepareBinaryExpression(self::SUBTRACT, $left, $right);
132
133
            default:
134
                throw new \InvalidArgumentException('onArithmeticExpression');
135
        }
136
    }
137
138
    /**
139
     * Call-back for relational expression.
140
     *
141
     * @param ExpressionType $expressionType The type of relation expression
142
     * @param string         $left           The left expression
143
     * @param string         $right          The left expression
144
     *
145
     * @return string
146
     */
147
    public function onRelationalExpression($expressionType, $left, $right)
148
    {
149
        switch ($expressionType) {
150
            case ExpressionType::GREATERTHAN():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...sionType::GREATERTHAN() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

150
            case ExpressionType::/** @scrutinizer ignore-call */ GREATERTHAN():
Loading history...
151
                return $this->prepareBinaryExpression(self::GREATER_THAN, $left, $right);
152
153
            case ExpressionType::GREATERTHAN_OR_EQUAL():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...:GREATERTHAN_OR_EQUAL() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

153
            case ExpressionType::/** @scrutinizer ignore-call */ GREATERTHAN_OR_EQUAL():
Loading history...
154
                return $this->prepareBinaryExpression(self::GREATER_THAN_OR_EQUAL, $left, $right);
155
156
            case ExpressionType::LESSTHAN():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...ressionType::LESSTHAN() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

156
            case ExpressionType::/** @scrutinizer ignore-call */ LESSTHAN():
Loading history...
157
                return $this->prepareBinaryExpression(self::LESS_THAN, $left, $right);
158
159
            case ExpressionType::LESSTHAN_OR_EQUAL():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...pe::LESSTHAN_OR_EQUAL() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

159
            case ExpressionType::/** @scrutinizer ignore-call */ LESSTHAN_OR_EQUAL():
Loading history...
160
                return $this->prepareBinaryExpression(self::LESS_THAN_OR_EQUAL, $left, $right);
161
162
            case ExpressionType::EQUAL():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...ExpressionType::EQUAL() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

162
            case ExpressionType::/** @scrutinizer ignore-call */ EQUAL():
Loading history...
163
                return $this->prepareBinaryExpression(self::EQUAL, $left, $right);
164
165
            case ExpressionType::NOTEQUAL():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...ressionType::NOTEQUAL() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

165
            case ExpressionType::/** @scrutinizer ignore-call */ NOTEQUAL():
Loading history...
166
                return $this->prepareBinaryExpression(self::NOT_EQUAL, $left, $right);
167
168
            default:
169
                throw new \InvalidArgumentException('onRelationalExpression');
170
        }
171
    }
172
173
    /**
174
     * Call-back for unary expression.
175
     *
176
     * @param ExpressionType $expressionType The type of unary expression
177
     * @param string         $child          The child expression
178
     *
179
     * @return string
180
     */
181
    public function onUnaryExpression($expressionType, $child)
182
    {
183
        switch ($expressionType) {
184
            case ExpressionType::NEGATE():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...xpressionType::NEGATE() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

184
            case ExpressionType::/** @scrutinizer ignore-call */ NEGATE():
Loading history...
185
                return $this->prepareUnaryExpression(self::NEGATE, $child);
186
187
            case ExpressionType::NOT_LOGICAL():
0 ignored issues
show
Bug Best Practice introduced by
The method POData\UriProcessor\Quer...sionType::NOT_LOGICAL() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

187
            case ExpressionType::/** @scrutinizer ignore-call */ NOT_LOGICAL():
Loading history...
188
                return $this->prepareUnaryExpression(self::LOGICAL_NOT, $child);
189
190
            default:
191
                throw new \InvalidArgumentException('onUnaryExpression');
192
        }
193
    }
194
195
    /**
196
     * Call-back for constant expression.
197
     *
198
     * @param IType $type  The type of constant
199
     * @param mixed $value The value of the constant
200
     *
201
     * @return string
202
     */
203 View Code Duplication
    public function onConstantExpression(IType $type, $value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
204
    {
205
        if (is_bool($value)) {
206
            return var_export($value, true);
207
        } elseif (null === $value) {
208
            return var_export(null, true);
209
        }
210
211
        return strval($value);
212
    }
213
214
    /**
215
     * Call-back for property access expression.
216
     *
217
     * @param PropertyAccessExpression $expression The property access expression
218
     *
219
     * @return string
220
     */
221
    public function onPropertyAccessExpression($expression)
222
    {
223
        if (null == $expression) {
224
            throw new \InvalidArgumentException('onPropertyAccessExpression - expression null');
225
        }
226
        if (!($expression instanceof PropertyAccessExpression)) {
227
            throw new \InvalidArgumentException('onPropertyAccessExpression - expression is incorrect type');
228
        }
229
        if (null == $this->resourceType) {
230
            throw new \InvalidArgumentException('onPropertyAccessExpression - resourceType null');
231
        }
232
        if (null == $this->resourceType->getName()) {
233
            throw new \InvalidArgumentException('onPropertyAccessExpression - resourceType has no name');
234
        }
235
        if (null == $expression->getResourceProperty()) {
236
            throw new \InvalidArgumentException('onPropertyAccessExpression - expression has no resource property');
237
        }
238
        $parent = $expression;
239
        $variable = null;
240
241
        do {
242
            $variable = $parent->getResourceProperty()->getName() . self::MEMBER_ACCESS . $variable;
243
            $parent = $parent->getParent();
244
        } while ($parent != null);
245
246
        $variable = rtrim($variable, self::MEMBER_ACCESS);
247
        $variable = $this->getIteratorName() . self::MEMBER_ACCESS . $variable;
248
249
        return $variable;
250
    }
251
252
    /**
253
     * Call-back for function call expression.
254
     *
255
     * @param FunctionDescription $functionDescription Description of the function
256
     * @param array<string>       $params              Parameters to the function
257
     *
258
     * @return string
259
     */
260
    public function onFunctionCallExpression($functionDescription, $params)
261
    {
262
        switch ($functionDescription->name) {
263
            case ODataConstants::STRFUN_COMPARE:
264
                return 'strcmp(' . $params[0] . ', ' . $params[1] . ')';
265
266
            case ODataConstants::STRFUN_ENDSWITH:
267
                return '(strcmp(substr(' . $params[0] . ', strlen(' . $params[0] . ') - strlen(' . $params[1] . ')), '
268
                        .$params[1] . ') === 0)';
269
270
            case ODataConstants::STRFUN_INDEXOF:
271
                return 'strpos(' . $params[0] . ', ' . $params[1] . ')';
272
273 View Code Duplication
            case ODataConstants::STRFUN_REPLACE:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
274
                return 'str_replace(' . $params[1] . ', ' . $params[2] . ', ' . $params[0] . ')';
275
276
            case ODataConstants::STRFUN_STARTSWITH:
277
                return '(strpos(' . $params[0] . ', ' . $params[1] . ') === 0)';
278
279
            case ODataConstants::STRFUN_TOLOWER:
280
                return 'strtolower(' . $params[0] . ')';
281
282
            case ODataConstants::STRFUN_TOUPPER:
283
                return 'strtoupper(' . $params[0] . ')';
284
285
            case ODataConstants::STRFUN_TRIM:
286
                return 'trim(' . $params[0] . ')';
287
288 View Code Duplication
            case ODataConstants::STRFUN_SUBSTRING:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
289
                return count($params) == 3 ?
290
                    'substr(' . $params[0] . ', ' . $params[1] .
291
                    ', ' . $params[2] . ')' : 'substr(' . $params[0] .
292
                    ', ' . $params[1] . ')';
293
294
            case ODataConstants::STRFUN_SUBSTRINGOF:
295
                return '(strpos(' . $params[1] . ', ' . $params[0] . ') !== false)';
296
297
            case ODataConstants::STRFUN_CONCAT:
298
                return $params[0] . ' . ' . $params[1];
299
300
            case ODataConstants::STRFUN_LENGTH:
301
                return 'strlen(' . $params[0] . ')';
302
303 View Code Duplication
            case ODataConstants::GUIDFUN_EQUAL:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
304
                return self::TYPE_NAMESPACE . 'Guid::guidEqual(' . $params[0] . ', ' . $params[1] . ')';
305
306 View Code Duplication
            case ODataConstants::DATETIME_COMPARE:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
307
                return self::TYPE_NAMESPACE . 'DateTime::dateTimeCmp(' . $params[0] . ', ' . $params[1] . ')';
308
309
            case ODataConstants::DATETIME_YEAR:
310
                return self::TYPE_NAMESPACE . 'DateTime::year(' . $params[0] . ')';
311
312
            case ODataConstants::DATETIME_MONTH:
313
                return self::TYPE_NAMESPACE . 'DateTime::month(' . $params[0] . ')';
314
315
            case ODataConstants::DATETIME_DAY:
316
                return self::TYPE_NAMESPACE . 'DateTime::day(' . $params[0] . ')';
317
318
            case ODataConstants::DATETIME_HOUR:
319
                return self::TYPE_NAMESPACE . 'DateTime::hour(' . $params[0] . ')';
320
321
            case ODataConstants::DATETIME_MINUTE:
322
                return self::TYPE_NAMESPACE . 'DateTime::minute(' . $params[0] . ')';
323
324
            case ODataConstants::DATETIME_SECOND:
325
                return self::TYPE_NAMESPACE . 'DateTime::second(' . $params[0] . ')';
326
327
            case ODataConstants::MATHFUN_ROUND:
328
                return 'round(' . $params[0] . ')';
329
330
            case ODataConstants::MATHFUN_CEILING:
331
                return 'ceil(' . $params[0] . ')';
332
333
            case ODataConstants::MATHFUN_FLOOR:
334
                return 'floor(' . $params[0] . ')';
335
336 View Code Duplication
            case ODataConstants::BINFUL_EQUAL:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
337
                return self::TYPE_NAMESPACE . 'Binary::binaryEqual(' . $params[0] . ', ' . $params[1] . ')';
338
339
            case 'is_null':
340
                return 'is_null(' . $params[0] . ')';
341
342
            default:
343
                throw new \InvalidArgumentException('onFunctionCallExpression');
344
        }
345
    }
346
347
    /**
348
     * To format binary expression.
349
     *
350
     * @param string $operator The binary operator
351
     * @param string $left     The left operand
352
     * @param string $right    The right operand
353
     *
354
     * @return string
355
     */
356
    private function prepareBinaryExpression($operator, $left, $right)
357
    {
358
        return
359
            self::OPEN_BRACKET . $left . ' ' . $operator . ' ' . $right . self::CLOSE_BRACKET;
360
    }
361
362
    /**
363
     * To format unary expression.
364
     *
365
     * @param string $operator The unary operator
366
     * @param string $child    The operand
367
     *
368
     * @return string
369
     */
370
    private function prepareUnaryExpression($operator, $child)
371
    {
372
        return $operator . self::OPEN_BRACKET . $child . self::CLOSE_BRACKET;
373
    }
374
}
375