de704dcb5d4d97fb8bbc36f98bc41f24fc0f3c4b
[GitHub/WoltLab/WCF.git] /
1 <?php
2 namespace wcf\data\package\installation\plugin;
3 use wcf\data\AbstractDatabaseObjectAction;
4 use wcf\data\devtools\project\DevtoolsProject;
5 use wcf\system\cache\CacheHandler;
6 use wcf\system\devtools\pip\DevtoolsPackageInstallationDispatcher;
7 use wcf\system\devtools\pip\DevtoolsPip;
8 use wcf\system\devtools\pip\IIdempotentPackageInstallationPlugin;
9 use wcf\system\exception\PermissionDeniedException;
10 use wcf\system\exception\UserInputException;
11 use wcf\system\package\SplitNodeException;
12 use wcf\system\search\SearchIndexManager;
13 use wcf\system\version\VersionTracker;
14 use wcf\system\WCF;
15
16 /**
17 * Executes package installation plugin-related actions.
18 *
19 * @author Alexander Ebert
20 * @copyright 2001-2017 WoltLab GmbH
21 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
22 * @package WoltLabSuite\Core\Data\Package\Installation\Plugin
23 *
24 * @method PackageInstallationPlugin create()
25 * @method PackageInstallationPluginEditor[] getObjects()
26 * @method PackageInstallationPluginEditor getSingleObject()
27 */
28 class PackageInstallationPluginAction extends AbstractDatabaseObjectAction {
29 /**
30 * @inheritDoc
31 */
32 protected $className = PackageInstallationPluginEditor::class;
33
34 /**
35 * @inheritDoc
36 */
37 protected $requireACP = ['invoke'];
38
39 /**
40 * @var DevtoolsPip
41 */
42 public $devtoolsPip;
43
44 /**
45 * @var PackageInstallationPlugin
46 */
47 public $packageInstallationPlugin;
48
49 /**
50 * @var DevtoolsProject
51 */
52 public $project;
53
54 public function validateInvoke() {
55 if (!ENABLE_DEVELOPER_TOOLS || !WCF::getSession()->getPermission('admin.configuration.package.canInstallPackage')) {
56 throw new PermissionDeniedException();
57 }
58
59 $this->readString('pluginName');
60 $this->readInteger('projectID');
61 $this->readString('target');
62
63 $this->project = new DevtoolsProject($this->parameters['projectID']);
64 if (!$this->project->projectID || $this->project->validate() !== '') {
65 throw new UserInputException('projectID');
66 }
67
68 $this->packageInstallationPlugin = new PackageInstallationPlugin($this->parameters['pluginName']);
69 if (!$this->packageInstallationPlugin->pluginName) {
70 throw new UserInputException('pluginName');
71 }
72
73 $this->devtoolsPip = new DevtoolsPip($this->packageInstallationPlugin);
74 $targets = $this->devtoolsPip->getTargets($this->project);
75 if (!in_array($this->parameters['target'], $targets)) {
76 throw new UserInputException('target');
77 }
78 }
79
80 public function invoke() {
81 $dispatcher = new DevtoolsPackageInstallationDispatcher($this->project);
82 /** @var IIdempotentPackageInstallationPlugin $pip */
83 $pip = new $this->packageInstallationPlugin->className($dispatcher, [
84 'value' => $this->devtoolsPip->getInstructionValue($this->project, $this->parameters['target'])
85 ]);
86
87 $start = microtime(true);
88
89 try {
90 $pip->update();
91 }
92 catch (SplitNodeException $e) {
93 throw new \RuntimeException("PIP '{$this->packageInstallationPlugin->pluginName}' is not allowed to throw a 'SplitNodeException'.");
94 }
95
96 // clear cache
97
98 // TODO: use a central method instead!
99
100 // create search index tables
101 SearchIndexManager::getInstance()->createSearchIndices();
102
103 VersionTracker::getInstance()->createStorageTables();
104
105 CacheHandler::getInstance()->flushAll();
106
107
108 return [
109 'pluginName' => $this->packageInstallationPlugin->pluginName,
110 'target' => $this->parameters['target'],
111 'timeElapsed' => WCF::getLanguage()->getDynamicVariable('wcf.acp.devtools.sync.status.success', ['timeElapsed' => round(microtime(true) - $start, 3)])
112 ];
113 }
114 }