Completed
Push — master ( c1a156...8cadde )
by Kirill
08:14
created

Deferred::throw()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 1
dl 0
loc 16
ccs 0
cts 9
cp 0
crap 20
rs 9.7333
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\SDL\Compiler\Process;
11
12
/**
13
 * Class Deferred
14
 */
15
class Deferred implements DeferredInterface, Emittable
16
{
17
    /**
18
     * @var \SplQueue|\Closure[]
19
     */
20
    private $handlers;
21
22
    /**
23
     * @var \SplQueue|\Closure[]
24
     */
25
    private $interceptors;
26
27
    /**
28
     * Deferred constructor.
29
     */
30 119
    public function __construct()
31
    {
32 119
        $this->handlers = new \SplQueue();
33 119
        $this->interceptors = new \SplQueue();
34 119
    }
35
36
    /**
37
     * @param \Closure $then
38
     * @return DeferredInterface
39
     */
40 119
    public function then(\Closure $then): DeferredInterface
41
    {
42 119
        $this->handlers->push($then);
43
44 119
        return $this;
45
    }
46
47
    /**
48
     * @param \Closure $exception
49
     * @return DeferredInterface
50
     */
51
    public function catch(\Closure $exception): DeferredInterface
0 ignored issues
show
Coding Style introduced by
Possible parse error: non-abstract method defined as abstract
Loading history...
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
52
    {
53
        $this->interceptors->push($exception);
54
55
        return $this;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $this.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
56
    }
57
58
    /**
59
     * @return \Generator
60
     * @throws \Throwable
61
     */
62 119
    public function emit(): \Generator
63
    {
64 119
        while ($this->handlers->count() > 0) {
65 119
            $callback = $this->handlers->shift();
66
67
            try {
68 119
                yield $callback();
69
            } catch (\Throwable $e) {
70
                $this->throw($e);
71
            }
72
        }
73 119
    }
74
75
    /**
76
     * @return mixed|null
77
     * @throws \Throwable
78
     */
79
    public function wait()
80
    {
81
        foreach ($ctx = $this->emit() as $i => $tick) {
82
            if ($tick instanceof \Throwable) {
83
                $ctx->throw($tick);
84
            }
85
        }
86
87
        return $ctx->getReturn();
88
    }
89
90
    /**
91
     * @param \Throwable $exception
92
     * @throws \Throwable
93
     */
94
    private function throw(\Throwable $exception)
95
    {
96
        if ($this->interceptors->count() === 0) {
97
            throw $exception;
98
        }
99
100
        while ($this->interceptors->count() > 0) {
101
            $catch = $this->interceptors->shift();
102
103
            try {
104
                $catch($exception);
105
            } catch (\Throwable $e) {
106
                $this->throw($e);
107
            }
108
        }
109
    }
110
}
111