CreateClaim::factory()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 9.472
c 0
b 0
f 0
cc 1
nc 1
nop 2
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\Repo\ChangeOp\ChangeOpMainSnak;
11
use Wikibase\Repo\ChangeOp\StatementChangeOpFactory;
12
use Wikibase\Repo\WikibaseRepo;
13
14
/**
15
 * API module for creating claims.
16
 *
17
 * @license GPL-2.0-or-later
18
 * @author Jeroen De Dauw < [email protected] >
19
 * @author Daniel Kinzler
20
 * @author Tobias Gritschacher < [email protected] >
21
 */
22
class CreateClaim extends ApiBase {
23
24
	use FederatedPropertyApiValidatorTrait;
25
26
	/**
27
	 * @var StatementChangeOpFactory
28
	 */
29
	private $statementChangeOpFactory;
30
31
	/**
32
	 * @var ApiErrorReporter
33
	 */
34
	protected $errorReporter;
35
36
	/**
37
	 * @var StatementModificationHelper
38
	 */
39
	private $modificationHelper;
40
41
	/**
42
	 * @var ResultBuilder
43
	 */
44
	private $resultBuilder;
45
46
	/**
47
	 * @var EntitySavingHelper
48
	 */
49
	private $entitySavingHelper;
50
51
	public function __construct(
52
		ApiMain $mainModule,
53
		string $moduleName,
54
		StatementChangeOpFactory $statementChangeOpFactory,
55
		ApiErrorReporter $errorReporter,
56
		StatementModificationHelper $modificationHelper,
57
		callable $resultBuilderInstantiator,
58
		callable $entitySavingHelperInstantiator,
59
		bool $federatedPropertiesEnabled
60
	) {
61
		parent::__construct( $mainModule, $moduleName );
62
63
		$this->statementChangeOpFactory = $statementChangeOpFactory;
64
		$this->errorReporter = $errorReporter;
65
		$this->modificationHelper = $modificationHelper;
66
		$this->resultBuilder = $resultBuilderInstantiator( $this );
67
		$this->entitySavingHelper = $entitySavingHelperInstantiator( $this );
68
		$this->entitySavingHelper->setEntityIdParam( 'entity' );
69
		$this->federatedPropertiesEnabled = $federatedPropertiesEnabled;
70
	}
71
72
	public static function factory( ApiMain $mainModule, string $moduleName ): self {
73
		$wikibaseRepo = WikibaseRepo::getDefaultInstance();
74
		$changeOpFactoryProvider = $wikibaseRepo->getChangeOpFactoryProvider();
75
		$apiHelperFactory = $wikibaseRepo->getApiHelperFactory( $mainModule->getContext() );
76
		$errorReporter = $apiHelperFactory->getErrorReporter( $mainModule );
77
78
		$modificationHelper = new StatementModificationHelper(
79
			$wikibaseRepo->getSnakFactory(),
80
			$wikibaseRepo->getEntityIdParser(),
81
			$wikibaseRepo->getStatementGuidValidator(),
82
			$errorReporter
83
		);
84
85
		return new self(
86
			$mainModule,
87
			$moduleName,
88
			$changeOpFactoryProvider->getStatementChangeOpFactory(),
89
			$errorReporter,
90
			$modificationHelper,
91
			function ( $module ) use ( $apiHelperFactory ) {
92
				return $apiHelperFactory->getResultBuilder( $module );
93
			},
94
			function ( $module ) use ( $apiHelperFactory ) {
95
				return $apiHelperFactory->getEntitySavingHelper( $module );
96
			},
97
			$wikibaseRepo->inFederatedPropertyMode()
98
		);
99
	}
100
101
	/**
102
	 * @inheritDoc
103
	 */
104
	public function execute(): void {
105
		$params = $this->extractRequestParams();
106
		$this->validateParameters( $params );
107
108
		$entityId = $this->entitySavingHelper->getEntityIdFromParams( $params );
109
		$this->validateAlteringEntityById( $entityId );
110
111
		$entity = $this->entitySavingHelper->loadEntity( $entityId );
112
113
		$propertyId = $this->modificationHelper->getEntityIdFromString( $params['property'] );
114
		if ( !( $propertyId instanceof PropertyId ) ) {
115
			$this->errorReporter->dieWithError(
116
				'wikibase-api-invalid-property-id',
117
				'param-illegal'
118
			);
119
		}
120
121
		$snak = $this->modificationHelper->getSnakInstance( $params, $propertyId );
0 ignored issues
show
Compatibility introduced by
$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.

Loading history...
122
123
		$summary = $this->modificationHelper->createSummary( $params, $this );
124
125
		/** @var ChangeOpMainSnak $changeOp */
126
		$changeOp = $this->statementChangeOpFactory->newSetMainSnakOp( '', $snak );
127
128
		$this->modificationHelper->applyChangeOp( $changeOp, $entity, $summary );
129
130
		// @phan-suppress-next-line PhanUndeclaredMethod
131
		$statement = $entity->getStatements()->getFirstStatementWithGuid( $changeOp->getStatementGuid() );
132
133
		$status = $this->entitySavingHelper->attemptSaveEntity( $entity, $summary );
134
		$this->resultBuilder->addRevisionIdFromStatusToResult( $status, 'pageinfo' );
135
		$this->resultBuilder->markSuccess();
136
		$this->resultBuilder->addStatement( $statement );
137
	}
138
139
	/**
140
	 * Checks if the required parameters are set and the ones that make no sense given the
141
	 * snaktype value are not set.
142
	 *
143
	 * @param array $params
144
	 */
145
	private function validateParameters( array $params ): void {
146
		if ( $params['snaktype'] === 'value' xor isset( $params['value'] ) ) {
147
			if ( $params['snaktype'] === 'value' ) {
148
				$this->errorReporter->dieWithError(
149
					[ 'wikibase-api-claim-value-missing' ],
150
					'param-missing'
151
				);
152
			} else {
153
				$this->errorReporter->dieWithError(
154
					[ 'wikibase-api-claim-value-unexpected' ],
155
					'param-illegal'
156
				);
157
			}
158
		}
159
160
		if ( !isset( $params['property'] ) ) {
161
			$this->errorReporter->dieWithError(
162
				[ 'wikibase-api-param-missing', 'property' ],
163
				'param-missing'
164
			);
165
		}
166
167
		if ( isset( $params['value'] ) && json_decode( $params['value'], true ) === null ) {
168
			$this->errorReporter->dieWithError(
169
				[ 'wikibase-api-invalid-snak' ],
170
				'invalid-snak'
171
			);
172
		}
173
	}
174
175
	/**
176
	 * @inheritDoc
177
	 */
178
	public function isWriteMode(): bool {
179
		return true;
180
	}
181
182
	/**
183
	 * @see ApiBase::needsToken
184
	 *
185
	 * @return string
186
	 */
187
	public function needsToken(): string {
188
		return 'csrf';
189
	}
190
191
	/**
192
	 * @inheritDoc
193
	 */
194
	protected function getAllowedParams(): array {
195
		return array_merge(
196
			[
197
				'entity' => [
198
					self::PARAM_TYPE => 'string',
199
					self::PARAM_REQUIRED => true,
200
				],
201
				'snaktype' => [
202
					self::PARAM_TYPE => [ 'value', 'novalue', 'somevalue' ],
203
					self::PARAM_REQUIRED => true,
204
				],
205
				'property' => [
206
					self::PARAM_TYPE => 'string',
207
					self::PARAM_REQUIRED => true,
208
				],
209
				'value' => [
210
					self::PARAM_TYPE => 'text',
211
					self::PARAM_REQUIRED => false,
212
				],
213
				'summary' => [
214
					self::PARAM_TYPE => 'string',
215
				],
216
				'tags' => [
217
					self::PARAM_TYPE => 'tags',
218
					self::PARAM_ISMULTI => true,
219
				],
220
				'token' => null,
221
				'baserevid' => [
222
					self::PARAM_TYPE => 'integer',
223
				],
224
				'bot' => false,
225
			],
226
			parent::getAllowedParams()
227
		);
228
	}
229
230
	/**
231
	 * @inheritDoc
232
	 */
233
	protected function getExamplesMessages(): array {
234
		return [
235
			'action=wbcreateclaim&entity=Q42&property=P9001&snaktype=novalue'
236
				=> 'apihelp-wbcreateclaim-example-1',
237
			'action=wbcreateclaim&entity=Q42&property=P9002&snaktype=value&value="itsastring"'
238
				=> 'apihelp-wbcreateclaim-example-2',
239
			'action=wbcreateclaim&entity=Q42&property=P9003&snaktype=value&value='
240
				. '{"entity-type":"item","numeric-id":1}'
241
				=> 'apihelp-wbcreateclaim-example-3',
242
			'action=wbcreateclaim&entity=Q42&property=P9004&snaktype=value&value='
243
				. '{"latitude":40.748433,"longitude":-73.985656,'
244
				. '"globe":"http://www.wikidata.org/entity/Q2","precision":0.000001}'
245
				=> 'apihelp-wbcreateclaim-example-4',
246
		];
247
	}
248
249
}
250