Fixed package uninstallation and removed requirement map
authorAlexander Ebert <ebert@woltlab.com>
Sat, 29 Dec 2012 00:51:46 +0000 (01:51 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Sat, 29 Dec 2012 00:51:46 +0000 (01:51 +0100)
Fixes #962
Fixes #1002
Fixes #1021

wcfsetup/install/files/lib/acp/action/UninstallPackageAction.class.php
wcfsetup/install/files/lib/data/package/Package.class.php
wcfsetup/install/files/lib/system/package/PackageInstallationDispatcher.class.php
wcfsetup/install/files/lib/system/package/PackageUninstallationDispatcher.class.php
wcfsetup/install/files/lib/system/package/PackageUninstallationNodeBuilder.class.php
wcfsetup/setup/db/install.sql

index 58d85dddceb13a4f139874239b50dcd9996abb75..0e513da56e297124aa770042fd30feea7007507d 100644 (file)
@@ -103,6 +103,7 @@ class UninstallPackageAction extends InstallPackageAction {
         * @return      string
         */
        public function stepUninstall() {
+               die("current node is ".$this->node);
                $node = $this->installation->uninstall($this->node);
                
                if ($node == '') {
index c90463f987a55218979f5d6f21ca0bf93aa4cf7d..27378dcd945893aea4a6cfa2b9573836b34f2908 100644 (file)
@@ -32,10 +32,10 @@ class Package extends DatabaseObject {
        protected static $databaseTableIndexName = 'packageID';
        
        /**
-        * package requirement map
+        * package requirements
         * @var array<integer>
         */
-       protected static $requirementMap = null;
+       protected static $requirements = null;
        
        /**
         * list of packages that this package requires
@@ -61,9 +61,9 @@ class Package extends DatabaseObject {
         * @return      boolean
         */
        public function isRequired() {
-               self::loadRequirementMap();
+               self::loadRequiremens();
                
-               return (isset(self::$requirementMap[$this->packageID]));
+               return (isset(self::$requirements[$this->packageID]));
        }
        
        /**
@@ -160,8 +160,8 @@ class Package extends DatabaseObject {
                        return false;
                }
                
-               // check if package is required by current application
-               if (self::isRequiredBy($this->packageID, PACKAGE_ID)) {
+               // check if package is required by another package
+               if (self::isRequired($this->packageID)) {
                        return false;
                }
                
@@ -187,43 +187,22 @@ class Package extends DatabaseObject {
        }
        
        /**
-        * Returns true, if package $packageID is required by package $targetPackageID.
-        * 
-        * @param       integer         $packageID
-        * @param       integer         $targetPackageID
-        * @return      boolean
-        */
-       public static function isRequiredBy($packageID, $targetPackageID) {
-               self::loadRequirementMap();
-               
-               if (isset(self::$requirementMap[$packageID])) {
-                       foreach (self::$requirementMap[$packageID] as $requiredBy) {
-                               if ($requiredBy == $targetPackageID) {
-                                       return true;
-                               }
-                       }
-               }
-               
-               return false;
-       }
-       
-       /**
-        * Loads package requirement map.
+        * Loads package requirements.
         */
-       protected static function loadRequirementMap() {
+       protected static function loadRequirements() {
                if (self::$requirementMap === null) {
                        $sql = "SELECT  packageID, requirement
-                               FROM    wcf".WCF_N."_package_requirement_map";
+                               FROM    wcf".WCF_N."_package_requirement";
                        $statement = WCF::getDB()->prepareStatement($sql);
                        $statement->execute();
                        
-                       self::$requirementMap = array();
+                       self::$requirements = array();
                        while ($row = $statement->fetchArray()) {
-                               if (!isset(self::$requirementMap[$row['requirement']])) {
-                                       self::$requirementMap[$row['requirement']] = array();
+                               if (!isset(self::$requirements[$row['packageID']])) {
+                                       self::$requirements[$row['packageID']] = array();
                                }
                                
-                               self::$requirementMap[$row['requirement']][] = $row['packageID'];
+                               self::$requirements[$row['packageID']][] = $row['requirement'];
                        }
                }
        }
@@ -333,81 +312,6 @@ class Package extends DatabaseObject {
                return $version;
        }
        
-       /**
-        * Rebuilds the requirement map for the given package id.
-        * 
-        * @param       integer         $packageID
-        */
-       public static function rebuildPackageRequirementMap($packageID) {
-               // delete old entries
-               $sql = "DELETE FROM     wcf".WCF_N."_package_requirement_map
-                       WHERE           packageID = ?";
-               $statement = WCF::getDB()->prepareStatement($sql);
-               $statement->execute(array($packageID));
-               
-               // fetch requirements of requirements
-               $requirements = array();
-               $sql = "SELECT          requirement, level
-                       FROM            wcf".WCF_N."_package_requirement_map
-                       WHERE           packageID IN (
-                                               SELECT  requirement
-                                               FROM    wcf".WCF_N."_package_requirement
-                                               WHERE   packageID = ?
-                                       )
-                       ORDER BY        level ASC";
-               $statement = WCF::getDB()->prepareStatement($sql);
-               $statement->execute(array($packageID));
-               while ($row = $statement->fetchArray()) {
-                       // use reverse order, highest level epic wins
-                       $requirements[$row['requirement']] = $row['level'];
-               }
-               
-               // insert requirements of requirements
-               if (!empty($requirements)) {
-                       $sql = "INSERT INTO     wcf".WCF_N."_package_requirement_map
-                                               (packageID, requirement, level)
-                               VALUES          (?, ?, ?)";
-                       $statement = WCF::getDB()->prepareStatement($sql);
-                       foreach ($requirements as $requirement => $level) {
-                               $statement->execute(array($packageID, $requirement, $level));
-                       }
-               }
-               
-               // fetch requirements
-               $directRequirements = array();
-               $conditions = new PreparedStatementConditionBuilder($sql);
-               $conditions->add("packageID = ?", array($packageID));
-               if (!empty($requirements)) {
-                       $conditions->add("requirement NOT IN (?)", array(array_keys($requirements)));
-               }
-               
-               $sql = "SELECT  requirement, 
-                               (
-                                       SELECT  MAX(level) AS requirementLevel
-                                       FROM    wcf".WCF_N."_package_requirement_map
-                                       WHERE   packageID = package_requirement.requirement
-                               ) AS requirementLevel
-                       FROM    wcf".WCF_N."_package_requirement package_requirement
-                       ".$conditions;
-               $statement = WCF::getDB()->prepareStatement($sql);
-               $statement->execute($conditions->getParameters());
-               while ($row = $statement->fetchArray()) {
-                       $row['requirementLevel'] = intval($row['requirementLevel']) + 1;
-                       $directRequirements[$row['requirement']] = $row['requirementLevel'];
-               }
-               
-               // insert requirements
-               if (!empty($directRequirements)) {
-                       $sql = "INSERT INTO     wcf".WCF_N."_package_requirement_map
-                                               (packageID, requirement, level)
-                               VALUES          (?, ?, ?)";
-                       $statement = WCF::getDB()->prepareStatement($sql);
-                       foreach ($directRequirements as $requirement => $level) {
-                               $statement->execute(array($packageID, $requirement, $level));
-                       }
-               }
-       }
-       
        /**
         * Writes the config.inc.php for an application.
         * 
index b221662b13dfd7d34c6e83156e4b7f1cbe52aaa8..f76cb3afcb805ede96acf8c7a9ea996c0e6f0998 100644 (file)
@@ -1,7 +1,5 @@
 <?php
 namespace wcf\system\package;
-use wcf\system\style\StyleHandler;
-
 use wcf\data\application\Application;
 use wcf\data\application\ApplicationEditor;
 use wcf\data\language\category\LanguageCategory;
@@ -24,6 +22,7 @@ use wcf\system\form;
 use wcf\system\language\LanguageFactory;
 use wcf\system\request\LinkHandler;
 use wcf\system\request\RouteHandler;
+use wcf\system\style\StyleHandler;
 use wcf\system\WCF;
 use wcf\util\FileUtil;
 use wcf\util\HeaderUtil;
@@ -279,9 +278,6 @@ class PackageInstallationDispatcher {
                                }
                        }
                        
-                       // build requirement map
-                       Package::rebuildPackageRequirementMap($package->packageID);
-                       
                        // reload queue
                        $this->queue = new PackageInstallationQueue($this->queue->queueID);
                        $this->package = null;
@@ -460,7 +456,13 @@ class PackageInstallationDispatcher {
                return $step;
        }
        
-       // @todo: comment
+       /**
+        * Displays a list to select optional packages or installs selection.
+        * 
+        * @param       string          $currentNode
+        * @param       array           $nodeData
+        * @return      wcf\system\package\PackageInstallationStep
+        */
        protected function selectOptionalPackages($currentNode, array $nodeData) {
                $installationStep = new PackageInstallationStep();
                
@@ -510,7 +512,7 @@ class PackageInstallationDispatcher {
        }
        
        /**
-        * Extracts files from .tar (or .tar.gz) archive and installs them
+        * Extracts files from .tar(.gz) archive and installs them
         * 
         * @param       string                  $targetDir
         * @param       string                  $sourceArchive
@@ -603,7 +605,11 @@ class PackageInstallationDispatcher {
                }
        }
        
-       // @todo: comment
+       /**
+        * Prompts a selection of optional packages.
+        * 
+        * @return      mixed
+        */
        protected function promptOptionalPackages(array $packages) {
                if (!PackageInstallationFormManager::findForm($this->queue, 'optionalPackages')) {
                        $container = new container\MultipleSelectionFormElementContainer();
index ae6f96ed1e19abd1acd5737377ea2b7d8f1d4959..62a4f1d69578671b590c1d51f05b238908d95591 100644 (file)
@@ -184,95 +184,6 @@ class PackageUninstallationDispatcher extends PackageInstallationDispatcher {
                self::addQueueEntries($package, $dependentPackages);
        }
        
-       /**
-        * Get all packages which require this package.
-        * 
-        * @param       integer         $packageID
-        * @return      array
-        */
-       public static function getPackageDependencies($packageID) {
-               $sql = "SELECT          *
-                       FROM            wcf".WCF_N."_package
-                       WHERE           packageID IN (
-                                               SELECT  packageID
-                                               FROM    wcf".WCF_N."_package_requirement_map
-                                               WHERE   requirement = ?
-                                       )";
-               $statement = WCF::getDB()->prepareStatement($sql);
-               $statement->execute(array($packageID));
-               $packages = array();
-               while ($row = $statement->fetchArray()) {
-                       $packages[] = $row;
-               }
-               
-               return $packages;
-       }
-       
-       /**
-        * Returns an ordered list of depenencies for given package id. The order is
-        * curcial, whereas the first package has to be uninstalled first.
-        * 
-        * @package     integer
-        * @return      wcf\data\package\PackageList
-        */
-       public static function getOrderedPackageDependencies($packageID) {
-               $sql = "SELECT          packageID, MAX(level) AS level
-                       FROM            wcf".WCF_N."_package_requirement_map
-                       WHERE           requirement = ?
-                       GROUP BY        packageID";
-               $statement = WCF::getDB()->prepareStatement($sql);
-               $statement->execute(array($packageID));
-               
-               $dependencies = array();
-               while ($row = $statement->fetchArray()) {
-                       $dependencies[$row['packageID']] = $row['level'];
-               }
-               
-               $packageIDs = array();
-               $maxLevel = max(array_values($dependencies));
-               if ($maxLevel == 0) {
-                       // order does not matter
-                       $packageIDs = array_keys($dependencies);
-               }
-               else {
-                       // order by level while ignoring individual connections as they don't
-                       // matter if uninstall begins with the lowest dependency in tree
-                       for ($i = $maxLevel; $i >= 0; $i--) {
-                               foreach ($dependencies as $packageID => $level) {
-                                       if ($level == $i) {
-                                               $packageIDs[] = $packageID;
-                                               unset($dependencies[$packageID]);
-                                       }
-                               }
-                       }
-               }
-               
-               // get packages
-               $packageList = new PackageList();
-               $packageList->sqlLimit = 0;
-               $packageList->getConditionBuilder()->add("packageID IN (?)", array($packageIDs));
-               $packageList->readObjects();
-               
-               return $packageList;
-       }
-       
-       /**
-        * Returns true if package has dependencies
-        * 
-        * @param       integer         $packageID
-        * @return      boolean
-        */
-       public static function hasDependencies($packageID) {
-               $sql = "SELECT  COUNT(*) AS count
-                       FROM    wcf".WCF_N."_package_requirement
-                       WHERE   requirement = ?";
-               $statement = WCF::getDB()->prepareStatement($sql);
-               $statement->execute(array($packageID));
-               $row = $statement->fetchArray();
-               
-               return ($row['count'] > 0);
-       }
-       
        /**
         * Adds an uninstall entry to the package installation queue.
         * 
index b21e74265e013cda70a628ffd24c724b07d748cf..1fdb709977fe335f0e55ef19faeed8687422bb0e 100644 (file)
@@ -23,9 +23,6 @@ class PackageUninstallationNodeBuilder extends PackageInstallationNodeBuilder {
                        $this->node = $this->getToken();
                }
                
-               // build nodes for dependent packages
-               $this->buildDependentPackageNodes();
-               
                // build pip nodes
                $this->buildPluginNodes();
                
@@ -33,37 +30,6 @@ class PackageUninstallationNodeBuilder extends PackageInstallationNodeBuilder {
                $this->buildPackageNode();
        }
        
-       /**
-        * Builds nodes for all dependent packages.
-        */
-       protected function buildDependentPackageNodes() {
-               if (!PackageUninstallationDispatcher::hasDependencies($this->installation->queue->packageID)) {
-                       return;
-               }
-               
-               $packageList = PackageUninstallationDispatcher::getOrderedPackageDependencies($this->installation->queue->packageID);
-               $queue = $this->installation->queue;
-               
-               foreach ($packageList as $package) {
-                       $queue = PackageInstallationQueueEditor::create(array(
-                               'processNo' => $queue->processNo,
-                               'parentQueueID' => $queue->queueID,
-                               'userID' => WCF::getUser()->userID,
-                               'package' => $package->package,
-                               'packageName' => $package->getName(),
-                               'packageID' => $package->packageID,
-                               'action' => 'uninstall'
-                       ));
-                       
-                       // spawn nodes
-                       $uninstallation = new PackageUninstallationDispatcher($queue);
-                       $uninstallation->nodeBuilder->setParentNode($this->node);
-                       $uninstallation->nodeBuilder->buildNodes();
-                       $this->parentNode = $uninstallation->nodeBuilder->getCurrentNode();
-                       $this->node = $this->getToken();
-               }
-       }
-       
        /**
         * @see wcf\system\package\PackageInstallationNodeBuilder::buildPluginNodes()
         */
index f2866cb8fb9d122f3157138e4dab66d43dfe5fa5..7922d74d30228aa0f68fd760f2e985dadb879474 100644 (file)
@@ -396,14 +396,6 @@ CREATE TABLE wcf1_package_requirement (
        UNIQUE KEY packageID (packageID, requirement)
 );
 
-DROP TABLE IF EXISTS wcf1_package_requirement_map;
-CREATE TABLE wcf1_package_requirement_map (
-       packageID INT(10) NOT NULL,
-       requirement INT(10) NOT NULL,
-       level INT(10) NOT NULL DEFAULT 0,
-       UNIQUE KEY packageID (packageID, requirement)
-);
-
 DROP TABLE IF EXISTS wcf1_package_update;
 CREATE TABLE wcf1_package_update (
        packageUpdateID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
@@ -803,9 +795,6 @@ ALTER TABLE wcf1_package_installation_sql_log ADD FOREIGN KEY (packageID) REFERE
 ALTER TABLE wcf1_package_requirement ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
 ALTER TABLE wcf1_package_requirement ADD FOREIGN KEY (requirement) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
 
-ALTER TABLE wcf1_package_requirement_map ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
-ALTER TABLE wcf1_package_requirement_map ADD FOREIGN KEY (requirement) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
-
 ALTER TABLE wcf1_package_update ADD FOREIGN KEY (packageUpdateServerID) REFERENCES wcf1_package_update_server (packageUpdateServerID) ON DELETE CASCADE;
 
 ALTER TABLE wcf1_package_update_exclusion ADD FOREIGN KEY (packageUpdateVersionID) REFERENCES wcf1_package_update_version (packageUpdateVersionID) ON DELETE CASCADE;