5530eecbf133e0a33cd54d609729c1030747bf6a
[GitHub/WoltLab/WCF.git] /
1 <?php
2 namespace wcf\system\package\plugin;
3 use wcf\data\acp\search\provider\ACPSearchProviderEditor;
4 use wcf\data\acp\search\provider\ACPSearchProviderList;
5 use wcf\system\cache\builder\ACPSearchProviderCacheBuilder;
6 use wcf\system\devtools\pip\IDevtoolsPipEntryList;
7 use wcf\system\devtools\pip\IGuiPackageInstallationPlugin;
8 use wcf\system\devtools\pip\TXmlGuiPackageInstallationPlugin;
9 use wcf\system\form\builder\container\FormContainer;
10 use wcf\system\form\builder\field\validation\FormFieldValidationError;
11 use wcf\system\form\builder\field\validation\FormFieldValidator;
12 use wcf\system\form\builder\field\ClassNameFormField;
13 use wcf\system\form\builder\field\IntegerFormField;
14 use wcf\system\form\builder\field\TextFormField;
15 use wcf\system\form\builder\IFormDocument;
16 use wcf\system\search\acp\IACPSearchResultProvider;
17 use wcf\system\WCF;
18
19 /**
20 * Installs, updates and deletes ACP search providers.
21 *
22 * @author Alexander Ebert
23 * @copyright 2001-2018 WoltLab GmbH
24 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
25 * @package WoltLabSuite\Core\System\Package\Plugin
26 */
27 class ACPSearchProviderPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin implements IGuiPackageInstallationPlugin {
28 use TXmlGuiPackageInstallationPlugin;
29
30 /**
31 * @inheritDoc
32 */
33 public $className = ACPSearchProviderEditor::class;
34
35 /**
36 * @inheritDoc
37 */
38 protected function handleDelete(array $items) {
39 $sql = "DELETE FROM wcf".WCF_N."_".$this->tableName."
40 WHERE providerName = ?
41 AND packageID = ?";
42 $statement = WCF::getDB()->prepareStatement($sql);
43
44 WCF::getDB()->beginTransaction();
45 foreach ($items as $item) {
46 $statement->execute([
47 $item['attributes']['name'],
48 $this->installation->getPackageID()
49 ]);
50 }
51 WCF::getDB()->commitTransaction();
52 }
53
54 /**
55 * @inheritDoc
56 */
57 protected function prepareImport(array $data) {
58 // get show order
59 $showOrder = isset($data['elements']['showorder']) ? $data['elements']['showorder'] : null;
60 $showOrder = $this->getShowOrder($showOrder);
61
62 return [
63 'className' => $data['elements']['classname'],
64 'providerName' => $data['attributes']['name'],
65 'showOrder' => $showOrder
66 ];
67 }
68
69 /**
70 * @inheritDoc
71 */
72 protected function findExistingItem(array $data) {
73 $sql = "SELECT *
74 FROM wcf".WCF_N."_".$this->tableName."
75 WHERE providerName = ?
76 AND packageID = ?";
77 $parameters = [
78 $data['providerName'],
79 $this->installation->getPackageID()
80 ];
81
82 return [
83 'sql' => $sql,
84 'parameters' => $parameters
85 ];
86 }
87
88 /**
89 * @inheritDoc
90 */
91 protected function cleanup() {
92 ACPSearchProviderCacheBuilder::getInstance()->reset();
93 }
94
95 /**
96 * @see \wcf\system\package\plugin\IPackageInstallationPlugin::getDefaultFilename()
97 * @since 3.0
98 */
99 public static function getDefaultFilename() {
100 return 'acpSearchProvider.xml';
101 }
102
103 /**
104 * @inheritDoc
105 * @since 3.1
106 */
107 public static function getSyncDependencies() {
108 return [];
109 }
110
111 /**
112 * @inheritDoc
113 * @since 3.2
114 */
115 protected function getElementData(\DOMElement $element, $saveData = false) {
116 $data = [
117 'className' => $element->getElementsByTagName('classname')->item(0)->nodeValue,
118 'packageID' => $this->installation->getPackage()->packageID,
119 'providerName' => $element->getAttribute('name')
120 ];
121
122 $showOrder = $element->getElementsByTagName('showorder')->item(0);
123 if ($showOrder) {
124 $data['showOrder'] = $showOrder->nodeValue;
125 }
126
127 return $data;
128 }
129
130 /**
131 * @inheritDoc
132 * @since 3.2
133 */
134 public function getElementIdentifier(\DOMElement $element) {
135 return $element->getAttribute('name');
136 }
137
138 /**
139 * @inheritDoc
140 * @since 3.2
141 */
142 public function addFormFields(IFormDocument $form) {
143 /** @var FormContainer $dataContainer */
144 $dataContainer = $form->getNodeById('data');
145
146 $dataContainer->appendChildren([
147 TextFormField::create('providerName')
148 ->objectProperty('name')
149 ->label('wcf.acp.pip.acpSearchProvider.providerName')
150 ->description('wcf.acp.pip.acpSearchProvider.providerName.description', ['project' => $this->installation->getProject()])
151 ->required()
152 ->addValidator(ObjectTypePackageInstallationPlugin::getObjectTypeAlikeValueValidator('wcf.acp.pip.acpSearchProvider.providerName'))
153 ->addValidator(new FormFieldValidator('uniqueness', function(TextFormField $formField) {
154 if (
155 $formField->getDocument()->getFormMode() === IFormDocument::FORM_MODE_CREATE ||
156 $this->editedEntry->getAttribute('name') !== $formField->getValue()
157 ) {
158 $providerList = new ACPSearchProviderList();
159 $providerList->getConditionBuilder()->add('providerName <> ?', [$formField->getValue()]);
160
161 if ($providerList->countObjects() > 0) {
162 $formField->addValidationError(
163 new FormFieldValidationError(
164 'notUnique',
165 'wcf.acp.pip.acpSearchProvider.providerName.error.notUnique'
166 )
167 );
168 }
169 }
170 })),
171
172 ClassNameFormField::create('className')
173 ->objectProperty('classname')
174 ->required()
175 ->implementedInterface(IACPSearchResultProvider::class),
176
177 IntegerFormField::create('showOrder')
178 ->objectProperty('showorder')
179 ->label('wcf.acp.pip.acpSearchProvider.showOrder')
180 ->description('wcf.acp.pip.acpSearchProvider.showOrder.description')
181 ->nullable()
182 ->minimum(1),
183 ]);
184 }
185
186 /**
187 * @inheritDoc
188 * @since 3.2
189 */
190 protected function setEntryListKeys(IDevtoolsPipEntryList $entryList) {
191 $entryList->setKeys([
192 'providerName' => 'wcf.acp.pip.acpSearchProvider.providerName',
193 'className' => 'wcf.form.field.className'
194 ]);
195 }
196
197 /**
198 * @inheritDoc
199 * @since 3.2
200 */
201 protected function sortDocument(\DOMDocument $document) {
202 $this->sortImportDelete($document);
203
204 $this->sortChildNodes($document->getElementsByTagName('import'), function(\DOMElement $element1, \DOMElement $element2) {
205 $showOrder1 = PHP_INT_MAX;
206 if ($element1->getElementsByTagName('showorder')->length === 1) {
207 $showOrder1 = $element1->getElementsByTagName('showorder')->item(0)->nodeValue;
208 }
209
210 $showOrder2 = PHP_INT_MAX;
211 if ($element2->getElementsByTagName('showorder')->length === 1) {
212 $showOrder2 = $element2->getElementsByTagName('showorder')->item(0)->nodeValue;
213 }
214
215 if ($showOrder1 !== $showOrder2) {
216 return $showOrder1 > $showOrder2;
217 }
218
219 return strcmp(
220 $element1->getAttribute('name'),
221 $element2->getAttribute('name')
222 );
223 });
224 $this->sortChildNodes($document->getElementsByTagName('delete'), function(\DOMElement $element1, \DOMElement $element2) {
225 return strcmp(
226 $element1->getAttribute('name'),
227 $element2->getAttribute('name')
228 );
229 });
230 }
231
232 /**
233 * @inheritDoc
234 * @since 3.2
235 */
236 protected function writeEntry(\DOMDocument $document, IFormDocument $form) {
237 $data = $form->getData()['data'];
238
239 $acpSearchProvider = $document->createElement('acpsearchprovider');
240 $acpSearchProvider->setAttribute('name', $data['name']);
241 $acpSearchProvider->appendChild($document->createElement('classname', $data['classname']));
242
243 /** @var IntegerFormField $showOrder */
244 if (!empty($data['showOrder'])) {
245 $acpSearchProvider->appendChild($document->createElement('showorder', (string) $data['showorder']));
246 }
247
248 $document->getElementsByTagName('import')->item(0)->appendChild($acpSearchProvider);
249
250 return $acpSearchProvider;
251 }
252 }