ResourceObject   A
last analyzed

Complexity

Total Complexity 31

Size/Duplication

Total Lines 238
Duplicated Lines 0 %

Importance

Changes 14
Bugs 2 Features 0
Metric Value
eloc 61
c 14
b 2
f 0
dl 0
loc 238
rs 9.92
wmc 31

16 Methods

Rating   Name   Duplication   Size   Complexity  
A asort() 0 7 2
A __toString() 0 12 2
A getIterator() 0 3 2
A offsetSet() 0 12 3
A ksort() 0 7 2
A __clone() 0 3 1
A transfer() 0 3 1
A setRenderer() 0 6 1
A _invokeRequest() 0 3 1
A __sleep() 0 14 4
A toString() 0 11 3
A jsonSerialize() 0 10 2
A offsetExists() 0 8 2
A offsetUnset() 0 5 1
A offsetGet() 0 8 2
A count() 0 7 2
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\IlligalAccessException;
10
use Countable;
11
use IteratorAggregate;
12
use JsonSerializable;
13
use Ray\Di\Di\Inject;
14
use ReturnTypeWillChange;
15
use Stringable;
16
use Throwable;
17
18
use function asort;
19
use function assert;
20
use function count;
21
use function is_array;
22
use function is_countable;
23
use function is_iterable;
24
use function is_string;
25
use function ksort;
26
use function sprintf;
27
use function trigger_error;
28
29
use const E_USER_WARNING;
30
31
/**
32
 * @phpstan-implements ArrayAccess<string, mixed>
33
 * @phpstan-implements IteratorAggregate<(int|string), mixed>
34
 */
