Completed
Pull Request — master (#30)
by Phil
04:28
created

QueryStringParserTrait::parseSearch()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 15
ccs 0
cts 8
cp 0
rs 9.4285
cc 2
eloc 8
nc 2
nop 1
crap 6
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 11
    public function parseQueryString($query)
18
    {
19 11
        if (empty($query)) {
20 1
            return [];
21
        }
22
23 10
        parse_str($query, $split);
24
25 10
        $query = [];
26
27 10
        while (list($key, $value) = each($split)) {
28 10
            $mapped = call_user_func_array([$this, 'filterQueryParams'], [$key, $value]);
29 8
            if ($mapped !== false) {
30 7
                $query[$key] = $mapped;
31 7
            }
32 8
        }
33
34 8
        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 10
    protected function filterQueryParams($key, $value)
46
    {
47
        switch ($key) {
48 10
            case 'limit':
49 10
            case 'offset':
50 1
                return (int) $value;
51 10
            case 'sort':
52 3
                return $this->parseSort($value);
53 10
            case 'filter':
54 9
                return $this->parseFilters((array) $value);
55 1
            case 'search':
56
                return $this->parseSearch($value);
57 1
            case 'minscore':
58
                return (float) $value;
59 1
            default:
60 1
                return false;
61 1
        }
62
    }
63
64
    /**
65
     * Map sorts to a usable format.
66
     *
67
     * @param string $value
68
     *
69
     * @return array
70
     */
71 3
    protected function parseSort($value)
72
    {
73 3
        $map   = [];
74 3
        $sorts = explode(',', $value);
75
76 3
        foreach ($sorts as $sort) {
77 3
            $sort      = explode('|', $sort);
78 3
            $direction = (count($sort) > 1) ? $sort[1] : 'asc';
79
80 3
            if (in_array($sort[0], ['rand', 'random'])) {
81
                return 'RAND()';
82
            }
83
84 3
            $map[] = [
85 3
                'field'     => $sort[0],
86
                'direction' => $direction
87 3
            ];
88 3
        }
89
90 3
        return $map;
91
    }
92
93
    /**
94
     * Map search to a usable format.
95
     *
96
     * @param string $value
97
     *
98
     * @return array
99
     */
100
    protected function parseSearch($value)
101
    {
102
        $search = explode('|', $value);
103
104
        if (count($search) !== 2) {
105
            throw new InvalidArgumentException(
106
                'Malformed query string, search format should be (search=field|term) or (search=field1,field2|term)'
107
            );
108
        }
109
110
        return [
111
            'fields' => $search[0],
112
            'term'   => $search[1]
113
        ];
114
    }
115
116
    /**
117
     * Map filters in to useable array.
118
     *
119
     * @param array $filters
120
     *
121
     * @return array
122
     */
123 9
    protected function parseFilters(array $filters)
124
    {
125 9
        $mapped = [];
126 9
        $param  = 0;
127
128 9
        foreach ($filters as $filter) {
129 9
            $filter = explode('|', $filter);
130
131 9
            if (count($filter) !== 3) {
132 1
                throw new InvalidArgumentException(
133
                    'Malformed query string, filter format should be (filter[]=field|delimiter|value)'
134 1
                );
135
            }
136
137 8
            $filter = array_combine(['field', 'delimiter', 'value'], $filter);
138
139 8
            $filter['binding']   = str_replace('.', '_', $filter['field']) . '_' . $param++;
140 8
            $filter['delimiter'] = strtolower($filter['delimiter']);
141 8
            $filter['delimiter'] = html_entity_decode($filter['delimiter']);
142
143 8
            if (! in_array($filter['delimiter'], [
144 8
                '=', '!=', '<>', '<=', '>=', '<', '>', 'in', 'not in', 'like', 'not like'
145 8
            ])) {
146 1
                throw new InvalidArgumentException(sprintf('(%s) is not an accepted delimiter', $filter['delimiter']));
147
            }
148
149 7
            $mapped[] = $filter;
150 7
        }
151
152 7
        return $mapped;
153
    }
154
}
155