diff --git a/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php b/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php index 5900049a..2cd4e5a3 100644 --- a/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php +++ b/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php @@ -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 + } + } }