bearsunday /
BEAR.Resource
| 1 | <?php |
||||
| 2 | |||||
| 3 | declare(strict_types=1); |
||||
| 4 | |||||
| 5 | namespace BEAR\Resource; |
||||
| 6 | |||||
| 7 | use Override; |
||||
| 8 | use Ray\Di\Di\Set; |
||||
| 9 | use Ray\Di\ProviderInterface; |
||||
|
0 ignored issues
–
show
|
|||||
| 10 | |||||
| 11 | use function array_merge; |
||||
| 12 | use function assert; |
||||
| 13 | use function is_string; |
||||
| 14 | use function trigger_error; |
||||
| 15 | |||||
| 16 | use const E_USER_DEPRECATED; |
||||
| 17 | |||||
| 18 | /** |
||||
| 19 | * Pure singleton Resource client - coroutine safe |
||||
| 20 | * |
||||
| 21 | * This class is stateless and can be safely shared across coroutines. |
||||
| 22 | * For legacy fluent interface usage ($resource->get->uri()), a deprecation |
||||
| 23 | * warning is triggered and a new Resource instance is created for fallback. |
||||
| 24 | * |
||||
| 25 | * @psalm-import-type Query from Types |
||||
| 26 | */ |
||||
| 27 | final class ResourcePure implements ResourceInterface |
||||
| 28 | { |
||||
| 29 | /** |
||||
| 30 | * @param FactoryInterface $factory Resource factory |
||||
| 31 | * @param InvokerInterface $invoker Resource request invoker |
||||
| 32 | * @param AnchorInterface $anchor Resource anchor |
||||
| 33 | * @param ProviderInterface<LinkerInterface> $linkerProvider Resource linker provider |
||||
| 34 | * @param UriFactory $uri URI factory |
||||
| 35 | */ |
||||
| 36 | public function __construct( |
||||
| 37 | private readonly FactoryInterface $factory, |
||||
| 38 | private readonly InvokerInterface $invoker, |
||||
| 39 | private readonly AnchorInterface $anchor, |
||||
| 40 | #[Set(LinkerInterface::class)] |
||||
| 41 | private readonly ProviderInterface $linkerProvider, |
||||
| 42 | private readonly UriFactory $uri, |
||||
|
0 ignored issues
–
show
The type
BEAR\Resource\UriFactory 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. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||||
| 43 | ) { |
||||
| 44 | } |
||||
| 45 | |||||
| 46 | /** |
||||
| 47 | * Fallback to legacy Resource for deprecated fluent interface |
||||
| 48 | * |
||||
| 49 | * @deprecated Use createRequest() or direct method calls instead |
||||
| 50 | * @psalm-suppress DeprecatedMethod |
||||
| 51 | */ |
||||
| 52 | public function __get(string $name): Resource |
||||
| 53 | { |
||||
| 54 | trigger_error( |
||||
| 55 | 'Fluent interface ($resource->get->uri()) is deprecated. Use createRequest() instead.', |
||||
| 56 | E_USER_DEPRECATED, |
||||
| 57 | ); |
||||
| 58 | |||||
| 59 | // Create a new mutable Resource instance for legacy compatibility |
||||
| 60 | $linker = $this->linkerProvider->get(); |
||||
| 61 | $resource = new Resource($this->factory, $this->invoker, $this->anchor, $linker, $this->uri); |
||||
| 62 | |||||
| 63 | // Set the method and return for chaining |
||||
| 64 | return $resource->__get($name); |
||||
|
0 ignored issues
–
show
The function
BEAR\Resource\Resource::__get() has been deprecated: Use createRequest() instead
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. Loading history...
|
|||||
| 65 | } |
||||
| 66 | |||||
| 67 | /** |
||||
| 68 | * {@inheritDoc} |
||||
| 69 | */ |
||||
| 70 | #[Override] |
||||
| 71 | public function newInstance($uri): ResourceObject |
||||
| 72 | { |
||||
| 73 | if (is_string($uri)) { |
||||
| 74 | $uri = ($this->uri)($uri); |
||||
| 75 | } |
||||
| 76 | |||||
| 77 | return $this->factory->newInstance($uri); |
||||
| 78 | } |
||||
| 79 | |||||
| 80 | /** |
||||
| 81 | * {@inheritDoc} |
||||
| 82 | */ |
||||
| 83 | #[Override] |
||||
| 84 | public function object(ResourceObject $ro): RequestInterface |
||||
| 85 | { |
||||
| 86 | return new Request($this->invoker, $ro, Request::GET); |
||||
| 87 | } |
||||
| 88 | |||||
| 89 | /** |
||||
| 90 | * {@inheritDoc} |
||||
| 91 | * |
||||
| 92 | * @deprecated Use createRequest() instead |
||||
| 93 | */ |
||||
| 94 | #[Override] |
||||
| 95 | public function uri($uri): RequestInterface |
||||
| 96 | { |
||||
| 97 | return $this->createRequest(Request::GET, (string) $uri); |
||||
| 98 | } |
||||
| 99 | |||||
| 100 | /** |
||||
| 101 | * {@inheritDoc} |
||||
| 102 | */ |
||||
| 103 | #[Override] |
||||
| 104 | public function createRequest(string $method, string $uri, array $query = []): RequestInterface |
||||
| 105 | { |
||||
| 106 | $linker = $this->linkerProvider->get(); |
||||
| 107 | $ro = $this->newInstance($uri); |
||||
| 108 | $ro->uri->method = $method; |
||||
| 109 | $ro->uri->query = array_merge($ro->uri->query, $query); |
||||
|
0 ignored issues
–
show
$ro->uri->query of type BEAR\Resource\Query is incompatible with the type array expected by parameter $arrays of array_merge().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
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...
|
|||||
| 110 | |||||
| 111 | return new Request($this->invoker, $ro, $method, $ro->uri->query, [], $linker); |
||||
| 112 | } |
||||
| 113 | |||||
| 114 | /** |
||||
| 115 | * {@inheritDoc} |
||||
| 116 | * |
||||
| 117 | * @psalm-suppress NoInterfaceProperties |
||||
| 118 | * @psalm-suppress MixedMethodCall |
||||
| 119 | */ |
||||
| 120 | #[Override] |
||||
| 121 | public function crawl(string $uri, string $linkKey, array $query = []): ResourceObject |
||||
| 122 | { |
||||
| 123 | /** @var Request $request */ |
||||
| 124 | $request = $this->createRequest(Request::GET, $uri, $query)->linkCrawl($linkKey); |
||||
| 125 | $request->in = 'eager'; |
||||
| 126 | $ro = $request->request(); |
||||
| 127 | assert($ro instanceof ResourceObject); |
||||
| 128 | |||||
| 129 | return $ro; |
||||
| 130 | } |
||||
| 131 | |||||
| 132 | /** |
||||
| 133 | * {@inheritDoc} |
||||
| 134 | * |
||||
| 135 | * @psalm-suppress NoInterfaceProperties |
||||
| 136 | * @psalm-suppress MixedMethodCall |
||||
| 137 | */ |
||||
| 138 | #[Override] |
||||
| 139 | public function href(string $rel, array $query = [], ResourceObject|null $ro = null): ResourceObject |
||||
| 140 | { |
||||
| 141 | assert($ro instanceof ResourceObject, 'ResourceObject is required for ResourcePure::href()'); |
||||
| 142 | $sourceRequest = new Request($this->invoker, $ro, $ro->uri->method, $ro->uri->query); |
||||
|
0 ignored issues
–
show
$ro->uri->query of type BEAR\Resource\Query is incompatible with the type array expected by parameter $query of BEAR\Resource\Request::__construct().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 143 | [$method, $uri] = $this->anchor->href($rel, $sourceRequest, $query); |
||||
| 144 | /** @var Request $request */ |
||||
| 145 | $request = $this->createRequest($method, $uri, $query); |
||||
| 146 | $request->in = 'eager'; |
||||
| 147 | $result = $request->request(); |
||||
| 148 | assert($result instanceof ResourceObject); |
||||
| 149 | |||||
| 150 | return $result; |
||||
| 151 | } |
||||
| 152 | |||||
| 153 | /** |
||||
| 154 | * {@inheritDoc} |
||||
| 155 | */ |
||||
| 156 | #[Override] |
||||
| 157 | public function get(string $uri, array $query = []): ResourceObject |
||||
| 158 | { |
||||
| 159 | return $this->methodUri(Request::GET, $uri)($query); |
||||
| 160 | } |
||||
| 161 | |||||
| 162 | /** |
||||
| 163 | * {@inheritDoc} |
||||
| 164 | */ |
||||
| 165 | #[Override] |
||||
| 166 | public function post(string $uri, array $query = []): ResourceObject |
||||
| 167 | { |
||||
| 168 | return $this->methodUri(Request::POST, $uri)($query); |
||||
| 169 | } |
||||
| 170 | |||||
| 171 | /** |
||||
| 172 | * {@inheritDoc} |
||||
| 173 | */ |
||||
| 174 | #[Override] |
||||
| 175 | public function put(string $uri, array $query = []): ResourceObject |
||||
| 176 | { |
||||
| 177 | return $this->methodUri(Request::PUT, $uri)($query); |
||||
| 178 | } |
||||
| 179 | |||||
| 180 | /** |
||||
| 181 | * {@inheritDoc} |
||||
| 182 | */ |
||||
| 183 | #[Override] |
||||
| 184 | public function patch(string $uri, array $query = []): ResourceObject |
||||
| 185 | { |
||||
| 186 | return $this->methodUri(Request::PATCH, $uri)($query); |
||||
| 187 | } |
||||
| 188 | |||||
| 189 | /** |
||||
| 190 | * {@inheritDoc} |
||||
| 191 | */ |
||||
| 192 | #[Override] |
||||
| 193 | public function delete(string $uri, array $query = []): ResourceObject |
||||
| 194 | { |
||||
| 195 | return $this->methodUri(Request::DELETE, $uri)($query); |
||||
| 196 | } |
||||
| 197 | |||||
| 198 | /** |
||||
| 199 | * {@inheritDoc} |
||||
| 200 | */ |
||||
| 201 | #[Override] |
||||
| 202 | public function options(string $uri, array $query = []): ResourceObject |
||||
| 203 | { |
||||
| 204 | return $this->methodUri(Request::OPTIONS, $uri)($query); |
||||
| 205 | } |
||||
| 206 | |||||
| 207 | /** |
||||
| 208 | * {@inheritDoc} |
||||
| 209 | */ |
||||
| 210 | #[Override] |
||||
| 211 | public function head(string $uri, array $query = []): ResourceObject |
||||
| 212 | { |
||||
| 213 | return $this->methodUri(Request::HEAD, $uri)($query); |
||||
| 214 | } |
||||
| 215 | |||||
| 216 | private function methodUri(string $method, string $uri): RequestInterface |
||||
| 217 | { |
||||
| 218 | return $this->createRequest($method, $uri); |
||||
| 219 | } |
||||
| 220 | } |
||||
| 221 |
Let?s assume that you have a directory layout like this:
. |-- OtherDir | |-- Bar.php | `-- Foo.php `-- SomeDir `-- Foo.phpand let?s assume the following content of
Bar.php:If both files
OtherDir/Foo.phpandSomeDir/Foo.phpare loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.phpHowever, as
OtherDir/Foo.phpdoes not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: