Completed
Push — master ( 565401...ee3df5 )
by Ivannis Suárez
02:53
created

PromiseDeferred::then()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 3
1
<?php
2
3
/*
4
 * This file is part of the Cubiche package.
5
 *
6
 * Copyright (c) Cubiche
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Cubiche\Core\Async\Promise;
13
14
/**
15
 * Promise Deferred class.
16
 *
17
 * @author Karel Osorio Ramírez <[email protected]>
18
 */
19
class PromiseDeferred extends AbstractPromise implements DeferredInterface
20
{
21
    /**
22
     * @var DeferredInterface[]
23
     */
24
    private $deferreds = array();
25
26
    /**
27
     * @var PromiseInterface
28
     */
29
    private $actual = null;
30
31
    /**
32
     * @param callable $onFulfilled
33
     * @param callable $onRejected
34
     * @param callable $onNotify
35
     *
36
     * @return PromiseInterface
37
     */
38
    public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onNotify = null)
39
    {
40
        if ($this->state()->equals(State::PENDING())) {
41
            return $this->enqueue($onFulfilled, $onRejected, $onNotify)->promise();
42
        }
43
44
        return $this->actual->then($onFulfilled, $onRejected, $onNotify);
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50
    public function resolve($value = null)
51
    {
52
        $this->changeState($value, true);
53
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58
    public function reject($reason = null)
59
    {
60
        $this->changeState($reason, false);
61
    }
62
63
    /**
64
     * {@inheritdoc}
65
     */
66
    public function notify($state = null)
67
    {
68
        if ($this->state()->equals(State::PENDING())) {
69
            foreach ($this->deferreds as $deferred) {
70
                $deferred->notify($state);
71
            }
72
        } else {
73
            throw new \LogicException(\sprintf('A %s promise cannot be notified', $this->state()->getValue()));
74
        }
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function state()
81
    {
82
        return $this->actual !== null ? $this->actual->state() : State::PENDING();
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88
    public function promise()
89
    {
90
        return $this;
91
    }
92
93
    /**
94
     * @param mixed $result
95
     * @param bool  $success
96
     *
97
     * @throws \LogicException
98
     */
99
    private function changeState($result, $success)
100
    {
101
        if ($this->state()->equals(State::PENDING())) {
102
            $this->actual = $success ? new FulfilledPromise($result) : new RejectedPromise($result);
103
104
            while (!empty($this->deferreds)) {
105
                /** @var \Cubiche\Core\Async\Promise\DeferredInterface $deferred */
106
                $deferred = array_shift($this->deferreds);
107
                if ($success) {
108
                    $deferred->resolve($result);
109
                } else {
110
                    $deferred->reject($result);
111
                }
112
            }
113
        } else {
114
            throw new \LogicException(
115
                \sprintf('A %s promise cannot be %s', $this->state()->getValue(), $success ? 'resolved' : 'rejected')
116
            );
117
        }
118
    }
119
120
    /**
121
     * @param callable $onFulfilled
122
     * @param callable $onRejected
123
     * @param callable $onNotify
124
     *
125
     * @return \Cubiche\Core\Async\Promise\DeferredProxy
126
     */
127
    private function enqueue(callable $onFulfilled = null, callable $onRejected = null, callable $onNotify = null)
128
    {
129
        $deferred = new DeferredProxy(new Deferred(), $onFulfilled, $onRejected, $onNotify, false);
130
        $this->deferreds[] = $deferred;
131
132
        return $deferred;
133
    }
134
}
135