source: trunk/Packages/Common/ModuleManager.php

Last change on this file was 95, checked in by chronos, 3 years ago
  • Modified: Updated Common package.
  • Added: Explicit types for better type checking.
  • Fixed: Support for php 8.0.
File size: 10.0 KB
Line 
1<?php
2
3/* Manage installed modules */
4class ModuleManager
5{
6 public array $Modules; // Module
7 public System $System;
8 public string $FileName;
9 public string $ModulesDir;
10 public $OnLoadModules;
11 public $OnInstallModel;
12 public $OnUninstsallModel;
13 public $OnInstallModule;
14 public $OnUninstsallModule;
15 private int $NewModuleId;
16
17 function __construct(System $System)
18 {
19 $this->Modules = array();
20 $this->System = &$System;
21 $this->FileName = dirname(__FILE__).'/../../Config/ModulesConfig.php';
22 $this->ModulesDir = dirname(__FILE__).'/../../Modules';
23 $this->OnInstallModel = null;
24 $this->OnUninstallModel = null;
25 $this->OnInstallModule = null;
26 $this->OnUninstallModule = null;
27 $this->NewModuleId = 1;
28 }
29
30 function Perform(array $Actions, array $Conditions = array(ModuleCondition::All)): void
31 {
32 $this->PerformList($this->Modules, $Actions, $Conditions);
33 }
34
35 function PerformList(array $List, array $Actions, array $Conditions = array(ModuleCondition::All)): void
36 {
37 foreach ($List as $Module)
38 {
39 if (in_array(ModuleCondition::All, $Conditions) or
40 ($Module->Running and in_array(ModuleCondition::Running, $Conditions)) or
41 (!$Module->Running and in_array(ModuleCondition::NotRunning, $Conditions)) or
42 ($Module->Installed and in_array(ModuleCondition::Installed, $Conditions)) or
43 (!$Module->Installed and in_array(ModuleCondition::NotInstalled, $Conditions)) or
44 ($Module->Enabled and in_array(ModuleCondition::Enabled, $Conditions)) or
45 (!$Module->Enabled and in_array(ModuleCondition::NotEnabled, $Conditions)) or
46 (($Module->Type == ModuleType::System) and in_array(ModuleCondition::System, $Conditions)) or
47 (($Module->Type == ModuleType::Application) and in_array(ModuleCondition::Application, $Conditions)) or
48 (($Module->Type == ModuleType::Library) and in_array(ModuleCondition::Library, $Conditions)))
49 {
50 foreach ($Actions as $Action)
51 {
52 if ($Action == ModuleAction::Start) $Module->Start();
53 if ($Action == ModuleAction::Stop) $Module->Stop();
54 if ($Action == ModuleAction::Install) $Module->Install();
55 if ($Action == ModuleAction::Uninstall) $Module->Uninstall();
56 if ($Action == ModuleAction::Enable) $Module->Enable();
57 if ($Action == ModuleAction::Disable) $Module->Disable();
58 if ($Action == ModuleAction::Upgrade) $Module->Upgrade();
59 if ($Action == ModuleAction::InsertSampleData) $Module->InsertSampleData();
60 }
61 }
62 }
63 }
64
65 function EnumDependenciesCascade(Module $Module, array &$List, array $Conditions = array(ModuleCondition::All))
66 {
67 foreach ($Module->Dependencies as $Dependency)
68 {
69 if (!array_key_exists($Dependency, $this->Modules))
70 throw new Exception(sprintf(T('Module "%s" dependency "%s" not found'), $Module->Name, $Dependency));
71 $DepModule = $this->Modules[$Dependency];
72 if (in_array(ModuleCondition::All, $Conditions) or
73 ($DepModule->Running and in_array(ModuleCondition::Running, $Conditions)) or
74 (!$DepModule->Running and in_array(ModuleCondition::NotRunning, $Conditions)) or
75 ($DepModule->Enabled and in_array(ModuleCondition::Enabled, $Conditions)) or
76 (!$DepModule->Enabled and in_array(ModuleCondition::NotEnabled, $Conditions)) or
77 ($DepModule->Installed and in_array(ModuleCondition::Installed, $Conditions)) or
78 (!$DepModule->Installed and in_array(ModuleCondition::NotInstalled, $Conditions)) or
79 (($DepModule->Type == ModuleType::System) and in_array(ModuleCondition::System, $Conditions)) or
80 (($DepModule->Type == ModuleType::Application) and in_array(ModuleCondition::Application, $Conditions)) or
81 (($DepModule->Type == ModuleType::Library) and in_array(ModuleCondition::Library, $Conditions)))
82 {
83 array_push($List, $DepModule);
84 $this->EnumDependenciesCascade($DepModule, $List, $Conditions);
85 }
86 }
87 }
88
89 function EnumSuperiorDependenciesCascade(Module $Module, array &$List, array $Conditions = array(ModuleCondition::All))
90 {
91 foreach ($this->Modules as $RefModule)
92 {
93 if (in_array($Module->Name, $RefModule->Dependencies) and
94 (in_array(ModuleCondition::All, $Conditions) or
95 ($RefModule->Running and in_array(ModuleCondition::Running, $Conditions)) or
96 (!$RefModule->Running and in_array(ModuleCondition::NotRunning, $Conditions)) or
97 ($RefModule->Enabled and in_array(ModuleCondition::Enabled, $Conditions)) or
98 (!$RefModule->Enabled and in_array(ModuleCondition::NotEnabled, $Conditions)) or
99 ($RefModule->Installed and in_array(ModuleCondition::Installed, $Conditions)) or
100 (!$RefModule->Installed and in_array(ModuleCondition::NotInstalled, $Conditions)) or
101 (($RefModule->Type == ModuleType::System) and in_array(ModuleCondition::System, $Conditions)) or
102 (($RefModule->Type == ModuleType::Application) and in_array(ModuleCondition::Application, $Conditions)) or
103 (($RefModule->Type == ModuleType::Library) and in_array(ModuleCondition::Library, $Conditions))))
104 {
105 array_push($List, $RefModule);
106 $this->EnumSuperiorDependenciesCascade($RefModule, $List, $Conditions);
107 }
108 }
109 }
110
111 function StartAll(array $Conditions = array(ModuleCondition::All)): void
112 {
113 $this->Perform(array(ModuleAction::Start), $Conditions);
114 }
115
116 function StopAll(array $Conditions = array(ModuleCondition::All)): void
117 {
118 $this->Perform(array(ModuleAction::Stop), $Conditions);
119 }
120
121 function InstallAll(array $Conditions = array(ModuleCondition::All)): void
122 {
123 $this->Perform(array(ModuleAction::Install), $Conditions);
124 $this->SaveState();
125 }
126
127 function UninstallAll(array $Conditions = array(ModuleCondition::All)): void
128 {
129 $this->Perform(array(ModuleAction::Uninstall), $Conditions);
130 $this->SaveState();
131 }
132
133 function EnableAll(array $Conditions = array(ModuleCondition::All)): void
134 {
135 $this->Perform(array(ModuleAction::Enable), $Conditions);
136 $this->SaveState();
137 }
138
139 function DisableAll(array $Conditions = array(ModuleCondition::All)): void
140 {
141 $this->Perform(array(ModuleAction::Disable), $Conditions);
142 $this->SaveState();
143 }
144
145 function UpgradeAll(array $Conditions = array(ModuleCondition::All)): void
146 {
147 $this->Perform(array(ModuleAction::Upgrade), $Conditions);
148 $this->SaveState();
149 }
150
151 function ModulePresent(string $Name): bool
152 {
153 return array_key_exists($Name, $this->Modules);
154 }
155
156 function ModuleEnabled(string $Name): bool
157 {
158 return array_key_exists($Name, $this->Modules) and $this->Modules[$Name]->Enabled;
159 }
160
161 function ModuleRunning(string $Name): bool
162 {
163 return array_key_exists($Name, $this->Modules) and $this->Modules[$Name]->Running;
164 }
165
166 function GetModule(string $Name): Module
167 {
168 return $this->Modules[$Name];
169 }
170
171 function SearchModuleById(int $Id): string
172 {
173 foreach ($this->Modules as $Module)
174 {
175 if ($Module->Id == $Id) return $Module->Name;
176 }
177 return '';
178 }
179
180 function LoadState(): void
181 {
182 $ConfigModules = array();
183 include $this->FileName;
184 foreach ($ConfigModules as $Mod)
185 {
186 $ModuleName = $Mod['Name'];
187 if (array_key_exists($ModuleName, $this->Modules))
188 {
189 if (array_key_exists('Id', $Mod))
190 {
191 $this->Modules[$ModuleName]->Id = $Mod['Id'];
192 }
193 if (array_key_exists('Enabled', $Mod))
194 {
195 $this->Modules[$ModuleName]->Enabled = $Mod['Enabled'];
196 }
197 if (array_key_exists('Installed', $Mod))
198 {
199 $this->Modules[$ModuleName]->Installed = $Mod['Installed'];
200 }
201 if (array_key_exists('InstalledVersion', $Mod))
202 {
203 $this->Modules[$ModuleName]->InstalledVersion = $Mod['InstalledVersion'];
204 }
205 }
206 }
207 }
208
209 function SaveState(): void
210 {
211 $Data = array();
212 foreach ($this->Modules as $Module)
213 {
214 $Data[] = array(
215 'Id' => $Module->Id,
216 'Name' => $Module->Name,
217 'Enabled' => $Module->Enabled,
218 'InstalledVersion' => $Module->InstalledVersion,
219 'Installed' => $Module->Installed
220 );
221 }
222 if (file_put_contents($this->FileName, "<?php \n\n\$ConfigModules = ".var_export($Data, true).";\n") === FALSE)
223 {
224 echo($this->FileName.' is not writeable.');
225 }
226 }
227
228 function RegisterModule(Module $Module): void
229 {
230 if (array_key_exists($Module->Name, $this->Modules))
231 die('Can\'t register module '.$Module->Name.' because it already exists.');
232 $this->Modules[$Module->Name] = &$Module;
233 $Module->Manager = &$this;
234 $Module->OnChange = &$this->OnModuleChange;
235 }
236
237 function UnregisterModule(Module $Module): void
238 {
239 unset($this->Modules[array_search($Module, $this->Modules)]);
240 }
241
242 function GetUniqueModuleId()
243 {
244 $this->NewModuleId++;
245 return $this->NewModuleId - 1;
246 }
247
248 function LoadModule(string $FileName): Module
249 {
250 $ClassName = 'Module'.pathinfo($FileName, PATHINFO_FILENAME);
251 if (!array_key_exists($ClassName::GetName(), $this->Modules))
252 {
253 $Module = new $ClassName($this->System);
254 $Module->Id = $this->GetUniqueModuleId();
255 $this->RegisterModule($Module);
256 return $Module;
257 } else
258 {
259 $Module = $this->Modules[$ClassName::GetName()];
260 return $Module;
261 }
262 }
263
264 function LoadModulesFromDir(string $Directory): void
265 {
266 $FileNames = array();
267 $List = scandir($Directory);
268 foreach ($List as $Item)
269 {
270 if (is_dir($Directory.'/'.$Item) and ($Item != '.') and ($Item != '..') and ($Item != '.svn'))
271 {
272 $FileName = $Directory.'/'.$Item.'/'.$Item.'.php';
273 $FileNames[] = $FileName;
274 include_once($FileName);
275 }
276 }
277 foreach ($FileNames as $FileName)
278 {
279 $this->LoadModule($FileName);
280 }
281 }
282
283 function LoadModules(): void
284 {
285 if (is_array($this->OnLoadModules) and (count($this->OnLoadModules) == 2) and method_exists($this->OnLoadModules[0], $this->OnLoadModules[1]))
286 call_user_func($this->OnLoadModules);
287 else $this->LoadModulesFromDir($this->ModulesDir);
288 }
289}
Note: See TracBrowser for help on using the repository browser.