From dbaeb33dc43f7dec21f5991a94ce7be8fe5d25a4 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 6 Jul 2026 16:24:15 +0000 Subject: [PATCH] fix(installer): gate update() on schema + use enqueueMessage for success Mirrors the install() smart-check on update() and replaces echo with a proper Joomla message for consistency. Claude-Session: https://claude.ai/code/session_01MrxXW9iyuDda5yDZrjZMbF --- source/packages/com_mokoog/script.php | 221 ++++++++++++++------------ 1 file changed, 119 insertions(+), 102 deletions(-) diff --git a/source/packages/com_mokoog/script.php b/source/packages/com_mokoog/script.php index c77018c..cf2cc39 100644 --- a/source/packages/com_mokoog/script.php +++ b/source/packages/com_mokoog/script.php @@ -1,102 +1,119 @@ - - * @copyright Copyright (C) 2026 Moko Consulting. All rights reserved. - * @license GNU General Public License version 3 or later; see LICENSE - */ - -defined('_JEXEC') or die; - -use Joomla\CMS\Factory; -use Joomla\CMS\Installer\InstallerAdapter; - -class Com_MokoOGInstallerScript -{ - /** - * Called after install. - * - * @param InstallerAdapter $parent Installer adapter - * - * @return void - */ - public function install(InstallerAdapter $parent): void - { - // Be smart: verify EVERY table the component's own install SQL declares is - // actually present. If any are missing the install did not complete — say - // so instead of showing "installed successfully". - $missing = $this->missingTables(); - - if ($missing !== []) { - $detail = count($missing) > 6 - ? count($missing) . ' expected database tables are missing' - : 'missing tables: ' . htmlspecialchars(implode(', ', $missing), ENT_QUOTES, 'UTF-8'); - - Factory::getApplication()->enqueueMessage( - 'MokoSuiteOpenGraph did not install correctly. ' . $detail - . ' — review the errors above, then reinstall.', - 'error' - ); - - return; - } - - echo '

MokoSuiteOpenGraph component installed successfully.

'; - } - - /** - * Called after update. - * - * @param InstallerAdapter $parent Installer adapter - * - * @return void - */ - public function update(InstallerAdapter $parent): void - { - echo '

MokoSuiteOpenGraph component updated successfully.

'; - } - - /** - * Smart schema check: parse the component's own installed install SQL for every - * CREATE TABLE, then return the ones missing from the database. An empty array - * means the full schema installed. Fails open (returns []) if the SQL can't be - * read, so a good install is never flagged as failed. - * - * @return string[] Names (without the #__ prefix) of missing tables. - */ - private function missingTables(): array - { - try { - $sqlFile = JPATH_ADMINISTRATOR . '/components/com_mokoog/sql/install.mysql.sql'; - - if (!is_file($sqlFile)) { - return []; - } - - $sql = file_get_contents($sqlFile); - - if ($sql === false - || !preg_match_all('/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?[`"\']?(#__[A-Za-z0-9_]+)/i', $sql, $m)) { - return []; - } - - $db = Factory::getDbo(); - $prefix = strtolower($db->getPrefix()); - $have = array_map('strtolower', $db->getTableList()); - $missing = []; - - foreach (array_unique($m[1]) as $decl) { - $bare = substr($decl, 3); // strip "#__" - if (!in_array($prefix . strtolower($bare), $have, true)) { - $missing[] = $bare; - } - } - - return $missing; - } catch (\Throwable $e) { - return []; - } - } -} + + * @copyright Copyright (C) 2026 Moko Consulting. All rights reserved. + * @license GNU General Public License version 3 or later; see LICENSE + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Factory; +use Joomla\CMS\Installer\InstallerAdapter; + +class Com_MokoOGInstallerScript +{ + /** + * Called after install. + * + * @param InstallerAdapter $parent Installer adapter + * + * @return void + */ + public function install(InstallerAdapter $parent): void + { + // Be smart: verify EVERY table the component's own install SQL declares is + // actually present. If any are missing the install did not complete — say + // so instead of showing "installed successfully". + $missing = $this->missingTables(); + + if ($missing !== []) { + $detail = count($missing) > 6 + ? count($missing) . ' expected database tables are missing' + : 'missing tables: ' . htmlspecialchars(implode(', ', $missing), ENT_QUOTES, 'UTF-8'); + + Factory::getApplication()->enqueueMessage( + 'MokoSuiteOpenGraph did not install correctly. ' . $detail + . ' — review the errors above, then reinstall.', + 'error' + ); + + return; + } + + Factory::getApplication()->enqueueMessage('

MokoSuiteOpenGraph installed successfully!

', 'info'); + } + + /** + * Called after update. + * + * @param InstallerAdapter $parent Installer adapter + * + * @return void + */ + public function update(InstallerAdapter $parent): void + { + // Same smart check on update: only report success if the schema is intact. + $missing = $this->missingTables(); + + if ($missing !== []) { + $detail = count($missing) > 6 + ? count($missing) . ' expected database tables are missing' + : 'missing tables: ' . htmlspecialchars(implode(', ', $missing), ENT_QUOTES, 'UTF-8'); + + Factory::getApplication()->enqueueMessage( + 'MokoSuiteOpenGraph did not update correctly. ' . $detail + . ' — review the errors above.', + 'error' + ); + + return; + } + + Factory::getApplication()->enqueueMessage('MokoSuiteOpenGraph updated successfully.', 'info'); + } + + /** + * Smart schema check: parse the component's own installed install SQL for every + * CREATE TABLE, then return the ones missing from the database. An empty array + * means the full schema installed. Fails open (returns []) if the SQL can't be + * read, so a good install is never flagged as failed. + * + * @return string[] Names (without the #__ prefix) of missing tables. + */ + private function missingTables(): array + { + try { + $sqlFile = JPATH_ADMINISTRATOR . '/components/com_mokoog/sql/install.mysql.sql'; + + if (!is_file($sqlFile)) { + return []; + } + + $sql = file_get_contents($sqlFile); + + if ($sql === false + || !preg_match_all('/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?[`"\']?(#__[A-Za-z0-9_]+)/i', $sql, $m)) { + return []; + } + + $db = Factory::getDbo(); + $prefix = strtolower($db->getPrefix()); + $have = array_map('strtolower', $db->getTableList()); + $missing = []; + + foreach (array_unique($m[1]) as $decl) { + $bare = substr($decl, 3); // strip "#__" + if (!in_array($prefix . strtolower($bare), $have, true)) { + $missing[] = $bare; + } + } + + return $missing; + } catch (\Throwable $e) { + return []; + } + } +}