Completed
Push — master ( d36be2...7f9690 )
by Phil
8s
created

QueryStringParserTrait   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 98.55%

Importance

Changes 9
Bugs 1 Features 1
Metric Value
wmc 22
c 9
b 1
f 1
lcom 1
cbo 0
dl 0
loc 150
ccs 68
cts 69
cp 0.9855
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A parseQueryString() 0 19 4
B filterQueryParams() 0 20 8
A parseSort() 0 21 4
A parseSearch() 0 15 2
B parseFilters() 0 31 4
1
<?php
2
3
namespace Percy\Http;
4
5
use InvalidArgumentException;
6
7
trait QueryStringParserTrait
8
{
9
    /**
10
     * Parse HTTP query string and return array representation
11
     * to be attached to a database query.
12
     *
13
     * @param string $query
14
     *
15
     * @return array
16
     */
17 15
    public function parseQueryString($query)
18
    {
19 15
        if (empty($query)) {
20 1
            return [];
21
        }
22
23 14
        parse_str($query, $split);
24
25 14
        $query = [];
26
27 14
        while (list($key, $value) = each($split)) {
28 14
            $mapped = call_user_func_array([$this, 'filterQueryParams'], [$key, $value]);
29 11
            if ($mapped !== false) {
30 10
                $query[$key] = $mapped;
31 10
            }
32 11
        }
33
34 11
        return $query;
35
    }
36
37
    /**
38
     * Map the parsed query string in to correct array structure.
39
     *
40
     * @param string $key
41
     * @param mixed  $value
42
     *
43
     * @return array|boolean
44
     */
45 14
    protected function filterQueryParams($key, $value)
46
    {
47
        switch ($key) {
48 14
            case 'limit':
49 14
            case 'offset':
50 1
                return (int) $value;
51 14
            case 'sort':
52 5
                return $this->parseSort($value);
53 13
            case 'filter':
54 10
                return $this->parseFilters((array) $value);
55 5
            case 'has':
56
                return explode(',', $value);
57 5
            case 'search':
58 4
                return $this->parseSearch($value);
59 4
            case 'minscore':
60 3
                return (float) $value;
61 1
            default:
62 1
                return false;
63 1
        }
64
    }
65
66
    /**
67
     * Map sorts to a usable format.
68
     *
69
     * @param string $value
70
     *
71
     * @return array
72
     */
73 5
    protected function parseSort($value)
74
    {
75 5
        $map   = [];
76 5
        $sorts = explode(',', $value);
77
78 5
        foreach ($sorts as $sort) {
79 5
            $sort      = explode('|', $sort);
80 5
            $direction = (count($sort) > 1) ? $sort[1] : 'asc';
81
82 5
            if (in_array($sort[0], ['rand', 'random'])) {
83 2
                return 'RAND()';
84
            }
85
86 4
            $map[] = [
87 4
                'field'     => $sort[0],
88
                'direction' => $direction
89 4
            ];
90 4
        }
91
92 4
        return $map;
93
    }
94
95
    /**
96
     * Map search to a usable format.
97
     *
98
     * @param string $value
99
     *
100
     * @return array
101
     */
102 4
    protected function parseSearch($value)
103
    {
104 4
        $search = explode('|', $value);
105
106 4
        if (count($search) !== 2) {
107 1
            throw new InvalidArgumentException(
108
                'Malformed query string, search format should be (search=field|term) or (search=field1,field2|term)'
109 1
            );
110
        }
111
112
        return [
113 3
            'fields' => $search[0],
114 3
            'term'   => $search[1]
115 3
        ];
116
    }
117
118
    /**
119
     * Map filters in to useable array.
120
     *
121
     * @param array $filters
122
     *
123
     * @return array
124
     */
125 10
    protected function parseFilters(array $filters)
126
    {
127 10
        $mapped = [];
128 10
        $param  = 0;
129
130 10
        foreach ($filters as $filter) {
131 10
            $filter = explode('|', $filter);
132
133 10
            if (count($filter) !== 3) {
134 1
                throw new InvalidArgumentException(
135
                    'Malformed query string, filter format should be (filter[]=field|delimiter|value)'
136 1
                );
137
            }
138
139 9
            $filter = array_combine(['field', 'delimiter', 'value'], $filter);
140
141 9
            $filter['binding']   = str_replace('.', '_', $filter['field']) . '_' . $param++;
142 9
            $filter['delimiter'] = strtolower($filter['delimiter']);
143 9
            $filter['delimiter'] = html_entity_decode($filter['delimiter']);
144
145 9
            if (! in_array($filter['delimiter'], [
146 9
                '=', '!=', '<>', '<=', '>=', '<', '>', 'in', 'not in', 'like', 'not like'
147 9
            ])) {
148 2
                throw new InvalidArgumentException(sprintf('(%s) is not an accepted delimiter', $filter['delimiter']));
149
            }
150
151 8
            $mapped[] = $filter;
152 8
        }
153
154 8
        return $mapped;
155
    }
156
}
157