source: trunk/Packages/Common/Modules/ModuleSetup.php

Last change on this file was 8, checked in by chronos, 19 months ago
  • Modified: Updated Common package.
  • Modified: Form types made as separate FormManager package.
  • Fixed: PHP 8.1 support.
File size: 13.6 KB
Line 
1<?php
2
3class ModuleSetup extends Module
4{
5 public UpdateManager $UpdateManager;
6
7 function __construct(System $System)
8 {
9 global $DatabaseRevision;
10
11 parent::__construct($System);
12 $this->Name = 'Setup';
13 $this->Version = '1.0';
14 $this->Creator = 'Chronos';
15 $this->License = 'GNU/GPLv3';
16 $this->Description = 'Base setup module';
17 $this->Version = 1;
18 $this->Type = ModuleType::System;
19
20 // Check database persistence structure
21 $this->UpdateManager = new UpdateManager();
22 $this->UpdateManager->Database = &$this->Database;
23 $this->UpdateManager->Revision = $DatabaseRevision;
24 $this->UpdateManager->InstallMethod = 'FullInstall';
25 }
26
27 static function Cast(Module $Module): ModuleSetup
28 {
29 if ($Module instanceof ModuleSetup)
30 {
31 return $Module;
32 }
33 throw new Exception('Expected ModuleSetup type but '.gettype($Module));
34 }
35
36 function DoStart(): void
37 {
38 Core::Cast($this->System)->RegisterPage([''], 'PageSetupRedirect');
39 Core::Cast($this->System)->RegisterPage(['setup'], 'PageSetup');
40 }
41
42 function DoStop(): void
43 {
44 unset($this->UpdateManager);
45 Core::Cast($this->System)->UnregisterPage(['']);
46 Core::Cast($this->System)->UnregisterPage(['setup']);
47 }
48
49 function CheckState(): bool
50 {
51 return $this->Database->Connected() and $this->UpdateManager->IsInstalled() and
52 $this->UpdateManager->IsUpToDate();
53 }
54
55 function DoUpgrade(): string
56 {
57 $Updates = new Updates();
58 $this->UpdateManager->Trace = $Updates->Get();
59 $Output = $this->UpdateManager->Upgrade();
60 return $Output;
61 }
62}
63
64class PageSetup extends Page
65{
66 public UpdateManager $UpdateManager;
67 public array $ConfigDefinition;
68 public array $Config;
69 public int $DatabaseRevision;
70 public int $Revision;
71 public string $ConfigDir;
72 public array $YesNo;
73
74 function __construct(System $System)
75 {
76 parent::__construct($System);
77 $this->Title = T('Application setup');
78 //$this->ParentClass = 'PageSetupRedirect';
79 $this->ConfigDir = dirname(dirname(dirname(__FILE__))).'/Config';
80 $this->YesNo = array(false => T('No'), true => T('Yes'));
81 }
82
83 function LoginPanel(): string
84 {
85 $Output = '<h3>Přihlášení k instalaci</h3>'.
86 '<form action="?" method="post">'.
87 '<table>'.
88 '<tr><td>Systémové heslo:</td><td> <input type="password" name="SystemPassword" value=""/></td></tr>'.
89 '</table>'.
90 '<input type="submit" name="login" value="'.T('Login').'"/>'.
91 '</form>';
92 return $Output;
93 }
94
95 function ControlPanel(): string
96 {
97 $Output = '<h3>'.T('Instance management').'</h3>';
98
99 $Output .= 'Je připojení k databázi: '.$this->YesNo[$this->UpdateManager->Database->Connected()].'<br/>';
100 if ($this->UpdateManager->Database->Connected())
101 {
102 $Output .= 'Je instalováno: '.$this->YesNo[$this->UpdateManager->IsInstalled()].'<br/>';
103 if ($this->UpdateManager->IsInstalled())
104 $Output .= 'Je aktuální: '.$this->YesNo[$this->UpdateManager->IsUpToDate()].'<br/>'.
105 'Verze databáze: '.$this->UpdateManager->GetDbVersion().'<br/>';
106 $Output .= 'Verze databáze kódu: '.$this->UpdateManager->Revision.'<br/>';
107 if ($this->UpdateManager->IsInstalled())
108 {
109 if (!$this->UpdateManager->IsUpToDate())
110 $Output .= '<a href="?action=upgrade">'.T('Upgrade').'</a> ';
111 $Output .= '<a href="?action=insert_sample_data">Vložit vzorová data</a> ';
112 $Output .= '<a href="?action=reload-modules">Obnovit seznam modulů</a> ';
113 $Output .= '<a href="?action=uninstall">Odinstalovat</a> ';
114 $Output .= '<a href="'.$this->System->Link('/modules/').'">Správa modulů</a> ';
115 $Output .= '<a href="?action=models">Přegenerovat modely</a> ';
116 } else $Output .= '<a href="?action=install">Instalovat</a> ';
117 }
118 $Output .= '<a href="?action=configure">Nastavit</a> ';
119 $Output .= '<a href="?action=logout">Odhlásit</a> ';
120 $Output .= '<a href="'.$this->System->Link('/').'">'.T('Go to main page').'</a> ';
121 $Output .= '';
122 return $Output;
123 }
124
125 function Show(): string
126 {
127 global $ConfigDefinition, $DatabaseRevision, $Config, $Updates;
128
129 $this->UpdateManager = ModuleSetup::Cast($this->System->GetModule('Setup'))->UpdateManager;
130 $DefaultConfig = new DefaultConfig();
131 $this->ConfigDefinition = $DefaultConfig->Get();
132 $this->DatabaseRevision = $DatabaseRevision;
133 $this->Config = &$Config;
134
135 $Output = '';
136 if (isset($this->Config))
137 {
138 if (!array_key_exists('SystemPassword', $_SESSION)) $_SESSION['SystemPassword'] = '';
139 if (array_key_exists('login', $_POST)) $_SESSION['SystemPassword'] = $_POST['SystemPassword'];
140 if (sha1($_SESSION['SystemPassword']) != $this->Config['SystemPassword'])
141 {
142 $Output .= $this->LoginPanel();
143 } else
144 {
145 if (array_key_exists('action', $_GET)) $Action = $_GET['action'];
146 else $Action = '';
147 if ($Action == 'logout')
148 {
149 $_SESSION['SystemPassword'] = '';
150 $Output .= 'Odhlášen';
151 $Output .= $this->LoginPanel();
152 }
153 else if ($Action == 'models')
154 {
155 Core::Cast($this->System)->FormManager->UpdateSQLMeta();
156 }
157 else if ($Action == 'upgrade')
158 {
159 $Output .= '<h3>Povýšení</h3>';
160 try
161 {
162 $Output .= ModuleSetup::Cast($this->System->GetModule('Setup'))->DoUpgrade();
163 $this->System->ModuleManager->UpgradeAll(array(ModuleCondition::System));
164 } catch (Exception $E)
165 {
166 $Output .= $this->SystemMessage('Chyba aktualizace',
167 'Došlo k chybě v SQL dotazu při aktualizaci: <br/>'.$E->getMessage());
168 }
169 $Output .= $this->ControlPanel();
170 }
171 else if ($Action == 'install')
172 {
173 $Output .= '<h3>Instalace systém</h3>';
174 global $DatabaseRevision;
175
176 $this->Database->query("CREATE TABLE IF NOT EXISTS `".$this->UpdateManager->VersionTable."` (".
177 '`Id` int(11) NOT NULL AUTO_INCREMENT, '.
178 '`Revision` int(11) NOT NULL, '.
179 'PRIMARY KEY (`Id`) '.
180 ') ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;');
181 $DbResult = $this->Database->select($this->UpdateManager->VersionTable, 'Id');
182 if ($DbResult->num_rows == 0)
183 {
184 $this->Database->query("INSERT INTO `".$this->UpdateManager->VersionTable.
185 "` (`Id`, `Revision`) VALUES (1, ".$DatabaseRevision.");");
186 }
187 $this->System->ModuleManager->InstallAll(array(ModuleCondition::System));
188 $this->System->ModuleManager->LoadModules();
189 $this->System->ModuleManager->SaveState();
190 //$Output .= ModuleSetup::Cast($this->System->GetModule('Setup'))->Upgrade();
191 $Output .= $this->ControlPanel();
192 }
193 else if ($Action == 'uninstall')
194 {
195 $Output .= '<h3>Odinstalace vše</h3>';
196 $this->System->ModuleManager->UninstallAll(array(ModuleCondition::All));
197 $this->Database->query('DROP TABLE IF EXISTS `'.$this->UpdateManager->VersionTable.'`');
198 $Output .= $this->ControlPanel();
199 }
200 else if ($Action == 'reload-modules')
201 {
202 $Output .= '<h3>Znovunačtení seznamu modulů</h3>';
203 $this->System->ModuleManager->LoadModules();
204 $this->System->ModuleManager->SaveState();
205 $Output .= $this->ControlPanel();
206 }
207 else if ($Action == 'insert_sample_data')
208 {
209 $Output .= '<h3>Vložení vzorových dat</h3>';
210 $this->System->ModuleManager->Perform(array(ModuleAction::InsertSampleData), array(ModuleCondition::Installed));
211 $Output .= $this->ControlPanel();
212 }
213 else if ($Action == 'configure_save')
214 {
215 $Output .= $this->ConfigSave($this->Config);
216 $Output .= $this->ControlPanel();
217 }
218 else if ($Action == 'configure')
219 {
220 $Output .= $this->PrepareConfig($this->Config);
221 }
222 else
223 {
224 $Output .= $this->ControlPanel();
225 }
226 }
227 } else
228 {
229 if (array_key_exists('configure_save', $_POST))
230 {
231 $Output .= $this->ConfigSave(array());
232 $Output .= 'Pokračujte k přihlášení <a href="">zde</a>';
233 } else {
234 $Output .= $this->PrepareConfig(array());
235 }
236 }
237 return $Output;
238 }
239
240 function PrepareConfig($Config): string
241 {
242 $Output = '';
243 if (!file_exists($this->ConfigDir.'/Config.php') and !is_writable($this->ConfigDir))
244 $Output .= 'Varování: Konfigurační soubor nebude možné zapsat, protože složka "'.$this->ConfigDir.'" není povolená pro zápis!';
245 if (file_exists($this->ConfigDir.'/Config.php') and !is_writable($this->ConfigDir.'/Config.php'))
246 $Output .= 'Varování: Konfigurační soubor nebude možné zapsat, protože soubor "'.$this->ConfigDir.'/Config.php" není povolen pro zápis!';
247 $Output .= '<h3>Nastavení systému</h3>'.
248 '<form action="?action=configure_save" method="post">'.
249 '<table>';
250 foreach ($this->ConfigDefinition as $Def)
251 {
252 $PathParts = explode('/', $Def['Name']);
253 $TempConfig = &$Config;
254 foreach ($PathParts as $Part)
255 if (array_key_exists($Part, $TempConfig))
256 {
257 $TempConfig = &$TempConfig[$Part];
258 }
259 if (!is_array($TempConfig)) $Value = $TempConfig;
260 else $Value = $Def['Default'];
261 $Output .= '<tr><td>'.$Def['Title'].'</td><td>';
262 if ($Def['Type'] == 'String') $Output .= '<input type="text" name="'.$Def['Name'].'" value="'.$Value.'"/>';
263 if ($Def['Type'] == 'Password') $Output .= '<input type="password" name="'.$Def['Name'].'"/>';
264 if ($Def['Type'] == 'PasswordEncoded') $Output .= '<input type="password" name="'.$Def['Name'].'"/>';
265 if ($Def['Type'] == 'Integer') $Output .= '<input type="text" name="'.$Def['Name'].'" value="'.$Value.'"/>';
266 if ($Def['Type'] == 'Float') $Output .= '<input type="text" name="'.$Def['Name'].'" value="'.$Value.'"/>';
267 if ($Def['Type'] == 'Boolean') $Output .= '<input type="text" name="'.$Def['Name'].'" value="'.$Value.'"/>';
268 if ($Def['Type'] == 'Array') $Output .= '<input type="text" name="'.$Def['Name'].'" value="'.implode(',', $Value).'"/>';
269 }
270 $Output .= '</td></tr>'.
271 '<tr><td colspan="2"><input type="submit" name="configure_save" value="'.T('Save').'"/></td></tr>'.
272 '</table>'.
273 '</form>';
274 return $Output;
275 }
276
277 function ConfigSave($DefaultConfig)
278 {
279 $Config = $DefaultConfig;
280 foreach ($this->ConfigDefinition as $Def)
281 {
282 $Value = null;
283 if ($Def['Type'] == 'String') if (array_key_exists($Def['Name'], $_POST))
284 $Value = $_POST[$Def['Name']];
285 if ($Def['Type'] == 'Password') if (array_key_exists($Def['Name'], $_POST) and ($_POST[$Def['Name']] != ''))
286 $Value = $_POST[$Def['Name']];
287 if ($Def['Type'] == 'PasswordEncoded') if (array_key_exists($Def['Name'], $_POST) and ($_POST[$Def['Name']] != ''))
288 $Value = sha1($_POST[$Def['Name']]);
289 if ($Def['Type'] == 'Integer') if (array_key_exists($Def['Name'], $_POST))
290 $Value = $_POST[$Def['Name']];
291 if ($Def['Type'] == 'Float') if (array_key_exists($Def['Name'], $_POST))
292 $Value = $_POST[$Def['Name']];
293 if ($Def['Type'] == 'Boolean') if (array_key_exists($Def['Name'], $_POST))
294 $Value = $_POST[$Def['Name']];
295 if ($Def['Type'] == 'Array') if (array_key_exists($Def['Name'], $_POST))
296 $Value = explode(',', $_POST[$Def['Name']]);
297 if (!is_null($Value))
298 {
299 $PathParts = explode('/', $Def['Name']);
300 $TempConfig = &$Config;
301 foreach ($PathParts as $Part)
302 {
303 $TempConfig = &$TempConfig[$Part];
304 }
305 if (!is_array($TempConfig)) $TempConfig = $Value;
306 else $Value = $Def['Default'];
307 }
308 }
309 $ConfigText = $this->CreateConfig($Config);
310 file_put_contents($this->ConfigDir.'/Config.php', $ConfigText);
311 $Output = 'Konfigurace nastavena<br/>';
312 return $Output;
313 }
314
315 function CreateConfig($Config): string
316 {
317 $Output = "<?php\n\n".
318 "\$IsDeveloper = array_key_exists('REMOTE_ADDR', \$_SERVER) and in_array(\$_SERVER['REMOTE_ADDR'], array('127.0.0.1'));\n\n";
319
320 foreach ($this->ConfigDefinition as $Def)
321 {
322 $PathParts = explode('/', $Def['Name']);
323 $Output .= "\$Config";
324 foreach ($PathParts as $Part)
325 $Output .= "['".$Part."']";
326 $TempConfig = &$Config;
327 $Output .= ' = ';
328 foreach ($PathParts as $Part)
329 if (array_key_exists($Part, $TempConfig))
330 {
331 $TempConfig = &$TempConfig[$Part];
332 }
333 if (!is_array($TempConfig)) $Value = $TempConfig;
334 else $Value = $Def['Default'];
335 if ($Def['Type'] == 'Array')
336 {
337 $Output .= ' array(';
338 foreach ($Value as $Index => $Item)
339 $Output .= '\''.$Item.'\', ';
340 $Output .= ')';
341 }
342 else $Output .= "'".$Value."'";
343 $Output .= ";\n";
344 }
345 $Output .= "\n\n";
346 return $Output;
347 }
348}
349
350class PageSetupRedirect extends Page
351{
352 function Show(): string
353 {
354 $Output = '';
355 if (!$this->Database->Connected())
356 {
357 $Output .= T('Can\'t connect to database.').'<br>';
358 } else
359 {
360 if (!ModuleSetup::Cast($this->System->GetModule('Setup'))->UpdateManager->IsInstalled())
361 {
362 $Output .= T('System requires database initialization.').'<br>';
363 } else
364 if (!ModuleSetup::Cast($this->System->GetModule('Setup'))->UpdateManager->IsUpToDate())
365 {
366 $Output .= T('System requires database upgrade.').'<br>';
367 }
368 }
369 $Output .= sprintf(T('Front page was not configured. Continue to %s.'), '<a href="'.$this->System->Link('/setup/').'">'.T('setup').'</a>');
370 return $Output;
371 }
372}
Note: See TracBrowser for help on using the repository browser.