| @@ -66,11 +66,15 @@ | ||
| 66 | 66 | public static function inspect(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : array |
| 67 | 67 | { |
| 68 | 68 | try { |
| 69 | 69 | return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED, 'value' => $promise->wait()]; |
| 70 | - } catch (\YoastSEO_Vendor\GuzzleHttp\Promise\RejectionException $e) { | |
| 71 | - return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e->getReason()]; | |
| 72 | 70 | } catch (\Throwable $e) { |
| 71 | + if ($e instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\AggregateException) { | |
| 72 | + return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e]; | |
| 73 | + } | |
| 74 | + if ($e instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\RejectionException) { | |
| 75 | + return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e->getReason()]; | |
| 76 | + } | |
| 73 | 77 | return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e]; |
| 74 | 78 | } |
| 75 | 79 | } |
| 76 | 80 | /** |
| @@ -84,8 +88,9 @@ | ||
| 84 | 88 | * @param PromiseInterface[] $promises Traversable of promises to wait upon. |
| 85 | 89 | */ |
| 86 | 90 | public static function inspectAll($promises) : array |
| 87 | 91 | { |
| 92 | + $promises = self::prepareIterable($promises, __FUNCTION__); | |
| 88 | 93 | $results = []; |
| 89 | 94 | foreach ($promises as $key => $promise) { |
| 90 | 95 | $results[$key] = self::inspect($promise); |
| 91 | 96 | } |
| @@ -103,8 +108,9 @@ | ||
| 103 | 108 | * @throws \Throwable on error |
| 104 | 109 | */ |
| 105 | 110 | public static function unwrap($promises) : array |
| 106 | 111 | { |
| 112 | + $promises = self::prepareIterable($promises, __FUNCTION__); | |
| 107 | 113 | $results = []; |
| 108 | 114 | foreach ($promises as $key => $promise) { |
| 109 | 115 | $results[$key] = $promise->wait(); |
| 110 | 116 | } |
| @@ -122,8 +128,9 @@ | ||
| 122 | 128 | * @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution. |
| 123 | 129 | */ |
| 124 | 130 | public static function all($promises, bool $recursive = \false) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface |
| 125 | 131 | { |
| 132 | + $promises = self::prepareIterable($promises, __FUNCTION__); | |
| 126 | 133 | $results = []; |
| 127 | 134 | $promise = \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx) use(&$results) : void { |
| 128 | 135 | $results[$idx] = $value; |
| 129 | 136 | }, function ($reason, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\Promise $aggregate) : void { |
| @@ -135,8 +142,13 @@ | ||
| 135 | 142 | return $results; |
| 136 | 143 | }); |
| 137 | 144 | if (\true === $recursive) { |
| 138 | 145 | $promise = $promise->then(function ($results) use($recursive, &$promises) { |
| 146 | + // A consumed generator cannot be traversed again, so a | |
| 147 | + // recursive pass has nothing further to observe. | |
| 148 | + if ($promises instanceof \Generator) { | |
| 149 | + return $results; | |
| 150 | + } | |
| 139 | 151 | foreach ($promises as $promise) { |
| 140 | 152 | if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($promise)) { |
| 141 | 153 | return self::all($promises, $recursive); |
| 142 | 154 | } |
| @@ -161,8 +173,9 @@ | ||
| 161 | 173 | * @param mixed $promises Promises or values. |
| 162 | 174 | */ |
| 163 | 175 | public static function some(int $count, $promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface |
| 164 | 176 | { |
| 177 | + $promises = self::prepareIterable($promises, __FUNCTION__); | |
| 165 | 178 | $results = []; |
| 166 | 179 | $rejections = []; |
| 167 | 180 | return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $p) use(&$results, $count) : void { |
| 168 | 181 | if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($p)) { |
| @@ -189,8 +202,9 @@ | ||
| 189 | 202 | * @param mixed $promises Promises or values. |
| 190 | 203 | */ |
| 191 | 204 | public static function any($promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface |
| 192 | 205 | { |
| 206 | + $promises = self::prepareIterable($promises, __FUNCTION__); | |
| 193 | 207 | return self::some(1, $promises)->then(function ($values) { |
| 194 | 208 | return $values[0]; |
| 195 | 209 | }); |
| 196 | 210 | } |
| @@ -205,8 +219,9 @@ | ||
| 205 | 219 | * @param mixed $promises Promises or values. |
| 206 | 220 | */ |
| 207 | 221 | public static function settle($promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface |
| 208 | 222 | { |
| 223 | + $promises = self::prepareIterable($promises, __FUNCTION__); | |
| 209 | 224 | $results = []; |
| 210 | 225 | return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx) use(&$results) : void { |
| 211 | 226 | $results[$idx] = ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED, 'value' => $value]; |
| 212 | 227 | }, function ($reason, $idx) use(&$results) : void { |
| @@ -214,6 +229,21 @@ | ||
| 214 | 229 | })->then(function () use(&$results) { |
| 215 | 230 | \ksort($results); |
| 216 | 231 | return $results; |
| 217 | 232 | }); |
| 233 | + } | |
| 234 | + private static function prepareIterable($promises, string $method) : iterable | |
| 235 | + { | |
| 236 | + if (\is_iterable($promises)) { | |
| 237 | + return $promises; | |
| 238 | + } | |
| 239 | + self::triggerNonIterableDeprecation($promises, $method); | |
| 240 | + return [$promises]; | |
| 241 | + } | |
| 242 | + private static function triggerNonIterableDeprecation($promises, string $method) : void | |
| 243 | + { | |
| 244 | + if (\is_iterable($promises)) { | |
| 245 | + return; | |
| 246 | + } | |
| 247 | + \YoastSEO_Vendor\trigger_deprecation('guzzlehttp/promises', '2.5', 'Passing a non-iterable to %s::%s() is deprecated; guzzlehttp/promises 3.0 will require an iterable.', self::class, $method); | |
| 218 | 248 | } |
| 219 | 249 | } |