Merge branch '3.0'
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / data / package / PackageAction.class.php
CommitLineData
158bd3ca
TD
1<?php
2namespace wcf\data\package;
3use wcf\data\AbstractDatabaseObjectAction;
93c9c717 4use wcf\system\database\util\PreparedStatementConditionBuilder;
eb0f6246 5use wcf\system\exception\SystemException;
e7714ce1 6use wcf\system\io\RemoteFile;
eb0f6246 7use wcf\system\request\LinkHandler;
317c8af5 8use wcf\system\WCF;
e7714ce1 9use wcf\util\HTTPRequest;
079b9ff4 10use wcf\util\JSON;
158bd3ca
TD
11
12/**
13 * Executes package-related actions.
14 *
15 * @author Alexander Ebert
c839bd49 16 * @copyright 2001-2018 WoltLab GmbH
158bd3ca 17 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
e71525e4 18 * @package WoltLabSuite\Core\Data\Package
0e8867ac
MS
19 *
20 * @method Package create()
21 * @method PackageEditor[] getObjects()
22 * @method PackageEditor getSingleObject()
158bd3ca
TD
23 */
24class PackageAction extends AbstractDatabaseObjectAction {
25 /**
0fcfe5f6 26 * @inheritDoc
158bd3ca 27 */
157054c9 28 protected $className = PackageEditor::class;
158bd3ca
TD
29
30 /**
0fcfe5f6 31 * @inheritDoc
158bd3ca 32 */
058cbd6a 33 protected $permissionsCreate = ['admin.configuration.package.canInstallPackage'];
158bd3ca
TD
34
35 /**
0fcfe5f6 36 * @inheritDoc
158bd3ca 37 */
058cbd6a 38 protected $permissionsDelete = ['admin.configuration.package.canUninstallPackage'];
158bd3ca
TD
39
40 /**
0fcfe5f6 41 * @inheritDoc
158bd3ca 42 */
058cbd6a 43 protected $permissionsUpdate = ['admin.configuration.package.canUpdatePackage'];
317c8af5 44
93c9c717 45 /**
0fcfe5f6 46 * @inheritDoc
93c9c717 47 */
058cbd6a 48 protected $requireACP = ['searchForPurchasedItems'];
93c9c717
AE
49
50 /**
51 * Validates parameters to search for purchased items in the WoltLab Plugin-Store.
52 */
317c8af5 53 public function validateSearchForPurchasedItems() {
058cbd6a 54 WCF::getSession()->checkPermissions(['admin.configuration.package.canInstallPackage', 'admin.configuration.package.canUpdatePackage']);
317c8af5
AE
55
56 $this->readString('password', true);
57 $this->readString('username', true);
58
317c8af5 59 if (empty($this->parameters['username'])) {
93c9c717 60 $conditions = new PreparedStatementConditionBuilder();
13f1e023 61 $conditions->add("serverURL REGEXP ?", ['https?://store\.woltlab\.com/[a-z]+/']);
93c9c717
AE
62 $conditions->add("loginUsername <> ''");
63 $conditions->add("loginPassword <> ''");
64
317c8af5
AE
65 // check if user has already provided credentials
66 $sql = "SELECT loginUsername, loginPassword
67 FROM wcf".WCF_N."_package_update_server
93c9c717 68 ".$conditions;
317c8af5 69 $statement = WCF::getDB()->prepareStatement($sql, 1);
93c9c717 70 $statement->execute($conditions->getParameters());
317c8af5
AE
71 $row = $statement->fetchArray();
72 if (!empty($row['loginUsername']) && !empty($row['loginPassword'])) {
73 $this->parameters['password'] = $row['loginPassword'];
74 $this->parameters['username'] = $row['loginUsername'];
75 }
76 }
77 }
78
93c9c717
AE
79 /**
80 * Searches for purchased items in the WoltLab Plugin-Store.
81 *
2b770bdd
MS
82 * @return string[]
83 * @throws SystemException
93c9c717 84 */
317c8af5 85 public function searchForPurchasedItems() {
e7714ce1 86 if (!RemoteFile::supportsSSL()) {
058cbd6a 87 return [
93c9c717 88 'noSSL' => WCF::getLanguage()->get('wcf.acp.pluginStore.api.noSSL')
058cbd6a 89 ];
93c9c717
AE
90 }
91
317c8af5 92 if (empty($this->parameters['username']) || empty($this->parameters['password'])) {
058cbd6a 93 return [
317c8af5 94 'template' => $this->renderAuthorizationDialog(false)
058cbd6a 95 ];
317c8af5
AE
96 }
97
183dea04 98 $request = new HTTPRequest('https://api.woltlab.com/1.1/customer/purchases/list.json', [
317c8af5 99 'method' => 'POST'
058cbd6a 100 ], [
317c8af5
AE
101 'username' => $this->parameters['username'],
102 'password' => $this->parameters['password'],
298a7cd8 103 'wcfVersion' => WCF_VERSION
058cbd6a 104 ]);
317c8af5
AE
105
106 $request->execute();
107 $reply = $request->getReply();
108 $response = JSON::decode($reply['body']);
109
63b9817b 110 $code = isset($response['status']) ? $response['status'] : 500;
317c8af5
AE
111 switch ($code) {
112 case 200:
113 if (empty($response['products'])) {
058cbd6a 114 return [
8e61f344 115 'noResults' => WCF::getLanguage()->getDynamicVariable('wcf.acp.pluginStore.purchasedItems.noResults')
058cbd6a 116 ];
317c8af5
AE
117 }
118 else {
119 WCF::getSession()->register('__pluginStoreProducts', $response['products']);
298a7cd8 120 WCF::getSession()->register('__pluginStoreWcfMajorReleases', $response['wcfMajorReleases']);
317c8af5 121
058cbd6a 122 return [
317c8af5 123 'redirectURL' => LinkHandler::getInstance()->getLink('PluginStorePurchasedItems')
058cbd6a 124 ];
317c8af5
AE
125 }
126 break;
127
128 // authentication error
129 case 401:
058cbd6a 130 return [
317c8af5 131 'template' => $this->renderAuthorizationDialog(true)
058cbd6a 132 ];
317c8af5
AE
133 break;
134
135 // any other kind of errors
136 default:
058cbd6a 137 throw new SystemException(WCF::getLanguage()->getDynamicVariable('wcf.acp.pluginStore.api.error', ['status' => $code]));
317c8af5
AE
138 break;
139 }
140 }
141
93c9c717
AE
142 /**
143 * Renders the authentication dialog.
144 *
145 * @param boolean $rejected
146 * @return string
147 */
317c8af5 148 protected function renderAuthorizationDialog($rejected) {
058cbd6a 149 WCF::getTPL()->assign([
317c8af5 150 'rejected' => $rejected
058cbd6a 151 ]);
317c8af5
AE
152
153 return WCF::getTPL()->fetch('pluginStoreAuthorization');
154 }
dcb3a44c 155}