Issues (169)

src/Resource.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource;
6
7
use Override;
8
9
use function array_merge;
10
use function assert;
11
use function is_string;
12
13
/**
14
 * Resource client with mutable state - supports legacy fluent interface
15
 *
16
 * This class maintains internal state for the fluent interface pattern.
17
 * It is NOT coroutine-safe due to mutable $method and $request properties.
18
 * For coroutine-safe usage, use ResourcePure instead.
19
 *
20
 * @property $this $get
21
 * @property $this $post
22
 * @property $this $put
23
 * @property $this $patch
24
 * @property $this $delete
25
 * @property $this $head
26
 * @property $this $options
27
 * @psalm-import-type Query from Types
28
 * @codeCoverageIgnore Deprecated legacy class - use ResourcePure instead
29
 */
30
final class Resource implements ResourceInterface
31
{
32
    /** @psalm-suppress PropertyNotSetInConstructor */
33
    private Request $request;
34
    private string $method = 'get';
35
36
    /**
37
     * @param FactoryInterface $factory Resource factory
38
     * @param InvokerInterface $invoker Resource request invoker
39
     * @param AnchorInterface  $anchor  Resource anchor
40
     * @param LinkerInterface  $linker  Resource linker
41
     * @param UriFactory       $uri     URI factory
42
     */
43
    public function __construct(
44
        private readonly FactoryInterface $factory,
45
        private readonly InvokerInterface $invoker,
46
        private readonly AnchorInterface $anchor,
47
        private readonly LinkerInterface $linker,
48
        private readonly UriFactory $uri,
49
    ) {
50
    }
51
52
    /**
53
     * Set HTTP method for fluent interface
54
     *
55
     * @deprecated Use createRequest() instead
56
     */
57
    public function __get(string $name): self
58
    {
59
        $this->method = $name;
60
61
        return $this;
62
    }
63
64
    /**
65
     * {@inheritDoc}
66
     */
67
    #[Override]
68
    public function newInstance($uri): ResourceObject
69
    {
70
        if (is_string($uri)) {
71
            $uri = ($this->uri)($uri);
72
        }
73
74
        return $this->factory->newInstance($uri);
75
    }
76
77
    /**
78
     * {@inheritDoc}
79
     */
80
    #[Override]
81
    public function object(ResourceObject $ro): RequestInterface
82
    {
83
        return new Request($this->invoker, $ro, $this->method);
84
    }
85
86
    /**
87
     * {@inheritDoc}
88
     *
89
     * @deprecated Use createRequest() instead
90
     */
91
    #[Override]
92
    public function uri($uri): RequestInterface
93
    {
94
        $method = $this->method; // save method, this may change on newInstance(), this is singleton!
95
        $this->method = 'get';
96
        $ro = $this->newInstance($uri);
97
        $ro->uri->method = $method;
98
        $this->request = new Request($this->invoker, $ro, $ro->uri->method, $ro->uri->query, [], $this->linker);
99
100
        return $this->request;
101
    }
102
103
    /**
104
     * {@inheritDoc}
105
     */
106
    #[Override]
107
    public function createRequest(string $method, string $uri, array $query = []): RequestInterface
108
    {
109
        $ro = $this->newInstance($uri);
110
        $ro->uri->method = $method;
111
        $ro->uri->query = array_merge($ro->uri->query, $query);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($ro->uri->query, $query) of type array is incompatible with the declared type BEAR\Resource\Query of property $query.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
112
        $this->request = new Request($this->invoker, $ro, $method, $ro->uri->query, [], $this->linker);
113
114
        return $this->request;
115
    }
116
117
    /**
118
     * {@inheritDoc}
119
     *
120
     * @psalm-suppress NoInterfaceProperties
121
     * @psalm-suppress MixedMethodCall
122
     */
123
    #[Override]
124
    public function crawl(string $uri, string $linkKey, array $query = []): ResourceObject
125
    {
126
        /** @var Request $request */
127
        $request = $this->createRequest(Request::GET, $uri, $query)->linkCrawl($linkKey);
128
        $request->in = 'eager';
129
        $ro = $request->request();
130
        assert($ro instanceof ResourceObject);
131
132
        return $ro;
133
    }
134
135
    /**
136
     * {@inheritDoc}
137
     *
138
     * @psalm-suppress NoInterfaceProperties
139
     * @psalm-suppress MixedMethodCall
140
     */
141
    #[Override]
142
    public function href(string $rel, array $query = [], ResourceObject|null $ro = null): ResourceObject
143
    {
144
        $sourceRequest = $ro !== null
145
            ? new Request($this->invoker, $ro, $ro->uri->method, $ro->uri->query)
146
            : $this->request;
147
        [$method, $uri] = $this->anchor->href($rel, $sourceRequest, $query);
148
        /** @var Request $request */
149
        $request = $this->createRequest($method, $uri, $query);
150
        $request->in = 'eager';
151
        $result = $request->request();
152
        assert($result instanceof ResourceObject);
153
154
        return $result;
155
    }
156
157
    /**
158
     * {@inheritDoc}
159
     */
160
    #[Override]
161
    public function get(string $uri, array $query = []): ResourceObject
162
    {
163
        return $this->methodUri(Request::GET, $uri)($query);
164
    }
165
166
    /**
167
     * {@inheritDoc}
168
     */
169
    #[Override]
170
    public function post(string $uri, array $query = []): ResourceObject
171
    {
172
        return $this->methodUri(Request::POST, $uri)($query);
173
    }
174
175
    /**
176
     * {@inheritDoc}
177
     */
178
    #[Override]
179
    public function put(string $uri, array $query = []): ResourceObject
180
    {
181
        return $this->methodUri(Request::PUT, $uri)($query);
182
    }
183
184
    /**
185
     * {@inheritDoc}
186
     */
187
    #[Override]
188
    public function patch(string $uri, array $query = []): ResourceObject
189
    {
190
        return $this->methodUri(Request::PATCH, $uri)($query);
191
    }
192
193
    /**
194
     * {@inheritDoc}
195
     */
196
    #[Override]
197
    public function delete(string $uri, array $query = []): ResourceObject
198
    {
199
        return $this->methodUri(Request::DELETE, $uri)($query);
200
    }
201
202
    /**
203
     * {@inheritDoc}
204
     */
205
    #[Override]
206
    public function options(string $uri, array $query = []): ResourceObject
207
    {
208
        return $this->methodUri(Request::OPTIONS, $uri)($query);
209
    }
210
211
    /**
212
     * {@inheritDoc}
213
     */
214
    #[Override]
215
    public function head(string $uri, array $query = []): ResourceObject
216
    {
217
        return $this->methodUri(Request::HEAD, $uri)($query);
218
    }
219
220
    /** @psalm-suppress DeprecatedMethod */
221
    private function methodUri(string $method, string $uri): RequestInterface
222
    {
223
        $this->method = $method;
224
225
        return $this->uri($uri);
226
    }
227
}
228