fix(install): reinstall broken plugins from package zip in postflight
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (push) Blocked by required conditions
Generic: Project CI / Tests (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 3: Self-Health Check (push) Blocked by required conditions
Platform: moko-platform CI / Gate 4: Governance (push) Blocked by required conditions
Platform: moko-platform CI / Gate 5: Template Integrity (push) Blocked by required conditions
Platform: moko-platform CI / CI Summary (push) Blocked by required conditions
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Blocked by required conditions
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Blocked by required conditions
Joomla: Extension CI / PHPStan Analysis (pull_request) Blocked by required conditions
Joomla: Extension CI / Build RC Pre-Release (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 3: Self-Health Check (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 4: Governance (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 5: Template Integrity (pull_request) Blocked by required conditions
Platform: moko-platform CI / CI Summary (pull_request) Blocked by required conditions
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 9s
Generic: Project CI / Lint & Validate (pull_request) Successful in 14s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Universal: Auto Version Bump / Version Bump (push) Successful in 13s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 17s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 32s
Platform: moko-platform CI / Gate 1: Code Quality (push) Failing after 35s
Platform: moko-platform CI / Gate 1: Code Quality (pull_request) Failing after 37s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 37s
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (push) Blocked by required conditions
Generic: Project CI / Tests (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 3: Self-Health Check (push) Blocked by required conditions
Platform: moko-platform CI / Gate 4: Governance (push) Blocked by required conditions
Platform: moko-platform CI / Gate 5: Template Integrity (push) Blocked by required conditions
Platform: moko-platform CI / CI Summary (push) Blocked by required conditions
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Blocked by required conditions
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Blocked by required conditions
Joomla: Extension CI / PHPStan Analysis (pull_request) Blocked by required conditions
Joomla: Extension CI / Build RC Pre-Release (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 3: Self-Health Check (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 4: Governance (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 5: Template Integrity (pull_request) Blocked by required conditions
Platform: moko-platform CI / CI Summary (pull_request) Blocked by required conditions
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 9s
Generic: Project CI / Lint & Validate (pull_request) Successful in 14s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Universal: Auto Version Bump / Version Bump (push) Successful in 13s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 17s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 32s
Platform: moko-platform CI / Gate 1: Code Quality (push) Failing after 35s
Platform: moko-platform CI / Gate 1: Code Quality (pull_request) Failing after 37s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 37s
When Joomla installs plugins with empty element, files go to the group root. Postflight now: 1. Deletes orphan rows (empty element or display-name-as-element) 2. Cleans stale files from group roots 3. Checks each expected plugin directory exists 4. If missing, extracts the plugin zip from the package source dir This guarantees all core plugins are correctly installed after every update, regardless of the MySQL DEFAULT '' issue.
This commit is contained in:
+93
-8
@@ -62,8 +62,12 @@ class Pkg_MokosuiteclientInstallerScript
|
||||
}
|
||||
}
|
||||
|
||||
/** @var \Joomla\CMS\Installer\InstallerAdapter|null */
|
||||
private $installerParent = null;
|
||||
|
||||
public function postflight($type, $parent)
|
||||
{
|
||||
$this->installerParent = $parent;
|
||||
// Migrate MokoWaaS database tables to MokoSuiteClient naming
|
||||
$this->migrateWaasTables();
|
||||
|
||||
@@ -527,20 +531,29 @@ class Pkg_MokosuiteclientInstallerScript
|
||||
{
|
||||
$db = Factory::getDbo();
|
||||
|
||||
// Delete orphaned extension rows with empty element — they'll be
|
||||
// recreated correctly on the next package update
|
||||
// 1. Delete orphaned extension rows with empty element
|
||||
$db->setQuery("DELETE FROM " . $db->quoteName('#__extensions')
|
||||
. " WHERE " . $db->quoteName('element') . " = ''"
|
||||
. " AND " . $db->quoteName('type') . " = 'plugin'");
|
||||
$db->execute();
|
||||
$deleted = $db->getAffectedRows();
|
||||
|
||||
// Also delete rows where element is the display name (spaces)
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->delete($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('element') . ' LIKE ' . $db->quote('% %'))
|
||||
->where($db->quoteName('element') . ' LIKE ' . $db->quote('%mokosuiteclient%'))
|
||||
);
|
||||
$db->execute();
|
||||
$deleted += $db->getAffectedRows();
|
||||
|
||||
if ($deleted > 0)
|
||||
{
|
||||
Log::add("Deleted {$deleted} orphaned plugin row(s) with empty element", Log::INFO, 'mokosuiteclient');
|
||||
Log::add("Deleted {$deleted} orphaned plugin row(s)", Log::INFO, 'mokosuiteclient');
|
||||
}
|
||||
|
||||
// Clean up stale plugin files that leaked to plugin group roots
|
||||
// 2. Clean up stale plugin files that leaked to group roots
|
||||
$groupDirs = [JPATH_PLUGINS . '/system', JPATH_PLUGINS . '/task', JPATH_PLUGINS . '/webservices'];
|
||||
|
||||
foreach ($groupDirs as $groupDir)
|
||||
@@ -552,7 +565,6 @@ class Pkg_MokosuiteclientInstallerScript
|
||||
if (is_dir($path))
|
||||
{
|
||||
$this->rmdirRecursive($path);
|
||||
Log::add("Removed stale: {$path}", Log::INFO, 'mokosuiteclient');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,20 +574,93 @@ class Pkg_MokosuiteclientInstallerScript
|
||||
@unlink($staleXml);
|
||||
}
|
||||
|
||||
// Remove dirs with spaces (Joomla uses display name as dir when element is empty)
|
||||
// Remove dirs with spaces (Joomla uses display name as dir)
|
||||
foreach (glob($groupDir . '/*mokosuiteclient*', GLOB_ONLYDIR) ?: [] as $badDir)
|
||||
{
|
||||
if (strpos(basename($badDir), ' ') !== false)
|
||||
{
|
||||
$this->rmdirRecursive($badDir);
|
||||
Log::add("Removed bad dir: " . basename($badDir), Log::INFO, 'mokosuiteclient');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Reinstall plugins that are missing their directory
|
||||
$this->reinstallBrokenPlugins();
|
||||
}
|
||||
catch (\Throwable $e)
|
||||
{
|
||||
Log::add('Empty element cleanup error: ' . $e->getMessage(), Log::WARNING, 'mokosuiteclient');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reinstall plugins whose files are missing from disk.
|
||||
*
|
||||
* Uses the sub-extension zip files from the package source directory
|
||||
* (still available during postflight) to reinstall any plugin that
|
||||
* doesn't have its directory on disk.
|
||||
*/
|
||||
private function reinstallBrokenPlugins(): void
|
||||
{
|
||||
if (!$this->installerParent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$installer = $this->installerParent->getParent();
|
||||
$sourceDir = $installer->getPath('source');
|
||||
|
||||
if (empty($sourceDir) || !is_dir($sourceDir . '/packages'))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Plugins that should exist on disk
|
||||
$expected = [
|
||||
'system' => ['mokosuiteclient_offline', 'mokosuiteclient_firewall', 'mokosuiteclient_tenant', 'mokosuiteclient_devtools', 'mokosuiteclient_dbip'],
|
||||
'task' => ['mokosuiteclient_tickets'],
|
||||
];
|
||||
|
||||
foreach ($expected as $group => $elements)
|
||||
{
|
||||
foreach ($elements as $element)
|
||||
{
|
||||
$pluginDir = JPATH_PLUGINS . '/' . $group . '/' . $element;
|
||||
|
||||
if (is_dir($pluginDir))
|
||||
{
|
||||
continue; // Already installed correctly
|
||||
}
|
||||
|
||||
$zipName = 'plg_' . $group . '_' . $element . '.zip';
|
||||
$zipPath = $sourceDir . '/packages/' . $zipName;
|
||||
|
||||
if (!is_file($zipPath))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract the zip to the correct plugin directory
|
||||
$zip = new \ZipArchive();
|
||||
|
||||
if ($zip->open($zipPath) !== true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@mkdir($pluginDir, 0755, true);
|
||||
$zip->extractTo($pluginDir);
|
||||
$zip->close();
|
||||
|
||||
Log::add("Reinstalled {$group}/{$element} from package zip", Log::INFO, 'mokosuiteclient');
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Throwable $e)
|
||||
{
|
||||
Log::add('Empty element cleanup error: ' . $e->getMessage(), Log::WARNING, 'mokosuiteclient');
|
||||
Log::add('Plugin reinstall error: ' . $e->getMessage(), Log::WARNING, 'mokosuiteclient');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user