Completed
Push — master ( 1eee69...fc8931 )
by Patrick
03:03
created

FilterClause::toMongoFilter()   D

Complexity

Conditions 10
Paths 18

Size

Total Lines 27
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 21
c 1
b 0
f 0
nc 18
nop 0
dl 0
loc 27
rs 4.8196

How to fix   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
namespace Data;
3
4
class FilterClause
5
{
6
    public $var1;
7
    public $var2;
8
    public $op;
9
10
    function __construct($string = false)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
11
    {
12
        if($string !== false)
13
        {
14
            $this->process_filter_string($string);
0 ignored issues
show
Documentation introduced by
$string is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
15
        }
16
    }
17
18
    /**
19
     * Find the string inside the other string
20
     *
21
     * @param string $haystack The string to search inside
22
     * @param string $needle The string to search for
23
     *
24
     * @return boolean True if the needle exists in the haystack, false otherwise
25
     */
26
    static function str_startswith($haystack, $needle)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
27
    {
28
        return substr($haystack, 0, strlen($needle)) === $needle;
29
    }
30
31
    protected function filterIsFunction($string)
32
    {
33
        return (self::str_startswith($string, 'substringof') || self::str_startswith($string, 'contains') ||
34
                self::str_startswith($string, 'indexof'));
35
    }
36
37
    protected function odataOpToStd($op)
38
    {
39
        switch($op)
40
        {
41
            case 'ne':
42
                return '!=';
43
            case 'eq':
44
                return '=';
45
            case 'lt':
46
                return '<';
47
            case 'le':
48
                return '<=';
49
            case 'gt':
50
                return '>';
51
            case 'ge':
52
                return '>=';
53
            default:
54
                return $op;
55
        }
56
    }
57
58
    /**
59
     * Convert the string into an OData Filter
60
     *
61
     * @param string $string The string to turn into a filter
62
     */
63
    protected function process_filter_string($string)
64
    {
65
        if($this->filterIsFunction($string))
66
        {
67
            $this->op   = strtok($string, '(');
68
            $this->var1 = strtok(',');
69
            $this->var2 = trim(strtok(')'));
70
            return;
71
        }
72
        $field = strtok($string, ' ');
73
        $op = strtok(' ');
74
        $rest = strtok("\0");
75
        $this->var1  = $field;
76
        $this->op    = $this->odataOpToStd($op);
77
        $this->var2  = $rest;
78
    }
79
80
    public function to_sql_string()
81
    {
82
        switch($this->op)
83
        {
84
            case 'substringof':
85
            case 'contains':
86
                return $this->var1.' LIKE \'%'.trim($this->var2, "'").'%\'';
87
                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...
88
            default:
89
                return $this->var1.$this->op.$this->var2;
90
                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...
91
        }
92
    }
93
94
    public function to_ldap_string()
95
    {
96
        $str = '(';
97
        switch($this->op)
98
        {
99
            case 'substringof':
100
            case 'contains':
101
                $str .= $this->var1.$this->op.'*'.trim($this->var2, "'").'*';
102
                break;
103
            case '!=':
104
                $str .= '!('.$this->var1.'='.$this->var2.')';
105
                break;
106
            default:
107
                $str .= $this->var1.$this->op.$this->var2;
108
                break;
109
        }
110
        return $str.')';
111
    }
112
113
    private function getMongoIndexOfOperator()
114
    {
115
        $field = $this->var1;
116
        $case  = false;
117
        if(self::str_startswith($this->var1, 'tolower'))
118
        {
119
            $field = substr($this->var1, strpos($this->var1, '(') + 1);
120
            $field = substr($field, 0, strpos($field, ')'));
121
            $case = true;
122
        }
123
        if($case)
124
        {
125
            return array($field=>array('$regex'=>new \MongoRegex('/'.$this->var2.'/i')));
126
        }
127
        return array($field=>$this->var2);       
128
    }
129
130
    public function toMongoFilter()
131
    {
132
        $this->var2 = trim($this->var2, "'");
133
        if($this->var1 === '_id')
134
        {
135
            $this->var2 = new \MongoId($this->var2);
136
        }
137
        switch($this->op)
138
        {
139
            case '!=':
140
                return array($this->var1=>array('$ne'=>$this->var2));
141
            case '=':
142
                return array($this->var1=>$this->var2);
143
            case '<';
144
                return array($this->var1=>array('$lt'=>$this->var2));
145
            case '<=':
146
                return array($this->var1=>array('$lte'=>$this->var2));
147
            case '>':
148
                return array($this->var1=>array('$gt'=>$this->var2));
149
            case '>=':
150
                return array($this->var1=>array('$gte'=>$this->var2));
151
            case 'substringof':
152
                return array($this->var1=>array('$regex'=>new MongoRegex('/'.$this->var2.'/i')));
153
            case 'indexof':
154
                return $this->getMongoIndexOfOperator();
155
        }
156
    }
157
158
    function php_compare($value)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
159
    {
160
        switch($this->op)
161
        {
162
            case '!=':
163
                return $value != $this->var2;
164
            case '=':
165
                return $value == $this->var2;
166
            case '<':
167
                return $value < $this->var2;
168
            case '<=':
169
                return $value <= $this->var2;
170
            case '>':
171
                return $value > $this->var2;
172
            case '>=':
173
                return $value >= $this->var2;
174
        }
175
    }
176
}
177