This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | declare( strict_types = 1 ); |
||
4 | |||
5 | namespace Wikibase\Repo\Api; |
||
6 | |||
7 | use ApiBase; |
||
8 | use ApiMain; |
||
9 | use Deserializers\Exceptions\DeserializationException; |
||
10 | use Wikibase\DataModel\DeserializerFactory; |
||
11 | use Wikibase\DataModel\Reference; |
||
12 | use Wikibase\DataModel\Services\Statement\StatementGuidParser; |
||
13 | use Wikibase\DataModel\Snak\SnakList; |
||
14 | use Wikibase\DataModel\Statement\Statement; |
||
15 | use Wikibase\Repo\ChangeOp\ChangeOp; |
||
16 | use Wikibase\Repo\ChangeOp\StatementChangeOpFactory; |
||
17 | use Wikibase\Repo\WikibaseRepo; |
||
18 | |||
19 | /** |
||
20 | * API module for creating a reference or setting the value of an existing one. |
||
21 | * |
||
22 | * @license GPL-2.0-or-later |
||
23 | * @author Jeroen De Dauw < [email protected] > |
||
24 | * @author Tobias Gritschacher < [email protected] > |
||
25 | */ |
||
26 | class SetReference extends ApiBase { |
||
27 | |||
28 | use FederatedPropertyApiValidatorTrait; |
||
29 | |||
30 | /** |
||
31 | * @var StatementChangeOpFactory |
||
32 | */ |
||
33 | private $statementChangeOpFactory; |
||
34 | |||
35 | /** |
||
36 | * @var ApiErrorReporter |
||
37 | */ |
||
38 | protected $errorReporter; |
||
39 | |||
40 | /** |
||
41 | * @var DeserializerFactory |
||
42 | */ |
||
43 | private $deserializerFactory; |
||
44 | |||
45 | /** |
||
46 | * @var StatementModificationHelper |
||
47 | */ |
||
48 | private $modificationHelper; |
||
49 | |||
50 | /** |
||
51 | * @var StatementGuidParser |
||
52 | */ |
||
53 | private $guidParser; |
||
54 | |||
55 | /** |
||
56 | * @var ResultBuilder |
||
57 | */ |
||
58 | private $resultBuilder; |
||
59 | |||
60 | /** |
||
61 | * @var EntitySavingHelper |
||
62 | */ |
||
63 | private $entitySavingHelper; |
||
64 | |||
65 | public function __construct( |
||
66 | ApiMain $mainModule, |
||
67 | string $moduleName, |
||
68 | DeserializerFactory $deserializerFactory, |
||
69 | ApiErrorReporter $errorReporter, |
||
70 | StatementChangeOpFactory $statementChangeOpFactory, |
||
71 | StatementModificationHelper $modificationHelper, |
||
72 | StatementGuidParser $guidParser, |
||
73 | callable $resultBuilderInstantiator, |
||
74 | callable $entitySavingHelperInstantiator, |
||
75 | bool $federatedPropertiesEnabled |
||
76 | ) { |
||
77 | parent::__construct( $mainModule, $moduleName ); |
||
78 | |||
79 | $this->deserializerFactory = $deserializerFactory; |
||
80 | $this->errorReporter = $errorReporter; |
||
81 | $this->statementChangeOpFactory = $statementChangeOpFactory; |
||
82 | $this->modificationHelper = $modificationHelper; |
||
83 | $this->guidParser = $guidParser; |
||
84 | $this->resultBuilder = $resultBuilderInstantiator( $this ); |
||
85 | $this->entitySavingHelper = $entitySavingHelperInstantiator( $this ); |
||
86 | $this->federatedPropertiesEnabled = $federatedPropertiesEnabled; |
||
87 | } |
||
88 | |||
89 | public static function factory( ApiMain $mainModule, string $moduleName ): self { |
||
90 | $wikibaseRepo = WikibaseRepo::getDefaultInstance(); |
||
91 | $apiHelperFactory = $wikibaseRepo->getApiHelperFactory( $mainModule->getContext() ); |
||
92 | $changeOpFactoryProvider = $wikibaseRepo->getChangeOpFactoryProvider(); |
||
93 | |||
94 | $modificationHelper = new StatementModificationHelper( |
||
95 | $wikibaseRepo->getSnakFactory(), |
||
96 | $wikibaseRepo->getEntityIdParser(), |
||
97 | $wikibaseRepo->getStatementGuidValidator(), |
||
98 | $apiHelperFactory->getErrorReporter( $mainModule ) |
||
99 | ); |
||
100 | |||
101 | return new self( |
||
102 | $mainModule, |
||
103 | $moduleName, |
||
104 | $wikibaseRepo->getBaseDataModelDeserializerFactory(), |
||
105 | $apiHelperFactory->getErrorReporter( $mainModule ), |
||
106 | $changeOpFactoryProvider->getStatementChangeOpFactory(), |
||
107 | $modificationHelper, |
||
108 | $wikibaseRepo->getStatementGuidParser(), |
||
109 | function ( $module ) use ( $apiHelperFactory ) { |
||
110 | return $apiHelperFactory->getResultBuilder( $module ); |
||
111 | }, |
||
112 | function ( $module ) use ( $apiHelperFactory ) { |
||
113 | return $apiHelperFactory->getEntitySavingHelper( $module ); |
||
114 | }, |
||
115 | $wikibaseRepo->inFederatedPropertyMode() |
||
116 | ); |
||
117 | } |
||
118 | |||
119 | /** |
||
120 | * @inheritDoc |
||
121 | */ |
||
122 | public function execute(): void { |
||
123 | $params = $this->extractRequestParams(); |
||
124 | $this->validateParameters( $params ); |
||
125 | |||
126 | $entityId = $this->guidParser->parse( $params['statement'] )->getEntityId(); |
||
127 | $this->validateAlteringEntityById( $entityId ); |
||
128 | |||
129 | $entity = $this->entitySavingHelper->loadEntity( $entityId ); |
||
130 | |||
131 | $summary = $this->modificationHelper->createSummary( $params, $this ); |
||
132 | |||
133 | $claim = $this->modificationHelper->getStatementFromEntity( $params['statement'], $entity ); |
||
134 | |||
135 | if ( isset( $params['reference'] ) ) { |
||
136 | $this->validateReferenceHash( $claim, $params['reference'] ); |
||
137 | } |
||
138 | |||
139 | if ( isset( $params['snaks-order' ] ) ) { |
||
140 | $snaksOrder = $this->getArrayFromParam( $params['snaks-order'], 'snaks-order' ); |
||
141 | } else { |
||
142 | $snaksOrder = []; |
||
143 | } |
||
144 | |||
145 | $deserializer = $this->deserializerFactory->newSnakListDeserializer(); |
||
146 | /** @var SnakList $snakList */ |
||
147 | try { |
||
148 | $snakList = $deserializer->deserialize( $this->getArrayFromParam( $params['snaks'], 'snaks' ) ); |
||
149 | } catch ( DeserializationException $e ) { |
||
150 | $this->errorReporter->dieError( |
||
0 ignored issues
–
show
|
|||
151 | 'Failed to get reference from reference Serialization ' . $e->getMessage(), |
||
152 | 'snak-instantiation-failure' |
||
153 | ); |
||
154 | } |
||
155 | $snakList->orderByProperty( $snaksOrder ); |
||
156 | |||
157 | $newReference = new Reference( $snakList ); |
||
158 | |||
159 | $changeOp = $this->getChangeOp( $newReference ); |
||
160 | $this->modificationHelper->applyChangeOp( $changeOp, $entity, $summary ); |
||
161 | |||
162 | $status = $this->entitySavingHelper->attemptSaveEntity( $entity, $summary ); |
||
163 | $this->resultBuilder->addRevisionIdFromStatusToResult( $status, 'pageinfo' ); |
||
164 | $this->resultBuilder->markSuccess(); |
||
165 | $this->resultBuilder->addReference( $newReference ); |
||
166 | } |
||
167 | |||
168 | private function validateParameters( array $params ): void { |
||
169 | if ( !( $this->modificationHelper->validateStatementGuid( $params['statement'] ) ) ) { |
||
170 | $this->errorReporter->dieError( 'Invalid claim guid', 'invalid-guid' ); |
||
0 ignored issues
–
show
The method
Wikibase\Repo\Api\ApiErrorReporter::dieError() has been deprecated with message: Use dieWithError() instead.
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. ![]() |
|||
171 | } |
||
172 | } |
||
173 | |||
174 | private function validateReferenceHash( Statement $statement, string $referenceHash ): void { |
||
175 | if ( !$statement->getReferences()->hasReferenceHash( $referenceHash ) ) { |
||
176 | $this->errorReporter->dieError( |
||
0 ignored issues
–
show
The method
Wikibase\Repo\Api\ApiErrorReporter::dieError() has been deprecated with message: Use dieWithError() instead.
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. ![]() |
|||
177 | 'Statement does not have a reference with the given hash', |
||
178 | 'no-such-reference' |
||
179 | ); |
||
180 | } |
||
181 | } |
||
182 | |||
183 | private function getArrayFromParam( string $arrayParam, string $parameter ): array { |
||
184 | $rawArray = json_decode( $arrayParam, true ); |
||
185 | |||
186 | if ( !is_array( $rawArray ) || !count( $rawArray ) ) { |
||
187 | $this->errorReporter->dieError( |
||
0 ignored issues
–
show
The method
Wikibase\Repo\Api\ApiErrorReporter::dieError() has been deprecated with message: Use dieWithError() instead.
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. ![]() |
|||
188 | 'No array or invalid JSON given for parameter: ' . $parameter, |
||
189 | 'invalid-json' |
||
190 | ); |
||
191 | } |
||
192 | |||
193 | return $rawArray; |
||
194 | } |
||
195 | |||
196 | private function getChangeOp( Reference $reference ): ChangeOp { |
||
197 | $params = $this->extractRequestParams(); |
||
198 | |||
199 | $guid = $params['statement']; |
||
200 | $hash = $params['reference'] ?? ''; |
||
201 | $index = $params['index'] ?? null; |
||
202 | |||
203 | return $this->statementChangeOpFactory->newSetReferenceOp( $guid, $reference, $hash, $index ); |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * @inheritDoc |
||
208 | */ |
||
209 | public function isWriteMode(): bool { |
||
210 | return true; |
||
211 | } |
||
212 | |||
213 | /** |
||
214 | * @see ApiBase::needsToken |
||
215 | * |
||
216 | * @return string |
||
217 | */ |
||
218 | public function needsToken(): string { |
||
219 | return 'csrf'; |
||
220 | } |
||
221 | |||
222 | /** |
||
223 | * @inheritDoc |
||
224 | */ |
||
225 | protected function getAllowedParams(): array { |
||
226 | return array_merge( |
||
227 | [ |
||
228 | 'statement' => [ |
||
229 | self::PARAM_TYPE => 'string', |
||
230 | self::PARAM_REQUIRED => true, |
||
231 | ], |
||
232 | 'snaks' => [ |
||
233 | self::PARAM_TYPE => 'text', |
||
234 | self::PARAM_REQUIRED => true, |
||
235 | ], |
||
236 | 'snaks-order' => [ |
||
237 | self::PARAM_TYPE => 'string', |
||
238 | ], |
||
239 | 'reference' => [ |
||
240 | self::PARAM_TYPE => 'string', |
||
241 | ], |
||
242 | 'index' => [ |
||
243 | self::PARAM_TYPE => 'integer', |
||
244 | ], |
||
245 | 'summary' => [ |
||
246 | self::PARAM_TYPE => 'string', |
||
247 | ], |
||
248 | 'tags' => [ |
||
249 | self::PARAM_TYPE => 'tags', |
||
250 | self::PARAM_ISMULTI => true, |
||
251 | ], |
||
252 | 'token' => null, |
||
253 | 'baserevid' => [ |
||
254 | self::PARAM_TYPE => 'integer', |
||
255 | ], |
||
256 | 'bot' => false, |
||
257 | ], |
||
258 | parent::getAllowedParams() |
||
259 | ); |
||
260 | } |
||
261 | |||
262 | /** |
||
263 | * @inheritDoc |
||
264 | */ |
||
265 | protected function getExamplesMessages(): array { |
||
266 | return [ |
||
267 | 'action=wbsetreference&statement=Q76$D4FDE516-F20C-4154-ADCE-7C5B609DFDFF&snaks=' |
||
268 | . '{"P212":[{"snaktype":"value","property":"P212","datavalue":{"type":"string",' |
||
269 | . '"value":"foo"}}]}&baserevid=7201010&token=foobar' |
||
270 | => 'apihelp-wbsetreference-example-1', |
||
271 | 'action=wbsetreference&statement=Q76$D4FDE516-F20C-4154-ADCE-7C5B609DFDFF' |
||
272 | . '&reference=1eb8793c002b1d9820c833d234a1b54c8e94187e&snaks=' |
||
273 | . '{"P212":[{"snaktype":"value","property":"P212","datavalue":{"type":"string",' |
||
274 | . '"value":"bar"}}]}&baserevid=7201010&token=foobar' |
||
275 | => 'apihelp-wbsetreference-example-2', |
||
276 | 'action=wbsetreference&statement=Q76$D4FDE516-F20C-4154-ADCE-7C5B609DFDFF&snaks=' |
||
277 | . '{"P212":[{"snaktype":"novalue","property":"P212"}]}' |
||
278 | . '&index=0&baserevid=7201010&token=foobar' |
||
279 | => 'apihelp-wbsetreference-example-3', |
||
280 | ]; |
||
281 | } |
||
282 | |||
283 | } |
||
284 |
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.