Completed
Pull Request — master (#30)
by Phil
02:04
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 1
Bugs 0 Features 0
Metric Value
c 1
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_direction':
52 1
                return strtoupper($value);
53 10
            case 'sort':
54 7
                return $value;
55 10
            case 'filter':
56 9
                $filters = $this->parseFilters((array) $value);
57 7
                return (empty($filters)) ? false : $filters;
58 1
            case 'search':
59
                $search = $this->parseSearch($value);
60
                return (empty($search)) ? false : $search;
61 1
            case 'minscore':
62
                return (float) $value;
63 1
            default:
64 1
                return false;
65 1
        }
66
    }
67
68
    /**
69
     * Map search to a usable format.
70
     *
71
     * @param string $value
72
     *
73
     * @return array
74
     */
75
    protected function parseSearch($value)
76
    {
77
        $search = explode('|', $value);
78
79
        if (count($search) !== 2) {
80
            throw new InvalidArgumentException(
81
                'Malformed query string, search format should be (search=column|term) or (search=column1,column2|term)'
82
            );
83
        }
84
85
        return [
86
            'columns' => $search[0],
87
            'term'    => $search[1]
88
        ];
89
    }
90
91
    /**
92
     * Map filters in to useable array.
93
     *
94
     * @param array $filters
95
     *
96
     * @return array
97
     */
98 9
    protected function parseFilters(array $filters)
99
    {
100 9
        $mapped = [];
101 9
        $param  = 0;
102
103 9
        foreach ($filters as $filter) {
104 9
            $filter = explode('|', $filter);
105
106 9
            if (count($filter) !== 3) {
107 1
                throw new InvalidArgumentException(
108
                    'Malformed query string, filter format should be (filter[]=field|delimiter|value)'
109 1
                );
110
            }
111
112 8
            $filter = array_combine(['field', 'delimiter', 'value'], $filter);
113
114 8
            $filter['binding']   = str_replace('.', '_', $filter['field']) . '_' . $param++;
115 8
            $filter['delimiter'] = strtolower($filter['delimiter']);
116 8
            $filter['delimiter'] = html_entity_decode($filter['delimiter']);
117
118 8
            if (! in_array($filter['delimiter'], [
119 8
                '=', '!=', '<>', '<=', '>=', '<', '>', 'in', 'not in', 'like', 'not like'
120 8
            ])) {
121 1
                throw new InvalidArgumentException(sprintf('(%s) is not an accepted delimiter', $filter['delimiter']));
122
            }
123
124 7
            $mapped[] = $filter;
125 7
        }
126
127 7
        return $mapped;
128
    }
129
}
130