diff --git a/administrator/components/com_admin/script.php b/administrator/components/com_admin/script.php index 79b0dbb71fe1f..fccc68572099c 100644 --- a/administrator/components/com_admin/script.php +++ b/administrator/components/com_admin/script.php @@ -501,6 +501,7 @@ protected function uninstallRepeatableFieldsPlugin() // And now uninstall the plugin $installer = new Installer; + $installer->setDatabase($db); $installer->uninstall('plugin', $extensionId); $db->transactionCommit(); @@ -551,6 +552,7 @@ protected function uninstallEosPlugin() // Uninstall the plugin $installer = new Installer; + $installer->setDatabase($db); $installer->uninstall('plugin', $extensionId); $db->transactionCommit(); @@ -607,6 +609,7 @@ protected function updateManifestCaches() } $installer = new Installer; + $installer->setDatabase($db); foreach ($extensions as $extension) { diff --git a/administrator/components/com_installer/src/Model/DiscoverModel.php b/administrator/components/com_installer/src/Model/DiscoverModel.php index 8b412b633c9a8..425cfca7588b3 100644 --- a/administrator/components/com_installer/src/Model/DiscoverModel.php +++ b/administrator/components/com_installer/src/Model/DiscoverModel.php @@ -232,6 +232,7 @@ public function discover_install() foreach ($eid as $id) { $installer = new Installer; + $installer->setDatabase($this->getDatabase()); $result = $installer->discover_install($id); diff --git a/administrator/components/com_installer/src/Model/UpdatesitesModel.php b/administrator/components/com_installer/src/Model/UpdatesitesModel.php index 2aaba2b86ee58..4be1b8c62079d 100644 --- a/administrator/components/com_installer/src/Model/UpdatesitesModel.php +++ b/administrator/components/com_installer/src/Model/UpdatesitesModel.php @@ -356,6 +356,7 @@ public function rebuild(): void foreach ($pathsToSearch as $extensionFolderPath) { $tmpInstaller = new Installer; + $tmpInstaller->setDatabase($this->getDatabase()); $tmpInstaller->setPath('source', $extensionFolderPath); diff --git a/installation/src/Application/InstallationApplication.php b/installation/src/Application/InstallationApplication.php index a48a5cbaf80ad..4ca3187a83fa5 100644 --- a/installation/src/Application/InstallationApplication.php +++ b/installation/src/Application/InstallationApplication.php @@ -311,11 +311,11 @@ private function executeController() list($controllerName, $task) = explode('.', $task, 2); } - // Compile the class name - $class = 'Joomla\\CMS\\Installation\\Controller\\' . ucfirst($controllerName) . 'Controller'; + $factory = new MVCFactory('Joomla\\CMS'); + $factory->setDatabase($this->getContainer()->get(DatabaseInterface::class)); // Create the instance - $controller = new $class([], new MVCFactory('Joomla\\CMS', $this), $this, $this->input); + $controller = $factory->createController($controllerName, 'Installation', [], $this, $this->input); // Execute the task $controller->execute($task); diff --git a/installation/src/Model/ConfigurationModel.php b/installation/src/Model/ConfigurationModel.php index d3fa5e4cc0e2f..5e0bc9dfb5342 100644 --- a/installation/src/Model/ConfigurationModel.php +++ b/installation/src/Model/ConfigurationModel.php @@ -150,6 +150,7 @@ public function setup($options) $return = false; } + // This is needed because the installer loads the extension table in constructor, needs to be refactored in 5.0 Factory::$database = $db; $installer = Installer::getInstance(); @@ -367,6 +368,7 @@ public function checkTestingSampledata($db) $db->insertObject('#__extensions', $testingPlugin, 'extension_id'); $installer = new Installer; + $installer->setDatabase($db); if (!$installer->refreshManifestCache($testingPlugin->extension_id)) { diff --git a/installation/src/Model/LanguagesModel.php b/installation/src/Model/LanguagesModel.php index 1317f0f366a89..73af151cf7ddf 100644 --- a/installation/src/Model/LanguagesModel.php +++ b/installation/src/Model/LanguagesModel.php @@ -22,6 +22,8 @@ use Joomla\CMS\Table\Table; use Joomla\CMS\Updater\Update; use Joomla\CMS\Updater\Updater; +use Joomla\Database\DatabaseAwareInterface; +use Joomla\Database\DatabaseAwareTrait; use Joomla\Registry\Registry; /** @@ -29,8 +31,10 @@ * * @since 3.1 */ -class LanguagesModel extends BaseInstallationModel +class LanguagesModel extends BaseInstallationModel implements DatabaseAwareInterface { + use DatabaseAwareTrait; + /** * @var object Client object. * @since 3.1 @@ -74,13 +78,6 @@ public function __construct() Factory::getApplication()->setConfiguration(new Registry(new \JConfig)); } - /* - * Factory::getDbo() gets called during app bootup, and because of the "uniqueness" of the install app, the config doesn't get read - * correctly at that point. So, we have to reset the factory database object here so that we can get a valid database configuration. - * The day we have proper dependency injection will be a glorious one. - */ - Factory::$database = null; - parent::__construct(); } @@ -94,7 +91,7 @@ public function __construct() public function getItems() { // Get the extension_id of the en-GB package. - $db = Factory::getDbo(); + $db = $this->getDatabase(); $extQuery = $db->getQuery(true); $extQuery->select($db->quoteName('extension_id')) @@ -152,6 +149,7 @@ public function install($lids) { $app = Factory::getApplication(); $installerBase = new Installer; + $installerBase->setDatabase($this->getDatabase()); // Loop through every selected language. foreach ($lids as $id) @@ -397,7 +395,7 @@ protected function getInstalledlangs($clientName = 'administrator') protected function getLanguageList($clientId = 1) { // Create a new db object. - $db = Factory::getDbo(); + $db = $this->getDatabase(); $query = $db->getQuery(true); // Select field element from the extensions table. diff --git a/libraries/src/Adapter/Adapter.php b/libraries/src/Adapter/Adapter.php index 738777623b824..e2161c130f401 100644 --- a/libraries/src/Adapter/Adapter.php +++ b/libraries/src/Adapter/Adapter.php @@ -12,6 +12,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Object\CMSObject; +use Joomla\Database\DatabaseAwareInterface; /** * Adapter Class @@ -79,6 +80,12 @@ public function __construct($basepath, $classprefix = null, $adapterfolder = nul $this->_adapterfolder = $adapterfolder ?: 'adapters'; $this->_db = Factory::getDbo(); + + // Ensure BC, when removed in 5, then the db must be set with setDatabase explicitly + if ($this instanceof DatabaseAwareInterface) + { + $this->setDatabase($this->_db); + } } /** diff --git a/libraries/src/Console/ExtensionDiscoverInstallCommand.php b/libraries/src/Console/ExtensionDiscoverInstallCommand.php index 2177800d60393..7d03ef5944c4f 100644 --- a/libraries/src/Console/ExtensionDiscoverInstallCommand.php +++ b/libraries/src/Console/ExtensionDiscoverInstallCommand.php @@ -119,6 +119,7 @@ protected function configure(): void public function processDiscover($eid): int { $jInstaller = new Installer; + $jInstaller->setDatabase($this->db); $count = 0; if ($eid === -1) diff --git a/libraries/src/Installer/Adapter/ComponentAdapter.php b/libraries/src/Installer/Adapter/ComponentAdapter.php index 4163155d0a617..a6079c4726ac5 100644 --- a/libraries/src/Installer/Adapter/ComponentAdapter.php +++ b/libraries/src/Installer/Adapter/ComponentAdapter.php @@ -447,7 +447,7 @@ protected function finaliseUninstall(): bool { $extensionId = $this->extension->extension_id; - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); // Remove the schema version $query = $db->getQuery(true) @@ -723,7 +723,7 @@ public function prepareDiscoverInstall() $element = $this->extension->element; // Try to delete existing failed records before retrying - $db = $this->db; + $db = $this->getDatabase(); $query = $db->getQuery(true) ->select($db->quoteName('extension_id')) @@ -869,6 +869,7 @@ protected function setupUpdates() // Use a temporary instance due to side effects; start in the administrator first $tmpInstaller = new Installer; + $tmpInstaller->setDatabase($this->getDatabase()); $tmpInstaller->setPath('source', $this->parent->getPath('extension_administrator')); if (!$tmpInstaller->findManifest()) @@ -926,7 +927,7 @@ protected function storeExtension($deleteExisting = false) $element = $this->extension->element; // Try to delete existing failed records before retrying - $db = $this->db; + $db = $this->getDatabase(); $query = $db->getQuery(true) ->select($db->quoteName('extension_id')) @@ -1011,7 +1012,7 @@ protected function storeExtension($deleteExisting = false) */ protected function _buildAdminMenus($componentId = null) { - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); $option = $this->element; // If a component exists with this option in the table within the protected menutype 'main' then we don't need to add menus @@ -1247,7 +1248,7 @@ protected function _buildAdminMenus($componentId = null) */ protected function _removeAdminMenus($id) { - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); /** @var \Joomla\CMS\Table\Menu $table */ $table = Table::getInstance('menu'); @@ -1318,7 +1319,7 @@ protected function _updateSiteMenus($componentId = null) */ protected function _updateMenus($componentId, $clientId = null) { - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); $option = $this->element; $link = 'index.php?option=' . $option; $linkMatch = 'index.php?option=' . $option . '&%'; @@ -1507,7 +1508,7 @@ public function refreshManifestCache() */ protected function _createAdminMenuItem(array &$data, $parentId) { - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); /** @var \Joomla\CMS\Table\Menu $table */ $table = Table::getInstance('menu'); diff --git a/libraries/src/Installer/Adapter/FileAdapter.php b/libraries/src/Installer/Adapter/FileAdapter.php index 02e7df432b377..60ba7eec54b71 100644 --- a/libraries/src/Installer/Adapter/FileAdapter.php +++ b/libraries/src/Installer/Adapter/FileAdapter.php @@ -166,7 +166,7 @@ protected function finaliseUninstall(): bool $extensionId = $this->extension->extension_id; - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); // Remove the schema version $query = $db->getQuery(true) @@ -461,7 +461,7 @@ protected function storeExtension() protected function extensionExistsInSystem($extension = null) { // Get a database connector object - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); $query = $db->getQuery(true) ->select($db->quoteName('extension_id')) diff --git a/libraries/src/Installer/Adapter/LanguageAdapter.php b/libraries/src/Installer/Adapter/LanguageAdapter.php index 50902af32a7ea..b7bcc026d734d 100644 --- a/libraries/src/Installer/Adapter/LanguageAdapter.php +++ b/libraries/src/Installer/Adapter/LanguageAdapter.php @@ -103,7 +103,7 @@ protected function finaliseUninstall(): bool $extensionId = $this->extension->extension_id; // Remove the schema version - $db = Factory::getDbo(); + $db = $this->getDatabase(); $query = $db->getQuery(true) ->delete($db->quoteName('#__schemas')) ->where($db->quoteName('extension_id') . ' = :extension_id') @@ -503,7 +503,7 @@ protected function getSefString($itemLanguageTag) $numberPrefixesFound = 0; // Get the sef value of all current content languages. - $db = Factory::getDbo(); + $db = $this->getDatabase(); $query = $db->getQuery(true) ->select($db->quoteName('sef')) ->from($db->quoteName('#__languages')); @@ -813,7 +813,7 @@ private function resetUserLanguage(): void } // Setting the language of users which have this language as the default language - $db = Factory::getDbo(); + $db = $this->getDatabase(); $query = $db->getQuery(true) ->select( [ diff --git a/libraries/src/Installer/Adapter/LibraryAdapter.php b/libraries/src/Installer/Adapter/LibraryAdapter.php index bf926dab4002c..6d83c43292577 100644 --- a/libraries/src/Installer/Adapter/LibraryAdapter.php +++ b/libraries/src/Installer/Adapter/LibraryAdapter.php @@ -47,12 +47,13 @@ protected function checkExtensionInFilesystem() // We don't want to compromise this instance! $installer = new Installer; + $installer->setDatabase($this->getDatabase()); $installer->setPackageUninstall(true); $installer->uninstall('library', $this->currentExtensionId); // Clear the cached data $this->currentExtensionId = null; - $this->extension = Table::getInstance('Extension', 'JTable', array('dbo' => $this->db)); + $this->extension = Table::getInstance('Extension', 'JTable', array('dbo' => $this->getDatabase())); // From this point we'll consider this an update $this->setRoute('update'); @@ -172,7 +173,7 @@ protected function finaliseUninstall(): bool { $extensionId = $this->extension->extension_id; - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); // Remove the schema version $query = $db->getQuery(true) diff --git a/libraries/src/Installer/Adapter/ModuleAdapter.php b/libraries/src/Installer/Adapter/ModuleAdapter.php index cbc52e26b5b97..ce160c26c2de4 100644 --- a/libraries/src/Installer/Adapter/ModuleAdapter.php +++ b/libraries/src/Installer/Adapter/ModuleAdapter.php @@ -223,7 +223,7 @@ protected function finaliseUninstall(): bool { $extensionId = $this->extension->extension_id; - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); $retval = true; // Remove the schema version @@ -710,7 +710,7 @@ protected function storeExtension() protected function _rollback_menu($arg) { // Get database connector object - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); $moduleId = $arg['id']; @@ -744,7 +744,7 @@ protected function _rollback_menu($arg) protected function _rollback_module($arg) { // Get database connector object - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); $moduleId = $arg['id']; diff --git a/libraries/src/Installer/Adapter/PackageAdapter.php b/libraries/src/Installer/Adapter/PackageAdapter.php index c0cadc06d6dba..b52f7660aa01f 100644 --- a/libraries/src/Installer/Adapter/PackageAdapter.php +++ b/libraries/src/Installer/Adapter/PackageAdapter.php @@ -159,6 +159,7 @@ protected function copyBaseFiles() } $tmpInstaller = new Installer; + $tmpInstaller->setDatabase($this->getDatabase()); $installResult = $tmpInstaller->install($package['dir']); if (!$installResult) @@ -223,7 +224,7 @@ protected function finaliseInstall() // Set the package ID for each of the installed extensions to track the relationship if (!empty($this->installedIds)) { - $db = $this->db; + $db = $this->getDatabase(); $query = $db->getQuery(true) ->update($db->quoteName('#__extensions')) ->set($db->quoteName('package_id') . ' = :id') @@ -316,7 +317,7 @@ protected function finaliseInstall() */ protected function finaliseUninstall(): bool { - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); // Remove the schema version $query = $db->getQuery(true) @@ -436,6 +437,7 @@ protected function removeExtensionFiles() foreach ($manifest->filelist as $extension) { $tmpInstaller = new Installer; + $tmpInstaller->setDatabase($this->getDatabase()); $tmpInstaller->setPackageUninstall(true); $id = $this->_getExtensionId($extension->type, $extension->id, $extension->client, $extension->group); @@ -681,7 +683,7 @@ protected function triggerManifestScript($method) */ protected function _getExtensionId($type, $id, $client, $group) { - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); $query = $db->getQuery(true) ->select($db->quoteName('extension_id')) diff --git a/libraries/src/Installer/Adapter/PluginAdapter.php b/libraries/src/Installer/Adapter/PluginAdapter.php index 70d4e108c551f..5412b09a0ddf2 100644 --- a/libraries/src/Installer/Adapter/PluginAdapter.php +++ b/libraries/src/Installer/Adapter/PluginAdapter.php @@ -136,6 +136,7 @@ protected function createExtensionRoot() { // Create a new installer because findManifest sets stuff; side effects! $tmpInstaller = new Installer; + $tmpInstaller->setDatabase($this->getDatabase()); // Look in the extension root $tmpInstaller->setPath('source', $this->parent->getPath('extension_root')); @@ -202,7 +203,7 @@ protected function finaliseUninstall(): bool { $extensionId = $this->extension->extension_id; - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); // Remove the schema version $query = $db->getQuery(true) diff --git a/libraries/src/Installer/Adapter/TemplateAdapter.php b/libraries/src/Installer/Adapter/TemplateAdapter.php index 5ca13ddf54190..41d90a2d4b1f9 100644 --- a/libraries/src/Installer/Adapter/TemplateAdapter.php +++ b/libraries/src/Installer/Adapter/TemplateAdapter.php @@ -186,7 +186,7 @@ protected function finaliseInstall() */ protected function finaliseUninstall(): bool { - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); $query = $db->getQuery(true); $element = $this->extension->element; @@ -317,7 +317,7 @@ protected function parseQueries() { if (\in_array($this->route, array('install', 'discover_install'))) { - $db = $this->db; + $db = $this->getDatabase(); $query = $db->getQuery(true); $lang = Factory::getLanguage(); $debug = $lang->setDebug(false); @@ -464,7 +464,7 @@ protected function setupUninstall() { $this->parent->extension = $this->extension; - $db = $this->parent->getDbo(); + $db = $this->getDatabase(); $name = $this->extension->element; $clientId = $this->extension->client_id; diff --git a/libraries/src/Installer/Installer.php b/libraries/src/Installer/Installer.php index be76901c9f26b..7b35d73e4c23f 100644 --- a/libraries/src/Installer/Installer.php +++ b/libraries/src/Installer/Installer.php @@ -21,7 +21,9 @@ use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Table\Extension; use Joomla\CMS\Table\Table; +use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\DatabaseDriver; +use Joomla\Database\DatabaseInterface; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\Exception\PrepareStatementFailureException; use Joomla\Database\ParameterType; @@ -34,6 +36,8 @@ */ class Installer extends Adapter { + use DatabaseAwareTrait; + /** * Array of paths needed by the installer * @@ -185,6 +189,7 @@ public static function getInstance($basepath = __DIR__, $classprefix = '\\Joomla if (!isset(self::$instances[$basepath])) { self::$instances[$basepath] = new static($basepath, $classprefix, $adapterfolder); + self::$instances[$basepath]->setDatabase(Factory::getContainer()->get(DatabaseInterface::class)); } return self::$instances[$basepath]; @@ -568,8 +573,8 @@ public function abort($msg = null, $type = null) case 'extension': // Get database connector object - $db = $this->getDbo(); - $query = $db->getQuery(true); + $db = $this->getDatabase(); + $query = $db->getQuery(true); $stepId = (int) $step['id']; // Remove the entry from the #__extensions table @@ -1208,7 +1213,7 @@ public function setSchemaVersion(\SimpleXMLElement $schema, $eid) { if ($eid && $schema) { - $db = Factory::getDbo(); + $db = $this->getDatabase(); $schemapaths = $schema->children(); if (!$schemapaths) @@ -1283,7 +1288,7 @@ public function parseSchemaUpdates(\SimpleXMLElement $schema, $eid) return $updateCount; } - $db = Factory::getDbo(); + $db = $this->getDatabase(); $schemapaths = $schema->children(); if (!\count($schemapaths)) @@ -2331,7 +2336,7 @@ public function generateManifestCache() */ public function cleanDiscoveredExtension($type, $element, $folder = '', $client = 0) { - $db = Factory::getDbo(); + $db = $this->getDatabase(); $query = $db->getQuery(true) ->delete($db->quoteName('#__extensions')) ->where('type = :type') @@ -2684,7 +2689,7 @@ public function loadAdapter($adapter, $options = array()) return Factory::getContainer()->get($class); } - $adapter = new $class($this, $this->getDbo(), $options); + $adapter = new $class($this, $this->getDatabase(), $options); if ($adapter instanceof ContainerAwareInterface) { diff --git a/libraries/src/Installer/InstallerAdapter.php b/libraries/src/Installer/InstallerAdapter.php index 0b5ab3018d7c9..2b0d99bcb3acc 100644 --- a/libraries/src/Installer/InstallerAdapter.php +++ b/libraries/src/Installer/InstallerAdapter.php @@ -19,6 +19,8 @@ use Joomla\CMS\Table\Extension; use Joomla\CMS\Table\Table; use Joomla\CMS\Table\TableInterface; +use Joomla\Database\DatabaseAwareInterface; +use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\DatabaseDriver; use Joomla\DI\Container; use Joomla\DI\ContainerAwareInterface; @@ -31,9 +33,9 @@ * * @since 3.4 */ -abstract class InstallerAdapter implements ContainerAwareInterface +abstract class InstallerAdapter implements ContainerAwareInterface, DatabaseAwareInterface { - use ContainerAwareTrait; + use ContainerAwareTrait, DatabaseAwareTrait; /** * Changelog URL of extensions @@ -147,7 +149,7 @@ abstract class InstallerAdapter implements ContainerAwareInterface public function __construct(Installer $parent, DatabaseDriver $db, array $options = array()) { $this->parent = $parent; - $this->db = $db; + $this->setDatabase($db); foreach ($options as $key => $value) { @@ -1385,4 +1387,31 @@ public function update() // Now jump into the install method to run the update return $this->install(); } + + /** + * Proxy for db variable. + * + * @param string $name The name of the element + * + * @return mixed The value of the element if set, null otherwise + * + * @since __DEPLOY_VERSION__ + * + * @deprecated 5.0 Use getDatabase() instead of directly accessing db + */ + public function __get($name) + { + if ($name === 'db') + { + return $this->getDatabase(); + } + + // Default the variable + if (!isset($this->$name)) + { + $this->$name = null; + } + + return $this->$name; + } }