Completed
Push — master ( f22a46...046041 )
by Patrick
02:27 queued 12s
created

Filter   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 237
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 237
rs 7.44
c 0
b 0
f 0
wmc 52
lcom 2
cbo 1

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
B process_string() 0 27 6
B to_sql_string() 0 25 6
B to_ldap_string() 0 34 8
B to_mongo_filter() 0 27 6
B filterElement() 0 40 10
A filter_array() 0 9 2
A contains() 0 4 1
A getClause() 0 16 5
A addToSQLString() 0 4 1
A appendChild() 0 16 4
A getChildren() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Filter 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 Filter, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace Flipside\Data;
3
4
class Filter
5
{
6
    protected $children = array();
7
    protected $string;
8
    protected $sqlAppend = '';
9
10
    /**
11
     * Creates a new filter object
12
     *
13
     * @param false|string $string The string to create the filter from or false for an empty filter
14
     */
15
    public function __construct($string = false)
16
    {
17
        if($string !== false)
18
        {
19
            $this->string = $string;
20
            $this->children = self::process_string($this->string);
21
        }
22
    }
23
24
    static public function process_string($string)
25
    {
26
        $parens = false;
27
        //First check for parenthesis...
28
        if($string[0] === '(' && substr($string, -1) === ')')
29
        {
30
            $string = substr($string, 1, strlen($string) - 2);
31
            $parens = true;
32
        }
33
        if(preg_match('/(.+?)( and | or )(.+)/', $string, $clauses) === 0)
34
        {
35
            return array(new FilterClause($string));
36
        }
37
        $children = array();
38
        if($parens)
39
        {
40
            array_push($children, '(');
41
        }
42
        $children = array_merge($children, self::process_string($clauses[1]));
43
        array_push($children, trim($clauses[2]));
44
        $children = array_merge($children, self::process_string($clauses[3]));
45
        if($parens)
46
        {
47
            array_push($children, ')');
48
        }
49
        return $children;
50
    }
51
52
    public function to_sql_string()
53
    {
54
        $ret = '';
55
        $count = count($this->children);
56
        for($i = 0; $i < $count; $i++)
57
        {
58
            if($this->children[$i] === '(' || $this->children[$i] === ')')
59
            {
60
                $ret .= $this->children[$i];
61
            }
62
            else if($this->children[$i] === 'and')
63
            {
64
                $ret .= ' AND ';
65
            }
66
            else if($this->children[$i] === 'or')
67
            {
68
                $ret .= ' OR ';
69
            }
70
            else
71
            {
72
                $ret .= $this->children[$i]->to_sql_string();
73
            }
74
        }
75
        return $ret.$this->sqlAppend;
76
    }
77
78
    public function to_ldap_string()
79
    {
80
        $ret = '';
81
        $count = count($this->children);
82
        $prefix = '';
83
        for($i = 0; $i < $count; $i++)
84
        {
85
            if($this->children[$i] === 'and')
86
            {
87
                if($prefix == '|')
88
                {
89
                    throw new \Exception('Do not support both and or');
90
                }
91
                $prefix = '&';
92
            }
93
            else if($this->children[$i] === 'or')
94
            {
95
                if($prefix == '&')
96
                {
97
                    throw new \Exception('Do not support both and or');
98
                }
99
                $prefix = '|';
100
            }
101
            else
102
            {
103
                $ret .= $this->children[$i]->to_ldap_string();
104
            }
105
        }
106
        if($count === 1 && $prefix === '')
107
        {
108
            return $ret;
109
        }
110
        return '('.$prefix.$ret.')';
111
    }
112
113
    public function to_mongo_filter()
114
    {
115
        $ret = array();
116
        $count = count($this->children);
117
        for($i = 0; $i < $count; $i++)
118
        {
119
            if($this->children[$i] === 'and')
120
            {
121
                $old = array_pop($ret);
122
                array_push($ret, array('$and'=>array($old, $this->children[++$i]->toMongoFilter())));
123
            }
124
            else if($this->children[$i] === 'or')
125
            {
126
                $old = array_pop($ret);
127
                array_push($ret, array('$or'=>array($old, $this->children[++$i]->toMongoFilter())));
128
            }
129
            else
130
            {
131
                array_push($ret, $this->children[$i]->toMongoFilter());
132
            }
133
        }
134
        if(count($ret) == 1 && is_array($ret[0]))
135
        {
136
            return $ret[0];
137
        }
138
        return $ret;
139
    }
140
141
    public function filterElement($element)
142
    {
143
        $res = array();
144
        $count = count($this->children);
145
	for($i = 0; $i < $count; $i++)
146
	{
147
            if($this->children[$i] === 'and' || $this->children[$i] === 'or')
148
	    {
149
                array_push($res, $this->children[$i]);
150
	    }
151
	    else
152
	    {
153
                $tmp = $this->children[$i]->php_compare($element);
154
		array_push($res, $tmp);
155
	    }
156
	}
157
	if($count === 1)
158
	{
159
            return $res[0];
160
	}
161
	while($count >= 3)
162
	{
163
	    if($res[1] === 'and')
164
            {
165
                $var1 = array_shift($res);
166
                array_shift($res);
167
                $var2 = array_shift($res);
168
	        $res = array_merge(array($var1 && $var2), $res);
169
            }
170
	    else if($res[1] === 'or')
171
            {
172
                $var1 = array_shift($res);
173
                array_shift($res);
174
                $var2 = array_shift($res);
175
                $res = array_merge(array($var1 || $var2), $res);
176
	    }
177
	    $count = count($res);
178
	}
179
        return $res[0];
180
    }
181
182
    public function filter_array(&$array)
183
    {
184
        if(is_array($array))
185
	{
186
            $res = array_filter($array, array($this, 'filterElement'));
187
            return array_values($res);
188
        }
189
        return array();
190
    }
191
192
    public function contains($substr)
193
    {
194
        return strstr($this->string, $substr) !== false;
195
    }
196
197
    public function getClause($substr)
198
    {
199
        $count = count($this->children);
200
        for($i = 0; $i < $count; $i++)
201
        {
202
            if(!is_object($this->children[$i]))
203
            {
204
                continue;
205
            }
206
            if(strstr($this->children[$i]->var1, $substr) !== false ||
207
               strstr($this->children[$i]->var2, $substr) !== false)
208
            {
209
                return $this->children[$i];
210
            }
211
        }
212
    }
213
214
    public function addToSQLString($string)
215
    {
216
        $this->sqlAppend .= $string;
217
    }
218
219
    public function appendChild($child)
220
    {
221
        if($child === 'and' || $child === 'or')
222
        {
223
            array_push($this->children, $child);
224
            return;
225
        }
226
        else if(is_a($child, '\Data\Filter'))
227
        {
228
            $this->children = array_merge($this->children, $child->children);
229
        }
230
        else
231
        {
232
            $this->children = array_merge($this->children, self::process_string($child));
233
        }
234
    }
235
236
    public function getChildren()
237
    {
238
        return $this->children;
239
    }
240
}
241