From 894597536e2851817c876b664c21b93eeeeb9c0e Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 21 Apr 2026 17:05:57 -0500 Subject: [PATCH] feat: unlock MokoCassiopeia + lock MokoOnyx during bridge migration Co-Authored-By: Claude Opus 4.6 (1M context) --- src/script.php | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/script.php b/src/script.php index c6d0023..5fa417a 100644 --- a/src/script.php +++ b/src/script.php @@ -122,11 +122,14 @@ class Tpl_MokocassiopeiaInstallerScript implements InstallerScriptInterface // 5. Redirect update server to MokoOnyx $this->updateUpdateServer(); - // 6. Notify + // 6. Unlock MokoCassiopeia (allow uninstall) + lock MokoOnyx (prevent accidental uninstall) + $this->updateExtensionLocks(); + + // 7. Notify $app->enqueueMessage( 'MokoOnyx has been installed as a replacement for MokoCassiopeia.
' . 'Your template settings have been migrated. MokoOnyx is now your active site template.
' - . 'You can safely uninstall MokoCassiopeia from Extensions → Manage.', + . 'MokoCassiopeia has been unlocked — you can uninstall it from Extensions → Manage.', 'success' ); @@ -362,6 +365,42 @@ class Tpl_MokocassiopeiaInstallerScript implements InstallerScriptInterface } } + private function updateExtensionLocks(): void + { + $db = Factory::getDbo(); + + // Unlock MokoCassiopeia — allow uninstall + try { + $query = $db->getQuery(true) + ->update('#__extensions') + ->set($db->quoteName('locked') . ' = 0') + ->set($db->quoteName('protected') . ' = 0') + ->where($db->quoteName('element') . ' = ' . $db->quote(self::OLD_NAME)) + ->where($db->quoteName('type') . ' = ' . $db->quote('template')); + $db->setQuery($query)->execute(); + if ($db->getAffectedRows() > 0) { + $this->log('Bridge: unlocked MokoCassiopeia (can be uninstalled).'); + } + } catch (\Throwable $e) { + $this->log('Bridge: failed to unlock MokoCassiopeia: ' . $e->getMessage(), 'warning'); + } + + // Lock MokoOnyx — prevent accidental uninstall + try { + $query = $db->getQuery(true) + ->update('#__extensions') + ->set($db->quoteName('locked') . ' = 1') + ->where($db->quoteName('element') . ' = ' . $db->quote(self::NEW_NAME)) + ->where($db->quoteName('type') . ' = ' . $db->quote('template')); + $db->setQuery($query)->execute(); + if ($db->getAffectedRows() > 0) { + $this->log('Bridge: locked MokoOnyx (protected from uninstall).'); + } + } catch (\Throwable $e) { + $this->log('Bridge: failed to lock MokoOnyx: ' . $e->getMessage(), 'warning'); + } + } + // ── Logging ──────────────────────────────────────────────────────── private function log(string $message, string $priority = 'info'): void