Passed
Pull Request — 1.x (#250)
by Akihito
02:55 queued 01:31
created

AbstractRequest::__serialize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource;
6
7
use ArrayAccess;
8
use ArrayIterator;
9
use BEAR\Resource\Exception\MethodException;
10
use BEAR\Resource\Exception\OutOfBoundsException;
11
use IteratorAggregate;
12
use JsonSerializable;
13
use LogicException;
14
use ReturnTypeWillChange;
15
use Serializable;
16
use Throwable;
17
18
use function array_merge;
19
use function assert;
20
use function get_class;
21
use function in_array;
22
use function is_array;
23
use function md5;
24
use function serialize;
25
use function strtolower;
26
use function trigger_error;
27
28
use const E_USER_ERROR;
29
use const PHP_EOL;
30
31
/**
32
 * @property int    $code
33
 * @property array  $headers
34
 * @property mixed  $body
35
 * @property string $view
36
 * @phpstan-implements IteratorAggregate<string, mixed>
37
 * @phpstan-implements ArrayAccess<string, mixed>
38
 * @psalm-suppress PropertyNotSetInConstructor
39
 */
40
abstract class AbstractRequest implements RequestInterface, ArrayAccess, IteratorAggregate, JsonSerializable, Serializable
41
{
42
    /**
43
     * URI
44
     *
45
     * @var string
46
     */
47
    public $uri;
48
49
    /**
50
     * Method
51
     *
52
     * @var string
53
     */
54
    public $method = '';
55
56
    /**
57
     * Query
58
     *
59
     * @var array<string, mixed>
60
     */
61
    public $query = [];
62
63
    /**
64
     * Options
65
     *
66
     * @var array<mixed>
67
     */
68
    public $options = [];
69
70
    /**
71
     * Request option (eager or lazy)
72
     *
73
     * @var 'eager'|'lazy'
0 ignored issues
show
Documentation Bug introduced by
The doc comment 'eager'|'lazy' at position 0 could not be parsed: Unknown type name ''eager'' at position 0 in 'eager'|'lazy'.
Loading history...
74
     */
75
    public $in = 'lazy'; // phpcs:ignore SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingAnyTypeHint
76
77
    /**
78
     * Links
79
     *
80
     * @var LinkType[]
81
     */
82
    public $links = [];
83
84
    /** @var ResourceObject */
85
    public $resourceObject;
86
87
    /**
88
     * Request Result
89
     *
90
     * @var ?ResourceObject
91
     */
92
    protected $result;
93
94
    /** @var InvokerInterface */
95
    protected $invoker;
96
97
    /** @var ?LinkerInterface */
98
    private $linker;
99 91
100
    /**
101
     * @param array<string, mixed> $query
102
     * @param list<LinkType>       $links
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
103
     *
104
     * @throws MethodException
105
     */
106
    public function __construct(
107 91
        InvokerInterface $invoker,
108 91
        ResourceObject $ro,
109 91
        string $method = Request::GET,
110 1
        array $query = [],
111
        array $links = [],
112 91
        ?LinkerInterface $linker = null
113 91
    ) {
114 91
        $this->invoker = $invoker;
115 91
        $this->resourceObject = $ro;
116 91
        if (! in_array(strtolower($method), ['get', 'post', 'put', 'patch', 'delete', 'head', 'options'], true)) {
117
            throw new MethodException($method, 400);
118 6
        }
119
120
        $this->method = $method;
121 6
        $this->query = $query;
122
        $this->links = $links;
123 5
        $this->linker = $linker;
124 1
    }
125 1
126
    public function __toString(): string
127 1
    {
128
        try {
129
            $this->invoke();
130
131
            return (string) $this->result;
132
        } catch (Throwable $e) {
133
            trigger_error($e->getMessage() . PHP_EOL . $e->getTraceAsString(), E_USER_ERROR);
134 56
135
            return '';
136 56
        }
137 15
    }
138
139 56
    /**
140 56
     * {@inheritdoc}
141 3
     *
142
     * @param array<string, mixed> $query
143
     */
144 53
    public function __invoke(?array $query = null): ResourceObject
145
    {
146
        if (is_array($query)) {
147
            $this->query = array_merge($this->query, $query);
148
        }
149
150 3
        $this->resourceObject->uri->query = $this->query;
151
        if ($this->links && $this->linker instanceof LinkerInterface) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->links of type BEAR\Resource\LinkType[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
152 3
            return $this->linker->invoke($this);
153
        }
154 3
155
        return clone $this->invoker->invoke($this);
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     *
161
     * @return mixed
162 1
     */
163
    public function __get(string $name)
164 1
    {
165
        $this->result = $this->invoke();
166
167
        return $this->result->{$name};
168
    }
169
170
    /**
171
     * {@inheritdoc}
172 1
     *
173
     * @throws OutOfBoundsException
174 1
     */
175
    #[ReturnTypeWillChange]
176 1
    public function offsetSet($offset, $value)
177
    {
178
        throw new OutOfBoundsException(__METHOD__ . ' is unavailable.', 400);
179
    }
180
181
    /**
182 26
     * {@inheritdoc}
183
     *
184 26
     * @throws OutOfBoundsException
185 19
     */
186
    #[ReturnTypeWillChange]
187 17
    public function offsetUnset($offset)
188
    {
189
        unset($offset);
190 8
191
        throw new OutOfBoundsException(__METHOD__ . ' is unavailable.', 400);
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197
    public function request()
198 2
    {
199
        if ($this->in === 'eager') {
200 2
            $this->result = $this->invoke();
201 2
202 1
            return $this->result;
203
        }
204
205
        return $this;
206
    }
207
208
    /**
209
     * {@inheritdoc}
210
     *
211
     * @param string $offset
212
     *
213 2
     * @return mixed
214
     *
215 2
     * @throws OutOfBoundsException
216
     */
217
    #[ReturnTypeWillChange]
218
    public function offsetGet($offset)
219
    {
220
        $this->invoke();
221
        assert($this->result instanceof ResourceObject);
222
        if (! is_array($this->result->body) || ! isset($this->result->body[$offset])) {
223 1
            throw new OutOfBoundsException("[{$offset}] for object[" . get_class($this->result) . ']', 400);
224 1
        }
225
226 1
        return $this->result->body[$offset];
227
    }
228
229
    /**
230
     * {@inheritdoc}
231
     */
232
    #[ReturnTypeWillChange]
233
    public function offsetExists($offset): bool
234 5
    {
235
        $this->invoke();
236
        assert($this->result instanceof ResourceObject);
237
238
        return isset($this->result->body[$offset]);
239
    }
240
241
    /**
242 1
     * Invoke resource request then return resource body iterator
243
     *
244
     * @psalm-return ArrayIterator
245
     * @phpstan-return ArrayIterator<string, mixed>
246
     */
247
    public function getIterator(): ArrayIterator
248
    {
249
        $this->invoke();
250
        assert($this->result instanceof ResourceObject);
251
252
        return is_array($this->result->body) ? new ArrayIterator($this->result->body) : new ArrayIterator([]);
253
    }
254
255 33
    /**
256
     * {@inheritdoc}
257 32
     */
258
    public function hash(): string
259
    {
260 30
        return md5(get_class($this->resourceObject) . $this->method . serialize($this->query) . serialize($this->links));
261
    }
262
263
    /**
264
     * {@inheritdoc}
265
     *
266
     * @return never
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\never was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
267
     */
268
    public function __serialize()
269
    {
270
        throw new LogicException(__METHOD__ . ' not supported');
271
    }
272
273
    private function invoke(): ResourceObject
274
    {
275
        if ($this->result === null) {
276
            /* @noinspection ImplicitMagicMethodCallInspection */
277
            $this->result = ($this)();
278
        }
279
280
        return $this->result;
281
    }
282
283
    public function jsonSerialize(): ResourceObject
284
    {
285
        return $this->invoke();
286
    }
287
288
    public function serialize()
289
    {
290
        $this->__serialize();
291
    }
292
293
    /**
294
     * @param string $data
295
     */
296
    public function unserialize($data)
297
    {
298
        unset($data);
299
    }
300
}
301