PromiseDeferred::changeState()   B
last analyzed

Complexity

Conditions 6
Paths 7

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 8.8571
c 0
b 0
f 0
cc 6
eloc 12
nc 7
nop 2
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
    use CancelDeferredTrait;
22
23
    /**
24
     * @var ResolverInterface[]
25
     */
26
    private $resolvers = array();
27
28
    /**
29
     * @var PromiseInterface
30
     */
31
    private $actual = null;
32
33
    /**
34
     * {@inheritdoc}
35
     */
36 View Code Duplication
    public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onNotify = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
37
    {
38
        if ($this->state()->equals(State::PENDING())) {
39
            $resolver = new ThenResolver($onFulfilled, $onRejected, $onNotify);
40
            $this->resolvers[] = $resolver;
41
42
            return $resolver->promise();
43
        }
44
45
        return $this->actual->then($onFulfilled, $onRejected, $onNotify);
46
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51 View Code Duplication
    public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onNotify = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
52
    {
53
        if ($this->state()->equals(State::PENDING())) {
54
            $resolver = new DoneResolver($onFulfilled, $onRejected, $onNotify);
55
            $this->resolvers[] = $resolver;
56
        } else {
57
            $this->actual->done($onFulfilled, $onRejected, $onNotify);
58
        }
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64
    public function resolve($value = null)
65
    {
66
        $this->changeState($value, true);
67
    }
68
69
    /**
70
     * {@inheritdoc}
71
     */
72
    public function reject($reason = null)
73
    {
74
        $this->changeState($reason, false);
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function notify($state = null)
81
    {
82
        if ($this->state()->equals(State::PENDING())) {
83
            foreach ($this->resolvers as $resolver) {
84
                $resolver->notify($state);
85
            }
86
        } else {
87
            throw new \LogicException(\sprintf('A %s promise cannot be notified', $this->state()));
88
        }
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94
    public function state()
95
    {
96
        return $this->actual !== null ? $this->actual->state() : State::PENDING();
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function promise()
103
    {
104
        return $this;
105
    }
106
107
    /**
108
     * @param mixed $result
109
     * @param bool  $success
110
     *
111
     * @throws \LogicException
112
     */
113
    private function changeState($result, $success)
114
    {
115
        if ($this->state()->equals(State::PENDING())) {
116
            $this->actual = $success ? new FulfilledPromise($result) : new RejectedPromise($result);
117
118
            while (!empty($this->resolvers)) {
119
                /** @var \Cubiche\Core\Async\Promise\ResolverInterface $resolver */
120
                $resolver = array_shift($this->resolvers);
121
                if ($success) {
122
                    $resolver->resolve($result);
123
                } else {
124
                    $resolver->reject($result);
125
                }
126
            }
127
        } else {
128
            throw new \LogicException(
129
                \sprintf('A %s promise cannot be %s', $this->state(), $success ? 'resolved' : 'rejected')
130
            );
131
        }
132
    }
133
}
134