InfoActionHookHandler::__construct()   A
last analyzed

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 Wikibase\Client\Hooks;
4
5
use Html;
6
use IContextSource;
7
use MediaWiki\Hook\InfoActionHook;
8
use Title;
9
use Wikibase\Client\NamespaceChecker;
10
use Wikibase\Client\RepoLinker;
11
use Wikibase\Client\Store\DescriptionLookup;
12
use Wikibase\Client\Usage\UsageLookup;
13
use Wikibase\Client\WikibaseClient;
14
use Wikibase\DataModel\Entity\EntityIdParser;
15
use Wikibase\DataModel\Entity\ItemId;
16
use Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookupFactory;
17
use Wikibase\Lib\Store\SiteLinkLookup;
18
19
/**
20
 * @license GPL-2.0-or-later
21
 * @author Katie Filbert < [email protected] >
22
 */
23
class InfoActionHookHandler implements InfoActionHook {
24
25
	/**
26
	 * @var NamespaceChecker
27
	 */
28
	private $namespaceChecker;
29
30
	/**
31
	 * @var RepoLinker
32
	 */
33
	private $repoLinker;
34
35
	/**
36
	 * @var SiteLinkLookup
37
	 */
38
	private $siteLinkLookup;
39
40
	/**
41
	 * @var string
42
	 */
43
	private $siteId;
44
45
	/**
46
	 * @var UsageLookup
47
	 */
48
	private $usageLookup;
49
50
	/**
51
	 * @var LanguageFallbackLabelDescriptionLookupFactory
52
	 */
53
	private $labelDescriptionLookupFactory;
54
55
	/**
56
	 * @var EntityIdParser
57
	 */
58
	private $idParser;
59
60
	/**
61
	 * @var DescriptionLookup
62
	 */
63
	private $descriptionLookup;
64
65
	public function __construct(
66
		NamespaceChecker $namespaceChecker,
67
		RepoLinker $repoLinker,
68
		SiteLinkLookup $siteLinkLookup,
69
		$siteId,
70
		UsageLookup $usageLookup,
71
		LanguageFallbackLabelDescriptionLookupFactory $labelDescriptionLookupFactory,
72
		EntityIdParser $idParser,
73
		DescriptionLookup $descriptionLookup
74
	) {
75
		$this->namespaceChecker = $namespaceChecker;
76
		$this->repoLinker = $repoLinker;
77
		$this->siteLinkLookup = $siteLinkLookup;
78
		$this->siteId = $siteId;
79
		$this->usageLookup = $usageLookup;
80
		$this->labelDescriptionLookupFactory = $labelDescriptionLookupFactory;
81
		$this->idParser = $idParser;
82
		$this->descriptionLookup = $descriptionLookup;
83
	}
84
85
	public static function factory(): self {
86
		$wikibaseClient = WikibaseClient::getDefaultInstance();
87
		$settings = $wikibaseClient->getSettings();
88
89
		$namespaceChecker = $wikibaseClient->getNamespaceChecker();
90
		$usageLookup = $wikibaseClient->getStore()->getUsageLookup();
91
		$labelDescriptionLookupFactory = new LanguageFallbackLabelDescriptionLookupFactory(
92
			$wikibaseClient->getLanguageFallbackChainFactory(),
93
			$wikibaseClient->getTermLookup(),
94
			$wikibaseClient->getTermBuffer()
95
		);
96
		$idParser = $wikibaseClient->getEntityIdParser();
97
		$descriptionLookup = $wikibaseClient->getDescriptionLookup();
98
99
		return new self(
100
			$namespaceChecker,
101
			$wikibaseClient->newRepoLinker(),
102
			$wikibaseClient->getStore()->getSiteLinkLookup(),
103
			$settings->getSetting( 'siteGlobalID' ),
104
			$usageLookup,
105
			$labelDescriptionLookupFactory,
106
			$idParser,
107
			$descriptionLookup
108
		);
109
	}
110
111
	/**
112
	 * Adds the Entity ID of the corresponding Wikidata item in action=info
113
	 *
114
	 * @param IContextSource $context
115
	 * @param array[] &$pageInfo
116
	 */
117
	public function onInfoAction( $context, &$pageInfo ) {
118
		// Check if wikibase namespace is enabled
119
		$title = $context->getTitle();
120
		$usage = $this->usageLookup->getUsagesForPage( $title->getArticleID() );
121
		$localDescription = $this->descriptionLookup->getDescription( $title,
122
			DescriptionLookup::SOURCE_LOCAL );
123
		$centralDescription = $this->descriptionLookup->getDescription( $title,
124
			DescriptionLookup::SOURCE_CENTRAL );
125
126
		if ( $this->namespaceChecker->isWikibaseEnabled( $title->getNamespace() ) && $title->exists() ) {
127
			$pageInfo['header-basic'][] = $this->getPageInfoRow( $context, $title );
128
		}
129
		if ( $localDescription ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $localDescription of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
130
			$pageInfo['header-basic'][] = $this->getDescriptionInfoRow( $context, $localDescription,
131
				DescriptionLookup::SOURCE_LOCAL );
132
		}
133
		if ( $centralDescription ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $centralDescription of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
134
			$pageInfo['header-basic'][] = $this->getDescriptionInfoRow( $context, $centralDescription,
135
				DescriptionLookup::SOURCE_CENTRAL );
136
		}
137
138
		if ( $usage ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $usage of type Wikibase\Client\Usage\EntityUsage[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
139
			$pageInfo['header-properties'][] = $this->formatEntityUsage( $context, $usage );
140
		}
141
	}
142
143
	/**
144
	 * @param IContextSource $context
145
	 * @param Title $title
146
	 *
147
	 * @return string[]
148
	 */
149
	private function getPageInfoRow( IContextSource $context, Title $title ) {
150
		$entityId = $this->siteLinkLookup->getItemIdForLink(
151
			$this->siteId,
152
			$title->getPrefixedText()
153
		);
154
155
		$row = $entityId ? $this->getItemPageInfo( $context, $entityId )
156
			: $this->getUnconnectedItemPageInfo( $context );
157
158
		return $row;
159
	}
160
161
	/**
162
	 * @param IContextSource $context
163
	 * @param string $description
164
	 * @param string $source
165
	 *
166
	 * @return string[]
167
	 */
168
	private function getDescriptionInfoRow( $context, $description, $source ) {
169
		return [
170
			// messages: wikibase-pageinfo-description-local, wikibase-pageinfo-description-central
171
			$context->msg( 'wikibase-pageinfo-description-' . $source )->parse(),
172
			$description
173
		];
174
	}
175
176
	/**
177
	 * Creating a Repo link with Item ID as anchor text
178
	 *
179
	 * @param IContextSource $context
180
	 * @param ItemId $itemId
181
	 *
182
	 * @return string[]
183
	 */
184
	private function getItemPageInfo( IContextSource $context, ItemId $itemId ) {
185
		$itemLink = $this->repoLinker->buildEntityLink(
186
			$itemId,
187
			[ 'external' ]
188
		);
189
190
		return [
191
			$context->msg( 'wikibase-pageinfo-entity-id' )->parse(),
192
			$itemLink
193
		];
194
	}
195
196
	/**
197
	 * @param IContextSource $context
198
	 *
199
	 * @return string[]
200
	 */
201
	private function getUnconnectedItemPageInfo( IContextSource $context ) {
202
		return [
203
			$context->msg( 'wikibase-pageinfo-entity-id' )->parse(),
204
			$context->msg( 'wikibase-pageinfo-entity-id-none' )->parse()
205
		];
206
	}
207
208
	/**
209
	 * @param string[][] $aspects
210
	 * @param IContextSource $context
211
	 * @return string
212
	 */
213
	private function formatAspects( array $aspects, IContextSource $context ) {
214
		$aspectContent = '';
215
		foreach ( $aspects as $aspect ) {
216
			// Possible messages:
217
			//   wikibase-pageinfo-entity-usage-L
218
			//   wikibase-pageinfo-entity-usage-L-with-modifier
219
			//   wikibase-pageinfo-entity-usage-D
220
			//   wikibase-pageinfo-entity-usage-D-with-modifier
221
			//   wikibase-pageinfo-entity-usage-C
222
			//   wikibase-pageinfo-entity-usage-C-with-modifier
223
			//   wikibase-pageinfo-entity-usage-S
224
			//   wikibase-pageinfo-entity-usage-T
225
			//   wikibase-pageinfo-entity-usage-X
226
			//   wikibase-pageinfo-entity-usage-O
227
			$msgKey = 'wikibase-pageinfo-entity-usage-' . $aspect[0];
228
			if ( $aspect[1] !== null ) {
229
				$msgKey .= '-with-modifier';
230
			}
231
			$aspectContent .= Html::rawElement(
232
				'li',
233
				[],
234
				$context->msg( $msgKey, $aspect[1] )->parse()
235
			);
236
		}
237
		return $aspectContent;
238
	}
239
240
	/**
241
	 * @param IContextSource $context
242
	 * @param array $usage
243
	 *
244
	 * @return string[]
245
	 */
246
	private function formatEntityUsage( IContextSource $context, array $usage ) {
247
		$usageAspectsByEntity = [];
248
		$entities = [];
249
		foreach ( $usage as $entityUsage ) {
250
			$entityId = $entityUsage->getEntityId()->getSerialization();
251
			$entities[$entityId] = $entityUsage->getEntityId();
252
			$usageAspectsByEntity[$entityId][] = [
253
				$entityUsage->getAspect(),
254
				$entityUsage->getModifier()
255
			];
256
		}
257
		$output = '';
258
		$entityIds = array_map(
259
			function( $entityId ) {
260
				return $this->idParser->parse( $entityId );
261
			},
262
			array_keys( $usageAspectsByEntity )
263
		);
264
		$labelLookup = $this->labelDescriptionLookupFactory->newLabelDescriptionLookup(
265
			$context->getLanguage(),
266
			$entityIds
267
		);
268
		foreach ( $usageAspectsByEntity as $entityId => $aspects ) {
269
			$label = $labelLookup->getLabel( $this->idParser->parse( $entityId ) );
270
			$text = $label === null ? $entityId : $label->getText();
271
272
			$output .= Html::rawElement( 'li', [],
273
				$this->repoLinker->buildEntityLink(
274
					$entities[$entityId],
275
					[ 'external' ],
276
					$text
277
				)
278
			);
279
280
			$aspectContent = $this->formatAspects( $aspects, $context );
281
			$output .= Html::rawElement( 'ul', [], $aspectContent );
282
		}
283
		$output = Html::rawElement( 'ul', [], $output );
284
		return [ $context->msg( 'wikibase-pageinfo-entity-usage' )->parse(), $output ];
285
	}
286
287
}
288