Completed
Push — master ( ee9170...1dcd4f )
by Kirill
03:45
created

Pipeline::next()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 0
loc 10
ccs 0
cts 9
cp 0
crap 12
rs 9.9332
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;
11
12
/**
13
 * Class Pipeline
14
 */
15
class Pipeline implements \IteratorAggregate, \Countable
16
{
17
    /**
18
     * @var int
19
     */
20
    public const PRIORITY_DEFINITION = 0x01;
21
22
    /**
23
     * @var int
24
     */
25
    public const PRIORITY_EXTENSION = 0x02;
26
27
    /**
28
     * @var int
29
     */
30
    public const PRIORITY_INVOCATION = 0x03;
31
32
    /**
33
     * Example struct:
34
     *
35
     * <code>
36
     *  [
37
     *      PRIORITY_1 => \SplQueue([1, 2, 3]),
38
     *      PRIORITY_2 => \SplQueue([1, 2, 3]),
39
     *      PRIORITY_3 => \SplQueue([1, 2, 3]),
40
     *  ]
41
     * </code>
42
     *
43
     * @var \SplQueue[]
44
     */
45
    private $queue = [];
46
47
    /**
48
     * @return \Traversable|callable[]
49
     */
50
    public function getIterator(): \Traversable
51
    {
52
        while ($next = $this->next()) {
53
            yield $next;
54
        }
55
    }
56
57
    /**
58
     * @return null|callable
59
     */
60
    private function next(): ?callable
61
    {
62
        foreach ($this->queue as $queue) {
63
            if ($queue->count() > 0) {
64
                return $queue->shift();
65
            }
66
        }
67
68
        return null;
69
    }
70
71
    /**
72
     * @param int $priority
73
     * @param callable $then
74
     */
75
    public function push(int $priority, callable $then): void
76
    {
77
        if (! \array_key_exists($priority, $this->queue)) {
78
            $this->queue[$priority] = $this->createList();
79
        }
80
81
        $this->queue[$priority]->push($then);
82
    }
83
84
    /**
85
     * @return \SplDoublyLinkedList
86
     */
87
    protected function createList(): \SplDoublyLinkedList
88
    {
89
        return new \SplQueue();
90
    }
91
92
    /**
93
     * @return int
94
     */
95
    public function count(): int
96
    {
97
        return (int)\array_reduce($this->queue, function (int $result, \SplQueue $queue): int {
98
            return $result + $queue->count();
99
        }, 0);
100
    }
101
102
    /**
103
     * @return callable
104
     * @throws \UnderflowException
105
     */
106
    public function pop(): callable
107
    {
108
        $result = $this->next();
109
110
        if ($result === null) {
111
            throw new \UnderflowException('Can not fetch data from empty heap');
112
        }
113
114
        return $result;
115
    }
116
}
117