Completed
Push — master ( 305542...5a5d85 )
by Joao
02:42
created

src/Repository/IteratorFilter.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace ByJG\AnyDataset\Repository;
4
5
use ByJG\AnyDataset\Database\SQLHelper;
6
use ByJG\AnyDataset\Enum\Relation;
7
8
class IteratorFilter
9
{
10
11
    const XPATH = 1;
12
    const SQL = 2;
13
14
    /**
15
     * @var array
16
     */
17
    private $_filters;
18
19
    /**
20
     * @desc IteratorFilter Constructor
21
     */
22
    public function __construct()
23
    {
24
        $this->_filters = array();
25
    }
26
27
    /**
28
     * @param
29
     * @return string - XPath String
30
     * @desc Get the XPATH string
31
     */
32
    public function getXPath()
33
    {
34
        $param = "";
35
        $xpathFilter = $this->getFilter(IteratorFilter::XPATH, $param);
36
37
        if ($xpathFilter == "") {
38
            return "/anydataset/row";
39
        } else {
40
            return "/anydataset/row[" . $xpathFilter . "]";
41
        }
42
    }
43
44
    /**
45
     * Get the SQL string
46
     *
47
     * @param string $tableName
48
     * @param array &$params
49
     * @param string $returnFields
50
     * @return string
51
     */
52
    public function getSql($tableName, &$params, $returnFields = "*")
53
    {
54
        $params = array();
55
56
        $sql = "select @@returnFields from @@tableName ";
57
        $sqlFilter = $this->getFilter(IteratorFilter::SQL, $params);
58
        if ($sqlFilter != "") {
59
            $sql .= " where @@sqlFilter ";
60
        }
61
62
        $sql = SQLHelper::createSafeSQL($sql,
63
                array(
64
                "@@returnFields" => $returnFields,
65
                "@@tableName" => $tableName,
66
                "@@sqlFilter" => $sqlFilter
67
        ));
68
69
        return $sql;
70
    }
71
72
    /**
73
     *
74
     * @param $array
75
     * @return SingleRow[]
76
     */
77
    public function match($array)
78
    {
79
        $returnArray = array();
80
81
        foreach ($array as $sr) {
82
            if ($this->evalString($sr)) {
83
                $returnArray[] = $sr;
84
            }
85
        }
86
87
        return $returnArray;
88
    }
89
90
    /**
91
     * Return a filter in SQL or XPATH
92
     *
93
     * @param string $type use XPATH or SQL
94
     * @param array $param
95
     * @return string
96
     */
97
    public function getFilter($type, &$param)
98
    {
99
        $filter = "";
100
        $param = array();
101
102
        $previousValue = null;
103
        foreach ($this->_filters as $value) {
104
            if ($value[0] == "(") {
105
                if (!is_null($previousValue)) {
106
                    $filter .= " or ( ";
107
                } else {
108
                    $filter .= " ( ";
109
                }
110
            } elseif ($value[0] == ")") {
111
                $filter .= ")";
112
            } else {
113
                if ((!is_null($previousValue)) && ($previousValue[0] != "(")) {
114
                    $filter .= $value[0];
115
                }
116
                if ($type == self::XPATH) {
117
                    $filter .= $this->getStrXpathRelation($value[1], $value[2], $value[3]);
118
                } elseif ($type == self::SQL) {
119
                    $filter .= $this->getStrSqlRelation($value[1], $value[2], $value[3], $param);
120
                }
121
            }
122
            $previousValue = $value;
123
        }
124
125
        return $filter;
126
    }
127
128
    /**
129
     * @param string $name Field name
130
     * @param int $relation Relation enum
131
     * @param string $value Field string value
132
     * @return string Xpath String
133
     * @desc Private method to get a Xpath string to a single string comparison
134
     */
135
    private function getStrXpathRelation($name, $relation, $value)
136
    {
137
        $str = is_numeric($value) ? "" : "'";
138
        $field = "field[@name='" . $name . "'] ";
139
        $value = " $str$value$str ";
140
141
        $result = "";
142
        switch ($relation) {
143
            case Relation::EQUAL: {
144
                    $result = $field . "=" . $value;
145
                    break;
146
                }
147
            case Relation::GREATER_THAN: {
148
                    $result = $field . ">" . $value;
149
                    break;
150
                }
151
            case Relation::LESS_THAN: {
152
                    $result = $field . "<" . $value;
153
                    break;
154
                }
155
            case Relation::GREATER_OR_EQUAL_THAN: {
156
                    $result = $field . ">=" . $value;
157
                    break;
158
                }
159
            case Relation::LESS_OR_EQUAL_THAN: {
160
                    $result = $field . "<=" . $value;
161
                    break;
162
                }
163
            case Relation::NOT_EQUAL: {
164
                    $result = $field . "!=" . $value;
165
                    break;
166
                }
167
            case Relation::STARTS_WITH: {
168
                    $result = " starts-with($field, $value) ";
169
                    break;
170
                }
171
            case Relation::CONTAINS: {
172
                    $result = " contains($field, $value) ";
173
                    break;
174
                }
175
        }
176
        return $result;
177
    }
178
179
    /**
180
     *
181
     * @param string $name
182
     * @param int $relation
183
     * @param string $value
184
     * @param string[] $param
185
     * @return string
186
     */
187
    private function getStrSqlRelation($name, $relation, $value, &$param)
188
    {
189
        $value = trim($value);
190
        $paramName = $name;
191
        $i = 0;
192
        while (array_key_exists($paramName, $param)) {
193
            $paramName = $name . ($i++);
194
        }
195
196
        $param[$paramName] = $value;
197
198
        $result = "";
199
        $field = " $name ";
200
        $valueparam = " [[" . $paramName . "]] ";
201
        switch ($relation) {
202
            case Relation::EQUAL: {
203
                    $result = $field . "=" . $valueparam;
204
                    break;
205
                }
206
            case Relation::GREATER_THAN: {
207
                    $result = $field . ">" . $valueparam;
208
                    break;
209
                }
210
            case Relation::LESS_THAN: {
211
                    $result = $field . "<" . $valueparam;
212
                    break;
213
                }
214
            case Relation::GREATER_OR_EQUAL_THAN: {
215
                    $result = $field . ">=" . $valueparam;
216
                    break;
217
                }
218
            case Relation::LESS_OR_EQUAL_THAN: {
219
                    $result = $field . "<=" . $valueparam;
220
                    break;
221
                }
222
            case Relation::NOT_EQUAL: {
223
                    $result = $field . "!=" . $valueparam;
224
                    break;
225
                }
226 View Code Duplication
            case Relation::STARTS_WITH: {
227
                    $param[$paramName] = $value . "%";
228
                    $result = $field . " like " . $valueparam;
229
                    break;
230
                }
231 View Code Duplication
            case Relation::CONTAINS: {
232
                    $param[$paramName] = "%" . $value . "%";
233
                    $result = $field . " like " . $valueparam;
234
                    break;
235
                }
236
        }
237
238
        return $result;
239
    }
240
241
    /**
242
     *
243
     * @param string[] $array
244
     * @return string
245
     */
246
    private function evalString($array)
247
    {
248
        $result = array();
249
        $finalResult = false;
250
        $pos = 0;
251
252
        $result[0] = true;
253
254
        foreach ($this->_filters as $filter) {
255
            if (($filter[0] == ")") || ($filter[0] == " or ")) {
256
                $finalResult |= $result[$pos];
257
                $result[++$pos] = true;
258
            }
259
260
            $name = $filter[1];
261
            $relation = $filter[2];
262
            $value = $filter[3];
263
264
            $field = $array->getField($name);
0 ignored issues
show
The method getField cannot be called on $array (of type array<integer,string>).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
265
266
            if (!is_array($field)) $field = array($field);
267
268
            foreach ($field as $valueparam) {
269
                switch ($relation) {
270
                    case Relation::EQUAL: {
271
                            $result[$pos] &= ($valueparam == $value);
272
                            break;
273
                        }
274
                    case Relation::GREATER_THAN: {
275
                            $result[$pos] &= ($valueparam > $value);
276
                            break;
277
                        }
278
                    case Relation::LESS_THAN: {
279
                            $result[$pos] &= ($valueparam < $value);
280
                            break;
281
                        }
282
                    case Relation::GREATER_OR_EQUAL_THAN: {
283
                            $result[$pos] &= ($valueparam >= $value);
284
                            break;
285
                        }
286
                    case Relation::LESS_OR_EQUAL_THAN: {
287
                            $result[$pos] &= ($valueparam <= $value);
288
                            break;
289
                        }
290
                    case Relation::NOT_EQUAL: {
291
                            $result[$pos] &= ($valueparam != $value);
292
                            break;
293
                        }
294
                    case Relation::STARTS_WITH: {
295
                            $result[$pos] &= (strpos($valueparam, $value) === 0);
296
                            break;
297
                        }
298
                    case Relation::CONTAINS: {
299
                            $result[$pos] &= (strpos($valueparam, $value) !== false);
300
                            break;
301
                        }
302
                }
303
            }
304
        }
305
306
        $finalResult |= $result[$pos];
307
308
        return $finalResult;
309
    }
310
311
    /**
312
     * @param string $name Field name
313
     * @param int $relation Relation enum
314
     * @param string $value Field string value
315
     * @return void
316
     * @desc Add a single string comparison to filter.
317
     */
318
    public function addRelation($name, $relation, $value)
319
    {
320
        $this->_filters[] = array(" and ", $name, $relation, $value);
321
    }
322
323
    /**
324
     * @param string $name Field name
325
     * @param int $relation Relation enum
326
     * @param string $value Field string value
327
     * @return void
328
     * @desc Add a single string comparison to filter. This comparison use the OR operator.
329
     */
330
    public function addRelationOr($name, $relation, $value)
331
    {
332
        $this->_filters[] = array(" or ", $name, $relation, $value);
333
    }
334
335
    /**
336
     * Add a "("
337
     *
338
     */
339
    public function startGroup()
340
    {
341
        $this->_filters[] = array("(", "", "", "");
342
    }
343
344
    /**
345
     * Add a ")"
346
     *
347
     */
348
    public function endGroup()
349
    {
350
        $this->_filters[] = array(")", "", "", "");
351
    }
352
}
353