Completed
Push — master ( 896ba9...cef96e )
by
unknown
01:45
created

UpdateConstraintsTableJob::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
cc 1
nc 1
nop 8

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\Job;
4
5
use Config;
6
use Job;
7
use JobQueueGroup;
8
use Serializers\Serializer;
9
use Title;
10
use MediaWiki\MediaWikiServices;
11
use Wikibase\DataModel\Entity\Property;
12
use Wikibase\DataModel\Entity\PropertyId;
13
use Wikibase\DataModel\Snak\SnakList;
14
use Wikibase\DataModel\Statement\Statement;
15
use Wikibase\Lib\Store\EntityRevisionLookup;
16
use Wikibase\Repo\WikibaseRepo;
17
use Wikibase\Store;
18
use WikibaseQuality\ConstraintReport\Constraint;
19
use WikibaseQuality\ConstraintReport\ConstraintRepository;
20
use WikibaseQuality\ConstraintReport\ConstraintsServices;
21
use Wikimedia\Assert\Assert;
22
23
/**
24
 * A job that updates the constraints table
25
 * when changes were made on a property.
26
 *
27
 * @author Lucas Werkmeister
28
 * @license GPL-2.0-or-later
29
 */
30
class UpdateConstraintsTableJob extends Job {
31
32
	const BATCH_SIZE = 10;
33
34
	public static function newFromGlobalState( Title $title, array $params ) {
35
		Assert::parameterType( 'string', $params['propertyId'], '$params["propertyId"]' );
36
		$repo = WikibaseRepo::getDefaultInstance();
37
		return new UpdateConstraintsTableJob(
38
			$title,
39
			$params,
40
			$params['propertyId'],
41
			$params['revisionId'] ?? null,
42
			MediaWikiServices::getInstance()->getMainConfig(),
43
			ConstraintsServices::getConstraintRepository(),
44
			$repo->getEntityRevisionLookup( Store::LOOKUP_CACHING_DISABLED ),
45
			$repo->getBaseDataModelSerializerFactory()->newSnakSerializer()
46
		);
47
	}
48
49
	/**
50
	 * @var string
51
	 */
52
	private $propertyId;
53
54
	/**
55
	 * @var int|null
56
	 */
57
	private $revisionId;
58
59
	/**
60
	 * @var Config
61
	 */
62
	private $config;
63
64
	/**
65
	 * @var ConstraintRepository
66
	 */
67
	private $constraintRepo;
68
69
	/**
70
	 * @var EntityRevisionLookup
71
	 */
72
	private $entityRevisionLookup;
73
74
	/**
75
	 * @var Serializer
76
	 */
77
	private $snakSerializer;
78
79
	/**
80
	 * @param Title $title
81
	 * @param string[] $params should contain 'propertyId' => 'P...'
82
	 * @param string $propertyId property ID of the property for this job (which has the constraint statements)
83
	 * @param int|null $revisionId revision ID that triggered this job, if any
84
	 * @param Config $config
85
	 * @param ConstraintRepository $constraintRepo
86
	 * @param EntityRevisionLookup $entityRevisionLookup
87
	 * @param Serializer $snakSerializer
88
	 */
89
	public function __construct(
90
		Title $title,
91
		array $params,
92
		$propertyId,
93
		$revisionId,
94
		Config $config,
95
		ConstraintRepository $constraintRepo,
96
		EntityRevisionLookup $entityRevisionLookup,
97
		Serializer $snakSerializer
98
	) {
99
		parent::__construct( 'constraintsTableUpdate', $title, $params );
100
101
		$this->propertyId = $propertyId;
102
		$this->revisionId = $revisionId;
103
		$this->config = $config;
104
		$this->constraintRepo = $constraintRepo;
105
		$this->entityRevisionLookup = $entityRevisionLookup;
106
		$this->snakSerializer = $snakSerializer;
107
	}
108
109
	public function extractParametersFromQualifiers( SnakList $qualifiers ) {
110
		$parameters = [];
111
		foreach ( $qualifiers as $qualifier ) {
112
			$qualifierId = $qualifier->getPropertyId()->getSerialization();
113
			$paramSerialization = $this->snakSerializer->serialize( $qualifier );
114
			$parameters[$qualifierId][] = $paramSerialization;
115
		}
116
		return $parameters;
117
	}
118
119
	public function extractConstraintFromStatement(
120
		PropertyId $propertyId,
121
		Statement $constraintStatement
122
	) {
123
		$constraintId = $constraintStatement->getGuid();
124
		$snak = $constraintStatement->getMainSnak();
125
		'@phan-var \Wikibase\DataModel\Snak\PropertyValueSnak $snak';
126
		$dataValue = $snak->getDataValue();
127
		'@phan-var \Wikibase\DataModel\Entity\EntityIdValue $dataValue';
128
		$entityId = $dataValue->getEntityId();
129
		$constraintTypeQid = $entityId->getSerialization();
130
		$parameters = $this->extractParametersFromQualifiers( $constraintStatement->getQualifiers() );
131
		return new Constraint(
132
			$constraintId,
133
			$propertyId,
134
			$constraintTypeQid,
135
			$parameters
136
		);
137
	}
138
139
	public function importConstraintsForProperty(
140
		Property $property,
141
		ConstraintRepository $constraintRepo,
142
		PropertyId $propertyConstraintPropertyId
143
	) {
144
		$constraintsStatements = $property->getStatements()
145
			->getByPropertyId( $propertyConstraintPropertyId )
146
			->getByRank( [ Statement::RANK_PREFERRED, Statement::RANK_NORMAL ] );
147
		$constraints = [];
148
		foreach ( $constraintsStatements->getIterator() as $constraintStatement ) {
149
			$constraints[] = $this->extractConstraintFromStatement( $property->getId(), $constraintStatement );
150
			if ( count( $constraints ) >= self::BATCH_SIZE ) {
151
				$constraintRepo->insertBatch( $constraints );
152
				$constraints = [];
153
			}
154
		}
155
		$constraintRepo->insertBatch( $constraints );
156
	}
157
158
	/**
159
	 * @see Job::run
160
	 *
161
	 * @return bool
162
	 */
163
	public function run() {
164
		// TODO in the future: only touch constraints affected by the edit (requires T163465)
165
166
		$propertyId = new PropertyId( $this->propertyId );
167
		$propertyRevision = $this->entityRevisionLookup->getEntityRevision(
168
			$propertyId,
169
			0, // latest
170
			EntityRevisionLookup::LATEST_FROM_REPLICA
171
		);
172
173
		if ( $this->revisionId !== null && $propertyRevision->getRevisionId() < $this->revisionId ) {
174
			JobQueueGroup::singleton()->push( $this );
175
			return true;
176
		}
177
178
		$this->constraintRepo->deleteForProperty( $propertyId );
179
180
		/** @var Property $property */
181
		$property = $propertyRevision->getEntity();
182
		'@phan-var Property $property';
183
		$this->importConstraintsForProperty(
184
			$property,
185
			$this->constraintRepo,
186
			new PropertyId( $this->config->get( 'WBQualityConstraintsPropertyConstraintId' ) )
187
		);
188
189
		return true;
190
	}
191
192
}
193