fix: preserve download keys across Joomla extension updates (#187)
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (push) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (push) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (push) Has been cancelled
Platform: moko-platform CI / Gate 3: Self-Health Check (push) Has been cancelled
Platform: moko-platform CI / Gate 4: Governance (push) Has been cancelled
Platform: moko-platform CI / Gate 5: Template Integrity (push) Has been cancelled
Platform: moko-platform CI / CI Summary (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Generic: Repo Health / Site Health (push) Has been cancelled
Generic: Repo Health / Access control (push) Has been cancelled
Universal: Auto Version Bump / Version Bump (push) Has been cancelled
Platform: moko-platform CI / Gate 1: Code Quality (push) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (push) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (push) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (push) Has been cancelled
Platform: moko-platform CI / Gate 3: Self-Health Check (push) Has been cancelled
Platform: moko-platform CI / Gate 4: Governance (push) Has been cancelled
Platform: moko-platform CI / Gate 5: Template Integrity (push) Has been cancelled
Platform: moko-platform CI / CI Summary (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Generic: Repo Health / Site Health (push) Has been cancelled
Generic: Repo Health / Access control (push) Has been cancelled
Universal: Auto Version Bump / Version Bump (push) Has been cancelled
Platform: moko-platform CI / Gate 1: Code Quality (push) Has been cancelled
Joomla's installer can wipe extra_query (dlid) from #__update_sites when rebuilding or reinstalling. The core plugin now backs up all download keys and auto-restores any that get cleared. Runs on every admin page load with a single lightweight query. Closes #187 Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -166,6 +166,12 @@ class MokoWaaS extends CMSPlugin implements BootableExtensionInterface
|
||||
{
|
||||
$this->handleMokoApi($mokoAction);
|
||||
}
|
||||
|
||||
// Preserve download keys (admin only, lightweight check)
|
||||
if ($this->app->isClient('administrator'))
|
||||
{
|
||||
$this->preserveDownloadKeys();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2046,6 +2052,107 @@ class MokoWaaS extends CMSPlugin implements BootableExtensionInterface
|
||||
return $this->masterNames;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Download Key Preservation
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Preserve download keys across Joomla extension updates.
|
||||
*
|
||||
* Joomla's installer can wipe the extra_query column (which holds
|
||||
* download keys / dlid) when rebuilding or reinstalling update sites.
|
||||
* This method keeps a backup of all non-empty extra_query values and
|
||||
* restores any that get cleared.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 02.34.12
|
||||
*/
|
||||
protected function preserveDownloadKeys(): void
|
||||
{
|
||||
try
|
||||
{
|
||||
$db = Factory::getDbo();
|
||||
|
||||
// Load current extra_query values for all update sites
|
||||
$query = $db->getQuery(true)
|
||||
->select([
|
||||
$db->quoteName('update_site_id'),
|
||||
$db->quoteName('extra_query'),
|
||||
$db->quoteName('location'),
|
||||
])
|
||||
->from($db->quoteName('#__update_sites'));
|
||||
$db->setQuery($query);
|
||||
$sites = $db->loadObjectList('update_site_id') ?: [];
|
||||
|
||||
$backupFile = JPATH_ADMINISTRATOR . '/cache/mokowaas_dlkeys.json';
|
||||
$backup = [];
|
||||
|
||||
if (file_exists($backupFile))
|
||||
{
|
||||
$backup = json_decode(file_get_contents($backupFile), true) ?: [];
|
||||
}
|
||||
|
||||
$restored = 0;
|
||||
$updated = false;
|
||||
|
||||
foreach ($sites as $id => $site)
|
||||
{
|
||||
$currentKey = trim((string) $site->extra_query);
|
||||
$backupKey = $backup[$id] ?? '';
|
||||
|
||||
if ($currentKey !== '')
|
||||
{
|
||||
// Site has a key — update backup if changed
|
||||
if ($currentKey !== $backupKey)
|
||||
{
|
||||
$backup[$id] = $currentKey;
|
||||
$updated = true;
|
||||
}
|
||||
}
|
||||
elseif ($backupKey !== '')
|
||||
{
|
||||
// Key was wiped — restore from backup
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->update($db->quoteName('#__update_sites'))
|
||||
->set($db->quoteName('extra_query') . ' = ' . $db->quote($backupKey))
|
||||
->where($db->quoteName('update_site_id') . ' = ' . (int) $id)
|
||||
)->execute();
|
||||
|
||||
$restored++;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up backup entries for update sites that no longer exist
|
||||
$currentIds = array_keys($sites);
|
||||
|
||||
foreach (array_keys($backup) as $backupId)
|
||||
{
|
||||
if (!isset($sites[$backupId]))
|
||||
{
|
||||
unset($backup[$backupId]);
|
||||
$updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($updated || $restored > 0)
|
||||
{
|
||||
file_put_contents($backupFile, json_encode($backup, JSON_PRETTY_PRINT));
|
||||
}
|
||||
|
||||
if ($restored > 0)
|
||||
{
|
||||
Log::add(
|
||||
sprintf('MokoWaaS: restored %d download key(s) that were cleared by Joomla.', $restored),
|
||||
Log::INFO,
|
||||
'mokowaas'
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (\Throwable $e)
|
||||
{
|
||||
// Non-critical — don't break the site over key backup
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user