NorthWindDSExpressionProvider::onUnaryExpression()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 10

Duplication

Lines 13
Ratio 100 %

Importance

Changes 0
Metric Value
dl 13
loc 13
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 10
nc 3
nop 2
1
<?php
2
3
use POData\UriProcessor\QueryProcessor\ExpressionParser\Expressions\ExpressionType;
4
use POData\Providers\Metadata\Type\IType;
5
use POData\Common\NotImplementedException;
6
use POData\Common\ODataConstants;
7
use POData\Providers\Metadata\ResourcePropertyKind;
8
use POData\Providers\Metadata\ResourceType;
9
use POData\Providers\Expression\IExpressionProvider as IExpressionProvider;
10
11
12
class NorthWindDSExpressionProvider implements IExpressionProvider
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
13
{
14
    const ADD                  = '+';
15
    const CLOSE_BRACKET        = ')';
16
    const COMMA                = ',';
17
    const DIVIDE               = '/';
18
    const SUBTRACT             = '-';
19
    const EQUAL                = '=';
20
    const GREATERTHAN          = '>';
21
    const GREATERTHAN_OR_EQUAL = '>=';
22
    const LESSTHAN             = '<';
23
    const LESSTHAN_OR_EQUAL    = '<=';
24
    const LOGICAL_AND          = 'AND';
25
    const LOGICAL_NOT          = 'not';
26
    const LOGICAL_OR           = 'OR';
27
    const MEMBERACCESS         = '';
28
    const MODULO               = '%';
29
    const MULTIPLY             = '*';
30
    const NEGATE               = '-';
31
    const NOTEQUAL             = '!=';
32
    const OPEN_BRAKET          = '(';
33
    // The default parameter for ROUND sql function-call
34
    private $_default_round = 0;
0 ignored issues
show
Unused Code introduced by
The property $_default_round is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
35
36
    /**
37
     * The name of iterator
38
     * 
39
     * @var string
40
     */
41
    private $_iterName;
0 ignored issues
show
Unused Code introduced by
The property $_iterName is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
42
43
    /**
44
     * The type of the resource pointed by the resource path segement
45
     *
46
     * @var ResourceType
47
     */
48
    private $_resourceType;
49
50
    /**
51
     * Constructs new instance of SQLSrverExpressionProvider for NorthWind DB
52
     * 
53
     * @param string $iterName The name of the iterator
0 ignored issues
show
Bug introduced by
There is no parameter named $iterName. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
54
     */
55
    public function __construct()
56
    {
57
    }
58
59
    /**
60
     * Get the name of the iterator
61
     * 
62
     * @return string
63
     */
64
    public function getIteratorName()
65
    {
66
      return null;
67
    }
68
69
    /**
70
     * call-back for setting the resource type.
71
     *
72
     * @param ResourceType $resourceType The resource type on which the filter
73
     *                                   is going to be applied.
74
     */
75
    public function setResourceType(ResourceType $resourceType)
76
    {
77
    	$this->_resourceType = $resourceType;
78
    }
79
80
    /**
81
     * Call-back for logical expression
82
     * 
83
     * @param ExpressionType $expressionType The type of logical expression.
84
     * @param string         $left           The left expression.
85
     * @param string         $right          The left expression.
86
     * 
87
     * @return string
88
     */
89 View Code Duplication
    public function onLogicalExpression($expressionType, $left, $right)
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...
90
    {
91
        switch($expressionType) {
92
        case ExpressionType::AND_LOGICAL:
93
            return $this->_prepareBinaryExpression(self::LOGICAL_AND, $left, $right);
94
            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...
95
        case ExpressionType::OR_LOGICAL:
96
            return $this->_prepareBinaryExpression(self::LOGICAL_OR, $left, $right);
97
            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...
98
        default:
99
            throw new \InvalidArgumentException('onLogicalExpression');
100
        }
101
    }
102
103
    /**
104
     * Call-back for arithmetic expression
105
     * 
106
     * @param ExpressionType $expressionType The type of arithmetic expression.
107
     * @param string         $left           The left expression.
108
     * @param string         $right          The left expression.
109
     * 
110
     * @return string
111
     */
112 View Code Duplication
    public function onArithmeticExpression($expressionType, $left, $right)
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...
113
    {
114
        switch($expressionType) {
115
        case ExpressionType::MULTIPLY:
116
            return $this->_prepareBinaryExpression(self::MULTIPLY, $left, $right);
117
            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...
118
        case ExpressionType::DIVIDE:
119
            return $this->_prepareBinaryExpression(self::DIVIDE, $left, $right);
120
            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...
121
        case ExpressionType::MODULO:
122
            return $this->_prepareBinaryExpression(self::MODULO, $left, $right);
123
            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...
124
        case ExpressionType::ADD:
125
            return $this->_prepareBinaryExpression(self::ADD, $left, $right);
126
            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...
127
        case ExpressionType::SUBTRACT:
128
            return $this->_prepareBinaryExpression(self::SUBTRACT, $left, $right);
129
            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...
130
        default:
131
            throw new \InvalidArgumentException('onArithmeticExpression');
132
        }
133
    }
134
135
    /**
136
     * Call-back for relational expression
137
     * 
138
     * @param ExpressionType $expressionType The type of relation expression
139
     * @param string         $left           The left expression
140
     * @param string         $right          The left expression
141
     * 
142
     * @return string
143
     */
144 View Code Duplication
    public function onRelationalExpression($expressionType, $left, $right)
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...
145
    {
146
        switch($expressionType) {
147
        case ExpressionType::GREATERTHAN:
148
            return $this->_prepareBinaryExpression(self::GREATERTHAN, $left, $right);
149
            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...
150
        case ExpressionType::GREATERTHAN_OR_EQUAL:
151
            return $this->_prepareBinaryExpression(
152
                self::GREATERTHAN_OR_EQUAL, $left, $right
153
            );
154
            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...
155
        case ExpressionType::LESSTHAN:
156
            return $this->_prepareBinaryExpression(self::LESSTHAN, $left, $right);
157
            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...
158
        case ExpressionType::LESSTHAN_OR_EQUAL:
159
            return $this->_prepareBinaryExpression(
160
                self::LESSTHAN_OR_EQUAL, $left, $right
161
            );
162
            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...
163
        case ExpressionType::EQUAL:
164
            return $this->_prepareBinaryExpression(self::EQUAL, $left, $right);
165
            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...
166
        case ExpressionType::NOTEQUAL:
167
            return $this->_prepareBinaryExpression(self::NOTEQUAL, $left, $right);
168
            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...
169
        default:
170
            throw new \InvalidArgumentException('onArithmeticExpression');
171
        }
172
    }
173
174
    /**
175
     * Call-back for unary expression
176
     * 
177
     * @param ExpressionType $expressionType The type of unary expression
178
     * @param string         $child          The child expression
179
     * 
180
     * @return string
181
     */
182 View Code Duplication
    public function onUnaryExpression($expressionType, $child)
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...
183
    {
184
        switch($expressionType) {
185
        case ExpressionType::NEGATE:
186
            return $this->_prepareUnaryExpression(self::NEGATE, $child);
187
            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...
188
        case ExpressionType::NOT_LOGICAL:
189
            return $this->_prepareUnaryExpression(self::LOGICAL_NOT, $child);
190
            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...
191
        default:
192
            throw new \InvalidArgumentException('onUnaryExpression');
193
        }
194
    }
195
196
    /**
197
     * Call-back for constant expression
198
     * 
199
     * @param IType  $type  The type of constant
200
     * @param objetc $value The value of the constant
201
     * 
202
     * @return string
203
     */
204 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...
205
    {    	
206
        if (is_bool($value)) {
207
            return var_export($value, true);
208
        } else if (is_null($value)) {
209
            return var_export(null, true);
210
        }
211
212
        return $value;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $value; (objetc) is incompatible with the return type declared by the interface POData\Providers\Express...r::onConstantExpression of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
213
    }
214
215
    /**
216
     * Call-back for property access expression
217
     * 
218
     * @param PropertyAccessExpression $expression The property access expression
219
     * 
220
     * @return string
221
     */
222
    public function onPropertyAccessExpression($expression)
223
    {
224
        $parent = $expression;
225
        $variable = null;
0 ignored issues
show
Unused Code introduced by
$variable is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
226
        $isFirstLevelPrimitive = is_null($parent->getParent());
227
        if (!$isFirstLevelPrimitive) {
228
        	// This propery access sub-expression in the $filter need access
229
        	// to level 2 or greater property of a complex or resource reference
230
        	// property.
231
        	// e.g. Customers?$filter=Address/City eq 'Kottayam'
232
        	//          Level_2 property access [Complex]
233
        	//      Customers?$filter=Address/AltAddress/City eq 'Seattle'
234
        	//          Level_3 property access [Complex]
235
        	//      Orders?$filter=Customer/CustomerID eq 'ALFKI'
236
        	//          Level_2 property access [Resource Reference]
237
        	$parent2 = null;
0 ignored issues
show
Unused Code introduced by
$parent2 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
238
        	do {
239
        		$parent2 = $parent;
240
        		$parent = $parent->getParent();
241
        	} while ($parent != null);
242
        	
243
        	$resourceProperty = $parent2->getResourceProperty();
244
        	if ($resourceProperty->isKindOf(ResourcePropertyKind::RESOURCE_REFERENCE)) {
245
        		// Orders?$filter=Customer/CustomerID eq 'ALFKI'
246
        		throw new NotImplementedException(
247
        				'This implementation not supports Resource reference in the filter',
248
        				500,
249
        				NULL
250
        		);
251
        	} else {
252
        		// Customers?$filter=Address/AltAddress/City eq 'Seattle'
253
        		// Customers?$filter=Address/City eq 'Seattle'
254
        		$propertyName = $parent2->getResourceProperty()->getName();
255
        		if ("Address" == $propertyName) {
256
        			$child = $parent2->getChild();
257
        			$propertyName = $child->getResourceProperty()->getName();
258
        			if ("AltAddress" != $propertyName) {
259
        				return $propertyName;
260
        			}
261
        			
262
        			throw new NotImplementedException(
263
        					'This implementation not supports Customer::Address::AltAddress in the filter',
264
        					500,
265
        					NULL
266
        			);
267
        		}
268
        	}
269
270
        } else {
271
        	// This is a first level property access
272
        	$resourceProperty = $parent->getResourceProperty();
273
        	if ($resourceProperty->isKindOf(ResourcePropertyKind::COMPLEX_TYPE)
274
        	    || $resourceProperty->isKindOf(ResourcePropertyKind::RESOURCE_REFERENCE)) {
275
        		// Customers?$filter=Address eq null
276
        		// Orders?$filter=Customer ne null
277
        		// First level property access to a complex or resource reference
278
        		// which is not supported by $this [this implementation of IDSQP2]
279
        		throw new NotImplementedException(
280
                    'First level complex and Resource reference are not supported in the filter', 
281
        		    500, 
282
        		    NULL
283
                );
284
        	} else {
285
        		// First level property access to primitive property
286
        		return $parent->getResourceProperty()->getName();
287
        	}
288
        }
289
    }
290
    /**
291
     * Call-back for function call expression
292
     * 
293
     * @param FunctionDescription $functionDescription Description of the function.
294
     * @param array<string>       $params              Paameters to the function.
295
     * 
296
     * @return string
297
     */
298
    public function onFunctionCallExpression($functionDescription, $params)
299
    {
300
        switch($functionDescription->functionName) {
301
        case ODataConstants::STRFUN_COMPARE:
302
            return "STRCMP($params[0]; $params[1])";
303
            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...
304
        case ODataConstants::STRFUN_ENDSWITH:
305
          return "(($params[1]) = RIGHT(($params[0]), LEN($params[1])))";
306
            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...
307
        case ODataConstants::STRFUN_INDEXOF:
308
          // In SQLServer the index of string starts from 1, but in OData
309
          // the string start with index 0, so the below subtraction of 1
310
          return "(CHARINDEX($params[1], $params[0]) - 1)";
311
            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...
312
        case ODataConstants::STRFUN_REPLACE:
313
          return "REPLACE($params[0], $params[1], $params[2])";
314
            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...
315
        case ODataConstants::STRFUN_STARTSWITH:
316
          return "(($params[1]) = LEFT(($params[0]), LEN($params[1])))";
317
            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...
318
        case ODataConstants::STRFUN_TOLOWER:
319
          return "LOWER($params[0])";
320
            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...
321
        case ODataConstants::STRFUN_TOUPPER:
322
          return "UPPER($params[0])";
323
            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...
324
        case ODataConstants::STRFUN_TRIM:
325
          // OData supports trim function
326
          // We don't have the same function SQL Server, so use SQL functions LTRIM and RTRIM together
327
          // to achieve TRIM functionality.
328
          return "RTRIM(LTRIM($params[0]))";
329
            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...
330 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...
331
          if (count($params) == 3) {
332
            // 3 Param version of OData substring
333
              return "SUBSTRING($params[0], $params[1] + 1, $params[2])";
334
          } else {
335
            // 2 Params version of OData substring
336
            // We don't have the same function for SQL Server, we have only:
337
            //
338
            // SUBSTRING ( value_expression , start_expression , length_expression )
339
            // http://msdn.microsoft.com/en-us/library/ms187748.aspx
340
            //
341
            // If the sum of start_expression and length_expression is greater than the number of characters 
342
            // in value_expression, the whole value expression beginning at start_expression is returned
343
            // In OData substring function the index start from 0, in SQL Server its from 1
344
            return "SUBSTRING($params[0], $params[1] + 1, LEN($params[0]))";        	    
345
          }
346
            break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
347
        case ODataConstants::STRFUN_SUBSTRINGOF:
348
          return "(CHARINDEX($params[0], $params[1]) != 0)";
349
            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...
350
        case ODataConstants::STRFUN_CONCAT:
351
            return "$params[0] + $params[1]";
352
            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...
353
        case ODataConstants::STRFUN_LENGTH:
354
            return "LEN($params[0])";
355
            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...
356
        case ODataConstants::GUIDFUN_EQUAL:
357
            return "($params[0] = $params[1])";
358
            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...
359
        case ODataConstants::DATETIME_COMPARE:
360
            return "DATETIMECMP($params[0]; $params[1])";
361
            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...
362
        case ODataConstants::DATETIME_YEAR:
363
            return "YEAR($params[0])";
364
            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...
365
        case ODataConstants::DATETIME_MONTH:
366
            return "MONTH($params[0])";
367
            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...
368
        case ODataConstants::DATETIME_DAY:
369
            return "DAY($params[0])";
370
            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...
371
        case ODataConstants::DATETIME_HOUR:
372
            return "DATENAME(HOUR, $params[0])";
373
            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...
374
        case ODataConstants::DATETIME_MINUTE:
375
            return "DATENAME(MINUTE, $params[0])";
376
            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...
377
        case ODataConstants::DATETIME_SECOND:
378
            return "DATENAME(SECOND, $params[0])";
379
            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...
380
        case ODataConstants::MATHFUN_ROUND:
381
            return "ROUND($params[0], $this->_default_round)";
382
            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...
383
        case ODataConstants::MATHFUN_CEILING:
384
            return "CEILING($params[0])";
385
            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...
386
        case ODataConstants::MATHFUN_FLOOR:
387
            return "FLOOR($params[0])";
388
            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...
389
        case ODataConstants::BINFUL_EQUAL:
390
            return "($params[0] = $params[1])";
391
            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...
392
         case 'is_null':
393
            return "is_null($params[0])";
394
            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...
395
396
        default:
397
            throw new \InvalidArgumentException('onFunctionCallExpression');
398
        }
399
    }
400
401
    /**
402
     * To format binary expression
403
     * 
404
     * @param string $operator The binary operator.
405
     * @param string $left     The left operand.
406
     * @param string $right    The right operand.
407
     * 
408
     * @return string
409
     */
410
    private function _prepareBinaryExpression($operator, $left, $right)
411
    {
412 View Code Duplication
      if (!substr_compare($left, "STRCMP", 0, 6)) {
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...
413
            $str = explode(';', $left, 2);
414
            $str[0] = str_replace('STRCMP', '', $str[0]);
415
            if ($right == 'false' and $right != '0') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
416
              if (!substr_compare($operator, '!', 0, 1)) {
417
                  $operator = str_replace('!', '', $operator);
418
              } else if ($operator == '>=') {
419
                  $operator = '<';
420
              } else if ($operator == '<=') {
421
                  $operator = '>';
422
              } else {
423
                    $operator = "!".$operator;
424
              }
425
              return self::OPEN_BRAKET 
426
                    . $str[0] . ' ' . $operator 
427
                    . ' ' . $str[1] . self::CLOSE_BRACKET;
428
            } else {
429
                return self::OPEN_BRAKET 
430
                    . $str[0] . ' ' . $operator 
431
                    . ' ' . $str[1] . self::CLOSE_BRACKET;
432
            }
433
        }
434
        
435
        //DATETIMECMP
436 View Code Duplication
        if (!substr_compare($left, "DATETIMECMP", 0, 11)) {
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...
437
          $str = explode(';', $left, 2);
438
          $str[0] = str_replace('DATETIMECMP', '', $str[0]);
439
          if ($right == 'false' and $right != '0') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
440
            if (!substr_compare($operator, '!', 0, 1)) {
441
              $operator = str_replace('!', '', $operator);
442
            } else if ($operator == '>=') {
443
              $operator = '<';
444
            } else if ($operator == '<=') {
445
              $operator = '>';
446
            } else {
447
              $operator = "!".$operator;
448
            }
449
            return self::OPEN_BRAKET
450
            . $str[0] . ' ' . $operator
451
            . ' ' . $str[1] . self::CLOSE_BRACKET;
452
          } else {
453
            return self::OPEN_BRAKET
454
            . $str[0] . ' ' . $operator
455
            . ' ' . $str[1] . self::CLOSE_BRACKET;
456
          }
457
        }
458
459
        return 
460
            self::OPEN_BRAKET 
461
            . $left . ' ' . $operator 
462
            . ' ' . $right . self::CLOSE_BRACKET;
463
    }
464
465
    /**
466
     * To format unary expression
467
     * 
468
     * @param string $operator The unary operator.
469
     * @param string $child    The operand.
470
     * 
471
     * @return string
472
     */
473
    private function _prepareUnaryExpression($operator, $child)
474
    {
475
        return $operator . self::OPEN_BRAKET . $child . self::CLOSE_BRACKET;
476
    }
477
}
478