PluginProbe
User Access Manager / 2.2.21
User Access Manager v2.2.21
2.3.20 2.3.19 2.3.18 2.3.17 2.3.16 2.3.15 2.3.14 2.3.13 trunk 0.6 0.6.1 0.6.2 0.7 0.7 Beta 0.7.0.1 0.8 0.8.0.1 0.8.0.2 0.9 0.9.1 0.9.1.1 0.9.1.2 0.9.1.3 0.9.1.4 1.0 All 136 releases
← All changes | src/Setup/Database/DatabaseHandler.php +193 -73 trunk2.2.21 View file →
@@ -1,5 +1,18 @@
1 1 <?php
2 +/**
3 + * DatabaseHandler.php
4 + *
5 + * The DatabaseHandler class file.
6 + *
7 + * PHP versions 5
8 + *
9 + * @author Alexander Schneider <alexanderschneider85@gmail.com>
10 + * @copyright 2008-2017 Alexander Schneider
11 + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2
12 + * @version SVN: $id$
13 + * @link http://wordpress.org/extend/plugins/user-access-manager/
14 + */
2 15
3 16 declare(strict_types=1);
4 17
5 18 namespace UserAccessManager\Setup\Database;
@@ -9,36 +22,82 @@
9 22 use UserAccessManager\Setup\Update\UpdateInterface;
10 23 use UserAccessManager\UserAccessManager;
11 24 use UserAccessManager\Wrapper\Wordpress;
12 25
26 +/**
27 + * Class DatabaseHandler
28 + *
29 + * @package UserAccessManager\Setup\Database
30 + */
13 31 class DatabaseHandler
14 32 {
15 - public const MISSING_TABLES = 'MISSING_TABLE';
16 - public const MISSING_COLUMNS = 'MISSING_COLUMNS';
17 - public const MODIFIED_COLUMNS = 'MODIFIED_COLUMNS';
18 - public const EXTRA_COLUMNS = 'EXTRA_COLUMNS';
33 + const MISSING_TABLES = 'MISSING_TABLE';
34 + const MISSING_COLUMNS = 'MISSING_COLUMNS';
35 + const MODIFIED_COLUMNS = 'MODIFIED_COLUMNS';
36 + const EXTRA_COLUMNS = 'EXTRA_COLUMNS';
19 37
38 + /**
39 + * @var Wordpress
40 + */
41 + private $wordpress;
42 +
43 + /**
44 + * @var Database
45 + */
46 + private $database;
47 +
48 + /**
49 + * @var DatabaseObjectFactory
50 + */
51 + private $databaseObjectFactory;
52 +
53 + /**
54 + * @var UpdateFactory
55 + */
56 + private $updateFactory;
57 +
58 + /**
59 + * DatabaseHandler constructor.
60 + * @param Wordpress $wordpress
61 + * @param Database $database
62 + * @param DatabaseObjectFactory $databaseObjectFactory
63 + * @param UpdateFactory $updateFactory
64 + */
20 65 public function __construct(
21 - private Wordpress $wordpress,
22 - private Database $database,
23 - private DatabaseObjectFactory $databaseObjectFactory,
24 - private UpdateFactory $updateFactory
66 + Wordpress $wordpress,
67 + Database $database,
68 + DatabaseObjectFactory $databaseObjectFactory,
69 + UpdateFactory $updateFactory
25 70 ) {
71 + $this->wordpress = $wordpress;
72 + $this->database = $database;
73 + $this->databaseObjectFactory = $databaseObjectFactory;
74 + $this->updateFactory = $updateFactory;
26 75 }
27 76
77 + /**
78 + * Checks if the table exists.
79 + * @param string $table
80 + * @return bool
81 + */
28 82 private function tableExists(string $table): bool
29 83 {
30 - $dbTable = $this->database->getVariable("SHOW TABLES LIKE '$table'");
84 + $dbTable = $this->database->getVariable("SHOW TABLES LIKE '{$table}'");
31 85
32 86 return ($table === $dbTable);
33 87 }
34 88
35 - private function addTable(Table $table): void
89 + /**
90 + * Adds a table.
91 + * @param Table $table
92 + */
93 + private function addTable(Table $table)
36 94 {
37 95 $this->database->dbDelta((string) $table);
38 96 }
39 97
40 98 /**
99 + * Returns all tables.
41 100 * @return Table[]
42 101 * @throws MissingColumnsException
43 102 */
44 103 private function getTables(): array
@@ -76,11 +135,12 @@
76 135 return $tables;
77 136 }
78 137
79 138 /**
139 + * Adds the tables to the database.
80 140 * @throws MissingColumnsException
81 141 */
82 - public function install(): void
142 + public function install()
83 143 {
84 144 foreach ($this->getTables() as $table) {
85 145 if ($this->tableExists($table->getName()) === false) {
86 146 $this->addTable($table);
@@ -90,8 +150,10 @@
90 150 $this->wordpress->addOption('uam_db_version', UserAccessManager::DB_VERSION);
91 151 }
92 152
93 153 /**
154 + * Returns the existing columns for a table.
155 + * @param Table $table
94 156 * @return Column[]
95 157 */
96 158 private function getExistingColumns(Table $table): array
97 159 {
@@ -112,9 +174,14 @@
112 174
113 175 return $existingColumns;
114 176 }
115 177
116 - private function addCorruptedRows(Table $table, array &$information): void
178 + /**
179 + * Add corrupted columns to the information array if the are some.
180 + * @param Table $table
181 + * @param array $information
182 + */
183 + private function addCorruptedRows(Table $table, array &$information)
117 184 {
118 185 $existingColumns = $this->getExistingColumns($table);
119 186
120 187 foreach ($table->getColumns() as $column) {
@@ -136,8 +203,10 @@
136 203 }
137 204 }
138 205
139 206 /**
207 + * Returns corrupted database information.
208 + * @return array
140 209 * @throws MissingColumnsException
141 210 */
142 211 public function getCorruptedDatabaseInformation(): array
143 212 {
@@ -159,14 +228,45 @@
159 228
160 229 return $information;
161 230 }
162 231
163 - private function alterTable(Table $table, string $alteration): bool
232 + /**
233 + * Adds a new column.
234 + * @param Table $table
235 + * @param Column $column
236 + * @return bool
237 + */
238 + private function addColumn(Table $table, Column $column): bool
164 239 {
165 - return $this->database->query("ALTER TABLE `{$table->getName()}` $alteration;") !== false;
240 + return $this->database->query("ALTER TABLE `{$table->getName()}` ADD $column;") !== false;
166 241 }
167 242
168 243 /**
244 + * Modify an existing column.
245 + * @param Table $table
246 + * @param Column $column
247 + * @return bool
248 + */
249 + private function modifyColumn(Table $table, Column $column): bool
250 + {
251 + return $this->database->query("ALTER TABLE `{$table->getName()}` MODIFY $column;") !== false;
252 + }
253 +
254 + /**
255 + * Drops an existing column.
256 + * @param Table $table
257 + * @param Column $column
258 + * @return bool
259 + */
260 + private function dropColumn(Table $table, Column $column): bool
261 + {
262 + return $this->database->query("ALTER TABLE `{$table->getName()}` DROP `{$column->getName()}`;") !== false;
263 + }
264 +
265 + /**
266 + * Repairs a corrupt database.
267 + * @param array $information
268 + * @return bool
169 269 * @throws MissingColumnsException
170 270 */
171 271 public function repairDatabase(array $information = []): bool
172 272 {
@@ -176,23 +276,27 @@
176 276 foreach ($information[self::MISSING_TABLES] as $table) {
177 277 $this->addTable($table);
178 278 }
179 279
180 - $alterationsByInformationKey = [
181 - self::MISSING_COLUMNS => static fn(Column $column) => "ADD $column",
182 - self::MODIFIED_COLUMNS => static fn(Column $column) => "MODIFY $column",
183 - self::EXTRA_COLUMNS => static fn(Column $column) => "DROP `{$column->getName()}`"
184 - ];
280 + foreach ($information[self::MISSING_COLUMNS] as $columnInformation) {
281 + $success = $success && $this->addColumn($columnInformation[0], $columnInformation[1]);
282 + }
185 283
186 - foreach ($alterationsByInformationKey as $informationKey => $buildAlteration) {
187 - foreach ($information[$informationKey] as [$table, $column]) {
188 - $success = $success && $this->alterTable($table, $buildAlteration($column));
189 - }
284 + foreach ($information[self::MODIFIED_COLUMNS] as $columnInformation) {
285 + $success = $success && $this->modifyColumn($columnInformation[0], $columnInformation[1]);
190 286 }
191 287
288 + foreach ($information[self::EXTRA_COLUMNS] as $columnInformation) {
289 + $success = $success && $this->dropColumn($columnInformation[0], $columnInformation[1]);
290 + }
291 +
192 292 return $success;
193 293 }
194 294
295 + /**
296 + * Returns all sites where the user access manager is active.
297 + * @return array
298 + */
195 299 private function getActivePluginSites(): array
196 300 {
197 301 $activeSites = [];
198 302
@@ -210,59 +314,40 @@
210 314
211 315 return $activeSites;
212 316 }
213 317
214 - private function hasSiteWithOutdatedDatabase(): bool
215 - {
216 - foreach ($this->getActivePluginSites() as $siteId) {
217 - $table = $this->database->getBlogPrefix($siteId) . 'options';
218 - $select = "SELECT `option_value` FROM `$table` WHERE `option_name` = '%s' LIMIT 1";
219 - $select = $this->database->prepare($select, 'uam_db_version');
220 - $currentDbVersion = $this->database->getVariable($select);
221 -
222 - if ($currentDbVersion !== null
223 - && version_compare((string) $currentDbVersion, UserAccessManager::DB_VERSION, '<') === true
224 - ) {
225 - return true;
226 - }
227 - }
228 -
229 - return false;
230 - }
231 -
232 318 /**
233 - * @throws MissingColumnsException
319 + * Checks if a database update is necessary.
320 + * @return bool
234 321 */
235 322 public function isDatabaseUpdateNecessary(): bool
236 323 {
237 - if ($this->wordpress->isSuperAdmin() === true && $this->hasSiteWithOutdatedDatabase() === true) {
238 - return true;
239 - }
324 + if ($this->wordpress->isSuperAdmin() === true) {
325 + foreach ($this->getActivePluginSites() as $siteId) {
326 + $table = $this->database->getBlogPrefix($siteId) . 'options';
327 + $select = "SELECT option_value FROM {$table} WHERE option_name = '%s' LIMIT 1";
328 + $select = $this->database->prepare($select, 'uam_db_version');
329 + $currentDbVersion = $this->database->getVariable($select);
240 330
241 - $currentDbVersion = (string) $this->wordpress->getOption('uam_db_version');
242 -
243 - if (empty($currentDbVersion) === true) {
244 - $this->install();
245 - $currentDbVersion = (string) $this->wordpress->getOption('uam_db_version');
331 + if ($currentDbVersion !== null
332 + && version_compare($currentDbVersion, UserAccessManager::DB_VERSION, '<') === true
333 + ) {
334 + return true;
335 + }
336 + }
246 337 }
247 338
339 + $currentDbVersion = $this->wordpress->getOption('uam_db_version');
248 340 return version_compare($currentDbVersion, UserAccessManager::DB_VERSION, '<');
249 341 }
250 342
251 343 /**
252 - * @return string[]
344 + * Creates a database backup.
345 + * @return bool
253 346 */
254 - private function getTableNames(): array
255 - {
256 - return [
257 - $this->database->getUserGroupTable(),
258 - $this->database->getUserGroupToObjectTable()
259 - ];
260 - }
261 -
262 347 public function backupDatabase(): bool
263 348 {
264 - $currentDbVersion = (string) $this->wordpress->getOption('uam_db_version');
349 + $currentDbVersion = $this->wordpress->getOption('uam_db_version');
265 350
266 351 if (empty($currentDbVersion) === true
267 352 || version_compare($currentDbVersion, '1.2', '<') === true
268 353 ) {
@@ -268,15 +353,20 @@
268 353 ) {
269 354 return false;
270 355 }
271 356
357 + $tables = [
358 + $this->database->getUserGroupTable(),
359 + $this->database->getUserGroupToObjectTable()
360 + ];
361 +
272 362 $currentDbVersion = str_replace('.', '-', $currentDbVersion);
273 363 $success = true;
274 364
275 - foreach ($this->getTableNames() as $table) {
276 - $createQuery = "CREATE TABLE `{$table}_$currentDbVersion` LIKE `$table`";
365 + foreach ($tables as $table) {
366 + $createQuery = "CREATE TABLE `{$table}_{$currentDbVersion}` LIKE `{$table}`";
277 367 $success = $success && ($this->database->query($createQuery) !== false);
278 - $insertQuery = "INSERT `{$table}_$currentDbVersion` SELECT * FROM `$table`";
368 + $insertQuery = "INSERT `{$table}_{$currentDbVersion}` SELECT * FROM `{$table}`";
279 369 $success = $success && ($this->database->query($insertQuery) !== false);
280 370 }
281 371
282 372 return $success;
@@ -281,17 +371,21 @@
281 371
282 372 return $success;
283 373 }
284 374
375 + /**
376 + * Returns the version for which a backup was created.
377 + * @return array
378 + */
285 379 public function getBackups(): array
286 380 {
287 381 $versions = [];
288 - $tables = $this->database->getColumn(
382 + $tables = (array) $this->database->getColumn(
289 383 "SHOW TABLES LIKE '{$this->database->getPrefix()}uam_%'"
290 384 );
291 385
292 386 foreach ($tables as $table) {
293 - if (preg_match('/.*_([0-9\-]+)/', $table, $matches) === 1) {
387 + if (preg_match('/.*_([0-9\-]+)/i', $table, $matches) === 1) {
294 388 $version = str_replace('-', '.', $matches[1]);
295 389 $versions[$version] = $version;
296 390 }
297 391 }
@@ -298,16 +392,26 @@
298 392
299 393 return $versions;
300 394 }
301 395
396 + /**
397 + * Returns the backup tables for the given version.
398 + * @param string $version
399 + * @return array
400 + */
302 401 private function getBackupTables(string $version): array
303 402 {
304 403 $backupTables = [];
404 + $tables = [
405 + $this->database->getUserGroupTable(),
406 + $this->database->getUserGroupToObjectTable()
407 + ];
408 +
305 409 $versionForDb = str_replace('.', '-', $version);
306 410
307 - foreach ($this->getTableNames() as $table) {
411 + foreach ($tables as $table) {
308 412 $backupTable = (string) $this->database->getVariable(
309 - "SHOW TABLES LIKE '{$table}_$versionForDb'"
413 + "SHOW TABLES LIKE '{$table}_{$versionForDb}'"
310 414 );
311 415
312 416 if ($backupTable !== '') {
313 417 $backupTables[$table] = $backupTable;
@@ -316,8 +420,13 @@
316 420
317 421 return $backupTables;
318 422 }
319 423
424 + /**
425 + * Reverts the database to the given version.
426 + * @param string $version
427 + * @return bool
428 + */
320 429 public function revertDatabase(string $version): bool
321 430 {
322 431 $success = true;
323 432 $tables = $this->getBackupTables($version);
@@ -322,11 +431,11 @@
322 431 $success = true;
323 432 $tables = $this->getBackupTables($version);
324 433
325 434 foreach ($tables as $table => $backupTable) {
326 - $dropQuery = "DROP TABLE IF EXISTS `$table`";
435 + $dropQuery = "DROP TABLE IF EXISTS `{$table}`";
327 436 $success = $success && ($this->database->query($dropQuery) !== false);
328 - $renameQuery = "RENAME TABLE `$backupTable` TO `$table`";
437 + $renameQuery = "RENAME TABLE `{$backupTable}` TO `{$table}`";
329 438 $success = $success && ($this->database->query($renameQuery) !== false);
330 439 }
331 440
332 441 if ($success === true) {
@@ -335,15 +444,20 @@
335 444
336 445 return $success;
337 446 }
338 447
448 + /**
449 + * Deletes the given database backup.
450 + * @param string $version
451 + * @return bool
452 + */
339 453 public function deleteBackup(string $version): bool
340 454 {
341 455 $success = true;
342 456 $tables = $this->getBackupTables($version);
343 457
344 - foreach ($tables as $backupTable) {
345 - $dropQuery = "DROP TABLE IF EXISTS `$backupTable`";
458 + foreach ($tables as $table => $backupTable) {
459 + $dropQuery = "DROP TABLE IF EXISTS `{$backupTable}`";
346 460 $success = $success && ($this->database->query($dropQuery) !== false);
347 461 }
348 462
349 463 return $success;
@@ -349,8 +463,9 @@
349 463 return $success;
350 464 }
351 465
352 466 /**
467 + * Returns the ordered updates.
353 468 * @return UpdateInterface[]
354 469 */
355 470 private function getOrderedDatabaseUpdates(): array
356 471 {
@@ -364,11 +479,15 @@
364 479 uksort($updates, 'version_compare');
365 480 return $updates;
366 481 }
367 482
483 + /**
484 + * Updates the database.
485 + * @return bool
486 + */
368 487 public function updateDatabase(): bool
369 488 {
370 - $currentDbVersion = (string) $this->wordpress->getOption('uam_db_version');
489 + $currentDbVersion = $this->wordpress->getOption('uam_db_version');
371 490
372 491 if (empty($currentDbVersion) === true) {
373 492 return false;
374 493 }
@@ -388,11 +507,12 @@
388 507 return $success;
389 508 }
390 509
391 510 /**
511 + * Removes the tables.
392 512 * @throws MissingColumnsException
393 513 */
394 - public function removeTables(): void
514 + public function removeTables()
395 515 {
396 516 foreach ($this->getTables() as $table) {
397 517 $dropQuery = "DROP TABLE IF EXISTS `{$table->getName()}`";
398 518 $this->database->query($dropQuery);