Passed
Push — master ( 89369f...5a90e9 )
by Vladimir
03:51
created

SyncPromiseAdapter::then()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 3
crap 1
1
<?php
2
namespace GraphQL\Executor\Promise\Adapter;
3
4
use GraphQL\Deferred;
5
use GraphQL\Error\InvariantViolation;
6
use GraphQL\Executor\Promise\Promise;
7
use GraphQL\Executor\Promise\PromiseAdapter;
8
use GraphQL\Utils\Utils;
9
10
/**
11
 * Class SyncPromiseAdapter
12
 *
13
 * Allows changing order of field resolution even in sync environments
14
 * (by leveraging queue of deferreds and promises)
15
 *
16
 * @package GraphQL\Executor\Promise\Adapter
17
 */
18
class SyncPromiseAdapter implements PromiseAdapter
19
{
20
    /**
21
     * @inheritdoc
22
     */
23 186
    public function isThenable($value)
24
    {
25 186
        return $value instanceof Deferred;
26
    }
27
28
    /**
29
     * @inheritdoc
30
     */
31 41
    public function convertThenable($thenable)
32
    {
33 41
        if (!$thenable instanceof Deferred) {
34 1
            throw new InvariantViolation('Expected instance of GraphQL\Deferred, got ' . Utils::printSafe($thenable));
35
        }
36 41
        return new Promise($thenable->promise, $this);
37
    }
38
39
    /**
40
     * @inheritdoc
41
     */
42 198
    public function then(Promise $promise, callable $onFulfilled = null, callable $onRejected = null)
43
    {
44
        /** @var SyncPromise $promise */
45 198
        $promise = $promise->adoptedPromise;
0 ignored issues
show
Bug introduced by
The property adoptedPromise does not seem to exist on GraphQL\Executor\Promise\Adapter\SyncPromise.
Loading history...
46 198
        return new Promise($promise->then($onFulfilled, $onRejected), $this);
47
    }
48
49
    /**
50
     * @inheritdoc
51
     */
52 188
    public function create(callable $resolver)
53
    {
54 188
        $promise = new SyncPromise();
55
56
        try {
57 188
            $resolver(
58 188
                [$promise, 'resolve'],
59 188
                [$promise, 'reject']
60
            );
61
        } catch (\Exception $e) {
62
            $promise->reject($e);
63
        } catch (\Throwable $e) {
64
            $promise->reject($e);
65
        }
66
67 188
        return new Promise($promise, $this);
68
    }
69
70
    /**
71
     * @inheritdoc
72
     */
73 61
    public function createFulfilled($value = null)
74
    {
75 61
        $promise = new SyncPromise();
76 61
        return new Promise($promise->resolve($value), $this);
77
    }
78
79
    /**
80
     * @inheritdoc
81
     */
82 27
    public function createRejected($reason)
83
    {
84 27
        $promise = new SyncPromise();
85 27
        return new Promise($promise->reject($reason), $this);
86
    }
87
88
    /**
89
     * @inheritdoc
90
     */
91 40
    public function all(array $promisesOrValues)
92
    {
93 40
        $all = new SyncPromise();
94
95 40
        $total = count($promisesOrValues);
96 40
        $count = 0;
97 40
        $result = [];
98
99 40
        foreach ($promisesOrValues as $index => $promiseOrValue) {
100 40
            if ($promiseOrValue instanceof Promise) {
101 40
                $result[$index] = null;
102 40
                $promiseOrValue->then(
103 40
                    function($value) use ($index, &$count, $total, &$result, $all) {
104 38
                        $result[$index] = $value;
105 38
                        $count++;
106 38
                        if ($count >= $total) {
107 38
                            $all->resolve($result);
108
                        }
109 40
                    },
110 40
                    [$all, 'reject']
111
                );
112
            } else {
113 10
                $result[$index] = $promiseOrValue;
114 40
                $count++;
115
            }
116
        }
117 40
        if ($count === $total) {
118 1
            $all->resolve($result);
119
        }
120 40
        return new Promise($all, $this);
121
    }
122
123
    /**
124
     * Synchronously wait when promise completes
125
     *
126
     * @param Promise $promise
127
     * @return mixed
128
     */
129 215
    public function wait(Promise $promise)
130
    {
131 215
        $this->beforeWait($promise);
132 215
        $dfdQueue = Deferred::getQueue();
133 215
        $promiseQueue = SyncPromise::getQueue();
134
135
        while (
136 215
            $promise->adoptedPromise->state === SyncPromise::PENDING &&
137 215
            !($dfdQueue->isEmpty() && $promiseQueue->isEmpty())
138
        ) {
139 193
            Deferred::runQueue();
140 193
            SyncPromise::runQueue();
141 193
            $this->onWait($promise);
142
        }
143
144
        /** @var SyncPromise $syncPromise */
145 215
        $syncPromise = $promise->adoptedPromise;
146
147 215
        if ($syncPromise->state === SyncPromise::FULFILLED) {
148 215
            return $syncPromise->result;
149
        } else if ($syncPromise->state === SyncPromise::REJECTED) {
150
            throw $syncPromise->result;
151
        }
152
153
        throw new InvariantViolation("Could not resolve promise");
154
    }
155
156
    /**
157
     * Execute just before starting to run promise completion
158
     *
159
     * @param Promise $promise
160
     */
161 215
    protected function beforeWait(Promise $promise)
0 ignored issues
show
Unused Code introduced by
The parameter $promise is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

161
    protected function beforeWait(/** @scrutinizer ignore-unused */ Promise $promise)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
162
    {
163 215
    }
164
165
    /**
166
     * Execute while running promise completion
167
     *
168
     * @param Promise $promise
169
     */
170 193
    protected function onWait(Promise $promise)
0 ignored issues
show
Unused Code introduced by
The parameter $promise is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

170
    protected function onWait(/** @scrutinizer ignore-unused */ Promise $promise)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
171
    {
172 193
    }
173
}
174