35
abstract class ResourceObject implements AcceptTransferInterface, ArrayAccess, Countable, IteratorAggregate, JsonSerializable, Stringable, InvokeRequestInterface
36
{
37
    /**
38
     * @var AbstractUri
39
     * @psalm-suppress PropertyNotSetInConstructor
40
     */
41
    public $uri;
42
43
    /** @var int */
44
    public $code = 200;
45
46
    /** @var array<string, string> */
47
    public $headers = [];
48
49
    /**
50
     * Resource representation
51
     *
52
     * @var ?string
53
     */
54
    public $view;
55
56
    /** @var mixed */
57
    public $body;
58
59
    /** @var ?RenderInterface */
60
    protected $renderer;
61
62
    /**
63
     * Return representational string
64
     *
65
     * Return object hash if representation renderer is not set.
66
     *
67
     * @return string
68
     */
69
    public function __toString()
70
    {
71
        try {
72
            $view = $this->toString();
73
        } catch (Throwable $e) {
74
            $msg = sprintf("%s(%s)\n%s", $e::class, $e->getMessage(), $e->getTraceAsString());
75
            trigger_error($msg, E_USER_WARNING);
76
77
            return '';
78
        }
79
80
        return $view;
81
    }
82
83
    /** @return list<string> */
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...
84
    public function __sleep()
85
    {
86
        if (is_array($this->body)) {
87
            /** @psalm-suppress MixedAssignment */
88
            foreach ($this->body as &$item) {
89
                if (! ($item instanceof RequestInterface)) {
90
                    continue;
91
                }
92
93
                $item = ($item)();
94
            }
95
        }
96
97
        return ['uri', 'code', 'headers', 'body', 'view'];
0 ignored issues
show
Bug Best Practice introduced by
The expression return array('uri', 'cod...aders', 'body', 'view') returns the type array<integer,string> which is incompatible with the documented return type BEAR\Resource\list.
Loading history...
98
    }
99
100
    /**
101
     * Returns the body value at the specified index
102
     *
103
     * @param int|string $offset offset
104
     *
105
     * @return mixed
106
     */
107
    #[ReturnTypeWillChange]
108
    public function offsetGet($offset)
109
    {
110
        if (is_array($this->body)) {
111
            return $this->body[$offset];
112
        }
113
114
        throw new IlligalAccessException((string) $offset);
115
    }
116
117
    /**
118
     * Sets the body value at the specified index to renew
119
     *
120
     * @param array-key $offset offset
0 ignored issues
show
Documentation Bug introduced by
The doc comment array-key at position 0 could not be parsed: Unknown type name 'array-key' at position 0 in array-key.
Loading history...
121
     * @param mixed     $value  value
122
     *
123
     * @return void
124
     */
125
    #[ReturnTypeWillChange]
126
    public function offsetSet($offset, mixed $value)
127
    {
128
        if ($this->body === null) {
129
            $this->body = [];
130
        }
131
132
        if (! is_array($this->body)) {
133
            throw new IlligalAccessException((string) $offset);
134
        }
135
136
        $this->body[$offset] = $value;
137
    }
138
139
    /**
140
     * Returns whether the requested index in body exists
141
     *
142
     * @param array-key $offset offset
0 ignored issues
show
Documentation Bug introduced by
The doc comment array-key at position 0 could not be parsed: Unknown type name 'array-key' at position 0 in array-key.
Loading history...
143
     *
144
     * @return bool
145
     */
146
    #[ReturnTypeWillChange]
147
    public function offsetExists($offset)
148
    {
149
        if (is_array($this->body)) {
150
            return isset($this->body[$offset]);
151
        }
152
153
        return false;
154
    }
155
156
    /**
157
     * Set the value at the specified index
158
     *
159
     * @param int|string $offset offset
160
     */
161
    #[ReturnTypeWillChange]
162
    public function offsetUnset($offset): void
163
    {
164
        assert(is_array($this->body));
165
        unset($this->body[$offset]);
166
    }
167
168
    /**
169
     * Get the number of public properties in the ArrayObject
170
     */
171
    public function count(): int
172
    {
173
        if (is_countable($this->body)) {
174
            return count($this->body);
175
        }
176
177
        throw new IlligalAccessException();
178
    }
179
180
    /**
181
     * Sort the entries by key
182
     */
183
    public function ksort(): void
184
    {
185
        if (! is_array($this->body)) {
186
            return;
187
        }
188
189
        ksort($this->body);
190
    }
191
192
    /**
193
     * Sort the entries by key
194
     */
195
    public function asort(): void
196
    {
197
        if (! is_array($this->body)) {
198
            return;
199
        }
200
201
        asort($this->body);
202
    }
203
204
    /**
205
     * @return ArrayIterator<int|string, mixed>
206
     * @psalm-return ArrayIterator<empty, empty>|ArrayIterator<int|string, mixed>
207
     * @phpstan-return ArrayIterator<int|string, mixed>
208
     */
209
    public function getIterator(): ArrayIterator
210
    {
211
        return is_array($this->body) ? new ArrayIterator($this->body) : new ArrayIterator([]);
212
    }
213
214
    /** @return self */
215
    #[Inject(optional: true)]
216
    public function setRenderer(RenderInterface $renderer)
217
    {
218
        $this->renderer = $renderer;
219
220
        return $this;
221
    }
222
223
    /**
224
     * {@inheritDoc}
225
     */
226
    public function toString(): string
227
    {
228
        if (is_string($this->view)) {
229
            return $this->view;
230
        }
231
232
        if (! $this->renderer instanceof RenderInterface) {
233
            $this->renderer = new JsonRenderer();
234
        }
235
236
        return $this->renderer->render($this);
237
    }
238
239
    /** @return array<int|string, mixed> */
240
    public function jsonSerialize(): array
241
    {
242
        /** @psalm-suppress MixedAssignment */
243
        if (! is_iterable($this->body)) {
244
            return ['value' => $this->body];
245
        }
246
247
        assert(is_array($this->body));
248
249
        return $this->body;
250
    }
251
252
    /**
253
     * {@inheritDoc}
254
     */
255
    public function transfer(TransferInterface $responder, array $server)
256
    {
257
        $responder($this, $server);
258
    }
259
260
    public function __clone()
261
    {
262
        $this->uri = clone $this->uri;
263
    }
264
265
    /**
266
     * {@inheritDoc}
267
     *
268
     * @SuppressWarnings(PHPMD.CamelCaseMethodName)
269
     */
270
    public function _invokeRequest(InvokerInterface $invoker, AbstractRequest $request): ResourceObject
271
    {
272
        return $invoker->invoke($request);
273
    }
274
}
275