Delegate::subscribe()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 13
rs 9.4286
cc 3
eloc 8
nc 4
nop 3
1
<?php
2
/**
3
 * Scabbia2 Events Component
4
 * https://github.com/eserozvataf/scabbia2
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 *
9
 * @link        https://github.com/eserozvataf/scabbia2-events for the canonical source repository
10
 * @copyright   2010-2016 Eser Ozvataf. (http://eser.ozvataf.com/)
11
 * @license     http://www.apache.org/licenses/LICENSE-2.0 - Apache License, Version 2.0
12
 */
13
14
namespace Scabbia\Events;
15
16
/**
17
 * Delegate is an inline members which executes an event-chain execution similar to Events,
18
 * but designed for object-oriented architecture
19
 *
20
 * @package     Scabbia\Events
21
 * @author      Eser Ozvataf <[email protected]>
22
 * @since       2.0.0
23
 *
24
 * @remark SplPriorityQueue could be used, but it doesn't support serialiations.
25
 */
26
class Delegate
27
{
28
    /** @type array   list of callbacks */
29
    public $callbacks = null;
30
    /** @type mixed   stop propagation if false is returned */
31
    public $stopPropagationWithReturn = true;
32
    /** @type bool    priorities sorted or not */
33
    private $prioritiesSorted = true;
34
35
36
    /**
37
     * Constructs a new delegate in order to assign it to a member
38
     *
39
     * @return Delegate a delegate
40
     */
41
    public static function assign()
42
    {
43
        $tNewInstance = new static();
44
45
        return function (/* callable */ $uCallback = null, $uState = null, $uPriority = 10) use ($tNewInstance) {
46
            if ($uCallback !== null) {
47
                $tNewInstance->subscribe($uCallback, $uState, $uPriority);
48
            }
49
50
            return $tNewInstance;
51
        };
52
    }
53
54
    // @codingStandardsIgnoreStart
55
    /**
56
     * Unserializes an instance of delegate
57
     *
58
     * @param array $uPropertyBag properties set of unserialized object
59
     *
60
     * @return Delegate a delegate
61
     */
62
    public static function __set_state(array $uPropertyBag)
63
    {
64
        $tNewInstance = new static();
65
        $tNewInstance->callbacks = $uPropertyBag["callbacks"];
66
67
        return $tNewInstance;
68
    }
69
    // @codingStandardsIgnoreEnd
70
71
    /**
72
     * Subscribes a callback to delegate
73
     *
74
     * @param callback  $uCallback  callback method
75
     * @param mixed     $uState     state object
76
     * @param null|int  $uPriority  priority level
77
     *
78
     * @return void
79
     */
80
    public function subscribe(/* callable */ $uCallback, $uState = null, $uPriority = null)
81
    {
82
        if ($uPriority === null) {
83
            $uPriority = 10;
84
        }
85
86
        if ($this->callbacks === null) {
87
            $this->callbacks = [[$uCallback, $uState, $uPriority]];
88
        } else {
89
            $this->callbacks[] = [$uCallback, $uState, $uPriority];
90
            $this->prioritiesSorted = false;
91
        }
92
    }
93
94
    /**
95
     * Invokes the event-chain execution
96
     *
97
     * @param array $uParameters execution parameters
98
     *
99
     * @return bool whether the propagation is stopped or not
100
     */
101
    public function invoke(...$uParameters)
102
    {
103
        if ($this->callbacks !== null) {
104
            if ($this->prioritiesSorted === false) {
105
                usort($this->callbacks, [$this, 'prioritySort']);
106
                $this->prioritiesSorted = true;
107
            }
108
109
            foreach ($this->callbacks as $tCallback) {
110
                if (call_user_func($tCallback[0], ...$uParameters) === false && $this->stopPropagationWithReturn) {
111
                    return false;
112
                }
113
            }
114
        }
115
116
        return true;
117
    }
118
119
    /**
120
     * Sorts callbacks in order to their priority
121
     *
122
     * @param int $uFirst  first array item
123
     * @param int $uSecond second array item
124
     *
125
     * @return int comparision result that indicates which item comes first
126
     */
127
    private function prioritySort($uFirst, $uSecond)
128
    {
129
        if ($uFirst[2] < $uSecond[2]) {
130
            return -1;
131
        }
132
133
        if ($uFirst[2] > $uSecond[2]) {
134
            return 1;
135
        }
136
137
        return 0;
138
    }
139
}
140