Repository: laravel/framework
File: src/Illuminate/Http/Client/Promises/LazyPromise.php (PHP)

Code before:
    /**
     * Create a new lazy promise instance.
     *
     * @param  (\Closure(): \GuzzleHttp\Promise\PromiseInterface)  $promiseBuilder  The callback to build a new PromiseInterface.
     */
    public function __construct(protected Closure $promiseBuilder)
    {
    }

    /**
     * Build the promise from the promise builder.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     *
     * @throws \RuntimeException If the promise has already been built
     */
    public function buildPromise(): PromiseInterface
    {
        if (! $this->promiseNeedsBuilt()) {
            throw new RuntimeException('Promise already built');
        }

        $this->guzzlePromise = call_user_func($this->promiseBuilder);

        foreach ($this->pending as $pendingCallback) {
            $pendingCallback($this->guzzlePromise);
        }

        return $this->guzzlePromise;
    }

    /**
     * If the promise has been created from the promise builder.
     *
     * @return bool
     */
    public function promiseNeedsBuilt(): bool
    {
        return ! isset($this->guzzlePromise);
    }

    #[\Override]
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface
    {
        $this->pending[] = static fn (PromiseInterface $promise) => $promise->then($onFulfilled, $onRejected);

        return $this;
    }

    #[\Override]
    public function otherwise(callable $onRejected): PromiseInterface

Review comment (suggestion):
We _could_ possibly merge the behavior of FluentPromise with this by doing something like:

```php
$result = $pendingCallback($this->guzzlePromise);
if ($result instanceof PromiseInterface) {
    $this->guzzlePromise = $result;
}
```

Code after:
    /**
     * Create a new lazy promise instance.
     *
     * @param  (\Closure(): \GuzzleHttp\Promise\PromiseInterface)  $promiseBuilder  The callback to build a new PromiseInterface.
     */
    public function __construct(protected Closure $promiseBuilder)
    {
    }

    /**
     * Build the promise from the promise builder.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     *
     * @throws \RuntimeException If the promise has already been built
     */
    public function buildPromise(): PromiseInterface
    {
        if (! $this->promiseNeedsBuilt()) {
            throw new RuntimeException('Promise already built');
        }

        $this->guzzlePromise = call_user_func($this->promiseBuilder);

        foreach ($this->pending as $pendingCallback) {
            $pendingCallback($this->guzzlePromise);
        }

        $this->pending = [];

        return $this->guzzlePromise;
    }

    #[\Override]
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface
    {
        if ($this->promiseNeedsBuilt()) {
            $this->pending[] = static fn (PromiseInterface $promise) => $promise->then($onFulfilled, $onRejected);

            return $this;
        }

        return $this->guzzlePromise->then($onFulfilled, $onRejected);
    }

    #[\Override]
    public function otherwise(callable $onRejected): PromiseInterface
    {
        if ($this->promiseNeedsBuilt()) {
            $this->pending[] = static fn (PromiseInterface $promise) => $promise->otherwise($onRejected);