Completed
Push — master ( 951284...b5c57e )
by
unknown
06:36 queued 11s
created

includes/Hooks/SkinAfterBottomScriptsHandler.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Wikibase\Client\Hooks;
4
5
use ExtensionRegistry;
6
use File;
7
use Html;
8
use PageImages\PageImages;
9
use Title;
10
11
use Wikibase\Client\RepoLinker;
12
use Wikibase\Client\WikibaseClient;
13
use Wikibase\DataModel\Entity\EntityDocument;
14
use Wikibase\DataModel\Entity\EntityId;
15
use Wikibase\DataModel\Services\Lookup\EntityLookupException;
16
use Wikibase\DataModel\Term\FingerprintProvider;
17
18
/**
19
 * @license GPL-2.0-or-later
20
 */
21
class SkinAfterBottomScriptsHandler {
22
	/** @var WikibaseClient */
23
	private $client;
24
	/** @var RepoLinker */
25
	private $repoLinker;
26
27
	/**
28
	 * @param WikibaseClient $client
29
	 */
30
	public function __construct( WikibaseClient $client, RepoLinker $repoLinker ) {
31
		$this->client = $client;
32
		$this->repoLinker = $repoLinker;
33
	}
34
35
	/**
36
	 * @param Title $title
37
	 * @param string|null $revisionTimestamp
38
	 * @param EntityId $entityId
39
	 *
40
	 * @return string
41
	 */
42
	public function createSchemaElement(
43
		Title $title,
44
		$revisionTimestamp,
45
		EntityId $entityId
46
	) {
47
		$entityConceptUri = $this->repoLinker->getEntityConceptUri( $entityId );
48
		$imageFile = $this->queryPageImage( $title );
49
		$entityDocument = $this->lookupEntityDocument( $entityId );
50
		$description = $this->getDescription( $entityDocument );
51
		$schema = $this->createSchema(
52
			$title, $revisionTimestamp, $entityConceptUri, $imageFile, $description
53
		);
54
55
		$html = Html::openElement( 'script', [ 'type' => 'application/ld+json' ] );
56
		$html .= json_encode( $schema );
57
		$html .= Html::closeElement( 'script' );
58
		return $html;
59
	}
60
61
	/**
62
	 * @param Title $title
63
	 * @param string|null $revisionTimestamp
64
	 * @param string $entityConceptUri
65
	 * @param File|null $imageFile
66
	 * @param string|null $description
67
	 *
68
	 * @return array
69
	 */
70
	public function createSchema(
71
		Title $title,
72
		$revisionTimestamp,
73
		$entityConceptUri,
74
		File $imageFile = null,
75
		$description = null
76
		) {
77
		$schema = [
78
			'@context' => 'https://schema.org',
79
			'@type' => 'Article',
80
			'name' => $title->getText(),
81
			'url' => $title->getFullURL( '', false, PROTO_CANONICAL ),
82
			'sameAs' => $entityConceptUri,
83
			'mainEntity' => $entityConceptUri,
84
			'author' => [
85
				'@type' => 'Organization',
86
				'name' => wfMessage( 'wikibase-page-schema-author-name' )->text()
87
			],
88
			'publisher' => [
89
				'@type' => 'Organization',
90
				'name' => wfMessage( 'wikibase-page-schema-publisher-name' )->text(),
91
				'logo' => [
92
					'@type' => 'ImageObject',
93
					'url' => wfMessage( 'wikibase-page-schema-publisher-logo-url' )->text()
94
				]
95
			],
96
			'datePublished' => wfTimestamp( TS_ISO_8601, $title->getEarliestRevTime() )
97
		];
98
99
		if ( $revisionTimestamp ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $revisionTimestamp 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...
100
			$schema['dateModified'] = wfTimestamp( TS_ISO_8601, $revisionTimestamp );
101
		}
102
103
		if ( $imageFile ) {
104
			$schema['image'] = wfExpandUrl( $imageFile->getUrl(), PROTO_CANONICAL );
105
		}
106
107
		if ( $description ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $description 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...
108
			$schema['headline'] = $description;
109
		}
110
111
		return $schema;
112
	}
113
114
	/**
115
	 * @param EntityId $entityId
116
	 *
117
	 * @return EntityDocument|null
118
	 */
119
	private function lookupEntityDocument( EntityId $entityId ) {
120
		try {
121
			$entityLookup = $this->client->getStore()->getEntityLookup();
122
			return $entityLookup->getEntity( $entityId );
123
		} catch ( EntityLookupException $ex ) {
124
			return null;
125
		}
126
	}
127
128
	/**
129
	 * If available, query the canonical page image injected into the og:image meta tag. It's
130
	 * important that the schema image match the page meta image since the schema describes the page.
131
	 * @param Title $title
132
	 *
133
	 * @return File|null
134
	 */
135
	private function queryPageImage( Title $title ) {
136
		if ( !ExtensionRegistry::getInstance()->isLoaded( 'PageImages' ) ) {
137
			return null;
138
		}
139
140
		return PageImages::getPageImage( $title ) ?: null;
141
	}
142
143
	/**
144
	 * @param EntityDocument|null $entity
145
	 *
146
	 * @return string
147
	 */
148
	private function getDescription( EntityDocument $entity = null ) {
149
		if ( !$entity || !( $entity instanceof FingerprintProvider ) ) {
150
			return '';
151
		}
152
153
		$langCode = $this->client->getContentLanguage()->getCode();
154
		$fingerprint = $entity->getFingerprint();
155
		if ( !$fingerprint->hasDescription( $langCode ) ) {
156
			return '';
157
		}
158
		return $fingerprint->getDescription( $langCode )->getText();
159
	}
160
161
}
162