|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare( strict_types = 1 ); |
|
4
|
|
|
|
|
5
|
|
|
namespace Wikibase\Repo\Api; |
|
6
|
|
|
|
|
7
|
|
|
use ApiBase; |
|
8
|
|
|
use ApiMain; |
|
9
|
|
|
use ApiUsageException; |
|
10
|
|
|
use LogicException; |
|
11
|
|
|
use MWContentSerializationException; |
|
12
|
|
|
use Status; |
|
13
|
|
|
use User; |
|
14
|
|
|
use Wikibase\DataModel\Entity\EntityDocument; |
|
15
|
|
|
use Wikibase\DataModel\Entity\EntityId; |
|
16
|
|
|
use Wikibase\Lib\Store\EntityRevisionLookup; |
|
17
|
|
|
use Wikibase\Lib\Store\LookupConstants; |
|
18
|
|
|
use Wikibase\Lib\StringNormalizer; |
|
19
|
|
|
use Wikibase\Lib\Summary; |
|
20
|
|
|
use Wikibase\Repo\ChangeOp\ChangeOp; |
|
21
|
|
|
use Wikibase\Repo\ChangeOp\ChangeOpException; |
|
22
|
|
|
use Wikibase\Repo\ChangeOp\ChangeOpResult; |
|
23
|
|
|
use Wikibase\Repo\ChangeOp\ChangeOpValidationException; |
|
24
|
|
|
use Wikibase\Repo\SiteLinkTargetProvider; |
|
25
|
|
|
use Wikibase\Repo\Store\EntityPermissionChecker; |
|
26
|
|
|
use Wikibase\Repo\Store\EntityTitleStoreLookup; |
|
27
|
|
|
use Wikibase\Repo\Store\Store; |
|
28
|
|
|
use Wikibase\Repo\WikibaseRepo; |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* Base class for API modules modifying a single entity identified based on id xor a combination of site and page title. |
|
32
|
|
|
* |
|
33
|
|
|
* @license GPL-2.0-or-later |
|
34
|
|
|
* @author John Erling Blad < [email protected] > |
|
35
|
|
|
* @author Daniel Kinzler |
|
36
|
|
|
* @author Michał Łazowik |
|
37
|
|
|
*/ |
|
38
|
|
|
abstract class ModifyEntity extends ApiBase { |
|
39
|
|
|
|
|
40
|
|
|
use FederatedPropertyApiValidatorTrait; |
|
41
|
|
|
|
|
42
|
|
|
/** |
|
43
|
|
|
* @var StringNormalizer |
|
44
|
|
|
*/ |
|
45
|
|
|
protected $stringNormalizer; |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* @var SiteLinkTargetProvider |
|
49
|
|
|
*/ |
|
50
|
|
|
protected $siteLinkTargetProvider; |
|
51
|
|
|
|
|
52
|
|
|
/** |
|
53
|
|
|
* @var EntityTitleStoreLookup |
|
54
|
|
|
*/ |
|
55
|
|
|
private $titleLookup; |
|
56
|
|
|
|
|
57
|
|
|
/** |
|
58
|
|
|
* @var string[] |
|
59
|
|
|
*/ |
|
60
|
|
|
protected $siteLinkGroups; |
|
61
|
|
|
|
|
62
|
|
|
/** |
|
63
|
|
|
* @var string[] |
|
64
|
|
|
*/ |
|
65
|
|
|
protected $badgeItems; |
|
66
|
|
|
|
|
67
|
|
|
/** |
|
68
|
|
|
* @var ApiErrorReporter |
|
69
|
|
|
*/ |
|
70
|
|
|
protected $errorReporter; |
|
71
|
|
|
|
|
72
|
|
|
/** |
|
73
|
|
|
* @var EntityPermissionChecker |
|
74
|
|
|
*/ |
|
75
|
|
|
private $permissionChecker; |
|
76
|
|
|
|
|
77
|
|
|
/** |
|
78
|
|
|
* @var EntityRevisionLookup |
|
79
|
|
|
*/ |
|
80
|
|
|
private $revisionLookup; |
|
81
|
|
|
|
|
82
|
|
|
/** |
|
83
|
|
|
* @var ResultBuilder |
|
84
|
|
|
*/ |
|
85
|
|
|
private $resultBuilder; |
|
86
|
|
|
|
|
87
|
|
|
/** |
|
88
|
|
|
* @var EntitySavingHelper |
|
89
|
|
|
*/ |
|
90
|
|
|
private $entitySavingHelper; |
|
91
|
|
|
|
|
92
|
|
|
/** |
|
93
|
|
|
* @var string[] |
|
94
|
|
|
*/ |
|
95
|
|
|
protected $enabledEntityTypes; |
|
96
|
|
|
|
|
97
|
|
|
/** |
|
98
|
|
|
* @param ApiMain $mainModule |
|
99
|
|
|
* @param string $moduleName |
|
100
|
|
|
* @param bool $federatedPropertiesEnabled |
|
101
|
|
|
* @param string $modulePrefix |
|
102
|
|
|
* |
|
103
|
|
|
* @see ApiBase::__construct |
|
104
|
|
|
*/ |
|
105
|
|
|
public function __construct( ApiMain $mainModule, string $moduleName, bool $federatedPropertiesEnabled, string $modulePrefix = '' ) { |
|
106
|
|
|
parent::__construct( $mainModule, $moduleName, $modulePrefix ); |
|
107
|
|
|
|
|
108
|
|
|
$wikibaseRepo = WikibaseRepo::getDefaultInstance(); |
|
109
|
|
|
$apiHelperFactory = $wikibaseRepo->getApiHelperFactory( $this->getContext() ); |
|
110
|
|
|
$settings = $wikibaseRepo->getSettings(); |
|
111
|
|
|
|
|
112
|
|
|
//TODO: provide a mechanism to override the services |
|
113
|
|
|
$this->errorReporter = $apiHelperFactory->getErrorReporter( $this ); |
|
114
|
|
|
$this->resultBuilder = $apiHelperFactory->getResultBuilder( $this ); |
|
115
|
|
|
$this->entitySavingHelper = $apiHelperFactory->getEntitySavingHelper( $this ); |
|
116
|
|
|
$this->stringNormalizer = $wikibaseRepo->getStringNormalizer(); |
|
117
|
|
|
$this->enabledEntityTypes = $wikibaseRepo->getLocalEntityTypes(); |
|
118
|
|
|
|
|
119
|
|
|
$this->entitySavingHelper->setEntityIdParam( 'id' ); |
|
120
|
|
|
|
|
121
|
|
|
$this->setServices( new SiteLinkTargetProvider( |
|
122
|
|
|
$wikibaseRepo->getSiteLookup(), |
|
123
|
|
|
$settings->getSetting( 'specialSiteLinkGroups' ) |
|
124
|
|
|
) ); |
|
125
|
|
|
|
|
126
|
|
|
// TODO: use the EntitySavingHelper to load the entity, instead of an EntityRevisionLookup. |
|
127
|
|
|
$this->revisionLookup = $wikibaseRepo->getEntityRevisionLookup( Store::LOOKUP_CACHING_DISABLED ); |
|
128
|
|
|
$this->permissionChecker = $wikibaseRepo->getEntityPermissionChecker(); |
|
129
|
|
|
$this->titleLookup = $wikibaseRepo->getEntityTitleLookup(); |
|
130
|
|
|
$this->siteLinkGroups = $settings->getSetting( 'siteLinkGroups' ); |
|
131
|
|
|
$this->badgeItems = $settings->getSetting( 'badgeItems' ); |
|
132
|
|
|
|
|
133
|
|
|
$this->federatedPropertiesEnabled = $federatedPropertiesEnabled; |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
|
|
public function setServices( SiteLinkTargetProvider $siteLinkTargetProvider ): void { |
|
137
|
|
|
$this->siteLinkTargetProvider = $siteLinkTargetProvider; |
|
138
|
|
|
} |
|
139
|
|
|
|
|
140
|
|
|
protected function getTitleLookup(): EntityTitleStoreLookup { |
|
141
|
|
|
return $this->titleLookup; |
|
142
|
|
|
} |
|
143
|
|
|
|
|
144
|
|
|
protected function getResultBuilder(): ResultBuilder { |
|
145
|
|
|
return $this->resultBuilder; |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
/** |
|
149
|
|
|
* Create a new Summary instance suitable for representing the action performed by this module. |
|
150
|
|
|
* |
|
151
|
|
|
* @param array $params |
|
152
|
|
|
* |
|
153
|
|
|
* @return Summary |
|
154
|
|
|
*/ |
|
155
|
|
|
protected function createSummary( array $params ): Summary { |
|
156
|
|
|
$summary = new Summary( $this->getModuleName() ); |
|
157
|
|
|
$summary->setUserSummary( $params['summary'] ); |
|
158
|
|
|
return $summary; |
|
159
|
|
|
} |
|
160
|
|
|
|
|
161
|
|
|
/** |
|
162
|
|
|
* Actually modify the entity. |
|
163
|
|
|
* |
|
164
|
|
|
* @param EntityDocument $entity |
|
165
|
|
|
* @param ChangeOp $changeOp |
|
166
|
|
|
* @param array $preparedParameters |
|
167
|
|
|
* |
|
168
|
|
|
* @return Summary|null a summary of the modification, or null to indicate failure. |
|
169
|
|
|
*/ |
|
170
|
|
|
abstract protected function modifyEntity( |
|
171
|
|
|
EntityDocument $entity, |
|
172
|
|
|
ChangeOp $changeOp, |
|
173
|
|
|
array $preparedParameters |
|
174
|
|
|
): ?Summary; |
|
175
|
|
|
|
|
176
|
|
|
/** |
|
177
|
|
|
* Applies the given ChangeOp to the given Entity. |
|
178
|
|
|
* Any ChangeOpException is converted into an ApiUsageException with the code 'modification-failed'. |
|
179
|
|
|
* |
|
180
|
|
|
* @param ChangeOp $changeOp |
|
181
|
|
|
* @param EntityDocument $entity |
|
182
|
|
|
* @param Summary|null $summary The summary object to update with information about the change. |
|
183
|
|
|
* |
|
184
|
|
|
* @return ChangeOpResult |
|
185
|
|
|
*/ |
|
186
|
|
|
protected function applyChangeOp( ChangeOp $changeOp, EntityDocument $entity, Summary $summary = null ): ChangeOpResult { |
|
187
|
|
|
try { |
|
188
|
|
|
// NOTE: Always validate modification against the current revision, if it exists! |
|
189
|
|
|
// Otherwise, we may miss e.g. a combination of language/label/description |
|
190
|
|
|
// that was already taken. |
|
191
|
|
|
// TODO: conflict resolution should be re-engineered, see T126231 |
|
192
|
|
|
// TODO: use the EntitySavingHelper to load the entity, instead of an EntityRevisionLookup. |
|
193
|
|
|
// TODO: consolidate with StatementModificationHelper::applyChangeOp |
|
194
|
|
|
// FIXME: this EntityRevisionLookup is uncached, we may be loading the Entity several times! |
|
195
|
|
|
$currentEntityRevision = $this->revisionLookup->getEntityRevision( |
|
196
|
|
|
$entity->getId(), |
|
|
|
|
|
|
197
|
|
|
0, |
|
198
|
|
|
LookupConstants::LATEST_FROM_REPLICA_WITH_FALLBACK |
|
199
|
|
|
); |
|
200
|
|
|
if ( $currentEntityRevision ) { |
|
201
|
|
|
$currentEntityResult = $changeOp->validate( $currentEntityRevision->getEntity() ); |
|
202
|
|
|
if ( !$currentEntityResult->isValid() ) { |
|
203
|
|
|
throw new ChangeOpValidationException( $currentEntityResult ); |
|
204
|
|
|
} |
|
205
|
|
|
} |
|
206
|
|
|
|
|
207
|
|
|
// Also validate the change op against the entity it would be applied on, as apply might |
|
208
|
|
|
// explode on cases validate would have caught. |
|
209
|
|
|
// Case for that seem to be a "clear" flag of wbeditentity which results in $entity being |
|
210
|
|
|
// quite a different entity from $currentEntity, and validation results might differ significantly. |
|
211
|
|
|
$result = $changeOp->validate( $entity ); |
|
212
|
|
|
|
|
213
|
|
|
if ( !$result->isValid() ) { |
|
214
|
|
|
throw new ChangeOpValidationException( $result ); |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
$changeOpResult = $changeOp->apply( $entity, $summary ); |
|
218
|
|
|
|
|
219
|
|
|
// Also validate change op result as it may contain further validation |
|
220
|
|
|
// that is not covered by change op validators |
|
221
|
|
|
$changeOpResultValidationResult = $changeOpResult->validate(); |
|
222
|
|
|
|
|
223
|
|
|
if ( !$changeOpResultValidationResult->isValid() ) { |
|
224
|
|
|
throw new ChangeOpValidationException( $changeOpResultValidationResult ); |
|
225
|
|
|
} |
|
226
|
|
|
|
|
227
|
|
|
return $changeOpResult; |
|
228
|
|
|
|
|
229
|
|
|
} catch ( ChangeOpException $ex ) { |
|
230
|
|
|
$this->errorReporter->dieException( $ex, 'modification-failed' ); |
|
231
|
|
|
} |
|
232
|
|
|
} |
|
233
|
|
|
|
|
234
|
|
|
/** |
|
235
|
|
|
* @param array $params |
|
236
|
|
|
* @return array |
|
237
|
|
|
*/ |
|
238
|
|
|
protected function prepareParameters( array $params ): array { |
|
239
|
|
|
return $params; |
|
240
|
|
|
} |
|
241
|
|
|
|
|
242
|
|
|
protected function validateEntitySpecificParameters( |
|
243
|
|
|
array $preparedParameters, |
|
244
|
|
|
EntityDocument $entity, |
|
245
|
|
|
int $baseRevId |
|
246
|
|
|
): void { |
|
247
|
|
|
} |
|
248
|
|
|
|
|
249
|
|
|
/** |
|
250
|
|
|
* Make sure the required parameters are provided and that they are valid. |
|
251
|
|
|
* |
|
252
|
|
|
* @param array $params |
|
253
|
|
|
*/ |
|
254
|
|
|
protected function validateParameters( array $params ): void { |
|
255
|
|
|
$entityReferenceBySiteLinkGiven = isset( $params['site'] ) && isset( $params['title'] ); |
|
256
|
|
|
$entityReferenceBySiteLinkPartial = ( isset( $params['site'] ) xor isset( $params['title'] ) ); |
|
257
|
|
|
$entityIdGiven = isset( $params['id'] ); |
|
258
|
|
|
$shouldCreateNewWithSomeType = isset( $params['new'] ); |
|
259
|
|
|
|
|
260
|
|
|
$noReferenceIsGiven = !$entityIdGiven && !$shouldCreateNewWithSomeType && !$entityReferenceBySiteLinkGiven; |
|
261
|
|
|
$bothReferencesAreGiven = $entityIdGiven && $entityReferenceBySiteLinkGiven; |
|
262
|
|
|
|
|
263
|
|
|
if ( $entityReferenceBySiteLinkPartial ) { |
|
264
|
|
|
$this->errorReporter->dieWithError( |
|
265
|
|
|
'wikibase-api-illegal-id-or-site-page-selector', |
|
266
|
|
|
'param-missing' |
|
267
|
|
|
); |
|
268
|
|
|
} |
|
269
|
|
|
|
|
270
|
|
|
if ( $noReferenceIsGiven || $bothReferencesAreGiven ) { |
|
271
|
|
|
$this->errorReporter->dieWithError( |
|
272
|
|
|
'wikibase-api-illegal-id-or-site-page-selector', |
|
273
|
|
|
'param-illegal' |
|
274
|
|
|
); |
|
275
|
|
|
} |
|
276
|
|
|
|
|
277
|
|
|
if ( $shouldCreateNewWithSomeType && ( $entityIdGiven || $entityReferenceBySiteLinkGiven ) ) { |
|
278
|
|
|
$this->errorReporter->dieWithError( |
|
279
|
|
|
'Either provide the item "id" or pairs of "site" and "title" or a "new" type for an entity', |
|
280
|
|
|
'param-illegal' |
|
281
|
|
|
); |
|
282
|
|
|
} |
|
283
|
|
|
} |
|
284
|
|
|
|
|
285
|
|
|
/** |
|
286
|
|
|
* @inheritDoc |
|
287
|
|
|
*/ |
|
288
|
|
|
public function execute(): void { |
|
289
|
|
|
$params = $this->extractRequestParams(); |
|
290
|
|
|
$user = $this->getUser(); |
|
291
|
|
|
|
|
292
|
|
|
$this->validateParameters( $params ); |
|
293
|
|
|
$entityId = $this->entitySavingHelper->getEntityIdFromParams( $params ); |
|
294
|
|
|
$this->validateAlteringEntityById( $entityId ); |
|
295
|
|
|
|
|
296
|
|
|
// Try to find the entity or fail and create it, or die in the process |
|
297
|
|
|
$entity = $this->loadEntityFromSavingHelper( $entityId ); |
|
298
|
|
|
$entityRevId = $this->entitySavingHelper->getBaseRevisionId(); |
|
299
|
|
|
|
|
300
|
|
|
if ( $entity->getId() === null ) { |
|
301
|
|
|
throw new LogicException( 'The Entity should have an ID at this point!' ); |
|
302
|
|
|
} |
|
303
|
|
|
|
|
304
|
|
|
$preparedParameters = $this->prepareParameters( $params ); |
|
305
|
|
|
unset( $params ); |
|
306
|
|
|
|
|
307
|
|
|
$this->validateEntitySpecificParameters( $preparedParameters, $entity, $entityRevId ); |
|
308
|
|
|
|
|
309
|
|
|
$changeOp = $this->getChangeOp( $preparedParameters, $entity ); |
|
310
|
|
|
|
|
311
|
|
|
$status = $this->checkPermissions( $entity, $user, $changeOp ); |
|
312
|
|
|
|
|
313
|
|
|
if ( !$status->isOK() ) { |
|
314
|
|
|
// Was …->dieError( 'You do not have sufficient permissions', … ) before T150512. |
|
315
|
|
|
$this->errorReporter->dieStatus( $status, 'permissiondenied' ); |
|
316
|
|
|
} |
|
317
|
|
|
|
|
318
|
|
|
$summary = $this->modifyEntity( $entity, $changeOp, $preparedParameters ); |
|
319
|
|
|
|
|
320
|
|
|
if ( !$summary ) { |
|
321
|
|
|
//XXX: This could rather be used for "silent" failure, i.e. in cases where |
|
322
|
|
|
// there was simply nothing to do. |
|
323
|
|
|
$this->errorReporter->dieError( 'Attempted modification of the item failed', 'failed-modify' ); |
|
|
|
|
|
|
324
|
|
|
} |
|
325
|
|
|
|
|
326
|
|
|
try { |
|
327
|
|
|
$status = $this->entitySavingHelper->attemptSaveEntity( |
|
328
|
|
|
$entity, |
|
329
|
|
|
$summary |
|
|
|
|
|
|
330
|
|
|
); |
|
331
|
|
|
} catch ( MWContentSerializationException $ex ) { |
|
|
|
|
|
|
332
|
|
|
// This happens if the $entity created via modifyEntity() above (possibly cleared |
|
333
|
|
|
// before) is not sufficiently initialized and failed serialization. |
|
334
|
|
|
$this->errorReporter->dieError( $ex->getMessage(), 'failed-save' ); |
|
|
|
|
|
|
335
|
|
|
} |
|
336
|
|
|
|
|
337
|
|
|
$this->addToOutput( $entity, $status, $entityRevId ); |
|
338
|
|
|
} |
|
339
|
|
|
|
|
340
|
|
|
/** |
|
341
|
|
|
* @param array $preparedParameters |
|
342
|
|
|
* @param EntityDocument $entity |
|
343
|
|
|
* |
|
344
|
|
|
* @return ChangeOp |
|
345
|
|
|
*/ |
|
346
|
|
|
abstract protected function getChangeOp( array $preparedParameters, EntityDocument $entity ): ChangeOp; |
|
347
|
|
|
|
|
348
|
|
|
/** |
|
349
|
|
|
* Try to find the entity or fail and create it, or die in the process. |
|
350
|
|
|
* |
|
351
|
|
|
* @param EntityId|null $entityId |
|
352
|
|
|
* |
|
353
|
|
|
* @return EntityDocument |
|
354
|
|
|
* @throws ApiUsageException |
|
355
|
|
|
*/ |
|
356
|
|
|
private function loadEntityFromSavingHelper( ?EntityId $entityId ): EntityDocument { |
|
357
|
|
|
$entity = $this->entitySavingHelper->loadEntity( $entityId, EntitySavingHelper::NO_FRESH_ID ); |
|
358
|
|
|
|
|
359
|
|
|
if ( $entity->getId() === null ) { |
|
360
|
|
|
// Make sure the user is allowed to create an entity before attempting to assign an id |
|
361
|
|
|
$permStatus = $this->permissionChecker->getPermissionStatusForEntity( |
|
362
|
|
|
$this->getUser(), |
|
363
|
|
|
EntityPermissionChecker::ACTION_EDIT, |
|
364
|
|
|
$entity |
|
365
|
|
|
); |
|
366
|
|
|
if ( !$permStatus->isOK() ) { |
|
367
|
|
|
$this->errorReporter->dieStatus( $permStatus, 'permissiondenied' ); |
|
368
|
|
|
} |
|
369
|
|
|
|
|
370
|
|
|
$entity = $this->entitySavingHelper->loadEntity( $entityId, EntitySavingHelper::ASSIGN_FRESH_ID ); |
|
371
|
|
|
} |
|
372
|
|
|
|
|
373
|
|
|
return $entity; |
|
374
|
|
|
} |
|
375
|
|
|
|
|
376
|
|
|
/** |
|
377
|
|
|
* Check the rights for the user accessing the module. |
|
378
|
|
|
* |
|
379
|
|
|
* @param EntityDocument $entity the entity to check |
|
380
|
|
|
* @param User $user User doing the action |
|
381
|
|
|
* @param ChangeOp $changeOp |
|
382
|
|
|
* |
|
383
|
|
|
* @return Status the check's result |
|
384
|
|
|
*/ |
|
385
|
|
|
private function checkPermissions( EntityDocument $entity, User $user, ChangeOp $changeOp ): Status { |
|
386
|
|
|
$status = Status::newGood(); |
|
387
|
|
|
|
|
388
|
|
|
foreach ( $changeOp->getActions() as $perm ) { |
|
389
|
|
|
$permStatus = $this->permissionChecker->getPermissionStatusForEntity( $user, $perm, $entity ); |
|
390
|
|
|
$status->merge( $permStatus ); |
|
391
|
|
|
} |
|
392
|
|
|
|
|
393
|
|
|
return $status; |
|
394
|
|
|
} |
|
395
|
|
|
|
|
396
|
|
|
private function addToOutput( EntityDocument $entity, Status $status, int $oldRevId ): void { |
|
397
|
|
|
$this->getResultBuilder()->addBasicEntityInformation( $entity->getId(), 'entity' ); |
|
|
|
|
|
|
398
|
|
|
$this->getResultBuilder()->addRevisionIdFromStatusToResult( $status, 'entity', $oldRevId ); |
|
399
|
|
|
|
|
400
|
|
|
$params = $this->extractRequestParams(); |
|
401
|
|
|
|
|
402
|
|
|
if ( isset( $params['site'] ) && isset( $params['title'] ) ) { |
|
403
|
|
|
$normTitle = $this->stringNormalizer->trimToNFC( $params['title'] ); |
|
404
|
|
|
if ( $normTitle !== $params['title'] ) { |
|
405
|
|
|
$this->getResultBuilder()->addNormalizedTitle( $params['title'], $normTitle, 'normalized' ); |
|
406
|
|
|
} |
|
407
|
|
|
} |
|
408
|
|
|
|
|
409
|
|
|
$this->getResultBuilder()->markSuccess( 1 ); |
|
410
|
|
|
} |
|
411
|
|
|
|
|
412
|
|
|
/** |
|
413
|
|
|
* @inheritDoc |
|
414
|
|
|
*/ |
|
415
|
|
|
protected function getAllowedParams(): array { |
|
416
|
|
|
return array_merge( |
|
417
|
|
|
parent::getAllowedParams(), |
|
418
|
|
|
$this->getAllowedParamsForId(), |
|
419
|
|
|
$this->getAllowedParamsForSiteLink(), |
|
420
|
|
|
$this->getAllowedParamsForEntity() |
|
421
|
|
|
); |
|
422
|
|
|
} |
|
423
|
|
|
|
|
424
|
|
|
/** |
|
425
|
|
|
* Get allowed params for the identification of the entity |
|
426
|
|
|
* Lookup through an id is common for all entities |
|
427
|
|
|
* |
|
428
|
|
|
* @return array[] |
|
429
|
|
|
*/ |
|
430
|
|
|
private function getAllowedParamsForId(): array { |
|
431
|
|
|
return [ |
|
432
|
|
|
'id' => [ |
|
433
|
|
|
self::PARAM_TYPE => 'string', |
|
434
|
|
|
], |
|
435
|
|
|
'new' => [ |
|
436
|
|
|
self::PARAM_TYPE => $this->enabledEntityTypes, |
|
437
|
|
|
], |
|
438
|
|
|
]; |
|
439
|
|
|
} |
|
440
|
|
|
|
|
441
|
|
|
/** |
|
442
|
|
|
* Get allowed params for the identification by a sitelink pair |
|
443
|
|
|
* Lookup through the sitelink object is not used in every subclasses |
|
444
|
|
|
* |
|
445
|
|
|
* @return array[] |
|
446
|
|
|
*/ |
|
447
|
|
|
private function getAllowedParamsForSiteLink(): array { |
|
448
|
|
|
$sites = $this->siteLinkTargetProvider->getSiteList( $this->siteLinkGroups ); |
|
449
|
|
|
|
|
450
|
|
|
return [ |
|
451
|
|
|
'site' => [ |
|
452
|
|
|
self::PARAM_TYPE => $sites->getGlobalIdentifiers(), |
|
453
|
|
|
], |
|
454
|
|
|
'title' => [ |
|
455
|
|
|
self::PARAM_TYPE => 'string', |
|
456
|
|
|
], |
|
457
|
|
|
]; |
|
458
|
|
|
} |
|
459
|
|
|
|
|
460
|
|
|
/** |
|
461
|
|
|
* Get allowed params for the entity in general |
|
462
|
|
|
* |
|
463
|
|
|
* @return array |
|
464
|
|
|
*/ |
|
465
|
|
|
private function getAllowedParamsForEntity(): array { |
|
466
|
|
|
return [ |
|
467
|
|
|
'baserevid' => [ |
|
468
|
|
|
self::PARAM_TYPE => 'integer', |
|
469
|
|
|
], |
|
470
|
|
|
'summary' => [ |
|
471
|
|
|
self::PARAM_TYPE => 'string', |
|
472
|
|
|
], |
|
473
|
|
|
'tags' => [ |
|
474
|
|
|
self::PARAM_TYPE => 'tags', |
|
475
|
|
|
self::PARAM_ISMULTI => true, |
|
476
|
|
|
], |
|
477
|
|
|
'token' => null, |
|
478
|
|
|
'bot' => false, |
|
479
|
|
|
]; |
|
480
|
|
|
} |
|
481
|
|
|
|
|
482
|
|
|
} |
|
483
|
|
|
|
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: