Completed
Push — master ( a10c95...1963b4 )
by Shcherbak
105:51 queued 90:49
created

Query   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 294
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 30
lcom 1
cbo 3
dl 0
loc 294
ccs 81
cts 81
cp 1
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 3 1
A typeIs() 0 10 1
A typeNot() 0 10 1
A valueIs() 0 9 1
A valueNot() 0 10 1
B valueLike() 0 24 5
A indexIs() 0 10 1
A indexNot() 0 9 1
A indexGt() 0 10 1
A indexLt() 0 9 1
A isValid() 0 17 4
B prepareValues() 0 21 6
B prepareIntValues() 0 21 5
A custom() 0 4 1
1
<?php
2
3
  declare(strict_types = 1);
4
5
  namespace Funivan\PhpTokenizer\Query;
6
7
  use Funivan\PhpTokenizer\Exception\Exception;
8
  use Funivan\PhpTokenizer\Exception\InvalidArgumentException;
9
  use Funivan\PhpTokenizer\Token;
10
11
  /**
12
   * @author Ivan Shcherbak <[email protected]>
13
   */
14
  class Query implements QueryInterface {
15
16
17
    /**
18
     * Array of check functions
19
     * As first argument accept token
20
     * Return boolean
21
     *
22
     * @var callable[]
23
     */
24
    protected $checkFunctions = [];
25
26
    /**
27
     * Storage of type conditions
28
     *
29
     * @var array
30
     */
31
    protected $type = [];
32
33
    /**
34
     * Storage of conditions conditions
35
     *
36
     * @var array
37
     */
38
    protected $value = [];
39
40
    /**
41
     * Storage of line conditions
42
     *
43
     * @var array
44
     */
45
    protected $line = [];
46
47
    /**
48
     * Storage of index conditions
49
     *
50
     * @var array
51
     */
52
    protected $index = [];
53
54
55
    /**
56
     * @return static
57 357
     */
58 357
    public static function create() {
59
      return new static();
60
    }
61
62
63
    /**
64
     * @param int|array $type Array<Int>|Int
65
     * @return $this
66 216
     */
67
    public function typeIs($type) {
68 216
69
      $types = $this->prepareIntValues($type);
70
71 216
      $this->checkFunctions[] = function (Token $token) use ($types) {
72
        return in_array($token->getType(), $types, true);
73
      };
74 210
75
      return $this;
76
    }
77
78
79
    /**
80
     * @param array|int $type Array<Int>|Int
81
     * @return $this
82 3
     */
83
    public function typeNot($type) {
84 3
85
      $types = $this->prepareIntValues($type);
86
87 3
      $this->checkFunctions[] = function (Token $token) use ($types) {
88
        return !in_array($token->getType(), $types, true);
89
      };
90 3
91
      return $this;
92
    }
93
94
95
    /**
96
     * @param array|string $value Array<String>|String
97
     * @return $this
98 306
     */
99 306
    public function valueIs($value) {
100
      $values = $this->prepareValues($value);
101
102 306
      $this->checkFunctions[] = function (Token $token) use ($values) {
103
        return in_array($token->getValue(), $values, true);
104
      };
105 306
106
      return $this;
107
    }
108
109
110
    /**
111
     * @param array|string $value Array<String>|String
112
     * @return $this
113 9
     */
114
    public function valueNot($value) {
115 9
116
      $values = $this->prepareValues($value);
117
118 3
      $this->checkFunctions[] = function (Token $token) use ($values) {
119
        return !in_array($token->getValue(), $values, true);
120
      };
121 3
122
      return $this;
123
    }
124
125
126
    /**
127
     * @param string[]|string $regex string[]
128
     * @return $this
129 99
     */
130 99
    public function valueLike($regex) {
131
      $regexConditions = $this->prepareValues($regex);
132
133 96
      $this->checkFunctions[] = function (Token $token) use ($regexConditions) {
134 3
        if (empty($regexConditions)) {
135
          return false;
136
        }
137 96
138
        $value = $token->getValue();
139 96
140 96
        if ($value === null) {
141 44
          return false;
142
        }
143 64
        foreach ($regexConditions as $regex) {
144
          if (!preg_match($regex, $value)) {
145 96
            return false;
146
          }
147
        }
148 99
149
        return true;
150
      };
151
152
      return $this;
153
    }
154
155
156 9
    /**
157
     * @param int|int[] $index
158 9
     * @return $this
159
     */
160
    public function indexIs($index) {
161 9
162
      $indexNumbers = $this->prepareIntValues($index);
163
164 9
      $this->checkFunctions[] = function (Token $token) use ($indexNumbers) {
165
        return in_array($token->getIndex(), $indexNumbers, true);
166
      };
167
168
      return $this;
169
    }
170
171
172 3
    /**
173 3
     * @param int|int[] $index
174
     * @return $this
175
     */
176 3
    public function indexNot($index) {
177
      $indexNumbers = $this->prepareIntValues($index);
178
179 3
      $this->checkFunctions[] = function (Token $token) use ($indexNumbers) {
180
        return !in_array($token->getIndex(), $indexNumbers, true);
181
      };
182
183
      return $this;
184
    }
185
186
187 3
    /**
188 3
     * @param int|int[] $index
189
     * @return $this
190
     */
191 3
    public function indexGt($index) {
192
      $indexNumbers = $this->prepareIntValues($index);
193
194
      $this->checkFunctions[] = function (Token $token) use ($indexNumbers) {
195 3
        return ($token->getIndex() > max($indexNumbers));
196
      };
197
198
199
      return $this;
200
    }
201
202
203 3
    /**
204 3
     * @param int|int[] $index
205
     * @return $this
206 3
     */
207 3
    public function indexLt($index) {
208
      $indexNumbers = $this->prepareIntValues($index);
209
210 3
      $this->checkFunctions[] = function (Token $token) use ($indexNumbers) {
211
        return ($token->getIndex() < min($indexNumbers));
212
      };
213
214
      return $this;
215
    }
216
217 366
218
    /**
219 366
     * @inheritdoc
220
     */
221 363
    public function isValid(\Funivan\PhpTokenizer\Token $token) {
222 363
223 3
      foreach ($this->checkFunctions as $check) {
224
225
        $result = $check($token);
226 360
        if (!is_bool($result)) {
227 348
          throw new Exception('Check function should return boolean value. Given:' . gettype($result));
228
        }
229
230 224
        if ($result === false) {
231
          return false;
232 330
        }
233
234
      }
235
236
      return true;
237
    }
238
239
240
    /**
241 318
     * @param string|int|array $value String|Int|Array<String>|Array<Int>
242
     * @return array Array<String>
243 318
     * @throws \Exception
244 33
     */
245
    protected function prepareValues($value) {
246
247 309
      if ($value === null) {
248 3
        return [];
249
      }
250
251 306
      if (is_object($value)) {
252
        throw new InvalidArgumentException('Invalid conditions. Must be string or array of string');
253 306
      }
254 306
255 3
      $value = array_values((array) $value);
256
257
      foreach ($value as $k => $val) {
258 303
        if (!is_string($val) and !is_numeric($val)) {
259 202
          throw new InvalidArgumentException('Invalid conditions. Must be string');
260 303
        }
261
262
        $value[$k] = (string) $val;
263
      }
264
      return $value;
265
    }
266
267
268
    /**
269 234
     * @param array|int $value Array<Int>|Int
270
     * @return array
271 234
     * @throws \Exception
272 3
     */
273
    protected function prepareIntValues($value) {
274
275 231
      if ($value === null) {
276 3
        return [];
277
      }
278
279 228
      if (is_object($value)) {
280
        throw new InvalidArgumentException('Invalid condition value. Must be int. Object given');
281
      }
282 228
283 228
      $value = array_values((array) $value);
284 78
285
286 150
      foreach ($value as $intValue) {
287
        if (!is_int($intValue)) {
288 225
          throw new InvalidArgumentException('Invalid conditions. Must be integer. Given:' . gettype($intValue));
289
        }
290
      }
291
292
      return $value;
293
    }
294
295
296
    /**
297
     * Under development
298 6
     *
299 6
     * @param callable $checkFunction
300 6
     * @return $this
301
     */
302
    public function custom(callable $checkFunction) {
303
      $this->checkFunctions[] = $checkFunction;
304
      return $this;
305
    }
306
307
  }