Completed
Branch master (fea354)
by
unknown
02:42
created

QueryParametersParser::parse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 13
ccs 10
cts 10
cp 1
rs 9.4285
cc 1
eloc 9
nc 1
nop 1
crap 1
1
<?php namespace Neomerx\JsonApi\Http\Query;
2
3
/**
4
 * Copyright 2015 [email protected] (www.neomerx.com)
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use \Psr\Log\LoggerAwareTrait;
20
use \Psr\Log\LoggerAwareInterface;
21
use \Psr\Http\Message\ServerRequestInterface;
22
use \Neomerx\JsonApi\Exceptions\JsonApiException as E;
23
use \Neomerx\JsonApi\Contracts\Http\HttpFactoryInterface;
24
use \Neomerx\JsonApi\Contracts\Encoder\Parameters\SortParameterInterface;
25
use \Neomerx\JsonApi\Contracts\Http\Query\QueryParametersParserInterface;
26
27
/**
28
 * @package Neomerx\JsonApi
29
 */
30
class QueryParametersParser implements QueryParametersParserInterface, LoggerAwareInterface
31
{
32
    use LoggerAwareTrait;
33
34
    /**
35
     * @var HttpFactoryInterface
36
     */
37
    private $factory;
38
39
    /**
40
     * @param HttpFactoryInterface $factory
41
     */
42 23
    public function __construct(HttpFactoryInterface $factory)
43
    {
44 23
        $this->factory = $factory;
45 23
    }
46
47
    /**
48
     * @inheritdoc
49
     */
50 22
    public function parse(ServerRequestInterface $request)
51
    {
52 22
        $parameters = $request->getQueryParams();
53
54 22
        return $this->factory->createQueryParameters(
55 22
            $this->getIncludePaths($parameters),
0 ignored issues
show
Bug introduced by
It seems like $this->getIncludePaths($parameters) targeting Neomerx\JsonApi\Http\Que...rser::getIncludePaths() can also be of type array; however, Neomerx\JsonApi\Contract...createQueryParameters() does only seem to accept array<integer,string>|null, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
56 21
            $this->getFieldSets($parameters),
57 20
            $this->getSortParameters($parameters),
58 18
            $this->getPagingParameters($parameters),
59 17
            $this->getFilteringParameters($parameters),
60 16
            $this->getUnrecognizedParameters($parameters)
61 16
        );
62
    }
63
64
    /**
65
     * @param array $parameters
66
     *
67
     * @return array|null
68
     */
69 22
    private function getIncludePaths(array $parameters)
70
    {
71 22
        $paths  = $this->getStringParamOrNull($parameters, self::PARAM_INCLUDE);
72 21
        $result = empty($paths) === false ? explode(',', rtrim($paths, ',')) : null;
73
74 21
        return $result;
75
    }
76
77
    /**
78
     * @param array $parameters
79
     *
80
     * @return array|null
81
     */
82 21
    private function getFieldSets(array $parameters)
83
    {
84 21
        $result    = [];
85 21
        $fieldSets = $this->getParamOrNull($parameters, self::PARAM_FIELDS);
86 21
        if (empty($fieldSets) === false && is_array($fieldSets)) {
87 14
            foreach ($fieldSets as $type => $fields) {
88
                // We expect fields to be comma separated or empty strings. Multi-dimension arrays are not allowed.
89 14
                is_string($fields) ?: E::throwException(new E([], E::HTTP_CODE_BAD_REQUEST));
90 13
                $result[$type] = (empty($fields) === true ? [] : explode(',', $fields));
91 13
            }
92 13
        } else {
93 7
            $result = null;
94
        }
95
96 20
        return $result;
97
    }
98
99
    /**
100
     * @param array $parameters
101
     *
102
     * @return SortParameterInterface[]|null
103
     */
104 20
    protected function getSortParameters(array $parameters)
105
    {
106 20
        $sortParams = null;
107 20
        $sortParam  = $this->getStringParamOrNull($parameters, self::PARAM_SORT);
108 19
        if ($sortParam !== null) {
109 13
            foreach (explode(',', $sortParam) as $param) {
110 13
                $isDesc = false;
111 13
                empty($param) === false ?
112 13
                    $isDesc = ($param[0] === '-') : E::throwException(new E([], E::HTTP_CODE_BAD_REQUEST));
113 13
                $sortField = ltrim($param, '+-');
114 13
                empty($sortField) === false ?: E::throwException(new E([], E::HTTP_CODE_BAD_REQUEST));
115 13
                $sortParams[] = $this->factory->createSortParam($sortField, $isDesc === false);
116 13
            }
117 12
        }
118 18
        return $sortParams;
119
    }
120
121
    /**
122
     * @param array $parameters
123
     *
124
     * @return array|null
125
     */
126 18
    private function getPagingParameters(array $parameters)
127
    {
128 18
        return $this->getArrayParamOrNull($parameters, self::PARAM_PAGE);
129
    }
130
131
    /**
132
     * @param array $parameters
133
     *
134
     * @return array|null
135
     */
136 17
    private function getFilteringParameters(array $parameters)
137
    {
138 17
        return $this->getArrayParamOrNull($parameters, self::PARAM_FILTER);
139
    }
140
141
    /**
142
     * @param array $parameters
143
     *
144
     * @return array|null
145
     */
146 16
    private function getUnrecognizedParameters(array $parameters)
147
    {
148
        $supported = [
149 16
            self::PARAM_INCLUDE => 0,
150 16
            self::PARAM_FIELDS  => 0,
151 16
            self::PARAM_PAGE    => 0,
152 16
            self::PARAM_FILTER  => 0,
153 16
            self::PARAM_SORT    => 0,
154 16
        ];
155 16
        $unrecognized = array_diff_key($parameters, $supported);
156 16
        return empty($unrecognized) === true ? null : $unrecognized;
157
    }
158
159
    /**
160
     * @param array $parameters
161
     * @param string $name
162
     *
163
     * @return array|null
164
     */
165 18
    private function getArrayParamOrNull(array $parameters, $name)
166
    {
167 18
        $value = $this->getParamOrNull($parameters, $name);
168
169 18
        $isArrayOrNull = ($value === null || is_array($value) === true);
170 18
        $isArrayOrNull === true ?: E::throwException(new E([], E::HTTP_CODE_BAD_REQUEST));
171
172 17
        return $value;
173
    }
174
175
    /**
176
     * @param array $parameters
177
     * @param string $name
178
     *
179
     * @return string|null
180
     */
181 22
    private function getStringParamOrNull(array $parameters, $name)
182
    {
183 22
        $value = $this->getParamOrNull($parameters, $name);
184
185 22
        $isStringOrNull = ($value === null || is_string($value) === true);
186 22
        $isStringOrNull === true ?: E::throwException(new E([], E::HTTP_CODE_BAD_REQUEST));
187
188 21
        return $value;
189
    }
190
191
    /**
192
     * @param array  $parameters
193
     * @param string $name
194
     *
195
     * @return mixed
196
     */
197 22
    private function getParamOrNull(array $parameters, $name)
198
    {
199 22
        return isset($parameters[$name]) === true ? $parameters[$name] : null;
200
    }
201
}
202