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