Completed
Push — master ( 5bbdfe...13b325 )
by Mihail
04:51
created

EventManager::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
namespace Ffcms\Core\Event;
3
4
use Ffcms\Core\App;
5
use Ffcms\Core\Helper\Type\Obj;
6
use Ffcms\Core\Helper\Type\Str;
7
use Ffcms\Core\Helper\FileSystem\Directory;
8
use Ffcms\Core\Helper\FileSystem\File;
9
10
/**
11
 * Class EventManager. Control and run events.
12
 * @package \Ffcms\Core\Event
13
 * @author zenn
14
 */
15
class EventManager
16
{
17
    private $events;
18
    private $runned;
19
    
20
    private $runOnBoot = false;
0 ignored issues
show
Unused Code introduced by
The property $runOnBoot is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
21
22
    /**
23
     * EventManager constructor. Get always initiated data from memory storage.
24
     */
25
    public function __construct()
26
    {
27
        // get events from memory object saver
28
        $this->events = App::$Memory->get('events.catched.save');
29
        $this->runned = App::$Memory->get('events.runned.save');
30
    }
31
32
    /**
33
     * Catch the event if it occurred after this initiation of interception
34
     * 
35
     * @param string|array $event            
36
     * @param \Closure $callback            
37
     */
38
    public function on($event, \Closure $callback)
39
    {
40
        // check if event is a single string and parse it to array single item
41
        if (! Obj::isArray($event)) {
42
            $event = [$event];
43
        }
44
        
45
        foreach ($event as $item) {
0 ignored issues
show
Bug introduced by
The expression $event of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
46
            $this->events[$item][] = $callback;
47
        }
48
    }
49
    
50
    /**
51
     * Catch the event if it occurred before the initiation of interception
52
     * @param string|array $event
53
     * @param \Closure $callback
54
     * @return mixed
55
     */
56
    public function listen($event, \Closure $callback)
57
    {
58
        // check if $event is a single string and set it as array with one item
59
        if (!Obj::isArray($event)) {
60
            $event = [$event];
61
        }
62
        
63
        // each every one event in array
64
        foreach ($event as $item) {
0 ignored issues
show
Bug introduced by
The expression $event of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
65
            if (Obj::isArray($this->runned) && array_key_exists($item, $this->runned)) {
66
                return call_user_func_array($callback, $this->runned[$item]);
67
            }    
68
        }
69
        
70
        return false;
71
    }
72
    
73
    /**
74
     * Initialize event on happend
75
     * @return mixed
76
     */
77
    public function run()
78
    {
79
        // dynamicly parse input params
80
        $args = func_get_args();
81
        
82
        if (count($args) < 1) {
83
            return false;
84
        }
85
        
86
        // get event name
87
        $eventName = array_shift($args);
88
        // get event args as array if passed
89
        $eventArgs = @array_shift($args);
90
        
91
        // if event is registered
92
        if (isset($this->events[$eventName]) && Obj::isArray($this->events[$eventName])) {
93
            foreach ($this->events[$eventName] as $callback) {
94
                // call anonymous function with args if passed
95
                return call_user_func_array($callback, $eventArgs);
96
            }
97
        }
98
        
99
        // set to post runned actions
100
        $this->runned[$eventName] = $eventArgs;
101
        return false;
102
    }
103
    
104
    /**
105
     * Initialize bootable static methods in controllers. System method.
106
     * @param object|bool $loader
107
     */
108
    public static function makeBoot($loader = false)
109
    {
110
        $controllers = [root . '/Apps/Controller/' . env_name];
111
        // get custom apps directories from composer autoloader maps
112
        if ($loader !== false) {
113
            $sources = $loader->getPrefixes();
114
            // is there any custom paths for apps binding?
115
            if (Obj::isArray($sources) && isset($sources['Apps\\'])) {
116
                // each every one add a new path to controllers map
117
                $controllers = [];
118
                foreach ($sources['Apps\\'] as $path) {
119
                    $controllers[] = $path . '/Apps/Controller/' . env_name;
120
                }
121
            }
122
        }
123
        
124
        // each every path try to run boot method in ever controller
125
        foreach ($controllers as $path) {
126
            // check if directory exists
127
            if (!Directory::exist($path)) {
128
                continue;
129
            }
130
            $list = File::listFiles($path, ['.php'], true);
131
            // foreach all files in list
132
            foreach ($list as $file) {
133
                // define full class name with namespace
134
                $class = 'Apps\Controller\\' . env_name . '\\' . Str::cleanExtension($file);
135
                // check if class exists (must be loaded over autoloader)
136
                if (class_exists($class)) {
137
                    // check if static method boot is exists
138
                    if (method_exists($class, 'boot')) {
139
                        // call to boot method
140
                        call_user_func([$class, 'boot']);
141
                    }
142
                }
143
            }
144
        }
145
    }
146
147
    /**
148
     * Save events data in memory to prevent any sh@ts ;D
149
     */
150
    public function __destruct()
151
    {
152
        App::$Memory->set('events.catched.save', $this->events);
153
        App::$Memory->set('events.runned.save', $this->runned);
154
        
155
    }
156
    
157
}