diff --git a/administrator/language/en-GB/en-GB.lib_joomla.ini b/administrator/language/en-GB/en-GB.lib_joomla.ini index 5aa2d69e3ff5c..0be3d035db13c 100644 --- a/administrator/language/en-GB/en-GB.lib_joomla.ini +++ b/administrator/language/en-GB/en-GB.lib_joomla.ini @@ -528,6 +528,8 @@ JLIB_INSTALLER_ABORT_REFRESH_MANIFEST_CACHE="Refresh Manifest Cache failed: Exte JLIB_INSTALLER_ABORT_REFRESH_MANIFEST_CACHE_VALID="Refresh Manifest Cache failed: Extension is not valid." JLIB_INSTALLER_ABORT_ROLLBACK="Extension %1$s: %2$s" JLIB_INSTALLER_ABORT_SQL_ERROR="Extension %1$s: SQL error processing query: %2$s" +JLIB_INSTALLER_ABORT_STORE_EXTENSION_ALREADY_EXISTS="%1$s %2$s: Extension %3$s already exists." +JLIB_INSTALLER_ABORT_STORE_EXTENSION_FAILED="%1$s %2$s: Failed to store extension %3$s: %4$s." JLIB_INSTALLER_ABORT_TPL_INSTALL_ALREADY_INSTALLED="Template Install: Template already installed." JLIB_INSTALLER_ABORT_TPL_INSTALL_ANOTHER_TEMPLATE_USING_DIRECTORY="Template Install: There is already a Template using the named folder: %s. Are you trying to install the same template again?" JLIB_INSTALLER_ABORT_TPL_INSTALL_COPY_FILES="Template Install: Could not copy files from the %s source." @@ -636,6 +638,14 @@ JLIB_INSTALLER_ERROR_TPL_UNINSTALL_TEMPLATE_DIRECTORY="Template Uninstall: Folde JLIB_INSTALLER_ERROR_TPL_UNINSTALL_TEMPLATE_ID_EMPTY="Template Uninstall: Template ID is empty, can't uninstall files." JLIB_INSTALLER_ERROR_TPL_UNINSTALL_WARNCORETEMPLATE="Template Uninstall: Trying to uninstall a core template: %s" JLIB_INSTALLER_ERROR_UNKNOWN_CLIENT_TYPE="Unknown Client Type [%s]" +JLIB_INSTALLER_EXTENSION_TYPE_COMPONENT="Component" +JLIB_INSTALLER_EXTENSION_TYPE_FILE="File" +JLIB_INSTALLER_EXTENSION_TYPE_LANGUAGE="Language" +JLIB_INSTALLER_EXTENSION_TYPE_LIBRARY="Library" +JLIB_INSTALLER_EXTENSION_TYPE_MODULE="Module" +JLIB_INSTALLER_EXTENSION_TYPE_PACKAGE="Package" +JLIB_INSTALLER_EXTENSION_TYPE_PLUGIN="Plugin" +JLIB_INSTALLER_EXTENSION_TYPE_TEMPLATE="Template" JLIB_INSTALLER_FILE_ERROR_MOVE="Error on moving file %s" JLIB_INSTALLER_INCORRECT_SEQUENCE="Downgrading from version %1$s to version %2$s is not allowed." JLIB_INSTALLER_INSTALL="Install" diff --git a/language/en-GB/en-GB.lib_joomla.ini b/language/en-GB/en-GB.lib_joomla.ini index 5aa2d69e3ff5c..0be3d035db13c 100644 --- a/language/en-GB/en-GB.lib_joomla.ini +++ b/language/en-GB/en-GB.lib_joomla.ini @@ -528,6 +528,8 @@ JLIB_INSTALLER_ABORT_REFRESH_MANIFEST_CACHE="Refresh Manifest Cache failed: Exte JLIB_INSTALLER_ABORT_REFRESH_MANIFEST_CACHE_VALID="Refresh Manifest Cache failed: Extension is not valid." JLIB_INSTALLER_ABORT_ROLLBACK="Extension %1$s: %2$s" JLIB_INSTALLER_ABORT_SQL_ERROR="Extension %1$s: SQL error processing query: %2$s" +JLIB_INSTALLER_ABORT_STORE_EXTENSION_ALREADY_EXISTS="%1$s %2$s: Extension %3$s already exists." +JLIB_INSTALLER_ABORT_STORE_EXTENSION_FAILED="%1$s %2$s: Failed to store extension %3$s: %4$s." JLIB_INSTALLER_ABORT_TPL_INSTALL_ALREADY_INSTALLED="Template Install: Template already installed." JLIB_INSTALLER_ABORT_TPL_INSTALL_ANOTHER_TEMPLATE_USING_DIRECTORY="Template Install: There is already a Template using the named folder: %s. Are you trying to install the same template again?" JLIB_INSTALLER_ABORT_TPL_INSTALL_COPY_FILES="Template Install: Could not copy files from the %s source." @@ -636,6 +638,14 @@ JLIB_INSTALLER_ERROR_TPL_UNINSTALL_TEMPLATE_DIRECTORY="Template Uninstall: Folde JLIB_INSTALLER_ERROR_TPL_UNINSTALL_TEMPLATE_ID_EMPTY="Template Uninstall: Template ID is empty, can't uninstall files." JLIB_INSTALLER_ERROR_TPL_UNINSTALL_WARNCORETEMPLATE="Template Uninstall: Trying to uninstall a core template: %s" JLIB_INSTALLER_ERROR_UNKNOWN_CLIENT_TYPE="Unknown Client Type [%s]" +JLIB_INSTALLER_EXTENSION_TYPE_COMPONENT="Component" +JLIB_INSTALLER_EXTENSION_TYPE_FILE="File" +JLIB_INSTALLER_EXTENSION_TYPE_LANGUAGE="Language" +JLIB_INSTALLER_EXTENSION_TYPE_LIBRARY="Library" +JLIB_INSTALLER_EXTENSION_TYPE_MODULE="Module" +JLIB_INSTALLER_EXTENSION_TYPE_PACKAGE="Package" +JLIB_INSTALLER_EXTENSION_TYPE_PLUGIN="Plugin" +JLIB_INSTALLER_EXTENSION_TYPE_TEMPLATE="Template" JLIB_INSTALLER_FILE_ERROR_MOVE="Error on moving file %s" JLIB_INSTALLER_INCORRECT_SEQUENCE="Downgrading from version %1$s to version %2$s is not allowed." JLIB_INSTALLER_INSTALL="Install" diff --git a/libraries/cms/installer/adapter.php b/libraries/cms/installer/adapter.php index c347ccd73a13e..410a47da96631 100644 --- a/libraries/cms/installer/adapter.php +++ b/libraries/cms/installer/adapter.php @@ -1085,4 +1085,30 @@ public function update() // Now jump into the install method to run the update return $this->install(); } + + /** + * Add a rollback step to parent installer. + * + * @param array $step The step to rollback. + * + * @return null + * + * @since __DEPLOY_VERSION__ + */ + public function addStepToInstaller(array $step = array()) + { + // We only add rollback step on new installs. + if ($this->currentExtensionId) + { + return null; + } + + // The rollback step need something. + if ($step === array()) + { + return null; + } + + $this->parent->pushStep($step); + } } diff --git a/libraries/cms/installer/adapter/component.php b/libraries/cms/installer/adapter/component.php index 76a0750272c76..4e399fcdf870e 100644 --- a/libraries/cms/installer/adapter/component.php +++ b/libraries/cms/installer/adapter/component.php @@ -570,90 +570,71 @@ protected function setupUpdates() /** * Method to store the extension to the database * - * @param bool $deleteExisting Should I try to delete existing records of the same component? - * * @return void * * @since 3.4 * @throws RuntimeException */ - protected function storeExtension($deleteExisting = false) + protected function storeExtension() { // The extension is stored during prepareDiscoverInstall for discover installs - if ($this->route == 'discover_install') + if ($this->route === 'discover_install') { return; } - // Add or update an entry to the extension table - $this->extension->name = $this->name; - $this->extension->type = 'component'; - $this->extension->element = $this->element; - - // If we are told to delete existing extension entries then do so. - if ($deleteExisting) + // If extension already exists, load the entry. + if ($this->currentExtensionId) { - $db = $this->parent->getDbo(); - - $query = $db->getQuery(true) - ->select($db->qn('extension_id')) - ->from($db->qn('#__extensions')) - ->where($db->qn('name') . ' = ' . $db->q($this->extension->name)) - ->where($db->qn('type') . ' = ' . $db->q($this->extension->type)) - ->where($db->qn('element') . ' = ' . $db->q($this->extension->element)); - - $db->setQuery($query); - - $extension_ids = $db->loadColumn(); - - if (!empty($extension_ids)) + // If we are not allowed to overwrite on update. + if (!$this->parent->isOverwrite()) { - foreach ($extension_ids as $eid) - { - // Remove leftover admin menus for this extension ID - $this->_removeAdminMenus($eid); - - // Remove the extension record itself - /** @var JTableExtension $extensionTable */ - $extensionTable = JTable::getInstance('extension'); - $extensionTable->delete($eid); - } + throw new RuntimeException( + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_ALREADY_EXISTS', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), + JText::_('JLIB_INSTALLER_' . $this->route), + $this->name + ) + ); } - } - // If there is not already a row, generate a heap of defaults - if (!$this->currentExtensionId) + $this->extension->load($this->currentExtensionId); + } + // If extension doesn't exist, add an entry to the extension table with defaults. + else { - $this->extension->folder = ''; - $this->extension->enabled = 1; - $this->extension->protected = 0; - $this->extension->access = 0; - $this->extension->client_id = 1; - $this->extension->params = $this->parent->getParams(); - $this->extension->custom_data = ''; + $this->extension->type = $this->type; + $this->extension->element = $this->element; + $this->extension->folder = ''; + $this->extension->enabled = 1; + $this->extension->protected = 0; + $this->extension->access = 0; + $this->extension->client_id = 1; + $this->extension->ordering = 0; + $this->extension->params = $this->parent->getParams(); $this->extension->system_data = ''; + $this->extension->custom_data = ''; } + // On install or update refresh name and manifest cache. + $this->extension->name = $this->name; $this->extension->manifest_cache = $this->parent->generateManifestCache(); - $couldStore = $this->extension->store(); - - if (!$couldStore && $deleteExisting) + // If store extension failed, abort and throw and extension. + if (!$this->extension->store()) { - // Install failed, roll back changes throw new RuntimeException( - JText::sprintf( - 'JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_FAILED', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->typee)), + JText::_('JLIB_INSTALLER_' . $this->route), + $this->name, $this->extension->getError() ) ); } - if (!$couldStore && !$deleteExisting) - { - // Maybe we have a failed installation (e.g. timeout). Let's retry after deleting old records. - $this->storeExtension(true); - } + // Add a installer rollback step to the installation step stack so we can rollback the changes if we need. + $this->addStepToInstaller(array('type' => 'extension', 'id' => $this->extension->extension_id)); } /** diff --git a/libraries/cms/installer/adapter/file.php b/libraries/cms/installer/adapter/file.php index 41a2f9b515ac4..f921cab1654af 100644 --- a/libraries/cms/installer/adapter/file.php +++ b/libraries/cms/installer/adapter/file.php @@ -218,63 +218,58 @@ protected function setupInstallPaths() */ protected function storeExtension() { + // If extension already exists, load the entry. if ($this->currentExtensionId) { - // Load the entry and update the manifest_cache - $this->extension->load($this->currentExtensionId); - - // Update name - $this->extension->name = $this->name; - - // Update manifest - $this->extension->manifest_cache = $this->parent->generateManifestCache(); - - if (!$this->extension->store()) + // If we are not allowed to overwrite on update. + if (!$this->parent->isOverwrite()) { - // Install failed, roll back changes throw new RuntimeException( - JText::sprintf( - 'JLIB_INSTALLER_ABORT_ROLLBACK', - JText::_('JLIB_INSTALLER_' . strtoupper($this->route)), - $this->extension->getError() - ) + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_ALREADY_EXISTS', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), + JText::_('JLIB_INSTALLER_' . $this->route), + $this->name + ) ); } + + $this->extension->load($this->currentExtensionId); } + // If extension doesn't exist, add an entry to the extension table with defaults. else { - // Add an entry to the extension table with a whole heap of defaults - $this->extension->name = $this->name; - $this->extension->type = 'file'; - $this->extension->element = $this->element; - - // There is no folder for files so leave it blank - $this->extension->folder = ''; - $this->extension->enabled = 1; - $this->extension->protected = 0; - $this->extension->access = 0; - $this->extension->client_id = 0; - $this->extension->params = ''; + $this->extension->type = $this->type; + $this->extension->element = $this->element; + $this->extension->folder = ''; + $this->extension->enabled = 1; + $this->extension->protected = 0; + $this->extension->access = 0; + $this->extension->client_id = 0; + $this->extension->ordering = 0; + $this->extension->params = ''; $this->extension->system_data = ''; - $this->extension->manifest_cache = $this->parent->generateManifestCache(); $this->extension->custom_data = ''; + } - if (!$this->extension->store()) - { - // Install failed, roll back changes - throw new RuntimeException( - JText::sprintf( - 'JLIB_INSTALLER_ABORT_ROLLBACK', - JText::_('JLIB_INSTALLER_' . strtoupper($this->route)), - $this->extension->getError() - ) - ); - } + // On install or update refresh name and manifest cache. + $this->extension->name = $this->name; + $this->extension->manifest_cache = $this->parent->generateManifestCache(); - // Since we have created a module item, we add it to the installation step stack - // so that if we have to rollback the changes we can undo it. - $this->parent->pushStep(array('type' => 'extension', 'extension_id' => $this->extension->extension_id)); + // If store extension failed, abort and throw and extension. + if (!$this->extension->store()) + { + throw new RuntimeException( + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_FAILED', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), + JText::_('JLIB_INSTALLER_' . $this->route), + $this->name, + $this->extension->getError() + ) + ); } + + // Add a installer rollback step to the installation step stack so we can rollback the changes if we need. + $this->addStepToInstaller(array('type' => 'extension', 'id' => $this->extension->extension_id)); } /** diff --git a/libraries/cms/installer/adapter/library.php b/libraries/cms/installer/adapter/library.php index 805e6aed8744e..fbd6acc7e5f75 100644 --- a/libraries/cms/installer/adapter/library.php +++ b/libraries/cms/installer/adapter/library.php @@ -238,10 +238,10 @@ protected function storeExtension() $manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest')); $this->extension->manifest_cache = json_encode($manifest_details); - $this->extension->state = 0; - $this->extension->name = $manifest_details['name']; - $this->extension->enabled = 1; - $this->extension->params = $this->parent->getParams(); + $this->extension->state = 0; + $this->extension->name = $manifest_details['name']; + $this->extension->enabled = 1; + $this->extension->params = $this->parent->getParams(); if (!$this->extension->store()) { @@ -252,39 +252,59 @@ protected function storeExtension() return; } - $this->extension->name = $this->name; - $this->extension->type = 'library'; - $this->extension->element = $this->element; - - // There is no folder for libraries - $this->extension->folder = ''; - $this->extension->enabled = 1; - $this->extension->protected = 0; - $this->extension->access = 1; - $this->extension->client_id = 0; - $this->extension->params = $this->parent->getParams(); + // If extension already exists, load the entry. + if ($this->currentExtensionId) + { + // If we are not allowed to overwrite on update. + if (!$this->parent->isOverwrite()) + { + throw new RuntimeException( + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_ALREADY_EXISTS', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), + JText::_('JLIB_INSTALLER_' . $this->route), + $this->name + ) + ); + } - // Custom data - $this->extension->custom_data = ''; - $this->extension->system_data = ''; + // Load the entry and update the manifest_cache + $this->extension->load($this->currentExtensionId); + } + // If extension doesn't exist, add an entry to the extension table with defaults. + else + { + $this->extension->type = $this->type; + $this->extension->element = $this->element; + $this->extension->folder = ''; + $this->extension->enabled = 1; + $this->extension->protected = 0; + $this->extension->access = 1; + $this->extension->client_id = 0; + $this->extension->ordering = 0; + $this->extension->params = $this->parent->getParams(); + $this->extension->system_data = ''; + $this->extension->custom_data = ''; + } - // Update the manifest cache for the entry + // On install or update refresh name and manifest cache. + $this->extension->name = $this->name; $this->extension->manifest_cache = $this->parent->generateManifestCache(); + // If store extension failed, abort and throw and extension. if (!$this->extension->store()) { - // Install failed, roll back changes throw new RuntimeException( - JText::sprintf( - 'JLIB_INSTALLER_ABORT_LIB_INSTALL_ROLLBACK', + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_FAILED', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), + JText::_('JLIB_INSTALLER_' . $this->route), + $this->name, $this->extension->getError() ) ); } - // Since we have created a library item, we add it to the installation step stack - // so that if we have to rollback the changes we can undo it. - $this->parent->pushStep(array('type' => 'extension', 'id' => $this->extension->extension_id)); + // Add a installer rollback step to the installation step stack so we can rollback the changes if we need. + $this->addStepToInstaller(array('type' => 'extension', 'id' => $this->extension->extension_id)); } /** diff --git a/libraries/cms/installer/adapter/module.php b/libraries/cms/installer/adapter/module.php index 150201cfab794..642e4f0eb71a6 100644 --- a/libraries/cms/installer/adapter/module.php +++ b/libraries/cms/installer/adapter/module.php @@ -324,97 +324,81 @@ protected function storeExtension() return; } - // Was there a module already installed with the same name? + // If extension already exists, load the entry. if ($this->currentExtensionId) { + // If we are not allowed to overwrite on update. if (!$this->parent->isOverwrite()) { - // Install failed, roll back changes throw new RuntimeException( - JText::sprintf( - 'JLIB_INSTALLER_ABORT_MOD_INSTALL_ALLREADY_EXISTS', + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_ALREADY_EXISTS', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), JText::_('JLIB_INSTALLER_' . $this->route), $this->name - ) + ) ); } - // Load the entry and update the manifest_cache $this->extension->load($this->currentExtensionId); - - // Update name - $this->extension->name = $this->name; - - // Update manifest - $this->extension->manifest_cache = $this->parent->generateManifestCache(); - - if (!$this->extension->store()) - { - // Install failed, roll back changes - throw new RuntimeException( - JText::sprintf( - 'JLIB_INSTALLER_ABORT_MOD_ROLLBACK', - JText::_('JLIB_INSTALLER_' . $this->route), - $this->extension->getError() - ) - ); - } } + // If extension doesn't exist, add an entry to the extension table with defaults. else { - $this->extension->name = $this->name; - $this->extension->type = 'module'; - $this->extension->element = $this->element; - - // There is no folder for modules - $this->extension->folder = ''; - $this->extension->enabled = 1; - $this->extension->protected = 0; - $this->extension->access = $this->clientId == 1 ? 2 : 0; - $this->extension->client_id = $this->clientId; - $this->extension->params = $this->parent->getParams(); - - // Custom data - $this->extension->custom_data = ''; - $this->extension->system_data = ''; - $this->extension->manifest_cache = $this->parent->generateManifestCache(); + $this->extension->type = $this->type; + $this->extension->element = $this->element; + $this->extension->folder = ''; + $this->extension->enabled = 1; + $this->extension->protected = 0; + $this->extension->access = $this->clientId == 1 ? 2 : 0; + $this->extension->client_id = $this->clientId; + $this->extension->ordering = 0; + $this->extension->params = $this->parent->getParams(); + $this->extension->system_data = ''; + $this->extension->custom_data = ''; + } - if (!$this->extension->store()) - { - // Install failed, roll back changes - throw new RuntimeException( - JText::sprintf( - 'JLIB_INSTALLER_ABORT_MOD_ROLLBACK', - JText::_('JLIB_INSTALLER_' . $this->route), - $this->extension->getError() - ) - ); - } + // On install or update refresh name and manifest cache. + $this->extension->name = $this->name; + $this->extension->manifest_cache = $this->parent->generateManifestCache(); - // Since we have created a module item, we add it to the installation step stack - // so that if we have to rollback the changes we can undo it. - $this->parent->pushStep( - array( - 'type' => 'extension', - 'extension_id' => $this->extension->extension_id, + // If store extension failed, abort and throw and extension. + if (!$this->extension->store()) + { + throw new RuntimeException( + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_FAILED', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), + JText::_('JLIB_INSTALLER_' . $this->route), + $this->name, + $this->extension->getError() ) ); + } - // Create unpublished module - $name = preg_replace('#[\*?]#', '', JText::_($this->name)); + // Add a installer rollback step to the installation step stack so we can rollback the changes if we need. + $this->addStepToInstaller(array('type' => 'extension', 'id' => $this->extension->extension_id)); + // If new install add a new module. + if (!$this->currentExtensionId) + { /** @var JTableModule $module */ $module = JTable::getInstance('module'); - $module->title = $name; + $module->title = preg_replace('#[\*?]#', '', JText::_($this->name)); $module->content = ''; $module->module = $this->element; - $module->access = '1'; - $module->showtitle = '1'; + $module->access = 1; + $module->showtitle = 1; $module->params = ''; $module->client_id = $this->clientId; $module->language = '*'; - $module->store(); + // Module install failed, roll back changes + if (!$module->store()) + { + throw new RuntimeException(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $module->getError())); + } + + // Add a installer rollback step to the installation step stack so we can rollback the changes if we need. + $this->addStepToInstaller(array('type' => 'module', 'id' => $module->id)); } } diff --git a/libraries/cms/installer/adapter/package.php b/libraries/cms/installer/adapter/package.php index 3ec5c076b5b19..80348bd9ba872 100644 --- a/libraries/cms/installer/adapter/package.php +++ b/libraries/cms/installer/adapter/package.php @@ -130,6 +130,8 @@ protected function copyBaseFiles() JEventDispatcher::getInstance()->register('onExtensionAfterInstall', array($this, 'onExtensionAfterInstall')); } + $childInstallers = array(); + foreach ($this->getManifest()->files->children() as $child) { $file = $source . '/' . (string) $child; @@ -147,11 +149,23 @@ protected function copyBaseFiles() $package = JInstallerHelper::unpack($file); } - $tmpInstaller = new JInstaller; - $installResult = $tmpInstaller->install($package['dir']); + $childInstallers[$file] = new JInstaller; + $installResult = $childInstallers[$file]->install($package['dir']); + // On package install failure rollback all other extensions already installed. if (!$installResult) { + // Remove current sicne it's already rollbacked. + unset($childInstallers[$file]); + + // Rollback all previous extensions. + foreach ($childInstallers as $childInstaller) + { + $childInstaller->abort(); + } + + $this->results = array(); + throw new RuntimeException( JText::sprintf( 'JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION', @@ -391,59 +405,58 @@ protected function setupInstallPaths() */ protected function storeExtension() { + // If extension already exists, load the entry. if ($this->currentExtensionId) { + // If we are not allowed to overwrite on update. if (!$this->parent->isOverwrite()) { - // Install failed, roll back changes throw new RuntimeException( - JText::sprintf( - 'JLIB_INSTALLER_ABORT_ALREADY_EXISTS', + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_ALREADY_EXISTS', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), JText::_('JLIB_INSTALLER_' . $this->route), $this->name - ) + ) ); } $this->extension->load($this->currentExtensionId); - $this->extension->name = $this->name; } + // If extension doesn't exist, add an entry to the extension table with defaults. else { - $this->extension->name = $this->name; - $this->extension->type = 'package'; - $this->extension->element = $this->element; - - // There is no folder for packages - $this->extension->folder = ''; - $this->extension->enabled = 1; - $this->extension->protected = 0; - $this->extension->access = 1; - $this->extension->client_id = 0; - - // Custom data - $this->extension->custom_data = ''; + $this->extension->type = $this->type; + $this->extension->element = $this->element; + $this->extension->folder = ''; + $this->extension->enabled = 1; + $this->extension->protected = 0; + $this->extension->access = 1; + $this->extension->client_id = 0; + $this->extension->ordering = 0; + $this->extension->params = $this->parent->getParams(); $this->extension->system_data = ''; - $this->extension->params = $this->parent->getParams(); + $this->extension->custom_data = ''; } - // Update the manifest cache for the entry + // On install or update refresh name and manifest cache. + $this->extension->name = $this->name; $this->extension->manifest_cache = $this->parent->generateManifestCache(); + // If store extension failed, abort and throw and extension. if (!$this->extension->store()) { - // Install failed, roll back changes throw new RuntimeException( - JText::sprintf( - 'JLIB_INSTALLER_ABORT_PACK_INSTALL_ROLLBACK', + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_FAILED', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), + JText::_('JLIB_INSTALLER_' . $this->route), + $this->name, $this->extension->getError() ) ); } - // Since we have created a package item, we add it to the installation step stack - // so that if we have to rollback the changes we can undo it. - $this->parent->pushStep(array('type' => 'extension', 'id' => $this->extension->extension_id)); + // Add a installer rollback step to the installation step stack so we can rollback the changes if we need. + $this->addStepToInstaller(array('type' => 'extension', 'id' => $this->extension->extension_id)); } /** diff --git a/libraries/cms/installer/adapter/plugin.php b/libraries/cms/installer/adapter/plugin.php index ea4b0b8a582d2..8b1c520d9a053 100644 --- a/libraries/cms/installer/adapter/plugin.php +++ b/libraries/cms/installer/adapter/plugin.php @@ -359,15 +359,15 @@ protected function setupInstallPaths() protected function storeExtension() { // Discover installs are stored a little differently - if ($this->route == 'discover_install') + if ($this->route === 'discover_install') { $manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest')); $this->extension->manifest_cache = json_encode($manifest_details); - $this->extension->state = 0; - $this->extension->name = $manifest_details['name']; - $this->extension->enabled = ('editors' == $this->extension->folder) ? 1 : 0; - $this->extension->params = $this->parent->getParams(); + $this->extension->state = 0; + $this->extension->name = $manifest_details['name']; + $this->extension->enabled = $this->extension->folder === 'editors' ? 1 : 0; + $this->extension->params = $this->parent->getParams(); if (!$this->extension->store()) { @@ -378,71 +378,58 @@ protected function storeExtension() return; } - // Was there a plugin with the same name already installed? + // If extension already exists, load the entry. if ($this->currentExtensionId) { + // If we are not allowed to overwrite on update. if (!$this->parent->isOverwrite()) { - // Install failed, roll back changes throw new RuntimeException( - JText::sprintf( - 'JLIB_INSTALLER_ABORT_PLG_INSTALL_ALLREADY_EXISTS', + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_ALREADY_EXISTS', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), JText::_('JLIB_INSTALLER_' . $this->route), $this->name - ) + ) ); } $this->extension->load($this->currentExtensionId); - $this->extension->name = $this->name; - $this->extension->manifest_cache = $this->parent->generateManifestCache(); - - // Update the manifest cache and name - $this->extension->store(); } + // If extension doesn't exist, add an entry to the extension table with defaults. else { - // Store in the extensions table (1.6) - $this->extension->name = $this->name; - $this->extension->type = 'plugin'; - $this->extension->ordering = 0; - $this->extension->element = $this->element; - $this->extension->folder = $this->group; - $this->extension->enabled = 0; - $this->extension->protected = 0; - $this->extension->access = 1; - $this->extension->client_id = 0; - $this->extension->params = $this->parent->getParams(); - - // Custom data - $this->extension->custom_data = ''; - - // System data + $this->extension->type = $this->type; + $this->extension->element = $this->element; + $this->extension->folder = $this->group; + $this->extension->enabled = $this->group === 'editors' ? 1 : 0; + $this->extension->protected = 0; + $this->extension->access = 1; + $this->extension->client_id = 0; + $this->extension->ordering = 0; + $this->extension->params = $this->parent->getParams(); $this->extension->system_data = ''; - $this->extension->manifest_cache = $this->parent->generateManifestCache(); + $this->extension->custom_data = ''; + } - // Editor plugins are published by default - if ($this->group == 'editors') - { - $this->extension->enabled = 1; - } + // On install or update refresh name and manifest cache. + $this->extension->name = $this->name; + $this->extension->manifest_cache = $this->parent->generateManifestCache(); - if (!$this->extension->store()) - { - // Install failed, roll back changes - throw new RuntimeException( - JText::sprintf( - 'JLIB_INSTALLER_ABORT_PLG_INSTALL_ROLLBACK', - JText::_('JLIB_INSTALLER_' . $this->route), - $this->extension->getError() - ) - ); - } - - // Since we have created a plugin item, we add it to the installation step stack - // so that if we have to rollback the changes we can undo it. - $this->parent->pushStep(array('type' => 'extension', 'id' => $this->extension->extension_id)); + // If store extension failed, abort and throw and extension. + if (!$this->extension->store()) + { + throw new RuntimeException( + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_FAILED', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), + JText::_('JLIB_INSTALLER_' . $this->route), + $this->name, + $this->extension->getError() + ) + ); } + + // Add a installer rollback step to the installation step stack so we can rollback the changes if we need. + $this->addStepToInstaller(array('type' => 'extension', 'id' => $this->extension->extension_id)); } /** diff --git a/libraries/cms/installer/adapter/template.php b/libraries/cms/installer/adapter/template.php index 15516f1587480..0edc740dfd8d2 100644 --- a/libraries/cms/installer/adapter/template.php +++ b/libraries/cms/installer/adapter/template.php @@ -346,52 +346,59 @@ protected function storeExtension() return; } - // Was there a template already installed with the same name? + // If extension already exists, load the entry. if ($this->currentExtensionId) { + // If we are not allowed to overwrite on update. if (!$this->parent->isOverwrite()) { - // Install failed, roll back changes throw new RuntimeException( - JText::_('JLIB_INSTALLER_ABORT_TPL_INSTALL_ALREADY_INSTALLED') + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_ALREADY_EXISTS', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), + JText::_('JLIB_INSTALLER_' . $this->route), + $this->name + ) ); } // Load the entry and update the manifest_cache $this->extension->load($this->currentExtensionId); } + // If extension doesn't exist, add an entry to the extension table with defaults. else { - $this->extension->type = 'template'; - $this->extension->element = $this->element; - - // There is no folder for templates - $this->extension->folder = ''; - $this->extension->enabled = 1; - $this->extension->protected = 0; - $this->extension->access = 1; - $this->extension->client_id = $this->clientId; - $this->extension->params = $this->parent->getParams(); - - // Custom data + $this->extension->type = $this->type; + $this->extension->element = $this->element; + $this->extension->folder = ''; + $this->extension->enabled = 1; + $this->extension->protected = 0; + $this->extension->access = 1; + $this->extension->ordering = 0; + $this->extension->client_id = $this->clientId; + $this->extension->params = $this->parent->getParams(); + $this->extension->system_data = ''; $this->extension->custom_data = ''; } - // Name might change in an update - $this->extension->name = $this->name; + // On install or update refresh name and manifest cache. + $this->extension->name = $this->name; $this->extension->manifest_cache = $this->parent->generateManifestCache(); + // If store extension failed, abort and throw and extension. if (!$this->extension->store()) { - // Install failed, roll back changes throw new RuntimeException( - JText::sprintf( - 'JLIB_INSTALLER_ABORT_ROLLBACK', - JText::_('JLIB_INSTALLER_' . strtoupper($this->route)), + JText::sprintf('JLIB_INSTALLER_ABORT_STORE_EXTENSION_FAILED', + JText::_('JLIB_INSTALLER_EXTENSION_TYPE_' . strtoupper($this->type)), + JText::_('JLIB_INSTALLER_' . $this->route), + $this->name, $this->extension->getError() ) ); } + + // Add a installer rollback step to the installation step stack so we can rollback the changes if we need. + $this->addStepToInstaller(array('type' => 'extension', 'id' => $this->extension->extension_id)); } /**