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