Completed
Push — master ( 5c18d0...3ae30d )
by
unknown
05:18
created

CheckConstraints::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 18
nc 1
nop 9

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace WikibaseQuality\ConstraintReport\Api;
4
5
use ApiBase;
6
use ApiMain;
7
use IBufferingStatsdDataFactory;
8
use MediaWiki\MediaWikiServices;
9
use RequestContext;
10
use ValueFormatters\FormatterOptions;
11
use Wikibase\DataModel\Entity\EntityId;
12
use Wikibase\DataModel\Entity\EntityIdParser;
13
use Wikibase\DataModel\Entity\EntityIdParsingException;
14
use Wikibase\DataModel\Services\Statement\StatementGuidValidator;
15
use Wikibase\Lib\SnakFormatter;
16
use Wikibase\Repo\Api\ApiErrorReporter;
17
use Wikibase\Repo\Api\ApiHelperFactory;
18
use Wikibase\Repo\Api\ResultBuilder;
19
use Wikibase\Repo\EntityIdLabelFormatterFactory;
20
use Wikibase\Repo\WikibaseRepo;
21
use WikibaseQuality\ConstraintReport\ConstraintCheck\Message\MultilingualTextViolationMessageRenderer;
22
use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult;
23
use WikibaseQuality\ConstraintReport\ConstraintReportFactory;
24
25
/**
26
 * API module that performs constraint check of entities, claims and constraint ID
27
 *
28
 * @author Olga Bode
29
 * @license GPL-2.0-or-later
30
 */
