2 namespace wcf\system\package\validation
;
3 use wcf\data\package\installation\plugin\PackageInstallationPluginList
;
4 use wcf\data\package\Package
;
5 use wcf\system\package\PackageArchive
;
6 use wcf\system\SingletonFactory
;
9 * Manages recursive validation of package archives.
11 * @author Alexander Ebert
12 * @copyright 2001-2018 WoltLab GmbH
13 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
14 * @package WoltLabSuite\Core\System\Package\Validation
16 class PackageValidationManager
extends SingletonFactory
{
18 * list of known package installation plugins
21 protected $packageInstallationPlugins = [];
24 * package validation archive object
25 * @var PackageValidationArchive
27 protected $packageValidationArchive = null;
30 * virtual package list containing package => packageVersion
33 protected $virtualPackageList = [];
36 * validation will only check if the primary package looks like it can be installed or updated
39 const VALIDATION_WEAK
= 0;
42 * validation will recursively check dependencies
45 const VALIDATION_RECURSIVE
= 1;
48 * validation will use the previously gathered exclusions and check them
51 const VALIDATION_EXCLUSION
= 2;
56 protected function init() {
57 $pipList = new PackageInstallationPluginList();
58 $pipList->readObjects();
59 foreach ($pipList as $pip) {
60 $this->packageInstallationPlugins
[$pip->pluginName
] = $pip->className
;
65 * Validates given archive for existence and ability to be installed/updated. If you set the
66 * second parameter $deepInspection to "false", the system will only check if the archive
67 * looks fine, this is useful for a rough check during upload when a more detailed check will
68 * be performed afterwards.
70 * @param string $archive
71 * @param boolean $deepInspection
74 public function validate($archive, $deepInspection) {
75 $this->virtualPackageList
= [];
76 $this->packageValidationArchive
= new PackageValidationArchive($archive);
78 if ($deepInspection) {
79 if (!$this->packageValidationArchive
->validate(self
::VALIDATION_RECURSIVE
)) {
83 return $this->packageValidationArchive
->validate(self
::VALIDATION_EXCLUSION
);
86 return $this->packageValidationArchive
->validate(self
::VALIDATION_WEAK
);
90 * Returns package validation archive object.
92 * @return PackageValidationArchive
94 public function getPackageValidationArchive() {
95 return $this->packageValidationArchive
;
99 * Adds a virtual package with the corresponding version, if the package is already known,
100 * the higher version number will be stored.
102 * @param string $package
103 * @param string $packageVersion
106 public function addVirtualPackage($package, $packageVersion) {
107 if (isset($this->virtualPackageList
[$package])) {
108 if (Package
::compareVersion($packageVersion, $this->virtualPackageList
[$package], '<')) {
113 $this->virtualPackageList
[$package] = $packageVersion;
119 * Returns the version number of a virtual package or null if it doesn't exist.
121 * @param string $package
124 public function getVirtualPackage($package) {
125 if (isset($this->virtualPackageList
[$package])) {
126 return $this->virtualPackageList
[$package];
133 * Returns the iterable package archive list.
135 * @return \RecursiveIteratorIterator
137 public function getPackageValidationArchiveList() {
138 $packageValidationArchive = new PackageValidationArchive('');
139 $packageValidationArchive->setChildren([$this->packageValidationArchive
]);
141 return new \
RecursiveIteratorIterator($packageValidationArchive, \RecursiveIteratorIterator
::SELF_FIRST
);
145 * Recursively traverses the package validation archives and returns the first exception message.
149 public function getExceptionMessage() {
150 foreach ($this->getPackageValidationArchiveList() as $packageArchive) {
151 if ($packageArchive->getExceptionMessage()) {
152 return $packageArchive->getExceptionMessage();
160 * Recursively traverses the package validation archives and returns the first exception.
164 public function getException() {
165 foreach ($this->getPackageValidationArchiveList() as $packageArchive) {
166 if ($packageArchive->getException() !== null) {
167 return $packageArchive->getException();
175 * Validates an instruction against the corresponding package installation plugin.
177 * Please be aware that unknown PIPs will silently ignored and cause no error.
179 * @param PackageArchive $archive
181 * @param string $instruction
184 public function validatePackageInstallationPluginInstruction(PackageArchive
$archive, $pip, $instruction) {
185 if (isset($this->packageInstallationPlugins
[$pip])) {
186 return call_user_func([$this->packageInstallationPlugins
[$pip], 'isValid'], $archive, $instruction);
193 * Returns the default filename for the given pip name. If no default filename
194 * exists `null` is returned.
197 * @return string|null
200 public function getDefaultFilenameForPackageInstallationPlugin($pip) {
201 if (isset($this->packageInstallationPlugins
[$pip])) {
202 return call_user_func([$this->packageInstallationPlugins
[$pip], 'getDefaultFilename']);