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 Wikibase\DataModel\Entity\PropertyId; |
||
10 | use Wikibase\DataModel\Services\Statement\StatementGuidParser; |
||
11 | use Wikibase\DataModel\Statement\Statement; |
||
12 | use Wikibase\Repo\ChangeOp\ChangeOp; |
||
13 | use Wikibase\Repo\ChangeOp\StatementChangeOpFactory; |
||
14 | use Wikibase\Repo\WikibaseRepo; |
||
15 | |||
16 | /** |
||
17 | * API module for creating a qualifier or setting the value of an existing one. |
||
18 | * |
||
19 | * @license GPL-2.0-or-later |
||
20 | * @author Jeroen De Dauw < [email protected] > |
||
21 | * @author Daniel Kinzler |
||
22 | * @author Tobias Gritschacher < [email protected] > |
||
23 | */ |
||
24 | class SetQualifier 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 | /** |
||
59 | * @param ApiMain $mainModule |
||
60 | * @param string $moduleName |
||
61 | * @param callable $errorReporterInstantiator |
||
62 | * @param StatementChangeOpFactory $statementChangeOpFactory |
||
63 | * @param StatementModificationHelper $modificationHelper |
||
64 | * @param StatementGuidParser $guidParser |
||
65 | * @param callable $resultBuilderInstantiator |
||
66 | * @param callable $entitySavingHelperInstantiator |
||
67 | * |
||
68 | * @note Using callable for several arguments because of circular dependency and unability to inject object to constructor |
||
69 | */ |
||
70 | public function __construct( |
||
71 | ApiMain $mainModule, |
||
72 | string $moduleName, |
||
73 | callable $errorReporterInstantiator, |
||
74 | StatementChangeOpFactory $statementChangeOpFactory, |
||
75 | StatementModificationHelper $modificationHelper, |
||
76 | StatementGuidParser $guidParser, |
||
77 | callable $resultBuilderInstantiator, |
||
78 | callable $entitySavingHelperInstantiator, |
||
79 | bool $federatedPropertiesEnabled |
||
80 | ) { |
||
81 | parent::__construct( $mainModule, $moduleName ); |
||
82 | |||
83 | $this->errorReporter = $errorReporterInstantiator( $this ); |
||
84 | $this->statementChangeOpFactory = $statementChangeOpFactory; |
||
85 | |||
86 | $this->modificationHelper = $modificationHelper; |
||
87 | $this->guidParser = $guidParser; |
||
88 | $this->resultBuilder = $resultBuilderInstantiator( $this ); |
||
89 | $this->entitySavingHelper = $entitySavingHelperInstantiator( $this ); |
||
90 | $this->federatedPropertiesEnabled = $federatedPropertiesEnabled; |
||
91 | } |
||
92 | |||
93 | public static function factory( ApiMain $mainModule, string $moduleName ): self { |
||
94 | $wikibaseRepo = WikibaseRepo::getDefaultInstance(); |
||
95 | $apiHelperFactory = $wikibaseRepo->getApiHelperFactory( $mainModule->getContext() ); |
||
96 | $changeOpFactoryProvider = $wikibaseRepo->getChangeOpFactoryProvider(); |
||
97 | |||
98 | $modificationHelper = new StatementModificationHelper( |
||
99 | $wikibaseRepo->getSnakFactory(), |
||
100 | $wikibaseRepo->getEntityIdParser(), |
||
101 | $wikibaseRepo->getStatementGuidValidator(), |
||
102 | $apiHelperFactory->getErrorReporter( $mainModule ) |
||
103 | ); |
||
104 | |||
105 | return new self( |
||
106 | $mainModule, |
||
107 | $moduleName, |
||
108 | function ( $module ) use ( $apiHelperFactory ) { |
||
109 | return $apiHelperFactory->getErrorReporter( $module ); |
||
110 | }, |
||
111 | $changeOpFactoryProvider->getStatementChangeOpFactory(), |
||
112 | $modificationHelper, |
||
113 | $wikibaseRepo->getStatementGuidParser(), |
||
114 | function ( $module ) use ( $apiHelperFactory ) { |
||
115 | return $apiHelperFactory->getResultBuilder( $module ); |
||
116 | }, |
||
117 | function ( $module ) use ( $apiHelperFactory ) { |
||
118 | return $apiHelperFactory->getEntitySavingHelper( $module ); |
||
119 | }, |
||
120 | $wikibaseRepo->inFederatedPropertyMode() |
||
121 | ); |
||
122 | } |
||
123 | |||
124 | /** |
||
125 | * @inheritDoc |
||
126 | */ |
||
127 | public function execute(): void { |
||
128 | $params = $this->extractRequestParams(); |
||
129 | $this->validateParameters( $params ); |
||
130 | |||
131 | $entityId = $this->guidParser->parse( $params['claim'] )->getEntityId(); |
||
132 | $this->validateAlteringEntityById( $entityId ); |
||
133 | |||
134 | $entity = $this->entitySavingHelper->loadEntity( $entityId ); |
||
135 | |||
136 | $summary = $this->modificationHelper->createSummary( $params, $this ); |
||
137 | |||
138 | $statement = $this->modificationHelper->getStatementFromEntity( $params['claim'], $entity ); |
||
139 | |||
140 | if ( isset( $params['snakhash'] ) ) { |
||
141 | $this->validateQualifierHash( $statement, $params['snakhash'] ); |
||
142 | } |
||
143 | |||
144 | $changeOp = $this->getChangeOp(); |
||
145 | $this->modificationHelper->applyChangeOp( $changeOp, $entity, $summary ); |
||
146 | |||
147 | $status = $this->entitySavingHelper->attemptSaveEntity( $entity, $summary ); |
||
148 | $this->resultBuilder->addRevisionIdFromStatusToResult( $status, 'pageinfo' ); |
||
149 | $this->resultBuilder->markSuccess(); |
||
150 | $this->resultBuilder->addStatement( $statement ); |
||
151 | } |
||
152 | |||
153 | /** |
||
154 | * Checks if the required parameters are set and the ones that make no sense given the |
||
155 | * snaktype value are not set. |
||
156 | * |
||
157 | * @param array $params |
||
158 | */ |
||
159 | private function validateParameters( array $params ): void { |
||
160 | if ( !( $this->modificationHelper->validateStatementGuid( $params['claim'] ) ) ) { |
||
161 | $this->errorReporter->dieError( 'Invalid claim guid', 'invalid-guid' ); |
||
0 ignored issues
–
show
|
|||
162 | } |
||
163 | |||
164 | if ( !isset( $params['snakhash'] ) ) { |
||
165 | if ( !isset( $params['snaktype'] ) ) { |
||
166 | $this->errorReporter->dieWithError( [ 'param-missing', 'snaktype' ], |
||
167 | 'param-missing' |
||
168 | ); |
||
169 | } |
||
170 | |||
171 | if ( !isset( $params['property'] ) ) { |
||
172 | $this->errorReporter->dieWithError( [ 'param-missing', 'property' ], |
||
173 | 'param-missing' |
||
174 | ); |
||
175 | } |
||
176 | } |
||
177 | |||
178 | if ( isset( $params['snaktype'] ) && $params['snaktype'] === 'value' && !isset( $params['value'] ) ) { |
||
179 | $this->errorReporter->dieWithError( [ 'param-missing', 'value' ], |
||
180 | 'param-missing' |
||
181 | ); |
||
182 | } |
||
183 | } |
||
184 | |||
185 | private function validateQualifierHash( Statement $statement, string $qualifierHash ): void { |
||
186 | if ( !$statement->getQualifiers()->hasSnakHash( $qualifierHash ) ) { |
||
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 | 'Claim does not have a qualifier with the given hash', |
||
189 | 'no-such-qualifier' |
||
190 | ); |
||
191 | } |
||
192 | } |
||
193 | |||
194 | private function getChangeOp(): ChangeOp { |
||
195 | $params = $this->extractRequestParams(); |
||
196 | |||
197 | $guid = $params['claim']; |
||
198 | |||
199 | $propertyId = $this->modificationHelper->getEntityIdFromString( $params['property'] ); |
||
200 | if ( !( $propertyId instanceof PropertyId ) ) { |
||
201 | $this->errorReporter->dieWithError( |
||
202 | [ 'wikibase-api-invalid-property-id', $propertyId->getSerialization() ], |
||
203 | 'param-illegal' |
||
204 | ); |
||
205 | } |
||
206 | $newQualifier = $this->modificationHelper->getSnakInstance( $params, $propertyId ); |
||
0 ignored issues
–
show
$propertyId of type object<Wikibase\DataModel\Entity\EntityId> is not a sub-type of object<Wikibase\DataModel\Entity\PropertyId> . It seems like you assume a child class of the class Wikibase\DataModel\Entity\EntityId to be always present.
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass. Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type. ![]() |
|||
207 | |||
208 | $snakHash = $params['snakhash'] ?? ''; |
||
209 | $changeOp = $this->statementChangeOpFactory->newSetQualifierOp( $guid, $newQualifier, $snakHash ); |
||
210 | |||
211 | return $changeOp; |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * @inheritDoc |
||
216 | */ |
||
217 | public function isWriteMode(): bool { |
||
218 | return true; |
||
219 | } |
||
220 | |||
221 | /** |
||
222 | * @see ApiBase::needsToken |
||
223 | * |
||
224 | * @return string |
||
225 | */ |
||
226 | public function needsToken(): string { |
||
227 | return 'csrf'; |
||
228 | } |
||
229 | |||
230 | /** |
||
231 | * @inheritDoc |
||
232 | */ |
||
233 | protected function getAllowedParams(): array { |
||
234 | return array_merge( |
||
235 | [ |
||
236 | 'claim' => [ |
||
237 | self::PARAM_TYPE => 'string', |
||
238 | self::PARAM_REQUIRED => true, |
||
239 | ], |
||
240 | 'property' => [ |
||
241 | self::PARAM_TYPE => 'string', |
||
242 | self::PARAM_REQUIRED => false, |
||
243 | ], |
||
244 | 'value' => [ |
||
245 | self::PARAM_TYPE => 'text', |
||
246 | self::PARAM_REQUIRED => false, |
||
247 | ], |
||
248 | 'snaktype' => [ |
||
249 | self::PARAM_TYPE => [ 'value', 'novalue', 'somevalue' ], |
||
250 | self::PARAM_REQUIRED => false, |
||
251 | ], |
||
252 | 'snakhash' => [ |
||
253 | self::PARAM_TYPE => 'string', |
||
254 | self::PARAM_REQUIRED => false, |
||
255 | ], |
||
256 | 'summary' => [ |
||
257 | self::PARAM_TYPE => 'string', |
||
258 | ], |
||
259 | 'tags' => [ |
||
260 | self::PARAM_TYPE => 'tags', |
||
261 | self::PARAM_ISMULTI => true, |
||
262 | ], |
||
263 | 'token' => null, |
||
264 | 'baserevid' => [ |
||
265 | self::PARAM_TYPE => 'integer', |
||
266 | ], |
||
267 | 'bot' => false, |
||
268 | ], |
||
269 | parent::getAllowedParams() |
||
270 | ); |
||
271 | } |
||
272 | |||
273 | /** |
||
274 | * @inheritDoc |
||
275 | */ |
||
276 | protected function getExamplesMessages(): array { |
||
277 | return [ |
||
278 | 'action=wbsetqualifier&claim=Q2$4554c0f4-47b2-1cd9-2db9-aa270064c9f3&property=P1' |
||
279 | . '&value="GdyjxP8I6XB3"&snaktype=value&token=foobar' |
||
280 | => 'apihelp-wbsetqualifier-example-1', |
||
281 | ]; |
||
282 | } |
||
283 | |||
284 | } |
||
285 |
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.