/** * Builds nodes for optional packages, whereas each package exists within * one node with the same parent node, seperated by sequence no (which does * not really matter at this point). */ protected function buildOptionalNodes() { $packages = array(); $optionalPackages = $this->installation->getArchive()->getOptionals(); foreach ($optionalPackages as $package) { // check if already installed if (Package::isAlreadyInstalled($package['name'])) { continue; } // extract package $index = $this->installation->getArchive()->getTar()->getIndexByFilename($package['file']); if ($index === false) { throw new SystemException("Unable to find required package '" . $package['file'] . "' within archive."); } $fileName = FileUtil::getTemporaryFilename('package_', preg_replace('!^.*(?=\\.(?:tar\\.gz|tgz|tar)$)!i', '', basename($package['file']))); $this->installation->getArchive()->getTar()->extract($index, $fileName); // get archive data $archive = new PackageArchive($fileName); $archive->openArchive(); // check if all requirements are met $isInstallable = true; foreach ($archive->getOpenRequirements() as $packageName => $package) { if (!isset($package['file'])) { // requirement is neither installed nor shipped, check if it is about to be installed if (!isset(self::$pendingPackages[$packageName])) { $isInstallable = false; break; } } } // check for exclusions $excludedPackages = $archive->getConflictedExcludedPackages(); if (!empty($excludedPackages)) { $isInstallable = false; } $excludingPackages = $archive->getConflictedExcludingPackages(); if (!empty($excludingPackages)) { $isInstallable = false; } $packages[] = array('archive' => $fileName, 'isInstallable' => $isInstallable, 'package' => $archive->getPackageInfo('name'), 'packageName' => $archive->getLocalizedPackageInfo('packageName'), 'packageDescription' => $archive->getLocalizedPackageInfo('packageDescription'), 'selected' => 0); self::$pendingPackages[$archive->getPackageInfo('name')] = $archive->getPackageInfo('version'); } if (!empty($packages)) { $this->parentNode = $this->node; $this->node = $this->getToken(); $this->sequenceNo = 0; $sql = "INSERT INTO\twcf" . WCF_N . "_package_installation_node\n\t\t\t\t\t\t(queueID, processNo, sequenceNo, node, parentNode, nodeType, nodeData)\n\t\t\t\tVALUES\t\t(?, ?, ?, ?, ?, ?, ?)"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($this->installation->queue->queueID, $this->installation->queue->processNo, $this->sequenceNo, $this->node, $this->parentNode, 'optionalPackages', serialize($packages))); } }
/** * Validates this package and optionally it's delivered requirements. The set validation * mode will toggle between different checks. * * @param integer $validationMode * @return boolean */ public function validate($validationMode, $requiredVersion = '') { if ($validationMode !== PackageValidationManager::VALIDATION_EXCLUSION) { try { // try to read archive $this->archive->openArchive(); // check if package is installable or suitable for an update $this->validateInstructions($requiredVersion, $validationMode); } catch (PackageValidationException $e) { $this->exception = $e; return false; } } $package = $this->archive->getPackageInfo('name'); if ($validationMode === PackageValidationManager::VALIDATION_RECURSIVE) { try { PackageValidationManager::getInstance()->addVirtualPackage($package, $this->archive->getPackageInfo('version')); // cache excluded packages self::$excludedPackages[$package] = array(); $excludedPackages = $this->archive->getExcludedPackages(); for ($i = 0, $count = count($excludedPackages); $i < $count; $i++) { if (!isset(self::$excludedPackages[$package][$excludedPackages[$i]['name']])) { self::$excludedPackages[$package][$excludedPackages[$i]['name']] = array(); } self::$excludedPackages[$package][$excludedPackages[$i]['name']][] = $excludedPackages[$i]['version']; } // traverse open requirements foreach ($this->archive->getOpenRequirements() as $requirement) { $virtualPackageVersion = PackageValidationManager::getInstance()->getVirtualPackage($requirement['name']); if ($virtualPackageVersion === null || Package::compareVersion($virtualPackageVersion, $requirement['minversion'], '<')) { if (empty($requirement['file'])) { // check if package is known $sql = "SELECT\t*\n\t\t\t\t\t\t\t\tFROM\twcf" . WCF_N . "_package\n\t\t\t\t\t\t\t\tWHERE\tpackage = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($requirement['name'])); $package = $statement->fetchObject('wcf\\data\\package\\Package'); throw new PackageValidationException(PackageValidationException::MISSING_REQUIREMENT, array('package' => $package, 'packageName' => $requirement['name'], 'packageVersion' => $requirement['minversion'])); } $archive = $this->archive->extractTar($requirement['file']); $index = count($this->children); $this->children[$index] = new PackageValidationArchive($archive, $this, $this->depth + 1); if (!$this->children[$index]->validate(PackageValidationManager::VALIDATION_RECURSIVE, $requirement['minversion'])) { return false; } PackageValidationManager::getInstance()->addVirtualPackage($this->children[$index]->getArchive()->getPackageInfo('name'), $this->children[$index]->getArchive()->getPackageInfo('version')); } } } catch (PackageValidationException $e) { $this->exception = $e; return false; } } else { if ($validationMode === PackageValidationManager::VALIDATION_EXCLUSION) { try { $this->validateExclusion($package); for ($i = 0, $count = count($this->children); $i < $count; $i++) { if (!$this->children[$i]->validate(PackageValidationManager::VALIDATION_EXCLUSION)) { return false; } } } catch (PackageValidationException $e) { $this->exception = $e; return false; } } } return true; }