diff --git a/administrator/components/com_installer/src/Model/DatabaseModel.php b/administrator/components/com_installer/src/Model/DatabaseModel.php index e29484c75a387..fa6a529ac0708 100644 --- a/administrator/components/com_installer/src/Model/DatabaseModel.php +++ b/administrator/components/com_installer/src/Model/DatabaseModel.php @@ -18,6 +18,7 @@ use Joomla\CMS\Table\Extension; use Joomla\CMS\Version; use Joomla\Component\Installer\Administrator\Helper\InstallerHelper; +use Joomla\Database\DatabaseQuery; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\ParameterType; use Joomla\Registry\Registry; @@ -145,18 +146,69 @@ private function fetchSchemaCache($cid = 0) } $db = $this->getDbo(); - $folderTmp = JPATH_ADMINISTRATOR . '/components/' . $result->element . '/sql/updates/'; - // If the extension doesn't follow the standard location for the - // update sql files we don't support it + if ($result->type === 'component') + { + $basePath = JPATH_ADMINISTRATOR . '/components/' . $result->element; + } + elseif ($result->type === 'plugin') + { + $basePath = JPATH_PLUGINS . '/' . $result->folder . '/' . $result->element; + } + elseif ($result->type === 'module') + { + // Typehint to integer to normalise some DBs returning strings and others integers + if ((int) $result->client_id === 1) + { + $basePath = JPATH_ADMINISTRATOR . '/modules/' . $result->element; + } + elseif ((int) $result->client_id === 0) + { + $basePath = JPATH_SITE . '/modules/' . $result->element; + } + else + { + // Module with unknown client id!? - bail + continue; + } + } + // Specific bodge for the Joomla CMS special database check which points to com_admin + elseif ($result->type === 'file' && $result->element === 'com_admin') + { + $basePath = JPATH_ADMINISTRATOR . '/components/' . $result->element; + } + else + { + // Unknown extension type (library, files etc which don't have known SQL paths right now) + continue; + } + + // Search the standard SQL Path for the SQL Updates and then if not there check the configuration of the XML + // file. This just gives us a small performance win of not parsing the XML every time. + $folderTmp = $basePath . '/sql/updates/'; + if (!file_exists($folderTmp)) { - $installationXML = InstallerHelper::getInstallationXML($result->element, $result->type); - $folderTmp = (string) $installationXML->update->schemas->schemapath[0]; + $installationXML = InstallerHelper::getInstallationXML( + $result->element, + $result->type, + $result->client_id, + $result->type === 'plugin' ? $result->folder : null + ); + + if ($installationXML !== null) + { + $folderTmp = (string) $installationXML->update->schemas->schemapath[0]; + $a = explode('/', $folderTmp); + array_pop($a); + $folderTmp = $basePath . '/' . implode('/', $a); + } + } - $a = explode('/', $folderTmp); - array_pop($a); - $folderTmp = JPATH_ADMINISTRATOR . '/components/' . $result->element . '/' . implode('/', $a); + // Can't find the folder still - give up now and move on. + if (!file_exists($folderTmp)) + { + continue; } $changeSet = new ChangeSet($db, $folderTmp); @@ -165,6 +217,12 @@ private function fetchSchemaCache($cid = 0) // than the update files, add to problems message $schema = $changeSet->getSchema(); + // If the schema is empty we couldn't find any update files. Just ignore the extension. + if (empty($schema)) + { + continue; + } + if ($result->version_id !== $schema) { $errorMessages[] = Text::sprintf('COM_INSTALLER_MSG_DATABASE_SCHEMA_ERROR', $result->version_id, $schema); @@ -301,7 +359,7 @@ public function getItems() /** * Method to get the database query * - * @return \JDatabaseQuery The database query + * @return DatabaseQuery The database query * * @since 4.0.0 */ @@ -502,7 +560,13 @@ public function compareUpdateVersion($extension) } else { - $installationXML = InstallerHelper::getInstallationXML($extension->element, $extension->type); + $installationXML = InstallerHelper::getInstallationXML( + $extension->element, + $extension->type, + $extension->client_id, + $extension->type === 'plugin' ? $extension->folder : null + ); + $extensionVersion = (string) $installationXML->version; } diff --git a/administrator/components/com_installer/src/Model/InstallerModel.php b/administrator/components/com_installer/src/Model/InstallerModel.php index e67ca549db268..ee2788e1dddf1 100644 --- a/administrator/components/com_installer/src/Model/InstallerModel.php +++ b/administrator/components/com_installer/src/Model/InstallerModel.php @@ -15,6 +15,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; +use Joomla\Database\DatabaseQuery; use Joomla\Utilities\ArrayHelper; /** @@ -54,9 +55,9 @@ public function __construct($config = array(), MVCFactoryInterface $factory = nu /** * Returns an object list * - * @param \JDatabaseQuery $query The query - * @param int $limitstart Offset - * @param int $limit The number of records + * @param DatabaseQuery $query The query + * @param int $limitstart Offset + * @param int $limit The number of records * * @return array */ diff --git a/libraries/src/Schema/ChangeSet.php b/libraries/src/Schema/ChangeSet.php index 651da6e6cbc7a..c57f4beb33a13 100644 --- a/libraries/src/Schema/ChangeSet.php +++ b/libraries/src/Schema/ChangeSet.php @@ -69,6 +69,13 @@ public function __construct($db, $folder = null) $this->db = $db; $this->folder = $folder; $updateFiles = $this->getUpdateFiles(); + + // If no files were found nothing more we can do - continue + if ($updateFiles === false) + { + return; + } + $updateQueries = $this->getUpdateQueries($updateFiles); foreach ($updateQueries as $obj) @@ -234,6 +241,13 @@ public function getStatus() public function getSchema() { $updateFiles = $this->getUpdateFiles(); + + // No schema files found - abort and return empty string + if (empty($updateFiles)) + { + return ''; + } + $result = new \SplFileInfo(array_pop($updateFiles)); return $result->getBasename('.sql'); @@ -242,7 +256,7 @@ public function getSchema() /** * Get list of SQL update files for this database * - * @return array list of sql update full-path names + * @return array|boolean list of sql update full-path names. False if directory doesn't exist * * @since 2.5 */ @@ -263,6 +277,13 @@ private function getUpdateFiles() $this->folder = JPATH_ADMINISTRATOR . '/components/com_admin/sql/updates/'; } + // We don't want to enqueue an error if the directory doesn't exist - this can be handled elsewhere/ + // So bail here. + if (!is_dir($this->folder . '/' . $sqlFolder)) + { + return []; + } + return Folder::files( $this->folder . '/' . $sqlFolder, '\.sql$', 1, true, array('.svn', 'CVS', '.DS_Store', '__MACOSX'), array('^\..*', '.*~'), true );