From f2c7470e55b14591ddcf781b73d1599894c022b9 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Sat, 4 Jul 2026 14:34:34 -0500 Subject: [PATCH] fix(installer): apply standard licensing + install-completion script pattern Adopts the Template-Joomla package-script pattern for download-key handling and post-install messaging, while preserving all MokoSuiteBackup-specific postflight steps (plugins, webcron secret, scheduled task, submenus, client_id fix, icon sync, backup_dir migration). - preflight (update): backupDownloadKey() caches the bare dlid value - postflight (update): restoreDownloadKey() re-writes extra_query as dlid= - postflight (install): installSuccessful() + warnMissingLicenseKey() - postflight (update): installSuccessful() - License nag now runs on install only (a fresh install never has a key), removing the previous always-run "is a key present?" guard - Licensing methods log via Joomla\CMS\Log\Log instead of error_log --- source/script.php | 117 ++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 61 deletions(-) diff --git a/source/script.php b/source/script.php index 67668df..ebf16d0 100644 --- a/source/script.php +++ b/source/script.php @@ -12,6 +12,7 @@ defined('_JEXEC') or die; use Joomla\CMS\Factory; use Joomla\CMS\Installer\InstallerAdapter; use Joomla\CMS\Language\Text; +use Joomla\CMS\Log\Log; use Joomla\CMS\Router\Route; class Pkg_MokoSuiteBackupInstallerScript @@ -73,22 +74,25 @@ class Pkg_MokoSuiteBackupInstallerScript /* Save download key before Joomla re-registers the update site */ if ($type === 'update') { - $this->preflight_saveKey(); + $this->backupDownloadKey(); } return true; } /** - * Called before install/update to preserve the download key. - * - * Joomla re-registers update sites from the manifest on every update, - * which can reset the extra_query (download key). We save it here - * and restore it in postflight. + * The download key cached during preflight so it survives an update. */ private ?string $savedDownloadKey = null; - public function preflight_saveKey(): void + /** + * Cache the existing download key from the update sites table before update runs. + * + * Joomla re-registers update sites from the manifest on every update, which + * can reset the extra_query (download key). We save it here and restore it + * in postflight. + */ + private function backupDownloadKey(): void { try { $db = Factory::getDbo(); @@ -108,19 +112,16 @@ class Pkg_MokoSuiteBackupInstallerScript ->where($db->quoteName('e.element') . ' = ' . $db->quote('pkg_mokosuitebackup')) ->where($db->quoteName('e.type') . ' = ' . $db->quote('package')) ->setLimit(1); - $db->setQuery($query); - $key = $db->loadResult(); - if (!empty($key)) { - $this->savedDownloadKey = $key; + $db->setQuery($query); + $extraQuery = (string) $db->loadResult(); + + if (!empty($extraQuery)) { + parse_str($extraQuery, $output); + $this->savedDownloadKey = $output['dlid'] ?? $extraQuery; } } catch (\Exception $e) { - error_log('MokoSuiteBackup: Could not save download key: ' . $e->getMessage()); - Factory::getApplication()->enqueueMessage( - 'MokoSuiteBackup could not preserve your download/license key before the update. ' - . 'Please verify your license key is still configured in System → Update Sites after this update completes.', - 'warning' - ); + Log::add('MokoSuiteBackup: Could not backup download key: ' . $e->getMessage(), Log::WARNING, 'jerror'); } } @@ -138,8 +139,8 @@ class Pkg_MokoSuiteBackupInstallerScript return; } - /* Restore download key if it was saved before update */ - if ($this->savedDownloadKey !== null) { + /* Restore the download key preserved before the update re-registered the site */ + if ($type === 'update') { $this->restoreDownloadKey(); } @@ -168,14 +169,17 @@ class Pkg_MokoSuiteBackupInstallerScript /* Sync submenu icons in #__menu (Joomla doesn't update icons on upgrades) */ $this->syncMenuIcons(); - /* Warn if no license key configured */ - $this->warnMissingLicenseKey(); - /* Migrate profiles with old default backup_dir values to [DEFAULT_DIR] placeholder */ $this->migrateDefaultBackupDir(); - /* Remind user to review backup profile settings */ + /* Install completion notice (install and update) */ + $this->installSuccessful(); + if ($type === 'install') { + /* Fresh install never carries a download key — prompt for one */ + $this->warnMissingLicenseKey(); + + /* Remind user to review backup profile settings */ $profileUrl = Route::_('index.php?option=com_mokosuitebackup&view=profiles'); Factory::getApplication()->enqueueMessage( @@ -640,66 +644,57 @@ class Pkg_MokoSuiteBackupInstallerScript ->where($db->quoteName('e.element') . ' = ' . $db->quote('pkg_mokosuitebackup')) ->where($db->quoteName('e.type') . ' = ' . $db->quote('package')) ->setLimit(1); + $db->setQuery($query); $updateSiteId = (int) $db->loadResult(); - if ($updateSiteId > 0) { + if ($updateSiteId > 0 && !empty($this->savedDownloadKey)) { $query = $db->getQuery(true) ->update($db->quoteName('#__update_sites')) - ->set($db->quoteName('extra_query') . ' = ' . $db->quote($this->savedDownloadKey)) + ->set($db->quoteName('extra_query') . ' = ' . $db->quote('dlid=' . $this->savedDownloadKey)) ->where($db->quoteName('update_site_id') . ' = ' . $updateSiteId); + $db->setQuery($query); $db->execute(); } } catch (\Exception $e) { - error_log('MokoSuiteBackup: Could not restore download key: ' . $e->getMessage()); + Log::add('MokoSuiteBackup: Could not restore download key: ' . $e->getMessage(), Log::WARNING, 'jerror'); + Factory::getApplication()->enqueueMessage( - 'MokoSuiteBackup: Your download/license key could not be preserved during the update. ' - . 'Please re-enter it in the Update Sites configuration to continue receiving updates.', + '

MokoSuiteBackup

' + . '

Your download/license key could not be preserved during the update.

' + . '

Please re-enter it in the Update Sites manager to continue receiving updates.

', 'warning' ); } } + /** + * Show post-install license key prompt. + */ private function warnMissingLicenseKey(): void { - try - { - $db = Factory::getDbo(); - $db->setQuery( - $db->getQuery(true) - ->select([$db->quoteName('update_site_id'), $db->quoteName('extra_query')]) - ->from($db->quoteName('#__update_sites')) - ->where('(' . $db->quoteName('name') . ' LIKE ' . $db->quote('%MokoSuiteBackup%') . ' OR ' . $db->quoteName('location') . ' LIKE ' . $db->quote('%MokoSuiteBackup%') . ')') - ->setLimit(1) - ); - $site = $db->loadObject(); - - if ($site) - { - $eq = (string) ($site->extra_query ?? ''); - if (!empty($eq) && strpos($eq, 'dlid=') !== false) { parse_str($eq, $p); if (!empty($p['dlid'])) { return; } } - $editUrl = 'index.php?option=com_installer&task=updatesite.edit&update_site_id=' . (int) $site->update_site_id; - } - else - { - $editUrl = 'index.php?option=com_installer&view=updatesites'; - } - + try { Factory::getApplication()->enqueueMessage( - 'Moko Consulting License Key Required — ' - . 'No download key is configured. Updates will not be available until a valid license key is entered. ' - . 'Enter License Key', + '

MokoSuiteBackup License Key Required

' + . '

A download/license key (DLID) is required to receive updates.

' + . '

Enter your key in the Update Sites manager ' + . 'or contact Moko Consulting Support to obtain one.

', 'warning' ); - } - catch (\Exception $e) { - error_log('MokoSuiteBackup: License key check failed: ' . $e->getMessage()); + } catch (\Exception $e) {} + } + + /** + * Show install successful prompt. + */ + private function installSuccessful(): void + { + try { Factory::getApplication()->enqueueMessage( - 'MokoSuiteBackup could not verify your license key status. ' - . 'Please check System → Update Sites to ensure a valid license key is configured.', - 'warning' + '

MokoSuiteBackup installed successfully!

', + 'info' ); - } + } catch (\Exception $e) {} } }