PriorityQueueTrait::getIterator()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Shared
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Shared\Queue;
16
17
/**
18
 * PriorityQueueTrait
19
 *
20
 * @package Phossa2\Shared
21
 * @author  Hong Zhang <[email protected]>
22
 * @see     PriorityQueueInterface
23
 * @version 2.0.20
24
 * @since   2.0.20 added
25
 * @since   2.0.21 updated to store extra data
26
 */
27
trait PriorityQueueTrait
28
{
29
    /**
30
     * inner data storage
31
     *
32
     * @var    array
33
     * @access protected
34
     */
35
    protected $queue = [];
36
37
    /**
38
     * marker for sorted queue
39
     *
40
     * @var    bool
41
     * @access protected
42
     */
43
    protected $sorted = false;
44
45
    /**
46
     * priority counter, descreasing
47
     *
48
     * @var    int
49
     * @access protected
50
     */
51
    protected $counter = 10000000;
52
53
    /**
54
     * {@inheritDoc}
55
     *
56
     * @since  2.0.21 added extra data
57
     */
58
    public function insert($data, /*# int */ $priority = 0, $extra = null)
59
    {
60
        // fix priority
61
        $pri = $this->fixPriority((int) $priority);
62
63
        // generate key to be used (int)
64
        $key = $this->generateKey($pri);
65
66
        // make sure not duplicated
67
        $this->remove($data);
68
69
        // added to the queue
70
        $this->queue[$key] = [
71
            'data' => $data, 'priority' => $pri, 'extra' => $extra
72
        ];
73
74
        // mark as not sorted
75
        $this->sorted = false;
76
77
        return $this;
78
    }
79
80
    /**
81
     * {@inheritDoc}
82
     */
83
    public function remove($data)
84
    {
85
        foreach ($this->queue as $key => $val) {
86
            if ($val['data'] === $data) {
87
                unset($this->queue[$key]);
88
                break;
89
            }
90
        }
91
        return $this;
92
    }
93
94
    /**
95
     * {@inheritdic}
96
     */
97
    public function flush()
98
    {
99
        $this->queue = [];
100
        return $this;
101
    }
102
103
    /**
104
     * {@inheritDoc}
105
     */
106
    public function combine(
107
        PriorityQueueInterface $queue
108
    )/*# : PriorityQueueInterface */ {
109
        // clone a new queue
110
        $nqueue = clone $this;
111
112
        // insert into new queue
113
        foreach ($queue as $data) {
114
            $nqueue->insert($data['data'], $data['priority'], $data['extra']);
115
        }
116
117
        return $nqueue;
118
    }
119
120
    /**
121
     * {@inheritDoc}
122
     */
123
    public function count()
124
    {
125
        return count($this->queue);
126
    }
127
128
    /**
129
     * {@inheritDoc}
130
     */
131
    public function getIterator()
132
    {
133
        // sort queue if not yet
134
        $this->sortQueue();
135
136
        // return iterator
137
        return new \ArrayIterator($this->queue);
138
    }
139
140
    /**
141
     * Make sure priority in the range of -100 - +100
142
     *
143
     * @param  int $priority
144
     * @return int
145
     * @access protected
146
     */
147
    protected function fixPriority(/*# int */ $priority)/*# : int */
148
    {
149
        return (int) ($priority > 100 ? 100 : ($priority < -100 ? -100 : $priority));
150
    }
151
152
    /**
153
     * Generate one int base on the priority
154
     *
155
     * @param  int $priority
156
     * @return int
157
     * @access protected
158
     */
159
    protected function generateKey(/*# int */ $priority)/*# : int */
160
    {
161
        return ($priority + 100) * 10000000 + --$this->counter;
162
    }
163
164
    /**
165
     * Sort the queue from higher to lower int $key
166
     *
167
     * @return $this
168
     * @access protected
169
     */
170
    protected function sortQueue()
171
    {
172
        if (!$this->sorted) {
173
            krsort($this->queue);
174
            $this->sorted = true;
175
        }
176
        return $this;
177
    }
178
}
179