1<?php
2
3declare(strict_types=1);
4
5namespace GuzzleHttp\Promise;
6
7final class Each
8{
9    /**
10     * Given an iterator that yields promises or values, returns a promise that
11     * is fulfilled with a null value when the iterator has been consumed or
12     * the aggregate promise has been fulfilled or rejected.
13     *
14     * $onFulfilled is a function that accepts the fulfilled value, iterator
15     * index, and the aggregate promise. The callback can invoke any necessary
16     * side effects and choose to resolve or reject the aggregate if needed.
17     *
18     * $onRejected is a function that accepts the rejection reason, iterator
19     * index, and the aggregate promise. The callback can invoke any necessary
20     * side effects and choose to resolve or reject the aggregate if needed.
21     *
22     * @param mixed $iterable Iterator or array to iterate over.
23     */
24    public static function of(
25        $iterable,
26        callable $onFulfilled = null,
27        callable $onRejected = null
28    ): PromiseInterface {
29        return (new EachPromise($iterable, [
30            'fulfilled' => $onFulfilled,
31            'rejected' => $onRejected,
32        ]))->promise();
33    }
34
35    /**
36     * Like of, but only allows a certain number of outstanding promises at any
37     * given time.
38     *
39     * $concurrency may be an integer or a function that accepts the number of
40     * pending promises and returns a numeric concurrency limit value to allow
41     * for dynamic a concurrency size.
42     *
43     * @param mixed        $iterable
44     * @param int|callable $concurrency
45     */
46    public static function ofLimit(
47        $iterable,
48        $concurrency,
49        callable $onFulfilled = null,
50        callable $onRejected = null
51    ): PromiseInterface {
52        return (new EachPromise($iterable, [
53            'fulfilled' => $onFulfilled,
54            'rejected' => $onRejected,
55            'concurrency' => $concurrency,
56        ]))->promise();
57    }
58
59    /**
60     * Like limit, but ensures that no promise in the given $iterable argument
61     * is rejected. If any promise is rejected, then the aggregate promise is
62     * rejected with the encountered rejection.
63     *
64     * @param mixed        $iterable
65     * @param int|callable $concurrency
66     */
67    public static function ofLimitAll(
68        $iterable,
69        $concurrency,
70        callable $onFulfilled = null
71    ): PromiseInterface {
72        return self::ofLimit(
73            $iterable,
74            $concurrency,
75            $onFulfilled,
76            function ($reason, $idx, PromiseInterface $aggregate): void {
77                $aggregate->reject($reason);
78            }
79        );
80    }
81}
82