Passed
Push — master ( 4ab488...bcfbc7 )
by Bálint
03:58
created

WordPressDSExpressionProvider   D

Complexity

Total Complexity 59

Size/Duplication

Total Lines 355
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 59
eloc 188
dl 0
loc 355
c 0
b 0
f 0
rs 4.08

12 Methods

Rating   Name   Duplication   Size   Complexity  
A getIteratorName() 0 3 1
A setResourceType() 0 3 1
A onArithmeticExpression() 0 20 6
B onRelationalExpression() 0 27 7
A onUnaryExpression() 0 11 3
A onPropertyAccessExpression() 0 15 4
D onFunctionCallExpression() 0 82 27
A __construct() 0 3 1
A onLogicalExpression() 0 11 3
A _prepareUnaryExpression() 0 3 1
A _prepareBinaryExpression() 0 15 2
A onConstantExpression() 0 9 3

How to fix   Complexity   

Complex Class

Complex classes like WordPressDSExpressionProvider often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WordPressDSExpressionProvider, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
use POData\UriProcessor\QueryProcessor\ExpressionParser\Expressions\ExpressionType;
4
use POData\Providers\Metadata\Type\IType;
5
use POData\Common\ODataConstants;
6
use POData\Providers\Expression\IExpressionProvider;
7
use POData\Providers\Metadata\ResourceType;
8
require_once 'WordPressMetadata.php';
9
10
class WordPressDSExpressionProvider implements IExpressionProvider
11
{
12
    const ADD                  = '+';
13
    const CLOSE_BRACKET        = ')';
14
    const COMMA                = ',';
15
    const DIVIDE               = '/';
16
    const SUBTRACT             = '-';
17
    const EQUAL                = '=';
18
    const GREATERTHAN          = '>';
19
    const GREATERTHAN_OR_EQUAL = '>=';
20
    const LESSTHAN             = '<';
21
    const LESSTHAN_OR_EQUAL    = '<=';
22
    const LOGICAL_AND          = '&&';
23
    const LOGICAL_NOT          = '!';
24
    const LOGICAL_OR           = '||';
25
    const MEMBERACCESS         = '';
26
    const MODULO               = '%';
27
    const MULTIPLY             = '*';
28
    const NEGATE               = '-';
29
    const NOTEQUAL             = '!=';
30
    const OPEN_BRAKET          = '(';
31
    
32
    /**
33
     * The type of the resource pointed by the resource path segement
34
     *
35
     * @var ResourceType
36
     */
37
    private $_resourceType;
38
39
    /**
40
     * 
41
     * @var array(string, array(string, string))
42
     */
43
    private $_entityMapping;
44
45
    /**
46
     * Constructs new instance of WordPressDSExpressionProvider
47
     *    
48
     */
49
    public function __construct()
50
    {
51
        $this->_entityMapping = CreateWordPressMetadata::getEntityMapping();
52
    }
53
54
    /**
55
     * Get the name of the iterator
56
     * 
57
     * @return string
58
     */
59
    public function getIteratorName()
60
    {
61
        return null;
62
    }
63
64
    /**
65
     * call-back for setting the resource type.
66
     *
67
     * @param ResourceType $resourceType The resource type on which the filter
68
     *                                   is going to be applied.
69
     */
70
    public function setResourceType(ResourceType $resourceType)
71
    {
72
        $this->_resourceType = $resourceType;
73
    }
74
75
    /**
76
     * Call-back for logical expression
77
     * 
78
     * @param ExpressionType $expressionType The type of logical expression.
79
     * @param string         $left           The left expression.
80
     * @param string         $right          The left expression.
81
     * 
82
     * @return string
83
     */
84
    public function onLogicalExpression($expressionType, $left, $right)
85
    {
86
        switch ($expressionType) {
87
            case ExpressionType::AND_LOGICAL:
88
                return $this->_prepareBinaryExpression(self::LOGICAL_AND, $left, $right);
89
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
90
            case ExpressionType::OR_LOGICAL:
91
                return $this->_prepareBinaryExpression(self::LOGICAL_OR, $left, $right);
92
                break;
93
            default:
94
                throw new \InvalidArgumentException('onLogicalExpression');
95
        }
96
    }
97
98
    /**
99
     * Call-back for arithmetic expression
100
     * 
101
     * @param ExpressionType $expressionType The type of arithmetic expression.
102
     * @param string         $left           The left expression.
103
     * @param string         $right          The left expression.
104
     * 
105
     * @return string
106
     */
107
    public function onArithmeticExpression($expressionType, $left, $right)
108
    {
109
        switch ($expressionType) {
110
            case ExpressionType::MULTIPLY:
111
                return $this->_prepareBinaryExpression(self::MULTIPLY, $left, $right);
112
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
113
            case ExpressionType::DIVIDE:
114
                return $this->_prepareBinaryExpression(self::DIVIDE, $left, $right);
115
                break;
116
            case ExpressionType::MODULO:
117
                return $this->_prepareBinaryExpression(self::MODULO, $left, $right);
118
                break;
119
            case ExpressionType::ADD:
120
                return $this->_prepareBinaryExpression(self::ADD, $left, $right);
121
                break;
122
            case ExpressionType::SUBTRACT:
123
                return $this->_prepareBinaryExpression(self::SUBTRACT, $left, $right);
124
                break;
125
            default:
126
                throw new \InvalidArgumentException('onArithmeticExpression');
127
        }
128
    }
129
130
    /**
131
     * Call-back for relational expression
132
     * 
133
     * @param ExpressionType $expressionType The type of relation expression
134
     * @param string         $left           The left expression
135
     * @param string         $right          The left expression
136
     * 
137
     * @return string
138
     */
139
    public function onRelationalExpression($expressionType, $left, $right)
140
    {
141
        switch ($expressionType) {
142
            case ExpressionType::GREATERTHAN:
143
                return $this->_prepareBinaryExpression(self::GREATERTHAN, $left, $right);
144
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
145
            case ExpressionType::GREATERTHAN_OR_EQUAL:
146
                return $this->_prepareBinaryExpression(
147
                    self::GREATERTHAN_OR_EQUAL, $left, $right
148
                );
149
                break;
150
            case ExpressionType::LESSTHAN:
151
                return $this->_prepareBinaryExpression(self::LESSTHAN, $left, $right);
152
                break;
153
            case ExpressionType::LESSTHAN_OR_EQUAL:
154
                return $this->_prepareBinaryExpression(
155
                    self::LESSTHAN_OR_EQUAL, $left, $right
156
                );
157
                break;
158
            case ExpressionType::EQUAL:
159
                return $this->_prepareBinaryExpression(self::EQUAL, $left, $right);
160
                break;
161
            case ExpressionType::NOTEQUAL:
162
                return $this->_prepareBinaryExpression(self::NOTEQUAL, $left, $right);
163
                break;
164
            default:
165
                throw new \InvalidArgumentException('onArithmeticExpression');
166
        }
167
    }
168
169
    /**
170
     * Call-back for unary expression
171
     * 
172
     * @param ExpressionType $expressionType The type of unary expression
173
     * @param string         $child          The child expression
174
     * 
175
     * @return string
176
     */
177
    public function onUnaryExpression($expressionType, $child)
178
    {
179
        switch ($expressionType) {
180
            case ExpressionType::NEGATE:
181
                return $this->_prepareUnaryExpression(self::NEGATE, $child);
182
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
183
            case ExpressionType::NOT_LOGICAL:
184
                return $this->_prepareUnaryExpression(self::LOGICAL_NOT, $child);
185
                break;
186
            default:
187
                throw new \InvalidArgumentException('onUnaryExpression');
188
        }
189
    }
190
191
    /**
192
     * Call-back for constant expression
193
     * 
194
     * @param IType  $type  The type of constant
195
     * @param objetc $value The value of the constant
0 ignored issues
show
Bug introduced by
The type objetc was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
196
     * 
197
     * @return string
198
     */
199
    public function onConstantExpression(IType $type, $value)
200
    {
201
        if (is_bool($value)) {
0 ignored issues
show
introduced by
The condition is_bool($value) is always false.
Loading history...
202
            return var_export($value, true);
203
        } else if (is_null($value)) {
204
            return var_export(null, true);
205
        }
206
207
        return $value;
208
    }
209
210
    /**
211
     * Call-back for property access expression
212
     * 
213
     * @param PropertyAccessExpression $expression The property access expression
0 ignored issues
show
Bug introduced by
The type PropertyAccessExpression was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
214
     * 
215
     * @return string
216
     */
217
218
    public function onPropertyAccessExpression($expression)
219
    {
220
        $parent = $expression;
221
        $variable = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $variable is dead and can be removed.
Loading history...
222
        $entityTypeName = $this->_resourceType->getName();
223
        $propertyName = $parent->getResourceProperty()->getName();
224
        if (is_array($this->_entityMapping)) {
0 ignored issues
show
introduced by
The condition is_array($this->_entityMapping) is always true.
Loading history...
225
            if (array_key_exists($entityTypeName, $this->_entityMapping)) {
226
            if (array_key_exists($propertyName, $this->_entityMapping[$entityTypeName])) {
227
                return $this->_entityMapping[$entityTypeName][$propertyName];
228
            }
229
            }
230
        }
231
     
232
        return $propertyName;
233
    }
234
235
    /**
236
     * Call-back for function call expression
237
     * 
238
     * @param FunctionDescription $functionDescription Description of the function.
0 ignored issues
show
Bug introduced by
The type FunctionDescription was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
239
     * @param array<string>       $params              Paameters to the function.
240
     * 
241
     * @return string
242
     */
243
    public function onFunctionCallExpression($functionDescription, $params)
244
    {
245
        switch ($functionDescription->functionName) {
246
            case ODataConstants::STRFUN_COMPARE:
247
                return "STRCMP($params[0], $params[1])";
248
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
249
            case ODataConstants::STRFUN_ENDSWITH:
250
              return "(STRCMP($params[1],RIGHT($params[0],LENGTH($params[1]))) = 0)";
251
                break;
252
            case ODataConstants::STRFUN_INDEXOF:
253
                return "INSTR($params[0], $params[1]) - 1";
254
                break;
255
            case ODataConstants::STRFUN_REPLACE:
256
              return "REPLACE($params[0],$params[1],$params[2])";
257
                break;
258
            case ODataConstants::STRFUN_STARTSWITH:
259
              return "(STRCMP($params[1],LEFT($params[0],LENGTH($params[1]))) = 0)";
260
                break; 
261
            case ODataConstants::STRFUN_TOLOWER:
262
              return "LOWER($params[0])";
263
                break;
264
            case ODataConstants::STRFUN_TOUPPER:
265
              return "UPPER($params[0])";
266
                break;
267
            case ODataConstants::STRFUN_TRIM:
268
              return "TRIM($params[0])";
269
                break;
270
            case ODataConstants::STRFUN_SUBSTRING:
271
                return count($params) == 3 ?
272
                    "SUBSTRING($params[0], $params[1] + 1, $params[2])" : "SUBSTRING($params[0], $params[1] + 1)";
273
                break;
274
            case ODataConstants::STRFUN_SUBSTRINGOF:
275
                return "(LOCATE($params[0], $params[1]) > 0)";
276
                break;
277
            case ODataConstants::STRFUN_CONCAT:
278
                return "CONCAT($params[0],$params[1])";
279
                break;
280
            case ODataConstants::STRFUN_LENGTH:
281
                return "LENGTH($params[0])";
282
                break;
283
            case ODataConstants::GUIDFUN_EQUAL:
284
                return "STRCMP($params[0], $params[1])";
285
                break;
286
            case ODataConstants::DATETIME_COMPARE:
287
                return "DATETIMECMP($params[0]; $params[1])";
288
                break;
289
            case ODataConstants::DATETIME_YEAR:
290
                return "EXTRACT(YEAR from " . $params[0] . ")";
291
                break;
292
            case ODataConstants::DATETIME_MONTH:
293
                return "EXTRACT(MONTH from " . $params[0] . ")";
294
                break;
295
            case ODataConstants::DATETIME_DAY:
296
                return "EXTRACT(DAY from " . $params[0] . ")";
297
                break;
298
            case ODataConstants::DATETIME_HOUR:
299
                return "EXTRACT(HOUR from " . $params[0] . ")";
300
                break;
301
            case ODataConstants::DATETIME_MINUTE:
302
                return "EXTRACT(MINUTE from " . $params[0] . ")";
303
                break;
304
            case ODataConstants::DATETIME_SECOND:
305
                return "EXTRACT(SECOND from " . $params[0] . ")";
306
                break;                
307
            case ODataConstants::MATHFUN_ROUND:
308
                return "ROUND($params[0])";
309
                break;
310
            case ODataConstants::MATHFUN_CEILING:
311
                return "CEIL($params[0])";
312
                break;
313
            case ODataConstants::MATHFUN_FLOOR:
314
                return "FLOOR($params[0])";
315
                break;
316
            case ODataConstants::BINFUL_EQUAL:
317
                return "($params[0] = $params[1])";
318
                break;
319
            case 'is_null':
320
                return "is_null($params[0])";
321
                break;
322
            
323
            default:
324
                throw new \InvalidArgumentException('onFunctionCallExpression');
325
        }
326
    }
327
328
    /**
329
     * To format binary expression
330
     * 
331
     * @param string $operator The binary operator.
332
     * @param string $left     The left operand.
333
     * @param string $right    The right operand.
334
     * 
335
     * @return string
336
     */
337
    private function _prepareBinaryExpression($operator, $left, $right)
338
    {
339
        // Special handling for DATETIMECMP
340
        if (!substr_compare($left, "DATETIMECMP", 0, 11)) {
341
        $str = explode(';', $left, 2);
342
        $str[0] = str_replace('DATETIMECMP', '', $str[0]);
343
        return self::OPEN_BRAKET
344
            . $str[0] . ' ' . $operator
345
            . ' ' . $str[1] . self::CLOSE_BRACKET;
346
        }
347
348
        return 
349
            self::OPEN_BRAKET 
350
            . $left . ' ' . $operator 
351
            . ' ' . $right . self::CLOSE_BRACKET;
352
    }
353
354
    /**
355
     * To format unary expression
356
     * 
357
     * @param string $operator The unary operator.
358
     * @param string $child    The operand.
359
     * 
360
     * @return string
361
     */
362
    private function _prepareUnaryExpression($operator, $child)
363
    {
364
        return $operator . self::OPEN_BRAKET . $child . self::CLOSE_BRACKET;
365
    }
366
}
367