Skip to content

Commit 27c1f77

Browse files
authored
refactor(upgrade): migrate upgrade framework to namespaced classes with DI (#10)
* refactor(upgrade): migrate upgrade framework to namespaced classes with DI Complete the upgrade framework modernization that was partially started with the scanner classes. Migrates the three core classes from legacy flat files to PSR-4 namespaced structure, adds a proper autoloader, and updates every upd_*/index.php to use constructor dependency injection. Framework changes: - class/abstract.php → class/Xoops/Upgrade/XoopsUpgrade.php - class/control.php → class/Xoops/Upgrade/UpgradeControl.php - class/patchstatus.php → class/Xoops/Upgrade/PatchStatus.php - class/autoload.php (new) PSR-4 autoloader for Xoops\Upgrade - class/fatal_error_handler.php (new) centralized fatal error capture Every upd_*/index.php file updated to: - use Xoops\Upgrade\XoopsUpgrade; use Xoops\Upgrade\UpgradeControl; - public function __construct(XoopsMySQLDatabase $db, UpgradeControl $control) - parent::__construct($db, $control, basename(__DIR__)) upd_2.5.11-to-2.7.0/index.php gains 6 new upgrade tasks: - widenconfid — config.conf_id + configoption.conf_id smallint → int - widenimagename — image.image_name varchar(30) → varchar(191) - cleanuplibraries — delete obsolete build artifacts from class/libraries/ - deletetinymce5nested — delete duplicate tinymce5/tinymce5/ nested directory - deleteflashsanitizer — delete obsolete Flash text sanitizer plugin - cleancache — clear compiled templates and cache files upgrade_tpl.php refactored to use a $viewModel array for cleaner separation between the upgrade controller and its template rendering. Tested end-to-end by running the upgrade wizard from a fresh XOOPS 2.5.11 install through to 2.7.0 RC1, including the System module update step that seeds menus. All upgrade tasks completed successfully. * fix(upgrade): resolve PR #10 review issues in upgrade refactor Fix the upgrade entrypoint `use`-statement placement, restore legacy license placeholder checks for older upgrade paths, and repopulate support links on the preflight page (resetting supportSites before each loadLanguage() call to prevent cross-language accumulation). Also restore noopener/noreferrer on external links and mask filesystem paths in the upgrade fatal error handler. * fix(upgrade): harden upgrade entrypoints and helper output Validate and normalize upgrade language selection before loading language files, add boundary checks for entrypoint includes, and mark the upgrader UI as errored when a patch apply fails. Escape view-model data rendered by the upgrade template, harden the fatal error handler against XSS and additional fatal types, update the legacy license upgrade guidance to match the actual 0644 permission change, escape parameters in UpgradeControl::oneButtonContinueForm(), and guard scandir() against false returns in the 2.7.0 folder cleanup helper. * fix(upgrade): harden remaining legacy patch and migration paths Replace the last raw upgrade request/cookie reads with Xmf\Request, harden legacy license file writers against fopen/file/fwrite failures, and stop treating failed SHOW KEYS metadata queries as success. Make the 2.2.x block migration fail fast before destructive table drops, escape the upgrade language stylesheet path, catch cache cleanup failures, and mask absolute filesystem paths in 2.7.0 cleanup logs via a new relativePath() helper that strips XOOPS_ROOT_PATH and XOOPS_TRUST_PATH. Restore @SInCE 2.7.0 on the 2.7.0 upgrade script (was stale from the wamp import), and drop the pre-write chmod calls in the 2.3.3 and 2.4.0 license writers since is_writable() is the real guard. * fix(upgrade): close remaining migration and file-write safety gaps Make upgrade patch discovery independent of the process working directory, clear stale mainfile rewrite keys, and harden the 2.2.x migration so config, profile, and block conversions fail fast on the first DB error. Also switch legacy license updates to temp-file writes before replacing the live license.php, wire advertised preflight paths into usedFiles, and sanitize cache cleanup exception text before it reaches upgrade logs. Also fold in follow-up hygiene: fail-fast on deletion errors in the 2.5.10 Smarty cleanup task, correct the 2.7.0 CleanCache folder ID docblock to match SystemMaintenance, and add string type hints to the legacy 2.0.x query() helpers so their signatures match the documented contract. * fix(upgrade): close final legacy patch and cleanup gaps Propagate DB write failures in the remaining 2.0.x auth patches, replace the hard-coded qmail config ID with a lookup by config name, and harden both recursive delete helpers against scandir() failure and symlink traversal. Also make library cleanup detection check the full obsolete target set, replace the remaining TYPE=MyISAM syntax with ENGINE=MyISAM, and correct the UpgradeControl supportSites PHPDoc shape. * fix(upgrade): resolve final review issues in upgrade flow and legacy patches Replace the remaining raw POST handling in the upgrade login flow, remove legacy addSlashes-based SQL building, and convert remaining upgrade-path failures to logged boolean returns instead of uncaught exceptions. Also fix broken migration log formatting, harden template and SameSite option writes, add delete-root validation for recursive cleanup, and record SHOW KEYS and ALTER TABLE failures in the legacy key upgrade patch. * fix(upgrade): resolve final PR #10 review issues Validate patch classes in UpgradeControl, merge writable-file requirements from PatchStatus, and document the language-file $supports coupling used during upgrade language loading. Also wire 2.5.11 preflight paths into usedFiles, allow safe unlink of top-level symlink cleanup targets in 2.7.0, and keep the remaining legacy upgrade fixes for login handling, license file paths, mainfile patching, and malformed custom block payloads in the same branch state. * fix(upgrade): resolve final PR #10 review issues Validate patch classes in UpgradeControl, merge writable-file requirements from PatchStatus, and document the language-file $supports coupling used during upgrade language loading. Also wire 2.5.11 preflight paths into usedFiles, allow safe unlink of top-level symlink cleanup targets in 2.7.0, and keep the remaining legacy upgrade fixes for login handling, license file paths, mainfile patching, and malformed custom block payloads in the same branch state. * fix(upgrade): harden check_imptotal guard and log apply_keys failures Check_imptotal() now validates the query result is a mysqli_result instance before calling mysqli_fetch_field_direct(), and logs the underlying DB error when either the query or the field-info read fails. Apply_keys() now logs which ALTER TABLE index creation failed instead of swallowing the exec() return value in an unused assignment. * fix(upgrade): harden block migration and make 2.5.11 patches rerunnable Fail fast in the 2.2.x block migration when the modules root cannot be resolved, replace unsupported ALTER IGNORE with explicit deduplication plus a plain primary-key add, and remove the remaining suppressed block lookup. Make the 2.5.11 template and notification-method patches fully idempotent by validating the complete expected template set, requiring tplsource rows, backfilling missing configoption rows, and treating missing reads or failed inserts as hard failures. Finally, stop treating a failed config_type metadata query in the 2.0.17-to-2.0.18 upgrade as success. Also add error logging to the 2.5.4 banner imptotal migration and include composer/ and firebase/ in the 2.7.0 class/libraries/ cleanup list since both are now redundant with xoops_lib/vendor/. * fix(upgrade): load Db_manager explicitly in 2.5.11 template upgrade Require the installer Db_manager class before the 2.5.10-to-2.5.11 upgrader instantiates it for template import/backfill work. This closes the last real runtime issue from the latest PR #10 review batch; the remaining comments are style/refactor suggestions rather than correctness bugs. * fix(upgrade): cast block id in legacy options update Cast the fetched block id to int when rebuilding non-custom block options in the 2.2.x-to-2.3.0 upgrader so the final UPDATE matches the defensive style already used elsewhere in the same migration.
1 parent 6362c41 commit 27c1f77

32 files changed

Lines changed: 3207 additions & 1380 deletions

File tree

upgrade/assets/fonts/glyphicons-halflings-regular.svg

Lines changed: 288 additions & 1 deletion
Loading

upgrade/checkmainfile.php

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,38 @@
11
<?php
2+
/*
3+
You may not change or alter any portion of this comment or credits
4+
of supporting developers from this source code or any supporting source code
5+
which is considered copyrighted (c) material of the original comment or credit authors.
6+
7+
This program is distributed in the hope that it will be useful,
8+
but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10+
*/
11+
212
/**
313
* Load mainfile.php wedge that checks for needed upgrades.
414
*
5-
* This should be included instead of mainfile.php
15+
* This should be included instead of mainfile.php.
616
*
7-
* You may not change or alter any portion of this comment or credits
8-
* of supporting developers from this source code or any supporting source code
9-
* which is considered copyrighted (c) material of the original comment or credit authors.
10-
* This program is distributed in the hope that it will be useful,
11-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13-
*
14-
* @copyright 2000-2026 XOOPS Project (https://xoops.org)
15-
* @license GNU GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html)
16-
* @package upgrader
17+
* @copyright (c) 2000-2026 XOOPS Project (https://xoops.org)
18+
* @license GNU GPL 2.0 or later (https://www.gnu.org/licenses/gpl-2.0.html)
1719
* @since 2.5.9
1820
* @author Richard Griffith <richard@geekwright.com>
21+
* @author XOOPS Development Team
1922
*/
2023

21-
$loadCommon = !isset($xoopsOption['nocommon']);
24+
$loadCommon = !isset($xoopsOption['nocommon']);
2225
$xoopsOption['nocommon'] = true;
23-
include_once __DIR__ . '/../mainfile.php';
26+
27+
if (!defined('XOOPS_ROOT_PATH')) {
28+
define('XOOPS_ROOT_PATH', dirname(__DIR__));
29+
}
30+
31+
if (file_exists(XOOPS_ROOT_PATH . '/mainfile.php')) {
32+
include_once XOOPS_ROOT_PATH . '/mainfile.php';
33+
} else {
34+
exit('mainfile.php not found.');
35+
}
2436

2537
$mainfileKeys = [
2638
// in mainfile.php
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
/*
3+
* You may not change or alter any portion of this comment or credits
4+
* of supporting developers from this source code or any supporting source code
5+
* which is considered copyrighted (c) material of the original comment or credit authors.
6+
*
7+
* This program is distributed in the hope that it will be useful,
8+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10+
*/
11+
12+
namespace Xoops\Upgrade;
13+
14+
defined('XOOPS_ROOT_PATH') || exit('Restricted access');
15+
16+
/**
17+
* XOOPS Upgrade PatchStatus
18+
*
19+
* Holds the status of a single upgrade patch, indicating whether it has been
20+
* applied and which tasks and files are still needed.
21+
*
22+
* @category Xoops\Upgrade
23+
* @package Xoops
24+
* @author XOOPS Development Team
25+
* @copyright 2000-2026 XOOPS Project (https://xoops.org)
26+
* @license GNU GPL 2 or later (https://www.gnu.org/licenses/gpl-2.0.html)
27+
* @link https://xoops.org
28+
*/
29+
class PatchStatus
30+
{
31+
/** @var string $patchClass class name of patch */
32+
public string $patchClass = '';
33+
34+
/** @var bool $applied true if this patch is applied, false if it is needed */
35+
public bool $applied = true;
36+
37+
/** @var string[] $tasks tasks that need to be run */
38+
public array $tasks = [];
39+
40+
/** @var string[] $files files that need to be writable */
41+
public array $files = [];
42+
43+
/** @var XoopsUpgrade the patch instance */
44+
private XoopsUpgrade $patch;
45+
46+
/**
47+
* PatchStatus constructor.
48+
*
49+
* @param XoopsUpgrade $patch patch to check status for
50+
*/
51+
public function __construct(XoopsUpgrade $patch)
52+
{
53+
$this->patchClass = get_class($patch);
54+
$this->patch = $patch;
55+
foreach ($patch->tasks as $task) {
56+
if (!$patch->{"check_{$task}"}()) {
57+
$this->addTask($task);
58+
}
59+
}
60+
if (!empty($patch->usedFiles) && !$this->applied) {
61+
$this->files = $patch->usedFiles;
62+
}
63+
}
64+
65+
/**
66+
* Get the stored patch instance.
67+
*
68+
* @return XoopsUpgrade
69+
*/
70+
public function getPatch(): XoopsUpgrade
71+
{
72+
return $this->patch;
73+
}
74+
75+
/**
76+
* Add a task that needs to be run to the tasks property
77+
*
78+
* @param string $task task name
79+
* @return void
80+
*/
81+
protected function addTask(string $task): void
82+
{
83+
$this->tasks[] = $task;
84+
$this->applied = false;
85+
}
86+
}

0 commit comments

Comments
 (0)