diff --git a/source/script.php b/source/script.php index 49481545..241c05d3 100644 --- a/source/script.php +++ b/source/script.php @@ -95,12 +95,18 @@ class Pkg_MokowaasInstallerScript // Mark MokoWaaS extensions as protected (prevents disable/uninstall at framework level) $this->protectExtensions(); + // Save download keys before any update site manipulation + $savedKeys = $this->backupDownloadKeys(); + // Migrate all Moko update server URLs to new format $this->migrateUpdateServerUrls(); // Clean up stale/duplicate update sites $this->cleanupStaleUpdateSites(); + // Restore download keys that were wiped by cleanup/migration + $this->restoreDownloadKeys($savedKeys); + // Fix orphaned update records (extension_id=0) $this->fixUpdateRecords(); @@ -656,6 +662,113 @@ class Pkg_MokowaasInstallerScript } } + /** + * Backup all non-empty extra_query values from update sites. + * + * @return array Map of update_site_id => extra_query + */ + private function backupDownloadKeys(): array + { + $keys = []; + + try + { + $db = Factory::getDbo(); + $db->setQuery( + $db->getQuery(true) + ->select([$db->quoteName('update_site_id'), $db->quoteName('extra_query'), $db->quoteName('location')]) + ->from($db->quoteName('#__update_sites')) + ->where($db->quoteName('extra_query') . ' != ' . $db->quote('')) + ); + $rows = $db->loadObjectList() ?: []; + + foreach ($rows as $row) + { + // Key by location so we can match after IDs change + $keys[$row->location] = $row->extra_query; + $keys['id_' . $row->update_site_id] = $row->extra_query; + } + + // Also save to file backup for the preserveDownloadKeys() runtime guard + $backupFile = JPATH_ADMINISTRATOR . '/cache/mokowaas_dlkeys.json'; + $existing = []; + + if (file_exists($backupFile)) + { + $existing = json_decode(file_get_contents($backupFile), true) ?: []; + } + + foreach ($rows as $row) + { + $existing[$row->update_site_id] = $row->extra_query; + } + + file_put_contents($backupFile, json_encode($existing, JSON_PRETTY_PRINT)); + } + catch (\Throwable $e) + { + // Non-critical + } + + return $keys; + } + + /** + * Restore download keys that were cleared by update site cleanup. + * + * @param array $savedKeys Map from backupDownloadKeys() + */ + private function restoreDownloadKeys(array $savedKeys): void + { + if (empty($savedKeys)) + { + return; + } + + try + { + $db = Factory::getDbo(); + $db->setQuery( + $db->getQuery(true) + ->select([$db->quoteName('update_site_id'), $db->quoteName('extra_query'), $db->quoteName('location')]) + ->from($db->quoteName('#__update_sites')) + ->where($db->quoteName('extra_query') . ' = ' . $db->quote('')) + ); + $sites = $db->loadObjectList() ?: []; + + $restored = 0; + + foreach ($sites as $site) + { + // Try to match by location URL first, then by old ID + $key = $savedKeys[$site->location] ?? $savedKeys['id_' . $site->update_site_id] ?? ''; + + if (!empty($key)) + { + $db->setQuery( + $db->getQuery(true) + ->update($db->quoteName('#__update_sites')) + ->set($db->quoteName('extra_query') . ' = ' . $db->quote($key)) + ->where($db->quoteName('update_site_id') . ' = ' . (int) $site->update_site_id) + )->execute(); + $restored++; + } + } + + if ($restored > 0) + { + Factory::getApplication()->enqueueMessage( + sprintf('Restored %d download key(s) after update site cleanup.', $restored), + 'message' + ); + } + } + catch (\Throwable $e) + { + // Non-critical + } + } + /** * Ensure the MokoWaaS update server entry stays enabled and points * to the correct dynamic endpoint with the license key attached.