RegisterDiscoveredEvents::doDiscovery()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 4
nop 0
dl 0
loc 15
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
namespace ByTIC\EventDispatcher\Discovery;
4
5
use Nip\Cache\Cacheable\CanCache;
6
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
7
use function app;
8
use function config;
9
10
/**
11
 * Class DiscoverProvider
12
 * @package ByTIC\EventDispatcher\ListenerProviders\Discover
13
 *
14
 * @internal
15
 */
16
class RegisterDiscoveredEvents
17
{
18
    use CanCache;
19
20
    /**
21
     * @var EventDispatcherInterface
22
     */
23
    protected $dispatcher;
24
25
    /**
26
     * @var ?array
27
     */
28
    protected $discovered = null;
29
30
    protected $discoveryPath = null;
31
32
    /**
33
     * RegisterDiscoveredEvents constructor.
34
     * @param EventDispatcherInterface $dispatcher
35
     */
36
    public function __construct(EventDispatcherInterface $dispatcher)
37
    {
38
        $this->dispatcher = $dispatcher;
39
    }
40
41
    /**
42
     * @inheritDoc
43
     */
44
    public function register()
45
    {
46
        $events = $this->discover();
47
        foreach ($events as $event => $listeners) {
48
            foreach ($listeners as $listener) {
49
                $this->dispatcher->addListener($event, $listener);
50
            }
51
        }
52
    }
53
54
    /**
55
     * @return null
56
     */
57
    protected function discover(): ?array
58
    {
59
        if ($this->discovered === null) {
60
            $data = $this->getDataFromCache();
61
            if (!is_array($data)) {
62
                $data = $this->doDiscovery();
63
                $this->saveDataToCache($data);
64
            }
65
            $this->discovered = $data;
66
        }
67
        return $this->discovered;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->discovered returns the type array which is incompatible with the documented return type null.
Loading history...
68
    }
69
70
    protected function doDiscovery(): array
71
    {
72
        $path = $this->discoverEventsWithin();
73
        $return = [];
74
75
        if (count($path) < 1) {
76
            return $return;
77
        }
78
        $eventsArray = DiscoverEvents::within($path);
79
        foreach ($eventsArray as $event => $listeners) {
80
            foreach ($listeners as $listener) {
81
                $return[$event][] = $listener;
82
            }
83
        }
84
        return $return;
85
    }
86
87
    /**
88
     * Get the listener directories that should be used to discover events.
89
     *
90
     * @return array
91
     */
92
    protected function discoverEventsWithin(): array
93
    {
94
        if ($this->discoveryPath === null) {
95
            $this->discoveryPath = $this->detectDiscoveryPath();
96
        }
97
98
        return $this->discoveryPath;
99
    }
100
101
    /**
102
     * @param string $path
103
     */
104
    public function addDiscoveryPath(string $path)
105
    {
106
        $this->discoveryPath[] = $path;
107
    }
108
109
    /**
110
     * @return array
111
     */
112
    protected function detectDiscoveryPath(): array
113
    {
114
        $paths = $this->detectDiscoveryFromConfig();
115
        if (count($paths)) {
116
            return $paths;
117
        }
118
        return $this->detectDiscoveryFromApplication();
119
    }
120
121
    protected function detectDiscoveryFromConfig(): array
122
    {
123
        if (!function_exists('config')) {
124
            return [];
125
        }
126
127
        $config = config('event-dispatcher.listener_paths');
128
        if (!$config) {
129
            return [];
130
        }
131
        $paths = $config->toArray();
132
        foreach ($paths as $key => $path) {
133
            if (!is_dir($path)) {
134
                unset($paths[$key]);
135
            }
136
        }
137
        return $paths;
138
    }
139
140
    protected function detectDiscoveryFromApplication(): array
141
    {
142
        $basePath = $this->detectApplicationPath();
143
        if (!is_dir($basePath)) {
0 ignored issues
show
Bug introduced by
It seems like $basePath can also be of type false; however, parameter $filename of is_dir() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

143
        if (!is_dir(/** @scrutinizer ignore-type */ $basePath)) {
Loading history...
144
            return [];
145
        }
146
147
        $folder = $basePath . '/Listeners';
0 ignored issues
show
Bug introduced by
Are you sure $basePath of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

147
        $folder = /** @scrutinizer ignore-type */ $basePath . '/Listeners';
Loading history...
148
        if (!is_dir($folder)) {
149
            return [];
150
        }
151
152
        return [
153
            $folder,
154
        ];
155
    }
156
157
    /**
158
     * @return false|string
159
     */
160
    protected function detectApplicationPath()
161
    {
162
        if (defined('APPLICATION_PATH')) {
163
            return APPLICATION_PATH;
0 ignored issues
show
Bug introduced by
The constant ByTIC\EventDispatcher\Discovery\APPLICATION_PATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
164
        }
165
        if (!function_exists('app')) {
166
            return false;
167
        }
168
        $app = app();
169
        if ($app->has('path')) {
170
            return $app->get('path');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $app->get('path') also could return the type object which is incompatible with the documented return type false|string.
Loading history...
171
        }
172
        return false;
173
    }
174
175
    public function generateCacheData(): array
176
    {
177
        return $this->doDiscovery();
178
    }
179
}
180