More work on package validation
authorAlexander Ebert <ebert@woltlab.com>
Thu, 10 Apr 2014 11:34:56 +0000 (13:34 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Thu, 10 Apr 2014 11:34:56 +0000 (13:34 +0200)
wcfsetup/install/files/lib/acp/form/PackageStartInstallForm.class.php
wcfsetup/install/files/lib/system/WCF.class.php
wcfsetup/install/files/lib/system/package/validation/PackageValidationArchive.class.php
wcfsetup/install/files/lib/system/package/validation/PackageValidationException.class.php
wcfsetup/install/files/lib/system/package/validation/PackageValidationManager.class.php

index 0e793e3ac1f2a1b93db1e419713650cec6bfb304..9173777c7ae692ef9fe47dd9a647b6d21c62b9b6 100755 (executable)
@@ -13,6 +13,7 @@ use wcf\system\WCF;
 use wcf\system\WCFACP;
 use wcf\util\FileUtil;
 use wcf\util\StringUtil;
+use wcf\system\package\validation\PackageValidationManager;
 
 /**
  * Shows the package install and update form.
@@ -136,6 +137,12 @@ class PackageStartInstallForm extends AbstractForm {
                        throw new UserInputException('uploadPackage', 'uploadFailed');
                }
                
+               if (PackageValidationManager::getInstance()->validate($this->uploadPackage['name'])) {
+                       die("win");
+               }
+               else {
+                       die("failed");
+               }
                $this->archive = new PackageArchive($this->uploadPackage['name'], $this->package);
                $this->validateArchive('uploadPackage');
        }
index 263d43d842210212fe45a6055526e2ac22c85c5c..28cd574b1caa12ef016e6c214a366c67fe6a9c41 100644 (file)
@@ -37,7 +37,7 @@ if (!@ini_get('date.timezone')) {
 }
 
 // define current wcf version
-define('WCF_VERSION', '2.1.0 Alpha 1 (Maelstrom)');
+define('WCF_VERSION', '2.1.0 Alpha 1 (Typhoon)');
 
 // define current unix timestamp
 define('TIME_NOW', time());
index 763a64ec252ab30c162a2e79bffea32dc507537d..f1445711a355f99dae63fcdcd62aac5656e7d0ca 100644 (file)
@@ -2,6 +2,8 @@
 namespace wcf\system\package\validation;
 use wcf\system\package\PackageArchive;
 use wcf\system\WCF;
+use wcf\data\package\Package;
+use wcf\data\package\PackageCache;
 
 /**
  * Recursively validates the package archive and it's delivered requirements.
@@ -50,38 +52,81 @@ class PackageValidationArchive implements \RecursiveIterator {
        /**
         * Validates this package and it's delivered requirements.
         * 
+        * @param       boolean         $deepInspection
         * @return      boolean
         */
-       public function validate() {
-               //
-               // step 1) try to read archive
-               //
+       public function validate($deepInspection = false, $requiredVersion = '') {
                try {
+                       // try to read archive
                        $this->archive->openArchive();
+                       
+                       // check if package is installable or suitable for an update
+                       $this->validateInstructions($requiredVersion);
                }
                catch (\Exception $e) {
                        $this->exception = $e;
+                       
+                       return false;
                }
                
-               //
-               // step 2) traverse requirements
-               //
-               die("<pre>".print_r($this->archive->getOpenRequirements(), true));
-               
-               //
-               // step 3) check requirements against virtual package table
-               //
-               
-               /* TODO: do something */
+               if ($deepInspection) {
+                       try {
+                               // check for exclusions
+                               $this->validateExclusion();
+                               
+                               // traverse open requirements
+                               foreach ($this->archive->getOpenRequirements() as $requirement) {
+                                       $archive = $this->archive->extractTar($requirement->file);
+                                               
+                                       $index = count($this->children);
+                                       $this->children[$index] = new PackageValidationArchive($archive);
+                                       if (!$this->children[$index]->validate(true)) {
+                                               return false;
+                                       }
+                               }
+                       }
+                       catch (PackageValidationException $e) {
+                               $this->exception = $e;
+                               
+                               return false;
+                       }
+               }
                
-               //
-               // step 4) check exclusions
-               //
+               return true;
                
-               /* TODO: do something */
+       }
+       
+       protected function validateInstructions($requiredVersion) {
+               $package = PackageCache::getInstance()->getPackageByIdentifier($this->archive->getPackageInfo('name'));
                
-               return true;
+               // package is not installed yet
+               if ($package === null) {
+                       if (empty($this->archive->getInstallInstructions())) {
+                               throw new PackageValidationException(PackageValidationException::NO_INSTALL_PATH, array('packageName' => $this->archive->getPackageInfo('name')));
+                       }
+               }
+               else {
+                       // package is already installed, check update path
+                       if (!$this->archive->isValidUpdate($package)) {
+                               throw new PackageValidationException(PackageValidationException::NO_UPDATE_PATH, array(
+                                       'packageName' => $package->packageName,
+                                       'packageVersion' => $package->packageVersion,
+                                       'deliveredPackageVersion' => $this->archive->getPackageInfo('version')
+                               ));
+                       }
+               }
+       }
+       
+       protected function validateExclusion() {
+               $excludingPackages = $this->archive->getConflictedExcludingPackages();
+               if (!empty($excludingPackages)) {
+                       throw new PackageValidationException(PackageValidationException::EXCLUDING_PACKAGES, array('packages' => $excludingPackages));
+               }
                
+               $excludedPackages = $this->archive->getConflictedExcludedPackages();
+               if (!empty($excludingPackages)) {
+                       throw new PackageValidationException(PackageValidationException::EXCLUDED_PACKAGES, array('packages' => $excludedPackages));
+               }
        }
        
        /**
@@ -95,7 +140,7 @@ class PackageValidationArchive implements \RecursiveIterator {
                }
                
                if ($this->exception instanceof PackageValidationException) {
-                       return WCF::getLanguage()->getDynamicVariable('wcf.package.validation.errorCode.' . $this->exception->getCode(), $this->exception->getDetails());
+                       return $this->exception->getErrorMessage();
                }
                
                return $this->exception->getMessage();
index 554e0c1cc813d860fb621c2037d0aa3edb405c81..e2177c9229173336868c6342beb51253145002c7 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 namespace wcf\system\package\validation;
 use wcf\system\exception\SystemException;
+use wcf\system\package\PackageArchive;
+use wcf\system\WCF;
 
 /**
  * Represents exceptions occured during validation of a package archive. This exception
@@ -44,6 +46,30 @@ class PackageValidationException extends SystemException {
         */
        const INVALID_PACKAGE_VERSION = 4;
        
+       /**
+        * package contains no install instructions and an update is not possible, expects the detail 'packageName'
+        * @var integer
+        */
+       const NO_INSTALL_PATH = 5;
+       
+       /**
+        * package is already installed and cannot be updated using current archive, expects the details 'packageName', 'packageVersion' and 'deliveredPackageVersion'
+        * @var integer
+        */
+       const NO_UPDATE_PATH = 6;
+       
+       /**
+        * packages which exclude the current package, expects the detail 'packages' (list of \wcf\data\package\Package)
+        * @var integer
+        */
+       const EXCLUDING_PACKAGES = 7;
+       
+       /**
+        * packages which are excluded by current package, expects the detail 'packages' (list of \wcf\data\package\Package)
+        * @var integer
+        */
+       const EXCLUDED_PACKAGES = 8;
+       
        /**
         * Creates a new PackageArchiveValidationException.
         * 
@@ -65,6 +91,15 @@ class PackageValidationException extends SystemException {
                return $this->details;
        }
        
+       /**
+        * Returns the readable error message.
+        * 
+        * @return      string
+        */
+       public function getErrorMessage() {
+               return WCF::getLanguage()->getDynamicVariable('wcf.package.validation.errorCode.' . $this->getCode(), $this->getDetails());
+       }
+       
        /**
         * Returns legacy error messages to mimic WCF 2.0.x PackageArchive's exceptions.
         * 
@@ -91,6 +126,10 @@ class PackageValidationException extends SystemException {
                        case self::INVALID_PACKAGE_VERSION:
                                return "package version '".$this->details['packageVersion']."' is invalid";
                        break;
+                       
+                       default:
+                               return 'Using getMessage() is discouraged, please use getErrorMessage() instead';
+                       break;
                }
        }
        
index c9c10459a1aab5b897e6837dae72cadccb6c9905..d469bbf4efedb663182bee695057b553d6eb6a70 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 namespace wcf\system\package\validation;
-use wcf\system\SingletonFactory;
 use wcf\data\package\Package;
+use wcf\system\SingletonFactory;
 
 /**
  * Manages recursive validation of package archives.