|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare( strict_types = 1 ); |
|
4
|
|
|
|
|
5
|
|
|
namespace Wikibase\Repo\Api; |
|
6
|
|
|
|
|
7
|
|
|
use ApiBase; |
|
8
|
|
|
use ApiMain; |
|
9
|
|
|
use Wikibase\DataModel\Services\Statement\StatementGuidParser; |
|
10
|
|
|
use Wikibase\DataModel\Statement\Statement; |
|
11
|
|
|
use Wikibase\Repo\ChangeOp\ChangeOp; |
|
12
|
|
|
use Wikibase\Repo\ChangeOp\ChangeOpException; |
|
13
|
|
|
use Wikibase\Repo\ChangeOp\ChangeOps; |
|
14
|
|
|
use Wikibase\Repo\ChangeOp\StatementChangeOpFactory; |
|
15
|
|
|
use Wikibase\Repo\WikibaseRepo; |
|
16
|
|
|
|
|
17
|
|
|
/** |
|
18
|
|
|
* API module for removing one or more references of the same statement. |
|
19
|
|
|
* |
|
20
|
|
|
* @license GPL-2.0-or-later |
|
21
|
|
|
* @author Jeroen De Dauw < [email protected] > |
|
22
|
|
|
* @author Tobias Gritschacher < [email protected] > |
|
23
|
|
|
*/ |
|
24
|
|
|
class RemoveReferences extends ApiBase { |
|
25
|
|
|
|
|
26
|
|
|
use FederatedPropertyApiValidatorTrait; |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* @var StatementChangeOpFactory |
|
30
|
|
|
*/ |
|
31
|
|
|
private $statementChangeOpFactory; |
|
32
|
|
|
|
|
33
|
|
|
/** |
|
34
|
|
|
* @var ApiErrorReporter |
|
35
|
|
|
*/ |
|
36
|
|
|
protected $errorReporter; |
|
37
|
|
|
|
|
38
|
|
|
/** |
|
39
|
|
|
* @var StatementModificationHelper |
|
40
|
|
|
*/ |
|
41
|
|
|
private $modificationHelper; |
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* @var StatementGuidParser |
|
45
|
|
|
*/ |
|
46
|
|
|
private $guidParser; |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* @var ResultBuilder |
|
50
|
|
|
*/ |
|
51
|
|
|
private $resultBuilder; |
|
52
|
|
|
|
|
53
|
|
|
/** |
|
54
|
|
|
* @var EntitySavingHelper |
|
55
|
|
|
*/ |
|
56
|
|
|
private $entitySavingHelper; |
|
57
|
|
|
|
|
58
|
|
|
public function __construct( |
|
59
|
|
|
ApiMain $mainModule, |
|
60
|
|
|
string $moduleName, |
|
61
|
|
|
ApiErrorReporter $errorReporter, |
|
62
|
|
|
StatementChangeOpFactory $statementChangeOpFactory, |
|
63
|
|
|
StatementModificationHelper $modificationHelper, |
|
64
|
|
|
StatementGuidParser $guidParser, |
|
65
|
|
|
callable $resultBuilderInstantiator, |
|
66
|
|
|
callable $entitySavingHelperInstantiator, |
|
67
|
|
|
bool $federatedPropertiesEnabled |
|
68
|
|
|
) { |
|
69
|
|
|
parent::__construct( $mainModule, $moduleName ); |
|
70
|
|
|
|
|
71
|
|
|
$this->errorReporter = $errorReporter; |
|
72
|
|
|
$this->statementChangeOpFactory = $statementChangeOpFactory; |
|
73
|
|
|
$this->modificationHelper = $modificationHelper; |
|
74
|
|
|
$this->guidParser = $guidParser; |
|
75
|
|
|
$this->resultBuilder = $resultBuilderInstantiator( $this ); |
|
76
|
|
|
$this->entitySavingHelper = $entitySavingHelperInstantiator( $this ); |
|
77
|
|
|
$this->federatedPropertiesEnabled = $federatedPropertiesEnabled; |
|
78
|
|
|
} |
|
79
|
|
|
|
|
80
|
|
|
public static function factory( ApiMain $mainModule, string $moduleName ): self { |
|
81
|
|
|
$wikibaseRepo = WikibaseRepo::getDefaultInstance(); |
|
82
|
|
|
$apiHelperFactory = $wikibaseRepo->getApiHelperFactory( $mainModule->getContext() ); |
|
83
|
|
|
$changeOpFactoryProvider = $wikibaseRepo->getChangeOpFactoryProvider(); |
|
84
|
|
|
|
|
85
|
|
|
$modificationHelper = new StatementModificationHelper( |
|
86
|
|
|
$wikibaseRepo->getSnakFactory(), |
|
87
|
|
|
$wikibaseRepo->getEntityIdParser(), |
|
88
|
|
|
$wikibaseRepo->getStatementGuidValidator(), |
|
89
|
|
|
$apiHelperFactory->getErrorReporter( $mainModule ) |
|
90
|
|
|
); |
|
91
|
|
|
|
|
92
|
|
|
return new self( |
|
93
|
|
|
$mainModule, |
|
94
|
|
|
$moduleName, |
|
95
|
|
|
$apiHelperFactory->getErrorReporter( $mainModule ), |
|
96
|
|
|
$changeOpFactoryProvider->getStatementChangeOpFactory(), |
|
97
|
|
|
$modificationHelper, |
|
98
|
|
|
$wikibaseRepo->getStatementGuidParser(), |
|
99
|
|
|
function ( $module ) use ( $apiHelperFactory ) { |
|
100
|
|
|
return $apiHelperFactory->getResultBuilder( $module ); |
|
101
|
|
|
}, |
|
102
|
|
|
function ( $module ) use ( $apiHelperFactory ) { |
|
103
|
|
|
return $apiHelperFactory->getEntitySavingHelper( $module ); |
|
104
|
|
|
}, |
|
105
|
|
|
$wikibaseRepo->inFederatedPropertyMode() |
|
106
|
|
|
); |
|
107
|
|
|
} |
|
108
|
|
|
|
|
109
|
|
|
/** |
|
110
|
|
|
* @inheritDoc |
|
111
|
|
|
*/ |
|
112
|
|
|
public function execute(): void { |
|
113
|
|
|
$params = $this->extractRequestParams(); |
|
114
|
|
|
$this->validateParameters( $params ); |
|
115
|
|
|
|
|
116
|
|
|
$guid = $params['statement']; |
|
117
|
|
|
$entityId = $this->guidParser->parse( $guid )->getEntityId(); |
|
118
|
|
|
|
|
119
|
|
|
$this->validateAlteringEntityById( $entityId ); |
|
120
|
|
|
|
|
121
|
|
|
$entity = $this->entitySavingHelper->loadEntity( $entityId ); |
|
122
|
|
|
$summary = $this->modificationHelper->createSummary( $params, $this ); |
|
123
|
|
|
|
|
124
|
|
|
$claim = $this->modificationHelper->getStatementFromEntity( $guid, $entity ); |
|
125
|
|
|
|
|
126
|
|
|
if ( !( $claim instanceof Statement ) ) { |
|
127
|
|
|
$this->errorReporter->dieError( |
|
|
|
|
|
|
128
|
|
|
'The referenced claim is not a statement and thus cannot have references', |
|
129
|
|
|
'not-statement' |
|
130
|
|
|
); |
|
131
|
|
|
} |
|
132
|
|
|
|
|
133
|
|
|
$referenceHashes = $this->getReferenceHashesFromParams( $params, $claim ); |
|
134
|
|
|
|
|
135
|
|
|
$changeOps = new ChangeOps(); |
|
136
|
|
|
$changeOps->add( $this->getChangeOps( $guid, $referenceHashes ) ); |
|
137
|
|
|
|
|
138
|
|
|
try { |
|
139
|
|
|
$changeOps->apply( $entity, $summary ); |
|
140
|
|
|
} catch ( ChangeOpException $e ) { |
|
141
|
|
|
$this->errorReporter->dieException( $e, 'failed-save' ); |
|
142
|
|
|
} |
|
143
|
|
|
|
|
144
|
|
|
$status = $this->entitySavingHelper->attemptSaveEntity( $entity, $summary ); |
|
145
|
|
|
$this->resultBuilder->addRevisionIdFromStatusToResult( $status, 'pageinfo' ); |
|
146
|
|
|
$this->resultBuilder->markSuccess(); |
|
147
|
|
|
} |
|
148
|
|
|
|
|
149
|
|
|
private function validateParameters( array $params ): void { |
|
150
|
|
|
if ( !( $this->modificationHelper->validateStatementGuid( $params['statement'] ) ) ) { |
|
151
|
|
|
$this->errorReporter->dieError( 'Invalid claim guid', 'invalid-guid' ); |
|
|
|
|
|
|
152
|
|
|
} |
|
153
|
|
|
} |
|
154
|
|
|
|
|
155
|
|
|
/** |
|
156
|
|
|
* @param string $guid |
|
157
|
|
|
* @param string[] $referenceHashes |
|
158
|
|
|
* |
|
159
|
|
|
* @return ChangeOp[] |
|
160
|
|
|
*/ |
|
161
|
|
|
private function getChangeOps( string $guid, array $referenceHashes ): array { |
|
162
|
|
|
$changeOps = []; |
|
163
|
|
|
|
|
164
|
|
|
foreach ( $referenceHashes as $referenceHash ) { |
|
165
|
|
|
$changeOps[] = $this->statementChangeOpFactory->newRemoveReferenceOp( $guid, $referenceHash ); |
|
166
|
|
|
} |
|
167
|
|
|
|
|
168
|
|
|
return $changeOps; |
|
169
|
|
|
} |
|
170
|
|
|
|
|
171
|
|
|
/** |
|
172
|
|
|
* @param array $params |
|
173
|
|
|
* @param Statement $statement |
|
174
|
|
|
* |
|
175
|
|
|
* @return string[] |
|
176
|
|
|
*/ |
|
177
|
|
|
private function getReferenceHashesFromParams( array $params, Statement $statement ): array { |
|
178
|
|
|
$references = $statement->getReferences(); |
|
179
|
|
|
$hashes = []; |
|
180
|
|
|
|
|
181
|
|
|
foreach ( array_unique( $params['references'] ) as $referenceHash ) { |
|
182
|
|
|
if ( !$references->hasReferenceHash( $referenceHash ) ) { |
|
183
|
|
|
$this->errorReporter->dieError( 'Invalid reference hash', 'no-such-reference' ); |
|
|
|
|
|
|
184
|
|
|
} |
|
185
|
|
|
$hashes[] = $referenceHash; |
|
186
|
|
|
} |
|
187
|
|
|
|
|
188
|
|
|
return $hashes; |
|
189
|
|
|
} |
|
190
|
|
|
|
|
191
|
|
|
/** |
|
192
|
|
|
* @inheritDoc |
|
193
|
|
|
*/ |
|
194
|
|
|
public function isWriteMode(): bool { |
|
195
|
|
|
return true; |
|
196
|
|
|
} |
|
197
|
|
|
|
|
198
|
|
|
/** |
|
199
|
|
|
* @see ApiBase::needsToken |
|
200
|
|
|
* |
|
201
|
|
|
* @return string |
|
202
|
|
|
*/ |
|
203
|
|
|
public function needsToken(): string { |
|
204
|
|
|
return 'csrf'; |
|
205
|
|
|
} |
|
206
|
|
|
|
|
207
|
|
|
/** |
|
208
|
|
|
* @inheritDoc |
|
209
|
|
|
*/ |
|
210
|
|
|
protected function getAllowedParams(): array { |
|
211
|
|
|
return array_merge( |
|
212
|
|
|
[ |
|
213
|
|
|
'statement' => [ |
|
214
|
|
|
self::PARAM_TYPE => 'string', |
|
215
|
|
|
self::PARAM_REQUIRED => true, |
|
216
|
|
|
], |
|
217
|
|
|
'references' => [ |
|
218
|
|
|
self::PARAM_TYPE => 'string', |
|
219
|
|
|
self::PARAM_REQUIRED => true, |
|
220
|
|
|
self::PARAM_ISMULTI => true, |
|
221
|
|
|
], |
|
222
|
|
|
'summary' => [ |
|
223
|
|
|
self::PARAM_TYPE => 'string', |
|
224
|
|
|
], |
|
225
|
|
|
'tags' => [ |
|
226
|
|
|
self::PARAM_TYPE => 'tags', |
|
227
|
|
|
self::PARAM_ISMULTI => true, |
|
228
|
|
|
], |
|
229
|
|
|
'token' => null, |
|
230
|
|
|
'baserevid' => [ |
|
231
|
|
|
self::PARAM_TYPE => 'integer', |
|
232
|
|
|
], |
|
233
|
|
|
'bot' => false, |
|
234
|
|
|
], |
|
235
|
|
|
parent::getAllowedParams() |
|
236
|
|
|
); |
|
237
|
|
|
} |
|
238
|
|
|
|
|
239
|
|
|
/** |
|
240
|
|
|
* @inheritDoc |
|
241
|
|
|
*/ |
|
242
|
|
|
protected function getExamplesMessages(): array { |
|
243
|
|
|
return [ |
|
244
|
|
|
'action=wbremovereferences&statement=Q42$D8404CDA-25E4-4334-AF13-A3290BCD9C0F' |
|
245
|
|
|
. '&references=455481eeac76e6a8af71a6b493c073d54788e7e9&token=foobar' |
|
246
|
|
|
. '&baserevid=7201010' |
|
247
|
|
|
=> 'apihelp-wbremovereferences-example-1', |
|
248
|
|
|
]; |
|
249
|
|
|
} |
|
250
|
|
|
|
|
251
|
|
|
} |
|
252
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.