PageRenderTime 46ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/Resources/Private/Vendor/Composer/vendor/guzzlehttp/promises/src/functions.php

https://bitbucket.org/imia_de/t3ext-imia-base
PHP | 471 lines | 225 code | 32 blank | 214 comment | 12 complexity | e4d365dd1401261fbc31ad5aacfecbe0 MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. namespace GuzzleHttp\Promise;
  3. /**
  4. * Get the global task queue used for promise resolution.
  5. *
  6. * This task queue MUST be run in an event loop in order for promises to be
  7. * settled asynchronously. It will be automatically run when synchronously
  8. * waiting on a promise.
  9. *
  10. * <code>
  11. * while ($eventLoop->isRunning()) {
  12. * GuzzleHttp\Promise\queue()->run();
  13. * }
  14. * </code>
  15. *
  16. * @param TaskQueueInterface $assign Optionally specify a new queue instance.
  17. *
  18. * @return TaskQueueInterface
  19. */
  20. function queue(TaskQueueInterface $assign = null)
  21. {
  22. static $queue;
  23. if ($assign) {
  24. $queue = $assign;
  25. } elseif (!$queue) {
  26. $queue = new TaskQueue();
  27. }
  28. return $queue;
  29. }
  30. /**
  31. * Adds a function to run in the task queue when it is next `run()` and returns
  32. * a promise that is fulfilled or rejected with the result.
  33. *
  34. * @param callable $task Task function to run.
  35. *
  36. * @return PromiseInterface
  37. */
  38. function task(callable $task)
  39. {
  40. $queue = queue();
  41. $promise = new Promise([$queue, 'run']);
  42. $queue->add(function () use ($task, $promise) {
  43. try {
  44. $promise->resolve($task());
  45. } catch (\Throwable $e) {
  46. $promise->reject($e);
  47. } catch (\Exception $e) {
  48. $promise->reject($e);
  49. }
  50. });
  51. return $promise;
  52. }
  53. /**
  54. * Creates a promise for a value if the value is not a promise.
  55. *
  56. * @param mixed $value Promise or value.
  57. *
  58. * @return PromiseInterface
  59. */
  60. function promise_for($value)
  61. {
  62. if ($value instanceof PromiseInterface) {
  63. return $value;
  64. }
  65. // Return a Guzzle promise that shadows the given promise.
  66. if (method_exists($value, 'then')) {
  67. $wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null;
  68. $cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null;
  69. $promise = new Promise($wfn, $cfn);
  70. $value->then([$promise, 'resolve'], [$promise, 'reject']);
  71. return $promise;
  72. }
  73. return new FulfilledPromise($value);
  74. }
  75. /**
  76. * Creates a rejected promise for a reason if the reason is not a promise. If
  77. * the provided reason is a promise, then it is returned as-is.
  78. *
  79. * @param mixed $reason Promise or reason.
  80. *
  81. * @return PromiseInterface
  82. */
  83. function rejection_for($reason)
  84. {
  85. if ($reason instanceof PromiseInterface) {
  86. return $reason;
  87. }
  88. return new RejectedPromise($reason);
  89. }
  90. /**
  91. * Create an exception for a rejected promise value.
  92. *
  93. * @param mixed $reason
  94. *
  95. * @return \Exception|\Throwable
  96. */
  97. function exception_for($reason)
  98. {
  99. return $reason instanceof \Exception || $reason instanceof \Throwable
  100. ? $reason
  101. : new RejectionException($reason);
  102. }
  103. /**
  104. * Returns an iterator for the given value.
  105. *
  106. * @param mixed $value
  107. *
  108. * @return \Iterator
  109. */
  110. function iter_for($value)
  111. {
  112. if ($value instanceof \Iterator) {
  113. return $value;
  114. } elseif (is_array($value)) {
  115. return new \ArrayIterator($value);
  116. } else {
  117. return new \ArrayIterator([$value]);
  118. }
  119. }
  120. /**
  121. * Synchronously waits on a promise to resolve and returns an inspection state
  122. * array.
  123. *
  124. * Returns a state associative array containing a "state" key mapping to a
  125. * valid promise state. If the state of the promise is "fulfilled", the array
  126. * will contain a "value" key mapping to the fulfilled value of the promise. If
  127. * the promise is rejected, the array will contain a "reason" key mapping to
  128. * the rejection reason of the promise.
  129. *
  130. * @param PromiseInterface $promise Promise or value.
  131. *
  132. * @return array
  133. */
  134. function inspect(PromiseInterface $promise)
  135. {
  136. try {
  137. return [
  138. 'state' => PromiseInterface::FULFILLED,
  139. 'value' => $promise->wait()
  140. ];
  141. } catch (RejectionException $e) {
  142. return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()];
  143. } catch (\Throwable $e) {
  144. return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
  145. } catch (\Exception $e) {
  146. return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
  147. }
  148. }
  149. /**
  150. * Waits on all of the provided promises, but does not unwrap rejected promises
  151. * as thrown exception.
  152. *
  153. * Returns an array of inspection state arrays.
  154. *
  155. * @param PromiseInterface[] $promises Traversable of promises to wait upon.
  156. *
  157. * @return array
  158. * @see GuzzleHttp\Promise\inspect for the inspection state array format.
  159. */
  160. function inspect_all($promises)
  161. {
  162. $results = [];
  163. foreach ($promises as $key => $promise) {
  164. $results[$key] = inspect($promise);
  165. }
  166. return $results;
  167. }
  168. /**
  169. * Waits on all of the provided promises and returns the fulfilled values.
  170. *
  171. * Returns an array that contains the value of each promise (in the same order
  172. * the promises were provided). An exception is thrown if any of the promises
  173. * are rejected.
  174. *
  175. * @param mixed $promises Iterable of PromiseInterface objects to wait on.
  176. *
  177. * @return array
  178. * @throws \Exception on error
  179. * @throws \Throwable on error in PHP >=7
  180. */
  181. function unwrap($promises)
  182. {
  183. $results = [];
  184. foreach ($promises as $key => $promise) {
  185. $results[$key] = $promise->wait();
  186. }
  187. return $results;
  188. }
  189. /**
  190. * Given an array of promises, return a promise that is fulfilled when all the
  191. * items in the array are fulfilled.
  192. *
  193. * The promise's fulfillment value is an array with fulfillment values at
  194. * respective positions to the original array. If any promise in the array
  195. * rejects, the returned promise is rejected with the rejection reason.
  196. *
  197. * @param mixed $promises Promises or values.
  198. * @param bool $recursive - If true, resolves new promises that might have been added to the stack during its own resolution.
  199. *
  200. * @return PromiseInterface
  201. */
  202. function all($promises, $recursive = false)
  203. {
  204. $results = [];
  205. $promise = \GuzzleHttp\Promise\each(
  206. $promises,
  207. function ($value, $idx) use (&$results) {
  208. $results[$idx] = $value;
  209. },
  210. function ($reason, $idx, Promise $aggregate) {
  211. $aggregate->reject($reason);
  212. }
  213. )->then(function () use (&$results) {
  214. ksort($results);
  215. return $results;
  216. });
  217. if (true === $recursive) {
  218. $promise = $promise->then(function ($results) use ($recursive, &$promises) {
  219. foreach ($promises AS $promise) {
  220. if (\GuzzleHttp\Promise\PromiseInterface::PENDING === $promise->getState()) {
  221. return all($promises, $recursive);
  222. }
  223. }
  224. return $results;
  225. });
  226. }
  227. return $promise;
  228. }
  229. /**
  230. * Initiate a competitive race between multiple promises or values (values will
  231. * become immediately fulfilled promises).
  232. *
  233. * When count amount of promises have been fulfilled, the returned promise is
  234. * fulfilled with an array that contains the fulfillment values of the winners
  235. * in order of resolution.
  236. *
  237. * This promise is rejected with a {@see GuzzleHttp\Promise\AggregateException}
  238. * if the number of fulfilled promises is less than the desired $count.
  239. *
  240. * @param int $count Total number of promises.
  241. * @param mixed $promises Promises or values.
  242. *
  243. * @return PromiseInterface
  244. */
  245. function some($count, $promises)
  246. {
  247. $results = [];
  248. $rejections = [];
  249. return \GuzzleHttp\Promise\each(
  250. $promises,
  251. function ($value, $idx, PromiseInterface $p) use (&$results, $count) {
  252. if ($p->getState() !== PromiseInterface::PENDING) {
  253. return;
  254. }
  255. $results[$idx] = $value;
  256. if (count($results) >= $count) {
  257. $p->resolve(null);
  258. }
  259. },
  260. function ($reason) use (&$rejections) {
  261. $rejections[] = $reason;
  262. }
  263. )->then(
  264. function () use (&$results, &$rejections, $count) {
  265. if (count($results) !== $count) {
  266. throw new AggregateException(
  267. 'Not enough promises to fulfill count',
  268. $rejections
  269. );
  270. }
  271. ksort($results);
  272. return array_values($results);
  273. }
  274. );
  275. }
  276. /**
  277. * Like some(), with 1 as count. However, if the promise fulfills, the
  278. * fulfillment value is not an array of 1 but the value directly.
  279. *
  280. * @param mixed $promises Promises or values.
  281. *
  282. * @return PromiseInterface
  283. */
  284. function any($promises)
  285. {
  286. return some(1, $promises)->then(function ($values) { return $values[0]; });
  287. }
  288. /**
  289. * Returns a promise that is fulfilled when all of the provided promises have
  290. * been fulfilled or rejected.
  291. *
  292. * The returned promise is fulfilled with an array of inspection state arrays.
  293. *
  294. * @param mixed $promises Promises or values.
  295. *
  296. * @return PromiseInterface
  297. * @see GuzzleHttp\Promise\inspect for the inspection state array format.
  298. */
  299. function settle($promises)
  300. {
  301. $results = [];
  302. return \GuzzleHttp\Promise\each(
  303. $promises,
  304. function ($value, $idx) use (&$results) {
  305. $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
  306. },
  307. function ($reason, $idx) use (&$results) {
  308. $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];
  309. }
  310. )->then(function () use (&$results) {
  311. ksort($results);
  312. return $results;
  313. });
  314. }
  315. /**
  316. * Given an iterator that yields promises or values, returns a promise that is
  317. * fulfilled with a null value when the iterator has been consumed or the
  318. * aggregate promise has been fulfilled or rejected.
  319. *
  320. * $onFulfilled is a function that accepts the fulfilled value, iterator
  321. * index, and the aggregate promise. The callback can invoke any necessary side
  322. * effects and choose to resolve or reject the aggregate promise if needed.
  323. *
  324. * $onRejected is a function that accepts the rejection reason, iterator
  325. * index, and the aggregate promise. The callback can invoke any necessary side
  326. * effects and choose to resolve or reject the aggregate promise if needed.
  327. *
  328. * @param mixed $iterable Iterator or array to iterate over.
  329. * @param callable $onFulfilled
  330. * @param callable $onRejected
  331. *
  332. * @return PromiseInterface
  333. */
  334. function each(
  335. $iterable,
  336. callable $onFulfilled = null,
  337. callable $onRejected = null
  338. ) {
  339. return (new EachPromise($iterable, [
  340. 'fulfilled' => $onFulfilled,
  341. 'rejected' => $onRejected
  342. ]))->promise();
  343. }
  344. /**
  345. * Like each, but only allows a certain number of outstanding promises at any
  346. * given time.
  347. *
  348. * $concurrency may be an integer or a function that accepts the number of
  349. * pending promises and returns a numeric concurrency limit value to allow for
  350. * dynamic a concurrency size.
  351. *
  352. * @param mixed $iterable
  353. * @param int|callable $concurrency
  354. * @param callable $onFulfilled
  355. * @param callable $onRejected
  356. *
  357. * @return PromiseInterface
  358. */
  359. function each_limit(
  360. $iterable,
  361. $concurrency,
  362. callable $onFulfilled = null,
  363. callable $onRejected = null
  364. ) {
  365. return (new EachPromise($iterable, [
  366. 'fulfilled' => $onFulfilled,
  367. 'rejected' => $onRejected,
  368. 'concurrency' => $concurrency
  369. ]))->promise();
  370. }
  371. /**
  372. * Like each_limit, but ensures that no promise in the given $iterable argument
  373. * is rejected. If any promise is rejected, then the aggregate promise is
  374. * rejected with the encountered rejection.
  375. *
  376. * @param mixed $iterable
  377. * @param int|callable $concurrency
  378. * @param callable $onFulfilled
  379. *
  380. * @return PromiseInterface
  381. */
  382. function each_limit_all(
  383. $iterable,
  384. $concurrency,
  385. callable $onFulfilled = null
  386. ) {
  387. return each_limit(
  388. $iterable,
  389. $concurrency,
  390. $onFulfilled,
  391. function ($reason, $idx, PromiseInterface $aggregate) {
  392. $aggregate->reject($reason);
  393. }
  394. );
  395. }
  396. /**
  397. * Returns true if a promise is fulfilled.
  398. *
  399. * @param PromiseInterface $promise
  400. *
  401. * @return bool
  402. */
  403. function is_fulfilled(PromiseInterface $promise)
  404. {
  405. return $promise->getState() === PromiseInterface::FULFILLED;
  406. }
  407. /**
  408. * Returns true if a promise is rejected.
  409. *
  410. * @param PromiseInterface $promise
  411. *
  412. * @return bool
  413. */
  414. function is_rejected(PromiseInterface $promise)
  415. {
  416. return $promise->getState() === PromiseInterface::REJECTED;
  417. }
  418. /**
  419. * Returns true if a promise is fulfilled or rejected.
  420. *
  421. * @param PromiseInterface $promise
  422. *
  423. * @return bool
  424. */
  425. function is_settled(PromiseInterface $promise)
  426. {
  427. return $promise->getState() !== PromiseInterface::PENDING;
  428. }
  429. /**
  430. * @see Coroutine
  431. *
  432. * @param callable $generatorFn
  433. *
  434. * @return PromiseInterface
  435. */
  436. function coroutine(callable $generatorFn)
  437. {
  438. return new Coroutine($generatorFn);
  439. }