Merge branch '2.0'
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / acp / form / PackageStartInstallForm.class.php
CommitLineData
158bd3ca
TD
1<?php
2namespace wcf\acp\form;
158bd3ca
TD
3use wcf\data\package\installation\queue\PackageInstallationQueue;
4use wcf\data\package\installation\queue\PackageInstallationQueueEditor;
2bc9f31d 5use wcf\data\package\Package;
264c6eea 6use wcf\form\AbstractForm;
ec45d5e8 7use wcf\system\exception\PermissionDeniedException;
158bd3ca
TD
8use wcf\system\exception\SystemException;
9use wcf\system\exception\UserInputException;
51654676 10use wcf\system\package\validation\PackageValidationManager;
158bd3ca
TD
11use wcf\system\package\PackageArchive;
12use wcf\system\package\PackageInstallationDispatcher;
2bc9f31d
TB
13use wcf\system\WCF;
14use wcf\system\WCFACP;
158bd3ca 15use wcf\util\FileUtil;
158bd3ca
TD
16use wcf\util\StringUtil;
17
18/**
19 * Shows the package install and update form.
6e048dca 20 *
158bd3ca 21 * @author Marcel Werk
ca4ba303 22 * @copyright 2001-2014 WoltLab GmbH
158bd3ca
TD
23 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
24 * @package com.woltlab.wcf
25 * @subpackage acp.form
9f959ced 26 * @category Community Framework
158bd3ca 27 */
264c6eea 28class PackageStartInstallForm extends AbstractForm {
21489986 29 /**
0ad90fc3 30 * @see \wcf\page\AbstractPage::$activeMenuItem
21489986 31 */
158bd3ca 32 public $activeMenuItem = 'wcf.acp.menu.link.package.install';
21489986 33
21489986
MS
34 /**
35 * updated package object
0ad90fc3 36 * @var \wcf\system\package\Package
21489986 37 */
158bd3ca 38 public $package = null;
21489986
MS
39
40 /**
41 * url to the package to download
42 * @var string
43 */
158bd3ca 44 public $downloadPackage = '';
21489986
MS
45
46 /**
47 * data of the uploaded package
48 * @var array<string>
49 */
158bd3ca 50 public $uploadPackage = '';
21489986
MS
51
52 /**
c945dba8 53 * archive of the installation/update package
0ad90fc3 54 * @var \wcf\system\package\PackageArchive
21489986 55 */
158bd3ca 56 public $archive = null;
21489986
MS
57
58 /**
59 * package installation/update queue
0ad90fc3 60 * @var \wcf\data\package\installation\queue\PackageInstallationQueue
21489986 61 */
158bd3ca
TD
62 public $queue = null;
63
b168bf95
MS
64 /**
65 * location of the package uploaded via style import
66 * @var string
67 */
68 public $stylePackageImportLocation = '';
69
70 /**
71 * @see \wcf\page\IPage::readParameters()
72 */
73 public function readParameters() {
74 parent::readParameters();
75
76 $this->stylePackageImportLocation = WCF::getSession()->getVar('stylePackageImportLocation');
77 if ($this->stylePackageImportLocation) {
78 $_POST['t'] = WCF::getSession()->getSecurityToken();
79 }
80 }
81
158bd3ca 82 /**
0ad90fc3 83 * @see \wcf\form\IForm::readFormParameters()
158bd3ca
TD
84 */
85 public function readFormParameters() {
86 parent::readFormParameters();
87
b168bf95
MS
88 if (!$this->stylePackageImportLocation) {
89 if (isset($_POST['downloadPackage'])) $this->downloadPackage = StringUtil::trim($_POST['downloadPackage']);
90 if (isset($_FILES['uploadPackage'])) $this->uploadPackage = $_FILES['uploadPackage'];
91 }
158bd3ca
TD
92 }
93
94 /**
0ad90fc3 95 * @see \wcf\form\IForm::validate()
158bd3ca
TD
96 */
97 public function validate() {
98 parent::validate();
99
b168bf95
MS
100 if ($this->stylePackageImportLocation) {
101 $this->archive = new PackageArchive($this->stylePackageImportLocation, $this->package);
102
103 try {
104 $this->validateArchive('uploadPackage');
105 }
106 catch (UserInputException $e) {
107 WCF::getSession()->unregister('stylePackageImportLocation');
108
109 throw $e;
110 }
111 }
112 else if (!empty($this->uploadPackage['name'])) {
158bd3ca
TD
113 $this->validateUploadPackage();
114 }
115 else if (!empty($this->downloadPackage)) {
116 $this->validateDownloadPackage();
117 }
118 else {
119 throw new UserInputException('uploadPackage');
120 }
121 }
122
123 /**
124 * Validates the upload package input.
125 */
126 protected function validateUploadPackage() {
e06392e6
AE
127 $this->activeTabMenuItem = 'upload';
128
158bd3ca
TD
129 if (empty($this->uploadPackage['tmp_name'])) {
130 throw new UserInputException('uploadPackage', 'uploadFailed');
131 }
132
133 // get filename
134 $this->uploadPackage['name'] = FileUtil::getTemporaryFilename('package_', preg_replace('!^.*(?=\.(?:tar\.gz|tgz|tar)$)!i', '', basename($this->uploadPackage['name'])));
135
136 if (!@move_uploaded_file($this->uploadPackage['tmp_name'], $this->uploadPackage['name'])) {
137 throw new UserInputException('uploadPackage', 'uploadFailed');
138 }
139
870b0938
AE
140 if (!PackageValidationManager::getInstance()->validate($this->uploadPackage['name'], false)) {
141 // TODO: do something
25c89d0a 142 die("validation failed: " . PackageValidationManager::getInstance()->getExceptionMessage());
4c5b87fc 143 }
870b0938
AE
144
145 $this->package = PackageValidationManager::getInstance()->getPackageValidationArchive()->getPackage();
158bd3ca
TD
146 }
147
148 /**
149 * Validates the download package input.
150 */
151 protected function validateDownloadPackage() {
b9e47fe0
AE
152 $this->activeTabMenuItem = 'upload';
153
158bd3ca
TD
154 if (FileUtil::isURL($this->downloadPackage)) {
155 // download package
156 $this->archive = new PackageArchive($this->downloadPackage, $this->package);
157
158 try {
159 $this->downloadPackage = $this->archive->downloadArchive();
158bd3ca
TD
160 }
161 catch (SystemException $e) {
a30c0984 162 throw new UserInputException('downloadPackage', 'downloadFailed');
158bd3ca
TD
163 }
164 }
165 else {
166 // probably local path
167 if (!file_exists($this->downloadPackage)) {
a30c0984 168 throw new UserInputException('downloadPackage', 'downloadFailed');
158bd3ca
TD
169 }
170
171 $this->archive = new PackageArchive($this->downloadPackage, $this->package);
172 }
173
174 $this->validateArchive('downloadPackage');
175 }
176
177 /**
178 * Validates the package archive.
6e048dca 179 *
158bd3ca
TD
180 * @param string $type upload or download package
181 */
182 protected function validateArchive($type) {
183 // try to open the archive
184 try {
185 // TODO: Exceptions thrown within openArchive() are discarded, resulting in
186 // the meaningless message 'not a valid package'
187 $this->archive->openArchive();
188 }
189 catch (SystemException $e) {
190 throw new UserInputException($type, 'noValidPackage');
191 }
192
193 // validate php requirements
194 $errors = PackageInstallationDispatcher::validatePHPRequirements($this->archive->getPhpRequirements());
15fa2802 195 if (!empty($errors)) {
158bd3ca
TD
196 WCF::getTPL()->assign('phpRequirements', $errors);
197 throw new UserInputException($type, 'phpRequirements');
198 }
199
ec45d5e8
AE
200 // try to find existing package
201 $sql = "SELECT *
202 FROM wcf".WCF_N."_package
203 WHERE package = ?";
204 $statement = WCF::getDB()->prepareStatement($sql);
205 $statement->execute(array($this->archive->getPackageInfo('name')));
206 $row = $statement->fetchArray();
207 if ($row !== false) {
208 $this->package = new Package(null, $row);
209 }
210
158bd3ca
TD
211 // check update or install support
212 if ($this->package !== null) {
ec45d5e8
AE
213 WCF::getSession()->checkPermissions(array('admin.system.package.canUpdatePackage'));
214 $this->activeMenuItem = 'wcf.acp.menu.link.package';
215
49ec1439 216 if (!$this->archive->isValidUpdate($this->package)) {
158bd3ca
TD
217 throw new UserInputException($type, 'noValidUpdate');
218 }
219 }
220 else {
ec45d5e8
AE
221 WCF::getSession()->checkPermissions(array('admin.system.package.canInstallPackage'));
222
158bd3ca
TD
223 if (!$this->archive->isValidInstall()) {
224 throw new UserInputException($type, 'noValidInstall');
225 }
58e1d71f 226 else if ($this->archive->isAlreadyInstalled()) {
158bd3ca
TD
227 throw new UserInputException($type, 'uniqueAlreadyInstalled');
228 }
549376a4
MS
229 else if ($this->archive->getPackageInfo('isApplication') && $this->archive->hasUniqueAbbreviation()) {
230 throw new UserInputException($type, 'noUniqueAbbrevation');
231 }
158bd3ca
TD
232 }
233 }
234
235 /**
0ad90fc3 236 * @see \wcf\form\IForm::save()
158bd3ca
TD
237 */
238 public function save() {
239 parent::save();
240
241 // get new process no
242 $processNo = PackageInstallationQueue::getNewProcessNo();
243
244 // obey foreign key
ec45d5e8 245 $packageID = ($this->package) ? $this->package->packageID : null;
158bd3ca 246
b168bf95
MS
247 $archive = $this->downloadPackage;
248 if ($this->stylePackageImportLocation) {
249 $archive = $this->stylePackageImportLocation;
250 }
251 else if (!empty($this->uploadPackage['tmp_name'])) {
252 $archive = $this->uploadPackage['name'];
253 }
254
158bd3ca 255 // insert queue
870b0938 256 $isApplication = PackageValidationManager::getInstance()->getPackageValidationArchive()->getArchive()->getPackageInfo('isApplication');
158bd3ca
TD
257 $this->queue = PackageInstallationQueueEditor::create(array(
258 'processNo' => $processNo,
259 'userID' => WCF::getUser()->userID,
870b0938
AE
260 'package' => PackageValidationManager::getInstance()->getPackageValidationArchive()->getArchive()->getPackageInfo('name'),
261 'packageName' => PackageValidationManager::getInstance()->getPackageValidationArchive()->getArchive()->getLocalizedPackageInfo('packageName'),
158bd3ca 262 'packageID' => $packageID,
b168bf95 263 'archive' => $archive,
158bd3ca 264 'action' => ($this->package != null ? 'update' : 'install'),
b33c97d2 265 'isApplication' => (!$isApplication ? '0' : '1')
158bd3ca
TD
266 ));
267
268 $this->saved();
269
270 // open queue
8059b673 271 PackageInstallationDispatcher::openQueue(0, $processNo);
158bd3ca
TD
272 }
273
274 /**
0ad90fc3 275 * @see \wcf\page\IPage::assignVariables()
158bd3ca
TD
276 */
277 public function assignVariables() {
278 parent::assignVariables();
279
280 WCF::getTPL()->assign(array(
b168bf95
MS
281 'package' => $this->package,
282 'installingImportedStyle' => $this->stylePackageImportLocation != ''
158bd3ca
TD
283 ));
284 }
285
286 /**
0ad90fc3 287 * @see \wcf\page\IPage::show()
158bd3ca
TD
288 */
289 public function show() {
ec45d5e8
AE
290 if (!WCF::getSession()->getPermission('admin.system.package.canInstallPackage') && !WCF::getSession()->getPermission('admin.system.package.canUpdatePackage')) {
291 throw new PermissionDeniedException();
7f4589b6 292 }
158bd3ca
TD
293
294 // check master password
295 WCFACP::checkMasterPassword();
296
297 parent::show();
298 }
299}