There are still a bunch of missing language variables and initial errors occurring during upload aren't properly handled yet. Furthermore it does not check local packages (or those downloaded via HTTP).
Additionally checks for package exclusions have been disabled for testing purposes.
<p>{$archive->getLocalizedPackageInfo('packageDescription')}</p>
</header>
-{if $missingPackages > 0}
- <p class="error">{lang}wcf.acp.package.install.error.missingRequirements{/lang}</p>
-{/if}
-
-{if $excludingPackages|count > 0}
- <div class="error">{lang}wcf.acp.package.install.error.excludingPackages{/lang}
- <ul>
- {foreach from=$excludingPackages item=excludingPackage}
- <li>{lang}wcf.acp.package.install.error.excludingPackages.excludingPackage{/lang}</li>
- {/foreach}
- </ul>
- </div>
-{/if}
-
-{if $excludedPackages|count > 0}
- <div class="error">{lang}wcf.acp.package.install.error.excludedPackages{/lang}
- <ul>
- {foreach from=$excludedPackages item=excludedPackage}
- <li>{lang}wcf.acp.package.install.error.excludedPackages.excludedPackage{/lang}</li>
- {/foreach}
- </ul>
- </div>
+{if !$validationPassed}
+ <p class="error">{lang}wcf.acp.package.validation.failed{/lang}</p>
{/if}
{if $installingImportedStyle}
</fieldset>
</div>
-{if $requiredPackages|count > 0}
+{if !$validationPassed}
<div class="tabularBox tabularBoxTitle marginTop">
<header>
- <h2>{lang}wcf.acp.package.dependencies.required{/lang} <span class="badge badgeInverse">{#$requiredPackages|count}</span></h2>
+ <h2>{lang}wcf.acp.package.validation{/lang}</h2>
</header>
<table class="table">
<tr>
<th class="columnTitle columnPackageName">{lang}wcf.acp.package.name{/lang}</th>
<th class="columnText columnPackage">{lang}wcf.acp.package.identifier{/lang}</th>
- <th class="columnText columnPackageVersion">{lang}wcf.acp.package.installation.requiredVersion{/lang}</th>
<th class="columnText">{lang}wcf.acp.package.installation.packageStatus{/lang}</th>
-
- {event name='columnHeads'}
</tr>
</thead>
-
<tbody>
- {foreach from=$requiredPackages item=$package}
+ {foreach from=$packageValidationArchives item=packageValidationArchive}
+ {assign var=exceptionMessage value=$packageValidationArchive->getExceptionMessage()}
<tr>
- <td class="columnTitle columnPackageName">{if $package[package]}{$package[package]->packageName|language}{/if}</td>
- <td class="columnText columnPackage">{@$package.name}</td>
- <td class="columnText columnPackageVersion">{if $package.minversion|isset}<span class="badge label {if $package.status == 'installed'}green{elseif $package.status == 'delivered'}yellow{else}red{/if}">{$package.minversion}</span>{/if}</td>
- <td class="columnText">{lang}wcf.acp.package.installation.packageStatus.{@$package.status}{/lang}</td>
-
- {event name='columns'}
+ <td class="columnTitle columnPackageName"><span{if $packageValidationArchive->getDepth()} style="padding-left: {@$packageValidationArchive->getDepth() * 14}px"{/if}>{$packageValidationArchive->getArchive()->getLocalizedPackageInfo('packageName')}</span></td>
+ <td class="columnText columnPackage">{$packageValidationArchive->getArchive()->getPackageInfo('name')}</td>
+ <td class="columnIcon columnStatus"><span class="icon icon16 {if $exceptionMessage}fa-times-circle red{else}fa-check-circle green{/if}"></span></td>
</tr>
+
+ {if $exceptionMessage}
+ <tr>
+ <td colspan="3"><span{if $packageValidationArchive->getDepth()} style="padding-left: {@$packageValidationArchive->getDepth() * 14}px"{/if}>{@$exceptionMessage}</span></td>
+ </tr>
+ {/if}
{/foreach}
</tbody>
</table>
<div class="formSubmit">
<input type="button" id="backButton" value="{lang}wcf.global.button.back{/lang}" accesskey="c" />
- {if $missingPackages == 0 && $excludingPackages|count == 0 && $excludedPackages|count == 0}
+ {if $validationPassed}
<input type="button" class="buttonPrimary" id="submitButton" value="{lang}wcf.global.button.next{/lang}" class="default" accesskey="s" />
{/if}
</div>
if (!PackageValidationManager::getInstance()->validate($this->uploadPackage['name'], false)) {
// TODO: do something
- die("validation failed");
+ die("validation failed: " . PackageValidationManager::getInstance()->getExceptionMessage());
}
$this->package = PackageValidationManager::getInstance()->getPackageValidationArchive()->getPackage();
<?php
namespace wcf\acp\page;
use wcf\data\package\installation\queue\PackageInstallationQueue;
-use wcf\data\package\Package;
-use wcf\data\package\PackageCache;
use wcf\page\AbstractPage;
use wcf\system\exception\IllegalLinkException;
-use wcf\system\package\PackageArchive;
+use wcf\system\package\validation\PackageValidationManager;
use wcf\system\package\PackageInstallationDispatcher;
use wcf\system\WCF;
use wcf\system\WCFACP;
-use wcf\system\package\validation\PackageValidationManager;
/**
* Shows a confirmation page prior to start installing.
*/
public $activeMenuItem = 'wcf.acp.menu.link.package.install';
- /**
- * number of missing packages
- * @var integer
- */
- public $missingPackages = 0;
-
- /**
- * list of unsatisfied requirements
- * @var array<array>
- */
- public $openRequirements = array();
-
/**
* package installation dispatcher object
* @var \wcf\system\package\PackageInstallationDispatcher
public $queueID = 0;
/**
- * list of requirements
- * @var array<array>
+ * package validation result
+ * @var boolean
*/
- public $requirements = array();
+ public $validationPassed = false;
/**
* true if the package to be installed was uploaded via the import style
$this->packageInstallationDispatcher = new PackageInstallationDispatcher($this->queue);
// validate the package and all it's requirements
- if (PackageValidationManager::getInstance()->validate($this->queue->archive, true)) {
- die("success");
- }
- else {
- /*echo "<pre>";
- foreach (PackageValidationManager::getInstance()->getPackageValidationArchiveList() as $archive) {
- echo '[' . $archive->getArchive()->getPackageInfo('name') . '] ' . $archive->getExceptionMessage() . "\n";
- }
- die("failed");*/
- return;
- }
-
- // get requirements
- $this->requirements = $this->packageInstallationDispatcher->getArchive()->getRequirements();
- $this->openRequirements = $this->packageInstallationDispatcher->getArchive()->getOpenRequirements();
-
- foreach ($this->requirements as &$requirement) {
- if (isset($this->openRequirements[$requirement['name']])) {
- $requirement['status'] = 'missing';
- $requirement['action'] = $this->openRequirements[$requirement['name']]['action'];
-
- if (!isset($requirement['file'])) {
- if ($requirement['action'] === 'update') {
- $requirement['status'] = 'missingVersion';
- $requirement['existingVersion'] = $this->openRequirements[$requirement['name']]['existingVersion'];
- }
- $this->missingPackages++;
- }
- else {
- $requirement['status'] = 'delivered';
- $packageArchive = new PackageArchive($this->packageInstallationDispatcher->getArchive()->extractTar($requirement['file']));
- $packageArchive->openArchive();
-
- // make sure that the delivered package is correct
- if ($requirement['name'] != $packageArchive->getPackageInfo('name')) {
- $requirement['status'] = 'invalidDeliveredPackage';
- $requirement['deliveredPackage'] = $packageArchive->getPackageInfo('name');
- $this->missingPackages++;
- }
- else if (isset($requirement['minversion'])) {
- // make sure that the delivered version is sufficient
- if (Package::compareVersion($requirement['minversion'], $packageArchive->getPackageInfo('version')) > 0) {
- $requirement['deliveredVersion'] = $packageArchive->getPackageInfo('version');
- $requirement['status'] = 'missingVersion';
- $this->missingPackages++;
- }
- }
- }
- }
- else {
- $requirement['status'] = 'installed';
- }
-
- $requirement['package'] = PackageCache::getInstance()->getPackageByIdentifier($requirement['name']);
- }
-
- unset($requirement);
+ $this->validationPassed = PackageValidationManager::getInstance()->validate($this->queue->archive, true);
}
/**
WCF::getTPL()->assign(array(
'archive' => $this->packageInstallationDispatcher->getArchive(),
- /*'requiredPackages' => $this->requirements,
- 'missingPackages' => $this->missingPackages,
- 'excludingPackages' => $this->packageInstallationDispatcher->getArchive()->getConflictedExcludingPackages(),
- 'excludedPackages' => $this->packageInstallationDispatcher->getArchive()->getConflictedExcludedPackages(),*/
'packageValidationArchives' => PackageValidationManager::getInstance()->getPackageValidationArchiveList(),
'queue' => $this->queue,
+ 'validationPassed' => $this->validationPassed,
'installingImportedStyle' => $this->installingImportedStyle
));
}
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\SystemException;
use wcf\system\language\LanguageFactory;
+use wcf\system\package\PackageArchive;
use wcf\system\WCF;
use wcf\util\XML;
* @see \wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::findExistingItem()
*/
protected function findExistingItem(array $data) { }
+
+ /**
+ * @see \wcf\system\package\plugin\IPackageInstallationPlugin::isValid()
+ */
+ public static function isValid(PackageArchive $archive, $instruction) {
+ return true;
+ }
}
<?php
namespace wcf\system\package\validation;
+use wcf\data\package\Package;
use wcf\data\package\PackageCache;
use wcf\system\package\PackageArchive;
-use wcf\data\package\Package;
/**
* Recursively validates the package archive and it's delivered requirements.
PackageValidationManager::getInstance()->addVirtualPackage($this->archive->getPackageInfo('name'), $this->archive->getPackageInfo('version'));
// check for exclusions
- if (true || WCF_VERSION != '2.1.0 Alpha 1 (Typhoon)') {
+ // TODO: exclusions are not checked for testing purposes
+ // REMOVE THIS BEFORE *ANY* PUBLIC RELEASE
+ if (WCF_VERSION != '2.1.0 Alpha 1 (Typhoon)') {
$this->validateExclusion();
}
}
+ /**
+ * Validates if the package has suitable install or update instructions. Setting $deepInspection
+ * to true will cause every single instruction to be validated against the corresponding PIP.
+ *
+ * Please be aware that unknown PIPs will be silently ignored and will not cause any error!
+ *
+ * @param string $requiredVersion
+ * @param boolean $deepInspection
+ */
protected function validateInstructions($requiredVersion, $deepInspection) {
$package = $this->getPackage();
throw new PackageValidationException(PackageValidationException::NO_INSTALL_PATH, array('packageName' => $this->archive->getPackageInfo('name')));
}
- $this->validatePackageInstallationPlugins('install', $instructions);
+ if ($deepInspection) {
+ $this->validatePackageInstallationPlugins('install', $instructions);
+ }
}
else {
// package is already installed, check update path
));
}
- $this->validatePackageInstallationPlugins('update', $this->archive->getUpdateInstructions());
+ if ($deepInspection) {
+ $this->validatePackageInstallationPlugins('update', $this->archive->getUpdateInstructions());
+ }
}
- exit;
}
+ /**
+ * Validates install or update instructions against the corresponding PIP, unknown PIPs will be silently ignored.
+ *
+ * @param string $type
+ * @param array<array> $instructions
+ */
protected function validatePackageInstallationPlugins($type, array $instructions) {
for ($i = 0, $length = count($instructions); $i < $length; $i++) {
$instruction = $instructions[$i];
}
}
+ /**
+ * Validates if an installed package excludes the current package and vice versa.
+ */
protected function validateExclusion() {
$excludingPackages = $this->archive->getConflictedExcludingPackages();
if (!empty($excludingPackages)) {
return $this->exception->getMessage();
}
+ /**
+ * Returns the package archive object.
+ *
+ * @return \wcf\system\package\PackageArchive
+ */
public function getArchive() {
return $this->archive;
}
+ /**
+ * Returns the package object based on the package archive's package identifier or null
+ * if the package isn't already installed.
+ *
+ * @return \wcf\data\package\Package
+ */
public function getPackage() {
if ($this->package === null) {
$this->package = PackageCache::getInstance()->getPackageByIdentifier($this->archive->getPackageInfo('name'));
<?php
namespace wcf\system\package\validation;
-use wcf\data\package\Package;
-use wcf\system\SingletonFactory;
use wcf\data\package\installation\plugin\PackageInstallationPluginList;
+use wcf\data\package\Package;
use wcf\system\package\PackageArchive;
+use wcf\system\SingletonFactory;
/**
* Manages recursive validation of package archives.
return new \RecursiveIteratorIterator($packageValidationArchive, \RecursiveIteratorIterator::SELF_FIRST);
}
+ /**
+ * Recursively traverses the package validation archives and returns the first exception message.
+ *
+ * @return string
+ */
+ public function getExceptionMessage() {
+ foreach ($this->getPackageValidationArchiveList() as $packageArchive) {
+ if ($packageArchive->getExceptionMessage()) {
+ return $packageArchive->getExceptionMessage();
+ }
+ }
+
+ return '';
+ }
+
+ /**
+ * Validates an instruction against the corresponding package installation plugin.
+ *
+ * Please be aware that unknown PIPs will silently ignored and cause no error.
+ *
+ * @param \wcf\data\package\PackageArchive $archive
+ * @param string $pip
+ * @param string $instruction
+ * @return boolean
+ */
public function validatePackageInstallationPluginInstruction(PackageArchive $archive, $pip, $instruction) {
if (isset($this->packageInstallationPlugins[$pip])) {
return call_user_func(array($this->packageInstallationPlugins[$pip], 'isValid'), $archive, $instruction);
}
- echo "(default success)\n";
+
return true;
}
}
<item name="wcf.acp.package.error.downloadFailed"><![CDATA[Das Herunterladen des Paketes{if $__downloadPackage|isset} „{$__downloadPackage}“{/if} ist fehlgeschlagen.]]></item>
<item name="wcf.acp.package.newVersion"><![CDATA[Neue Version]]></item>
+ <item name="wcf.acp.package.validation"><![CDATA[Prüfungsergebnis]]></item>
+ <item name="wcf.acp.package.validation.failed"><![CDATA[Das hochgeladene Paket kann nicht installiert werden, bitte beachten Sie das unten stehende Prüfungsergebnis.]]></item>
+
<!-- TODO: most error codes are still missing, they will be added during testing -->
<item name="wcf.acp.package.validation.errorCode.8"><![CDATA[Dieses Paket ist inkompatibel mit den folgenden, installierten Paketen: <ul class="nativeList">{foreach from=$packages item=package}<li>„{$package}“ ({$package->package})</li>{/foreach}</ul>]]></item>
<item name="wcf.acp.package.validation.errorCode.10"><![CDATA[Benötigt das Paket „{$packageName}“ in Version „{$packageVersion}“ oder höher, dies ist aber weder installiert noch wird es mitgeliefert.]]></item>