1 | <?php |
||
2 | |||
3 | namespace TwoDojo\ModuleManager; |
||
4 | |||
5 | use Illuminate\Support\Facades\Route; |
||
6 | use TwoDojo\Module\AbstractModule; |
||
7 | use TwoDojo\ModuleManager\Exceptions\ModuleNotFoundException; |
||
8 | use TwoDojo\ModuleManager\Support\EventDispatcher; |
||
9 | use TwoDojo\ModuleManager\Support\Requester; |
||
10 | |||
11 | class ModuleManager |
||
12 | { |
||
13 | /** |
||
14 | * @var \Illuminate\Support\Collection |
||
15 | */ |
||
16 | private $modules; |
||
17 | |||
18 | /** |
||
19 | * @var \Illuminate\Contracts\Foundation\Application |
||
20 | */ |
||
21 | private $app; |
||
22 | |||
23 | /** |
||
24 | * @var \TwoDojo\ModuleManager\Repositories\ModuleRegistryRepository |
||
25 | */ |
||
26 | private $registry; |
||
27 | |||
28 | /** |
||
29 | * @var \TwoDojo\ModuleManager\Support\EventDispatcher |
||
30 | */ |
||
31 | private $dispatcher; |
||
32 | |||
33 | /** |
||
34 | * @var array |
||
35 | */ |
||
36 | private $resolvedModules = []; |
||
37 | |||
38 | /** |
||
39 | * ModuleManager constructor. |
||
40 | * @param \Illuminate\Contracts\Foundation\Application $app |
||
41 | * @param \TwoDojo\ModuleManager\Repositories\ModuleRegistryRepository $registry |
||
42 | */ |
||
43 | public function __construct($app, $registry) |
||
44 | { |
||
45 | $this->modules = collect([]); |
||
46 | $this->app = $app; |
||
47 | $this->registry = $registry; |
||
48 | $this->dispatcher = $this->app->make(EventDispatcher::class); |
||
49 | } |
||
50 | |||
51 | /** |
||
52 | * @param string $module |
||
53 | * @return bool |
||
54 | */ |
||
55 | public function registerModule($module) : bool |
||
56 | { |
||
57 | $module = $this->app->make($module); |
||
58 | |||
59 | // If the module is already registered we skip it |
||
60 | if ($this->hasModule($module->getUniqueName())) { |
||
61 | return false; |
||
62 | } |
||
63 | |||
64 | // If the module not enabled we skip it |
||
65 | if (!$module->isEnabled()) { |
||
66 | return false; |
||
67 | } |
||
68 | |||
69 | $this->dispatcher->registerListener($module); |
||
70 | |||
71 | $this->modules->put($module->getUniqueName(), $module); |
||
72 | |||
73 | $record = $this->registry->find($module->getUniqueName()); |
||
74 | // If we not found the record for this module then we assumed the module is just installed |
||
75 | if ($record === null) { |
||
76 | $this->registry->save([ |
||
77 | 'uniqueName' => $module->getUniqueName(), |
||
78 | 'is_enabled' => true, |
||
79 | ]); |
||
80 | } |
||
81 | |||
82 | return true; |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * @param string $uniqueName |
||
87 | * @return bool |
||
88 | */ |
||
89 | public function hasModule(string $uniqueName) : bool |
||
90 | { |
||
91 | return $this->modules->has($uniqueName); |
||
92 | } |
||
93 | |||
94 | /** |
||
95 | * Get the requested module or all registered modules |
||
96 | * |
||
97 | * @param null|string $uniqueName |
||
98 | * @return \Illuminate\Support\Collection|\TwoDojo\Module\AbstractModule|null |
||
99 | */ |
||
100 | public function getModule($uniqueName = null) |
||
101 | { |
||
102 | if ($uniqueName === null) { |
||
103 | return $this->modules; |
||
104 | } |
||
105 | |||
106 | return $this->modules->get($uniqueName, null); |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * Initialize the modules |
||
111 | */ |
||
112 | public function initializeModules() |
||
113 | { |
||
114 | $modules = $this->registry->enabled()->all(); |
||
115 | foreach ($modules as $model) { |
||
116 | $module = $this->modules->first(function (AbstractModule $module) use ($model) { |
||
117 | return $module->getUniqueName() === $model->uniqueName; |
||
118 | }); |
||
119 | |||
120 | if ($module === null) { |
||
121 | continue; |
||
122 | } |
||
123 | |||
124 | if (isset($this->resolvedModules[$module->getUniqueName()])) { |
||
125 | continue; |
||
126 | } |
||
127 | |||
128 | $requester = Requester::make()->setBasePath($module->getModulePath()); |
||
129 | if ($requester->exists('routes')) { |
||
130 | $this->initializeModuleRoutes($module, $requester); |
||
131 | } |
||
132 | |||
133 | $this->dispatcher->dispatchEvent($module->getUniqueName(), 'initialized'); |
||
134 | $this->resolvedModules[$module->getUniqueName()] = true; |
||
135 | } |
||
136 | } |
||
137 | |||
138 | protected function initializeModuleRoutes(AbstractModule $module, Requester $requester) |
||
139 | { |
||
140 | foreach ($requester->getFiles('routes') as $routeFile) { |
||
141 | $name = basename($routeFile->getFilename(), '.php'); |
||
142 | $namespace = (new \ReflectionClass($module))->getNamespaceName(); |
||
143 | |||
144 | $route = Route::middleware($name)->namespace($namespace.'\\Http\\Controllers'); |
||
145 | switch ($name) { |
||
146 | case 'api': |
||
147 | $route = $route->prefix($name); |
||
148 | break; |
||
149 | } |
||
150 | |||
151 | $route->group($requester->path('routes/'.$routeFile->getFilename())); |
||
152 | } |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * Enable a module |
||
157 | * |
||
158 | * @param string $uniqueName |
||
159 | * @return bool |
||
160 | * @throws ModuleNotFoundException |
||
161 | */ |
||
162 | public function enableModule($uniqueName) : bool |
||
163 | { |
||
164 | if (!$this->hasModule($uniqueName)) { |
||
165 | throw new ModuleNotFoundException(); |
||
166 | } |
||
167 | |||
168 | return $this->setModuleState($uniqueName, true); |
||
169 | } |
||
170 | |||
171 | /** |
||
172 | * Disable a module |
||
173 | * |
||
174 | * @param string $uniqueName |
||
175 | * @return bool |
||
176 | * @throws ModuleNotFoundException |
||
177 | */ |
||
178 | public function disableModule($uniqueName) : bool |
||
179 | { |
||
180 | if (!$this->hasModule($uniqueName)) { |
||
181 | throw new ModuleNotFoundException(); |
||
182 | } |
||
183 | |||
184 | return $this->setModuleState($uniqueName, false); |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * @param $uniqueName |
||
189 | * @param bool $isEnabled |
||
190 | * @return bool |
||
191 | */ |
||
192 | protected function setModuleState($uniqueName, bool $isEnabled) : bool |
||
193 | { |
||
194 | $module = $this->getModule($uniqueName); |
||
195 | |||
196 | $saved = $this->updateModuleRecord($module, ['is_enabled' => $isEnabled]); |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
197 | if ($saved) { |
||
198 | $this->dispatcher->dispatchEvent($module->getUniqueName(), $isEnabled ? 'enabled' : 'disabled'); |
||
199 | } |
||
200 | |||
201 | return $saved; |
||
202 | } |
||
203 | |||
204 | /** |
||
205 | * @param \TwoDojo\Module\AbstractModule $module |
||
206 | * @param array $data |
||
207 | * @return bool |
||
208 | */ |
||
209 | protected function updateModuleRecord($module, array $data) : bool |
||
210 | { |
||
211 | $record = $this->registry->find($module->getUniqueName())->first(); |
||
212 | if ($record === null) { |
||
213 | $record = $this->registry->save(array_merge_recursive([ |
||
214 | 'uniqueName' => $module->getUniqueName() |
||
215 | ], $data)); |
||
216 | |||
217 | return $record->id !== null; |
||
218 | } |
||
219 | |||
220 | return $this->registry->update($record->id, $data); |
||
221 | } |
||
222 | } |
||
223 |