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