From 3b405baa948951eb0f3a6d85e0ae9ebfbd96c43b Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Sun, 14 Apr 2019 16:22:15 +0200 Subject: [PATCH] Delete language items when uninstalling cronjobs, menus and menu items Close #2896 --- .../lib/data/cronjob/CronjobEditor.class.php | 20 ++++++++ .../files/lib/data/menu/MenuEditor.class.php | 26 ++++++++++ .../data/menu/item/MenuItemEditor.class.php | 26 ++++++++++ ...CronjobPackageInstallationPlugin.class.php | 49 ++++++++++++------- ...enuItemPackageInstallationPlugin.class.php | 8 +++ .../MenuPackageInstallationPlugin.class.php | 8 +++ 6 files changed, 119 insertions(+), 18 deletions(-) diff --git a/wcfsetup/install/files/lib/data/cronjob/CronjobEditor.class.php b/wcfsetup/install/files/lib/data/cronjob/CronjobEditor.class.php index 506b8ca7a3..ba56df818e 100644 --- a/wcfsetup/install/files/lib/data/cronjob/CronjobEditor.class.php +++ b/wcfsetup/install/files/lib/data/cronjob/CronjobEditor.class.php @@ -144,6 +144,26 @@ class CronjobEditor extends DatabaseObjectEditor implements IEditableCachedObjec } } + /** + * @inheritDoc + */ + public static function deleteAll(array $objectIDs = []) { + // delete language items + if (!empty($objectIDs)) { + $sql = "DELETE FROM wcf".WCF_N."_language_item + WHERE languageItem = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + + WCF::getDB()->beginTransaction(); + foreach ($objectIDs as $cronjobID) { + $statement->execute(['wcf.acp.cronjob.description.cronjob' . $cronjobID]); + } + WCF::getDB()->commitTransaction(); + } + + return parent::deleteAll($objectIDs); + } + /** * @inheritDoc */ diff --git a/wcfsetup/install/files/lib/data/menu/MenuEditor.class.php b/wcfsetup/install/files/lib/data/menu/MenuEditor.class.php index dfa6481c4d..3d977908b2 100644 --- a/wcfsetup/install/files/lib/data/menu/MenuEditor.class.php +++ b/wcfsetup/install/files/lib/data/menu/MenuEditor.class.php @@ -79,6 +79,32 @@ class MenuEditor extends DatabaseObjectEditor implements IEditableCachedObject { return $menu; } + /** + * @inheritDoc + */ + public static function deleteAll(array $objectIDs = []) { + if (!empty($objectIDs)) { + // delete language items + $menuList = new MenuList(); + $menuList->setObjectIDs($objectIDs); + $menuList->readObjects(); + + if (count($menuList)) { + $sql = "DELETE FROM wcf".WCF_N."_language_item + WHERE languageItem = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + + WCF::getDB()->beginTransaction(); + foreach ($menuList as $menu) { + $statement->execute(['wcf.menu.' . $menu->identifier]); + } + WCF::getDB()->commitTransaction(); + } + } + + return parent::deleteAll($objectIDs); + } + /** * @inheritDoc */ diff --git a/wcfsetup/install/files/lib/data/menu/item/MenuItemEditor.class.php b/wcfsetup/install/files/lib/data/menu/item/MenuItemEditor.class.php index 41026e20ba..00b2315173 100644 --- a/wcfsetup/install/files/lib/data/menu/item/MenuItemEditor.class.php +++ b/wcfsetup/install/files/lib/data/menu/item/MenuItemEditor.class.php @@ -79,6 +79,32 @@ class MenuItemEditor extends DatabaseObjectEditor implements IEditableCachedObje return $menuItem; } + /** + * @inheritDoc + */ + public static function deleteAll(array $objectIDs = []) { + if (!empty($objectIDs)) { + // delete language items + $menuItemList = new MenuItemList(); + $menuItemList->setObjectIDs($objectIDs); + $menuItemList->readObjects(); + + if (count($menuItemList)) { + $sql = "DELETE FROM wcf".WCF_N."_language_item + WHERE languageItem = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + + WCF::getDB()->beginTransaction(); + foreach ($menuItemList as $menuItem) { + $statement->execute(['wcf.menu.item.' . $menuItem->identifier]); + } + WCF::getDB()->commitTransaction(); + } + } + + return parent::deleteAll($objectIDs); + } + /** * @inheritDoc */ diff --git a/wcfsetup/install/files/lib/system/package/plugin/CronjobPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/CronjobPackageInstallationPlugin.class.php index 9df9e06784..c24ec7afec 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/CronjobPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/CronjobPackageInstallationPlugin.class.php @@ -2,7 +2,9 @@ namespace wcf\system\package\plugin; use wcf\data\cronjob\Cronjob; use wcf\data\cronjob\CronjobEditor; +use wcf\data\cronjob\CronjobList; use wcf\system\cronjob\ICronjob; +use wcf\system\database\util\PreparedStatementConditionBuilder; use wcf\system\devtools\pip\IDevtoolsPipEntryList; use wcf\system\devtools\pip\IGuiPackageInstallationPlugin; use wcf\system\devtools\pip\TXmlGuiPackageInstallationPlugin; @@ -56,30 +58,41 @@ class CronjobPackageInstallationPlugin extends AbstractXMLPackageInstallationPlu * @inheritDoc */ protected function handleDelete(array $items) { - $sql = "DELETE FROM wcf".WCF_N."_".$this->tableName." - WHERE className = ? - AND packageID = ?"; - $legacyStatement = WCF::getDB()->prepareStatement($sql); - - $sql = "DELETE FROM wcf".WCF_N."_".$this->tableName." - WHERE cronjobName = ? - AND packageID = ?"; - $statement = WCF::getDB()->prepareStatement($sql); - + // read cronjobs from database because deleting the language items requires the + // cronjob id + $cronjobs = $legacyCronjobs = []; foreach ($items as $item) { if (!isset($item['attributes']['name'])) { - $legacyStatement->execute([ - $item['elements']['classname'], - $this->installation->getPackageID() - ]); + $legacyCronjobs[] = $item['elements']['classname']; } else { - $statement->execute([ - $item['attributes']['name'], - $this->installation->getPackageID() - ]); + $cronjobs[] = $item['attributes']['name']; } } + + if (empty($cronjobs) && empty($legacyCronjobs)) { + return; + } + + $cronjobList = new CronjobList(); + $cronjobList->getConditionBuilder()->add( + 'packageID = ?', + [$this->installation->getPackageID()] + ); + + $conditionBuilder = new PreparedStatementConditionBuilder(false, 'OR'); + if (!empty($cronjobs)) { + $conditionBuilder->add('cronjobName IN (?)', [$cronjobs]); + } + if (!empty($legacyCronjobs)) { + $conditionBuilder->add('className IN (?)', [$legacyCronjobs]); + } + $cronjobList->getConditionBuilder()->add($conditionBuilder, $conditionBuilder->getParameters()); + $cronjobList->readObjectIDs(); + + if (!empty($cronjobList->getObjectIDs())) { + CronjobEditor::deleteAll($cronjobList->getObjectIDs()); + } } /** diff --git a/wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php index ce48e9a2e3..19d7ad1646 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php @@ -56,12 +56,20 @@ class MenuItemPackageInstallationPlugin extends AbstractXMLPackageInstallationPl AND packageID = ?"; $statement = WCF::getDB()->prepareStatement($sql); + $sql = "DELETE FROM wcf" . WCF_N . "_language_item + WHERE languageItem = ?"; + $languageItemStatement = WCF::getDB()->prepareStatement($sql); + WCF::getDB()->beginTransaction(); foreach ($items as $item) { $statement->execute([ $item['attributes']['identifier'], $this->installation->getPackageID() ]); + + $languageItemStatement->execute([ + 'wcf.menu.item.' . $item['attributes']['identifier'] + ]); } WCF::getDB()->commitTransaction(); } diff --git a/wcfsetup/install/files/lib/system/package/plugin/MenuPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/MenuPackageInstallationPlugin.class.php index d72b0e2d8f..a5b095a166 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/MenuPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/MenuPackageInstallationPlugin.class.php @@ -71,12 +71,20 @@ class MenuPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin AND packageID = ?"; $statement = WCF::getDB()->prepareStatement($sql); + $sql = "DELETE FROM wcf" . WCF_N . "_language_item + WHERE languageItem = ?"; + $languageItemStatement = WCF::getDB()->prepareStatement($sql); + WCF::getDB()->beginTransaction(); foreach ($items as $item) { $statement->execute([ $item['attributes']['identifier'], $this->installation->getPackageID() ]); + + $languageItemStatement->execute([ + 'wcf.menu.' . $item['attributes']['identifier'] + ]); } WCF::getDB()->commitTransaction(); } -- 2.20.1