saveDownloadKey(); return true; } public function postflight(string $type, InstallerAdapter $parent): void { $app = Factory::getApplication(); // Download the MokoSuite package $tmpPath = Factory::getApplication()->get('tmp_path', sys_get_temp_dir()); $zipFile = $tmpPath . '/pkg_mokosuite_migration.zip'; // Append dlid if we have one $url = self::MOKOSUITE_URL; if ($this->savedDownloadKey) { $url .= (strpos($url, '?') === false ? '?' : '&') . $this->savedDownloadKey; } try { $http = \Joomla\CMS\Http\HttpFactory::getHttp(); $response = $http->get($url, [], 60); if ($response->code !== 200) { $app->enqueueMessage( 'MokoSuite migration: Failed to download package (HTTP ' . $response->code . '). ' . 'Please install MokoSuite manually from the Joomla extension manager.', 'error' ); return; } file_put_contents($zipFile, $response->body); } catch (\Throwable $e) { $app->enqueueMessage( 'MokoSuite migration: Download failed — ' . $e->getMessage() . '. ' . 'Please install MokoSuite manually.', 'error' ); return; } // Install the MokoSuite package (its postflight handles all migration) try { $installer = Installer::getInstance(); $result = $installer->install($zipFile); if ($result) { $app->enqueueMessage( 'MokoSuite installed successfully! ' . 'Your MokoWaaS installation has been migrated to MokoSuite. ' . 'All settings, tickets, and data have been preserved.', 'message' ); } else { $app->enqueueMessage( 'MokoSuite migration: Package install returned false. ' . 'Please check the Joomla installer log and install MokoSuite manually if needed.', 'warning' ); } } catch (\Throwable $e) { $app->enqueueMessage( 'MokoSuite migration: Install failed — ' . $e->getMessage(), 'error' ); } finally { // Clean up temp file if (is_file($zipFile)) { @unlink($zipFile); } } // Transfer the download key to the new MokoSuite update site $this->restoreDownloadKey(); } /** * Save the download key from whichever update site exists. */ private function saveDownloadKey(): void { try { $db = Factory::getDbo(); foreach (['pkg_mokosuite', 'pkg_mokowaas'] as $element) { $db->setQuery( $db->getQuery(true) ->select($db->quoteName('us.extra_query')) ->from($db->quoteName('#__update_sites', 'us')) ->join('INNER', $db->quoteName('#__update_sites_extensions', 'use') . ' ON use.update_site_id = us.update_site_id') ->join('INNER', $db->quoteName('#__extensions', 'e') . ' ON e.extension_id = use.extension_id') ->where($db->quoteName('e.element') . ' = ' . $db->quote($element)) ->setLimit(1) ); $key = $db->loadResult(); if (!empty($key) && strpos($key, 'dlid=') !== false) { $this->savedDownloadKey = $key; break; } } } catch (\Throwable $e) {} } /** * Copy the download key to the MokoSuite update site. */ private function restoreDownloadKey(): void { if ($this->savedDownloadKey === null) { return; } try { $db = Factory::getDbo(); $db->setQuery( $db->getQuery(true) ->select($db->quoteName('us.update_site_id')) ->from($db->quoteName('#__update_sites', 'us')) ->join('INNER', $db->quoteName('#__update_sites_extensions', 'use') . ' ON use.update_site_id = us.update_site_id') ->join('INNER', $db->quoteName('#__extensions', 'e') . ' ON e.extension_id = use.extension_id') ->where($db->quoteName('e.element') . ' = ' . $db->quote('pkg_mokosuite')) ->setLimit(1) ); $siteId = (int) $db->loadResult(); if ($siteId > 0) { $db->setQuery( $db->getQuery(true) ->update($db->quoteName('#__update_sites')) ->set($db->quoteName('extra_query') . ' = ' . $db->quote($this->savedDownloadKey)) ->where($db->quoteName('update_site_id') . ' = ' . $siteId) )->execute(); Log::add('Migrated download key to MokoSuite update site', Log::INFO, 'mokosuite'); } } catch (\Throwable $e) {} } }