31
class CheckConstraints extends ApiBase {
32
33
	const PARAM_ID = 'id';
34
	const PARAM_CLAIM_ID = 'claimid';
35
	const PARAM_CONSTRAINT_ID = 'constraintid';
36
	const PARAM_STATUS = 'status';
37
38
	/**
39
	 * @var EntityIdParser
40
	 */
41
	private $entityIdParser;
42
43
	/**
44
	 * @var StatementGuidValidator
45
	 */
46
	private $statementGuidValidator;
47
48
	/**
49
	 * @var ResultBuilder
50
	 */
51
	private $resultBuilder;
52
53
	/**
54
	 * @var ApiErrorReporter
55
	 */
56
	private $errorReporter;
57
58
	/**
59
	 * @var ResultsSource
60
	 */
61
	private $resultsSource;
62
63
	/**
64
	 * @var CheckResultsRenderer
65
	 */
66
	private $checkResultsRenderer;
67
68
	/**
69
	 * @var IBufferingStatsdDataFactory
70
	 */
71
	private $dataFactory;
72
73
	/**
74
	 * Creates new instance from global state.
75
	 *
76
	 * @param ApiMain $main
77
	 * @param string $name
78
	 * @param string $prefix
79
	 *
80
	 * @return self
81
	 */
82
	public static function newFromGlobalState( ApiMain $main, $name, $prefix = '' ) {
83
		$repo = WikibaseRepo::getDefaultInstance();
84
85
		$language = $repo->getUserLanguage();
86
		$formatterOptions = new FormatterOptions();
87
		$formatterOptions->setOption( SnakFormatter::OPT_LANG, $language->getCode() );
88
		$valueFormatterFactory = $repo->getValueFormatterFactory();
89
		$valueFormatter = $valueFormatterFactory->getValueFormatter( SnakFormatter::FORMAT_HTML, $formatterOptions );
90
91
		$languageFallbackLabelDescriptionLookupFactory = $repo->getLanguageFallbackLabelDescriptionLookupFactory();
92
		$labelDescriptionLookup = $languageFallbackLabelDescriptionLookupFactory->newLabelDescriptionLookup( $language );
93
		$entityIdHtmlLinkFormatterFactory = $repo->getEntityIdHtmlLinkFormatterFactory();
94
		$entityIdHtmlLinkFormatter = $entityIdHtmlLinkFormatterFactory->getEntityIdFormatter( $labelDescriptionLookup );
95
		$entityIdLabelFormatterFactory = new EntityIdLabelFormatterFactory();
96
		$entityIdLabelFormatter = $entityIdLabelFormatterFactory->getEntityIdFormatter( $labelDescriptionLookup );
97
		$config = MediaWikiServices::getInstance()->getMainConfig();
98
		$dataFactory = MediaWikiServices::getInstance()->getStatsdDataFactory();
99
		$constraintReportFactory = ConstraintReportFactory::getDefaultInstance();
100
101
		$checkResultsRenderer = new CheckResultsRenderer(
102
			$repo->getEntityTitleLookup(),
103
			$entityIdLabelFormatter,
104
			new MultilingualTextViolationMessageRenderer(
105
				$entityIdHtmlLinkFormatter,
106
				$valueFormatter,
107
				$main,
108
				$config
109
			),
110
			$config
111
		);
112
		$resultsSource = $constraintReportFactory->getResultsSource();
113
114
		return new CheckConstraints(
115
			$main,
116
			$name,
117
			$prefix,
118
			$repo->getEntityIdParser(),
119
			$repo->getStatementGuidValidator(),
120
			$repo->getApiHelperFactory( RequestContext::getMain() ),
121
			$resultsSource,
122
			$checkResultsRenderer,
123
			$dataFactory
124
		);
125
	}
126
127
	/**
128
	 * @param ApiMain $main
129
	 * @param string $name
130
	 * @param string $prefix
131
	 * @param EntityIdParser $entityIdParser
132
	 * @param StatementGuidValidator $statementGuidValidator
133
	 * @param ApiHelperFactory $apiHelperFactory
134
	 * @param ResultsSource $resultsSource
135
	 * @param CheckResultsRenderer $checkResultsRenderer
136
	 * @param IBufferingStatsdDataFactory $dataFactory
137
	 */
138
	public function __construct(
139
		ApiMain $main,
140
		$name,
141
		$prefix,
142
		EntityIdParser $entityIdParser,
143
		StatementGuidValidator $statementGuidValidator,
144
		ApiHelperFactory $apiHelperFactory,
145
		ResultsSource $resultsSource,
146
		CheckResultsRenderer $checkResultsRenderer,
147
		IBufferingStatsdDataFactory $dataFactory
148
	) {
149
		parent::__construct( $main, $name, $prefix );
150
		$this->entityIdParser = $entityIdParser;
151
		$this->statementGuidValidator = $statementGuidValidator;
152
		$this->resultBuilder = $apiHelperFactory->getResultBuilder( $this );
153
		$this->errorReporter = $apiHelperFactory->getErrorReporter( $this );
154
		$this->resultsSource = $resultsSource;
155
		$this->checkResultsRenderer = $checkResultsRenderer;
156
		$this->dataFactory = $dataFactory;
157
	}
158
159
	/**
160
	 * Evaluates the parameters, runs the requested constraint check, and sets up the result
161
	 */
162
	public function execute() {
163
		$this->dataFactory->increment(
164
			'wikibase.quality.constraints.api.checkConstraints.execute'
165
		);
166
167
		$params = $this->extractRequestParams();
168
169
		$this->validateParameters( $params );
170
		$entityIds = $this->parseEntityIds( $params );
171
		$claimIds = $this->parseClaimIds( $params );
172
		$constraintIDs = $params[self::PARAM_CONSTRAINT_ID];
173
		$statuses = $params[self::PARAM_STATUS];
174
175
		$this->getResult()->addValue(
176
			null,
177
			$this->getModuleName(),
178
			$this->checkResultsRenderer->render(
179
				$this->resultsSource->getResults(
180
					$entityIds,
181
					$claimIds,
182
					$constraintIDs,
183
					$statuses
184
				)
185
			)->getArray()
186
		);
187
		$this->resultBuilder->markSuccess( 1 );
188
	}
189
190
	/**
191
	 * @param array $params
192
	 *
193
	 * @return EntityId[]
194
	 */
195
	private function parseEntityIds( array $params ) {
196
		$ids = $params[self::PARAM_ID];
197
198
		if ( $ids === null ) {
199
			return [];
200
		} elseif ( $ids === [] ) {
201
			$this->errorReporter->dieError(
202
				'If ' . self::PARAM_ID . ' is specified, it must be nonempty.', 'no-data' );
203
		}
204
205
		return array_map( function ( $id ) {
206
			try {
207
				return $this->entityIdParser->parse( $id );
208
			} catch ( EntityIdParsingException $e ) {
209
				$this->errorReporter->dieError(
210
					"Invalid id: $id", 'invalid-entity-id', 0, [ self::PARAM_ID => $id ] );
211
			}
212
		}, $ids );
213
	}
214
215
	/**
216
	 * @param array $params
217
	 *
218
	 * @return string[]
219
	 */
220
	private function parseClaimIds( array $params ) {
221
		$ids = $params[self::PARAM_CLAIM_ID];
222
223
		if ( $ids === null ) {
224
			return [];
225
		} elseif ( $ids === [] ) {
226
			$this->errorReporter->dieError(
227
				'If ' . self::PARAM_CLAIM_ID . ' is specified, it must be nonempty.', 'no-data' );
228
		}
229
230
		foreach ( $ids as $id ) {
231
			if ( !$this->statementGuidValidator->validate( $id ) ) {
232
				$this->errorReporter->dieError(
233
					"Invalid claim id: $id", 'invalid-guid', 0, [ self::PARAM_CLAIM_ID => $id ] );
234
			}
235
		}
236
237
		return $ids;
238
	}
239
240
	private function validateParameters( array $params ) {
241
		if ( $params[self::PARAM_CONSTRAINT_ID] !== null
242
			 && empty( $params[self::PARAM_CONSTRAINT_ID] )
243
		) {
244
			$paramConstraintId = self::PARAM_CONSTRAINT_ID;
245
			$this->errorReporter->dieError(
246
				"If $paramConstraintId is specified, it must be nonempty.", 'no-data' );
247
		}
248
		if ( $params[self::PARAM_ID] === null && $params[self::PARAM_CLAIM_ID] === null ) {
249
			$paramId = self::PARAM_ID;
250
			$paramClaimId = self::PARAM_CLAIM_ID;
251
			$this->errorReporter->dieError(
252
				"At least one of $paramId, $paramClaimId must be specified.", 'no-data' );
253
		}
254
		// contents of PARAM_ID and PARAM_CLAIM_ID are validated by parse{Entity,Claim}Ids()
255
	}
256
257
	/**
258
	 * @return array[]
259
	 * @codeCoverageIgnore
260
	 */
261
	public function getAllowedParams() {
262
		return [
263
			self::PARAM_ID => [
264
				ApiBase::PARAM_TYPE => 'string',
265
				ApiBase::PARAM_ISMULTI => true,
266
			],
267
			self::PARAM_CLAIM_ID => [
268
				ApiBase::PARAM_TYPE => 'string',
269
				ApiBase::PARAM_ISMULTI => true,
270
			],
271
			self::PARAM_CONSTRAINT_ID => [
272
				ApiBase::PARAM_TYPE => 'string',
273
				ApiBase::PARAM_ISMULTI => true,
274
			],
275
			self::PARAM_STATUS => [
276
				ApiBase::PARAM_TYPE => [
277
					CheckResult::STATUS_COMPLIANCE,
278
					CheckResult::STATUS_VIOLATION,
279
					CheckResult::STATUS_WARNING,
280
					CheckResult::STATUS_EXCEPTION,
281
					CheckResult::STATUS_NOT_IN_SCOPE,
282
					CheckResult::STATUS_DEPRECATED,
283
					CheckResult::STATUS_BAD_PARAMETERS,
284
					CheckResult::STATUS_TODO,
285
				],
286
				ApiBase::PARAM_ISMULTI => true,
287
				ApiBase::PARAM_ALL => true,
288
				ApiBase::PARAM_DFLT => implode( '|', [
289
					CheckResult::STATUS_VIOLATION,
290
					CheckResult::STATUS_WARNING,
291
					CheckResult::STATUS_BAD_PARAMETERS,
292
				] ),
293
				ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
294
			],
295
		];
296
	}
297
298
	/**
299
	 * Returns usage examples for this module
300
	 *
301
	 * @return string[]
302
	 * @codeCoverageIgnore
303
	 */
304
	public function getExamplesMessages() {
305
		return [
306
			'action=wbcheckconstraints&id=Q5|Q42'
307
				=> 'apihelp-wbcheckconstraints-example-1',
308
			'action=wbcheckconstraints&claimid=q42%248419C20C-8EF8-4EC0-80D6-AF1CA55E7557'
309
				=> 'apihelp-wbcheckconstraints-example-2',
310
			'action=wbcheckconstraints&format=json&id=Q2&constraintid=P1082%24DA39C2DA-47DA-48FB-8A9A-DA80200FB2DB'
311
				=> 'apihelp-wbcheckconstraints-example-3',
312
		];
313
	}
314
315
}
316