Passed
Push — master ( 053352...f82a54 )
by Sebastian
02:59
created

Parser::strtonum()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 7
ccs 3
cts 4
cp 0.75
crap 2.0625
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Linna Filter
5
 *
6
 * @author Sebastian Rapetti <[email protected]>
7
 * @copyright (c) 2018, Sebastian Rapetti
8
 * @license http://opensource.org/licenses/MIT MIT License
9
 */
10
declare(strict_types = 1);
11
12
namespace Linna\Filter;
13
14
use Linna\Filter\Rules\Number;
15
use OutOfBoundsException;
16
17
/**
18
 * Parser
19
 */
20
class Parser
21
{
22
    /**
23
     * @var array Parsing rules.
24
     */
25
    private $rules;
26
    
27
    /**
28
     * Parser.
29
     *
30
     * @param array $array
31
     */
32 68
    public function parse(array $array, array $rules): array
33
    {
34 68
        $this->rules = $rules;
35
        
36 68
        $this->extractParams($array);
37 61
        $this->applyTypes($array);
38 61
        $this->normalizeParam($array);
39
        
40 61
        return $array;
41
    }
42
    
43
    /**
44
     * Separate keywords from parameters.
45
     *
46
     * @param array $words
47
     */
48 68
    private function extractParams(array &$words): void
49
    {
50 68
        $array = [];
51 68
        $actualWord = '';
52 68
        $field = $words[0];
53 68
        $count = count($words);
54
55 68
        $arguments = -1;
56
        
57 68
        for ($i = 1; $i < $count; $i++) {
58 68
            $word = strtolower($words[$i]);
59
60 68
            if (isset($this->rules[$word])) {
61 64
                $arguments = $this->rules[$word]['args_count'];
62 64
                $actualWord = $word;
63 64
                $array[$field][$word] = [];
64 64
                continue;
65
            }
66
67 48
            if (--$arguments < 0) {
68 7
                throw new OutOfBoundsException("{$word} isn't a valid filter");
69
            }
70
71 41
            $array[$field][$actualWord][] = $words[$i];
72
        }
73
74 61
        $words = $array;
75 61
    }
76
    
77
    /**
78
     * Apply types to rules parameters.
79
     *
80
     * @param array $words
81
     */
82 61
    private function applyTypes(array &$words): void
83
    {
84 61
        $rules = $this->rules;
85 61
        $field = key($words);
86
87 61
        foreach ($words[$field] as $key => $word) {
88 61
            $rule = $rules[$key];
89 61
            $keyword = $rule['keyword'];
90
            
91
            //first param passed as reference
92 61
            $this->castTypes($words[$field][$keyword], $rule['args_type']);
93
        }
94 61
    }
95
    
96
    /**
97
     * Organize rules' array.
98
     *
99
     * @param array $words
100
     */
101 61
    private function normalizeParam(array &$words): void
102
    {
103 61
        $field = array_keys($words)[0];
104 61
        $temp = [];
105
106 61
        foreach ($words[$field] as $key => $word) {
107 61
            if (count($word) === 0) {
108 25
                $words[$field][$key] = true;
109
            }
110
111 61
            if (count($word) === 1) {
112 30
                $words[$field][$key] = $word[0];
113
            }
114
115 61
            $temp[] = [$field, $key, $this->rules[$key], $words[$field][$key]];
116
        }
117
118 61
        $words = $temp;
119 61
    }
120
121
    /**
122
     * Apply types when there is one parameter.
123
     *
124
     * @param array $params
125
     * @param array $types
126
     */
127 61
    private function castTypes(array &$params, array $types): void
128
    {
129 61
        $number = new Number();
130 61
        $count = count($params);
131
132 61
        for ($i = 0; $i < $count; $i++) {
133 41
            $type = &$types[$i];
134 41
            $param = &$params[$i];
135
            
136 41
            if ($type === 'number') {
137 35
                $number->sanitize($param);
138 35
                continue;
139
            }
140
141 8
            settype($param, $type);
142
        }
143 61
    }
144
}
145