Completed
Branch master (ffe81d)
by Neomerx
04:33
created

BaseQueryParser::splitString()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 5
nc 3
nop 3
dl 0
loc 10
ccs 6
cts 6
cp 1
crap 4
rs 9.2
c 0
b 0
f 0
1
<?php namespace Neomerx\JsonApi\Http\Query;
2
3
/**
4
 * Copyright 2015-2018 [email protected]
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 Neomerx\JsonApi\Contracts\Http\Query\BaseQueryParserInterface;
20
use Neomerx\JsonApi\Document\Error;
21
use Neomerx\JsonApi\Exceptions\JsonApiException;
22
23
/**
24
 * @package Neomerx\JsonApi
25
 */
26
class BaseQueryParser implements BaseQueryParserInterface
27
{
28
    /** Message */
29
    public const MSG_ERR_INVALID_PARAMETER = 'Invalid Parameter.';
30
31
    /**
32
     * @var array
33
     */
34
    private $parameters;
35
36
    /**
37
     * @var string[]|null
38
     */
39
    private $messages;
40
41
    /**
42
     * @param array         $parameters
43
     * @param string[]|null $messages
44
     */
45 12
    public function __construct(array $parameters = [], array $messages = null)
46
    {
47 12
        $this->setParameters($parameters);
48 12
        $this->messages = $messages;
49 12
    }
50
51
    /**
52
     * @param array $parameters
53
     *
54
     * @return self
55
     */
56 12
    public function setParameters(array $parameters): self
57
    {
58 12
        $this->parameters = $parameters;
59
60 12
        return $this;
61
    }
62
63
    /**
64
     * @inheritdoc
65
     */
66 9
    public function getIncludes(): iterable
67
    {
68 9
        if (array_key_exists(static::PARAM_INCLUDE, $this->getParameters()) === true) {
69 8
            $splitByDot = function (string $path): iterable {
70 4
                foreach ($this->splitStringAndCheckNoEmpties(static::PARAM_INCLUDE, $path, '.') as $link) {
71 4
                    yield $link;
72
                }
73 8
            };
74
75 8
            $includes = $this->getParameters()[static::PARAM_INCLUDE];
76 8
            foreach ($this->splitCommaSeparatedStringAndCheckNoEmpties(static::PARAM_INCLUDE, $includes) as $path) {
77 4
                yield $path => $splitByDot($path);
78
            }
79
        }
80 4
    }
81
82
    /**
83
     * @inheritdoc
84
     */
85 3
    public function getFields(): iterable
86
    {
87 3
        if (array_key_exists(static::PARAM_FIELDS, $this->getParameters()) === true) {
88 2
            $fields = $this->getParameters()[static::PARAM_FIELDS];
89 2
            if (is_array($fields) === false || empty($fields) === true) {
90 1
                throw new JsonApiException($this->createParameterError(static::PARAM_FIELDS));
91
            }
92
93 1
            foreach ($fields as $type => $fieldList) {
94 1
                yield $type => $this->splitCommaSeparatedStringAndCheckNoEmpties($type, $fieldList);
95
            }
96
        }
97 2
    }
98
99
    /**
100
     * @inheritdoc
101
     */
102 1
    public function getSorts(): iterable
103
    {
104 1
        if (array_key_exists(static::PARAM_SORT, $this->getParameters()) === true) {
105 1
            $sorts = $this->getParameters()[static::PARAM_SORT];
106 1
            foreach ($this->splitCommaSeparatedStringAndCheckNoEmpties(static::PARAM_SORT, $sorts) as $orderAndField) {
107 1
                switch ($orderAndField[0]) {
108 1
                    case '-':
109 1
                        $isAsc = false;
110 1
                        $field = substr($orderAndField, 1);
111 1
                        break;
112 1
                    case '+':
113 1
                        $isAsc = true;
114 1
                        $field = substr($orderAndField, 1);
115 1
                        break;
116
                    default:
117 1
                        $isAsc = true;
118 1
                        $field = $orderAndField;
119 1
                        break;
120
                }
121
122 1
                yield $field => $isAsc;
123
            }
124
        }
125 1
    }
126
127
    /**
128
     * @param string       $paramName
129
     * @param string|mixed $shouldBeString
130
     * @param string       $separator
131
     *
132
     * @return iterable
133
     */
134 10
    protected function splitString(string $paramName, $shouldBeString, string $separator): iterable
135
    {
136 10
        if (is_string($shouldBeString) === false || ($trimmed = trim($shouldBeString)) === '') {
137 4
            throw new JsonApiException($this->createParameterError($paramName));
138
        }
139
140 6
        foreach (explode($separator, $trimmed) as $value) {
141 6
            yield $value;
142
        }
143 6
    }
144
145
    /**
146
     * @param string       $paramName
147
     * @param string|mixed $shouldBeString
148
     * @param string       $separator
149
     *
150
     * @return iterable
151
     */
152 10
    protected function splitStringAndCheckNoEmpties(string $paramName, $shouldBeString, string $separator): iterable
153
    {
154 10
        foreach ($this->splitString($paramName, $shouldBeString, $separator) as $value) {
155 6
            $trimmedValue = trim($value);
156 6
            if (($trimmedValue) === '') {
157 1
                throw new JsonApiException($this->createParameterError($paramName));
158
            }
159
160 6
            yield $trimmedValue;
161
        }
162 6
    }
163
164
    /**
165
     * @param string       $paramName
166
     * @param string|mixed $shouldBeString
167
     *
168
     * @return iterable
169
     */
170 10
    protected function splitCommaSeparatedStringAndCheckNoEmpties(string $paramName, $shouldBeString): iterable
171
    {
172 10
        return $this->splitStringAndCheckNoEmpties($paramName, $shouldBeString, ',');
173
    }
174
175
    /**
176
     * @return array
177
     */
178 12
    protected function getParameters(): array
179
    {
180 12
        return $this->parameters;
181
    }
182
183
    /**
184
     * @param string $parameterName
185
     *
186
     * @return Error
187
     */
188 6
    protected function createParameterError(string $parameterName): Error
189
    {
190 6
        return $this->createQueryError($parameterName, static::MSG_ERR_INVALID_PARAMETER);
191
    }
192
193
    /**
194
     * @param string $name
195
     * @param string $title
196
     *
197
     * @return Error
198
     */
199 6
    protected function createQueryError(string $name, string $title): Error
200
    {
201 6
        $title  = $this->getMessage($title);
202 6
        $source = [Error::SOURCE_PARAMETER => $name];
203 6
        $error  = new Error(null, null, null, null, $title, null, $source);
204
205 6
        return $error;
206
    }
207
208
    /**
209
     * @param string $message
210
     *
211
     * @return string
212
     */
213 6
    protected function getMessage(string $message): string
214
    {
215 6
        $hasTranslation = $this->messages !== null && array_key_exists($message, $this->messages) === false;
216
217 6
        return $hasTranslation === true ? $this->messages[$message] : $message;
218
    }
219
}
220