|
1 | | -<?php declare(strict_types=1); |
| 1 | +<?php declare (strict_types=1); |
2 | 2 |
|
3 | 3 | namespace OpenCloud\Common\Api; |
4 | 4 |
|
|
11 | 11 | use OpenCloud\Common\Transport\RequestSerializer; |
12 | 12 | use Psr\Http\Message\ResponseInterface; |
13 | 13 |
|
14 | | -/** |
15 | | - * {@inheritDoc} |
16 | | - */ |
17 | | -abstract class Operator implements OperatorInterface |
| 14 | +trait OperatorTrait |
18 | 15 | { |
19 | 16 | /** @var ClientInterface */ |
20 | 17 | protected $client; |
@@ -55,18 +52,58 @@ public function __debugInfo() |
55 | 52 | } |
56 | 53 |
|
57 | 54 | /** |
58 | | - * Retrieves a populated Operation according to the definition and values provided. A |
59 | | - * HTTP client is also injected into the object to allow it to communicate with the remote API. |
| 55 | + * Magic method which intercepts async calls, finds the sequential version, and wraps it in a |
| 56 | + * {@see Promise} object. In order for this to happen, the called methods need to be in the |
| 57 | + * following format: `createAsync`, where `create` is the sequential method being wrapped. |
| 58 | + * |
| 59 | + * @param $methodName The name of the method being invoked. |
| 60 | + * @param $args The arguments to be passed to the sequential method. |
60 | 61 | * |
61 | | - * @param array $definition The data that dictates how the operation works |
| 62 | + * @throws \RuntimeException If method does not exist |
62 | 63 | * |
63 | | - * @return Operation |
| 64 | + * @return Promise |
| 65 | + */ |
| 66 | + public function __call($methodName, $args) |
| 67 | + { |
| 68 | + $e = function ($name) { |
| 69 | + return new \RuntimeException(sprintf('%s::%s is not defined', get_class($this), $name)); |
| 70 | + }; |
| 71 | + |
| 72 | + if (substr($methodName, -5) === 'Async') { |
| 73 | + $realMethod = substr($methodName, 0, -5); |
| 74 | + if (!method_exists($this, $realMethod)) { |
| 75 | + throw $e($realMethod); |
| 76 | + } |
| 77 | + |
| 78 | + $promise = new Promise( |
| 79 | + function () use (&$promise, $realMethod, $args) { |
| 80 | + $value = call_user_func_array([$this, $realMethod], $args); |
| 81 | + $promise->resolve($value); |
| 82 | + } |
| 83 | + ); |
| 84 | + |
| 85 | + return $promise; |
| 86 | + } |
| 87 | + |
| 88 | + throw $e($methodName); |
| 89 | + } |
| 90 | + |
| 91 | + /** |
| 92 | + * {@inheritdoc} |
64 | 93 | */ |
65 | 94 | public function getOperation(array $definition): Operation |
66 | 95 | { |
67 | 96 | return new Operation($definition); |
68 | 97 | } |
69 | 98 |
|
| 99 | + /** |
| 100 | + * @param Operation $operation |
| 101 | + * @param array $userValues |
| 102 | + * @param bool $async |
| 103 | + * |
| 104 | + * @return mixed |
| 105 | + * @throws \Exception |
| 106 | + */ |
70 | 107 | protected function sendRequest(Operation $operation, array $userValues = [], bool $async = false) |
71 | 108 | { |
72 | 109 | $operation->validate($userValues); |
@@ -100,76 +137,16 @@ public function executeAsync(array $definition, array $userValues = []): Promise |
100 | 137 | public function model(string $class, $data = null): ResourceInterface |
101 | 138 | { |
102 | 139 | $model = new $class($this->client, $this->api); |
103 | | - |
104 | 140 | // @codeCoverageIgnoreStart |
105 | 141 | if (!$model instanceof ResourceInterface) { |
106 | 142 | throw new \RuntimeException(sprintf('%s does not implement %s', $class, ResourceInterface::class)); |
107 | 143 | } |
108 | 144 | // @codeCoverageIgnoreEnd |
109 | | - |
110 | 145 | if ($data instanceof ResponseInterface) { |
111 | 146 | $model->populateFromResponse($data); |
112 | 147 | } elseif (is_array($data)) { |
113 | 148 | $model->populateFromArray($data); |
114 | 149 | } |
115 | | - |
116 | 150 | return $model; |
117 | 151 | } |
118 | | - |
119 | | - /** |
120 | | - * Will create a new instance of this class with the current HTTP client and API injected in. This |
121 | | - * is useful when enumerating over a collection since multiple copies of the same resource class |
122 | | - * are needed. |
123 | | - * |
124 | | - * @return static |
125 | | - */ |
126 | | - public function newInstance(): self |
127 | | - { |
128 | | - return new static($this->client, $this->api); |
129 | | - } |
130 | | - |
131 | | - /** |
132 | | - * @return \GuzzleHttp\Psr7\Uri:null |
133 | | - */ |
134 | | - protected function getHttpBaseUrl() |
135 | | - { |
136 | | - return $this->client->getConfig('base_uri'); |
137 | | - } |
138 | | - |
139 | | - /** |
140 | | - * Magic method which intercepts async calls, finds the sequential version, and wraps it in a |
141 | | - * {@see Promise} object. In order for this to happen, the called methods need to be in the |
142 | | - * following format: `createAsync`, where `create` is the sequential method being wrapped. |
143 | | - * |
144 | | - * @param $methodName The name of the method being invoked. |
145 | | - * @param $args The arguments to be passed to the sequential method. |
146 | | - * |
147 | | - * @throws \RuntimeException If method does not exist |
148 | | - * |
149 | | - * @return Promise |
150 | | - */ |
151 | | - public function __call($methodName, $args) |
152 | | - { |
153 | | - $e = function ($name) { |
154 | | - return new \RuntimeException(sprintf('%s::%s is not defined', get_class($this), $name)); |
155 | | - }; |
156 | | - |
157 | | - if (substr($methodName, -5) === 'Async') { |
158 | | - $realMethod = substr($methodName, 0, -5); |
159 | | - if (!method_exists($this, $realMethod)) { |
160 | | - throw $e($realMethod); |
161 | | - } |
162 | | - |
163 | | - $promise = new Promise( |
164 | | - function () use (&$promise, $realMethod, $args) { |
165 | | - $value = call_user_func_array([$this, $realMethod], $args); |
166 | | - $promise->resolve($value); |
167 | | - } |
168 | | - ); |
169 | | - |
170 | | - return $promise; |
171 | | - } |
172 | | - |
173 | | - throw $e($methodName); |
174 | | - } |
175 | 152 | } |
0 commit comments