From 24d20582922b6ee16b3538b9840b9c4465a9143a Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Sun, 24 Jan 2016 11:44:01 +0100 Subject: [PATCH] Add support for uninstall scripts --- CHANGELOG.md | 1 + .../install/files/acp/uninstall/.htaccess | 1 + .../PackageUninstallationDispatcher.class.php | 58 ++++++++++++++----- 3 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 wcfsetup/install/files/acp/uninstall/.htaccess diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dbfa1e202..95d9383b77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ * `permissions` and `options` support for event listener PIP. * `name` attribute for event listener PIP (`listenerName` for event listener objects). * `permissions` and `options` support for template listener PIP. +* file `{WCF_DIR}/acp/uninstall/{packageName}.php` is automatically executed if package is uninstalled right before the first file PIP is executed #### Removed Code diff --git a/wcfsetup/install/files/acp/uninstall/.htaccess b/wcfsetup/install/files/acp/uninstall/.htaccess new file mode 100644 index 0000000000..3418e55a68 --- /dev/null +++ b/wcfsetup/install/files/acp/uninstall/.htaccess @@ -0,0 +1 @@ +deny from all \ No newline at end of file diff --git a/wcfsetup/install/files/lib/system/package/PackageUninstallationDispatcher.class.php b/wcfsetup/install/files/lib/system/package/PackageUninstallationDispatcher.class.php index abd508403c..f1a4c41a4c 100644 --- a/wcfsetup/install/files/lib/system/package/PackageUninstallationDispatcher.class.php +++ b/wcfsetup/install/files/lib/system/package/PackageUninstallationDispatcher.class.php @@ -20,17 +20,24 @@ use wcf\system\WCF; * Handles the whole uninstallation process. * * @author Alexander Ebert - * @copyright 2001-2015 WoltLab GmbH + * @copyright 2001-2016 WoltLab GmbH * @license GNU Lesser General Public License * @package com.woltlab.wcf * @subpackage system.package * @category Community Framework */ class PackageUninstallationDispatcher extends PackageInstallationDispatcher { + /** + * is true if the package's uninstall script has been executed or if no + * such script exists + * @var boolean + */ + protected $didExecuteUninstallScript = false; + /** * Creates a new instance of PackageUninstallationDispatcher. * - * @param \wcf\data\package\installation\queue\PackageInstallationQueue $queue + * @param PackageInstallationQueue $queue */ public function __construct(PackageInstallationQueue $queue) { $this->queue = $queue; @@ -58,6 +65,14 @@ class PackageUninstallationDispatcher extends PackageInstallationDispatcher { break; case 'pip': + // the file pip is always executed last, thus, just before it, + // execute the uninstall script + if ($nodeData['pluginName'] == 'file' && !$this->didExecuteUninstallScript) { + $this->executeUninstallScript(); + + $this->didExecuteUninstallScript = true; + } + $this->executePIP($nodeData); break; } @@ -96,7 +111,7 @@ class PackageUninstallationDispatcher extends PackageInstallationDispatcher { } /** - * @see \wcf\system\package\PackageInstallationDispatcher::executePIP() + * @inheritDoc */ protected function executePIP(array $nodeData) { $pip = new $nodeData['className']($this); @@ -104,23 +119,36 @@ class PackageUninstallationDispatcher extends PackageInstallationDispatcher { $pip->uninstall(); } + /** + * Executes the package's uninstall script (if existing). + * + * @since 2.2 + */ + protected function executeUninstallScript() { + // check if uninstall script file for the uninstalled package exists + $uninstallScript = WCF_DIR.'acp/uninstall/'.$this->package->package.'.php'; + if (file_exists($uninstallScript)) { + include($uninstallScript); + } + } + /** * Uninstalls current package. * * @param array $nodeData */ protected function uninstallPackage(array $nodeData) { - PackageEditor::deleteAll(array($this->queue->packageID)); + PackageEditor::deleteAll([$this->queue->packageID]); // remove localized package infos // todo: license/readme $sql = "DELETE FROM wcf".WCF_N."_language_item WHERE languageItem IN (?, ?)"; $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute(array( + $statement->execute([ 'wcf.acp.package.packageName.package'.$this->queue->packageID, 'wcf.acp.package.packageDescription.package'.$this->queue->packageID - )); + ]); // reset package cache PackageCacheBuilder::getInstance()->reset(); @@ -163,7 +191,7 @@ class PackageUninstallationDispatcher extends PackageInstallationDispatcher { throw new IllegalLinkException(); } - $dependentPackages = array(); + $dependentPackages = []; $uninstallAvailable = true; if ($package->isRequired()) { // get packages that requires this package @@ -186,24 +214,24 @@ class PackageUninstallationDispatcher extends PackageInstallationDispatcher { * @param Package $package * @param array $packages */ - public static function addQueueEntries(Package $package, $packages = array()) { + public static function addQueueEntries(Package $package, $packages = []) { // get new process no $processNo = PackageInstallationQueue::getNewProcessNo(); // add dependent packages to queue - $statementParameters = array(); + $statementParameters = []; foreach ($packages as $dependentPackage) { - $statementParameters[] = array( + $statementParameters[] = [ 'packageName' => $dependentPackage['packageName'], 'packageID' => $dependentPackage['packageID'] - ); + ]; } // add uninstalling package to queue - $statementParameters[] = array( + $statementParameters[] = [ 'packageName' => $package->getName(), 'packageID' => $package->packageID - ); + ]; // insert queue entry (entries) $sql = "INSERT INTO wcf".WCF_N."_package_installation_queue @@ -211,13 +239,13 @@ class PackageUninstallationDispatcher extends PackageInstallationDispatcher { VALUES (?, ?, ?, ?, ?)"; $statement = WCF::getDB()->prepareStatement($sql); foreach ($statementParameters as $parameter) { - $statement->execute(array( + $statement->execute([ $processNo, WCF::getUser()->userID, $parameter['packageName'], $parameter['packageID'], 'uninstall' - )); + ]); } self::openQueue(0, $processNo); -- 2.20.1