Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Hooks
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 3
110
0.00% covered (danger)
0.00%
0 / 1
 onBeforePageDisplay
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
 onSkinAddFooterLinks
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 onApiMaxLagInfo
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3namespace WikidataOrg;
4
5use ExtensionRegistry;
6use MediaWiki\Api\Hook\ApiMaxLagInfoHook;
7use MediaWiki\Hook\BeforePageDisplayHook;
8use MediaWiki\Hook\SkinAddFooterLinksHook;
9use MediaWiki\Html\Html;
10use MediaWiki\MediaWikiServices;
11use MediaWiki\Output\OutputPage;
12use RuntimeException;
13use Skin;
14use Wikibase\Repo\WikibaseRepo;
15use WikidataOrg\QueryServiceLag\CacheQueryServiceLagStore;
16
17/**
18 * File defining the hook handlers for the Wikidata.org extension.
19 *
20 * @since 0.1
21 *
22 * @license GPL-2.0-or-later
23 * @author Bene* < benestar.wikimedia@gmail.com >
24 * @author Lucie-Aimée Kaffee < lucie.kaffee@wikimedia.org >
25 */
26final class Hooks implements
27    BeforePageDisplayHook,
28    ApiMaxLagInfoHook,
29    SkinAddFooterLinksHook
30{
31
32    /**
33     * Handler for the BeforePageDisplay hook, adds the
34     * wikidata-org.badges module to all entity pages.
35     *
36     * @since 0.1
37     *
38     * @param OutputPage $out
39     * @param Skin $skin
40     */
41    public function onBeforePageDisplay( $out, $skin ): void {
42        if ( !ExtensionRegistry::getInstance()->isLoaded( 'WikibaseRepository' ) ) {
43            throw new RuntimeException( 'The Wikidata.org extension requires Wikibase to be installed' );
44        }
45        $entityNamespaceLookup = WikibaseRepo::getEntityNamespaceLookup();
46
47        $ns = $out->getTitle()->getNamespace();
48        if ( $entityNamespaceLookup->isEntityNamespace( $ns ) || $ns === NS_SPECIAL ) {
49            $out->addModuleStyles( 'ext.wikidata-org.badges' );
50        }
51    }
52
53    /**
54     * Add a "Data access" link to the footer
55     *
56     * @param Skin $skin
57     * @param string $key
58     * @param array &$footerItems
59     */
60    public function onSkinAddFooterLinks(
61        Skin $skin,
62        string $key,
63        array &$footerItems
64    ) {
65        if ( $key === 'places' ) {
66            $href = Skin::makeInternalOrExternalUrl( 'Special:MyLanguage/Wikidata:Data_access' );
67            $footerItems['data-access'] = Html::element(
68                'a',
69                [ 'href' => $href ],
70                $skin->msg( 'data-access' )->text()
71            );
72        }
73    }
74
75    /**
76     * Handler for the ApiMaxLagInfo to add queryservice lag stats
77     *
78     * @see https://www.mediawiki.org/wiki/Manual:Hooks/ApiMaxLagInfo
79     *
80     * @param array &$lagInfo
81     */
82    public function onApiMaxLagInfo( &$lagInfo ): void {
83        $mw = MediaWikiServices::getInstance();
84        $config = $mw->getMainConfig();
85
86        $factor = (int)$config->get( 'WikidataOrgQueryServiceMaxLagFactor' );
87        if ( $factor <= 0 ) {
88            return;
89        }
90
91        $store = new CacheQueryServiceLagStore(
92            $mw->getMainWANObjectCache(),
93            // Need to pass TTL that is not used.. (>0)
94            1
95        );
96
97        $storedLag = $store->getLag();
98
99        if ( !$storedLag ) {
100            return;
101        }
102
103        [ $server, $lag ] = $storedLag;
104
105        $fakeDispatchLag = $lag / (float)$factor;
106        if ( $fakeDispatchLag > $lagInfo['lag'] ) {
107            $lagInfo = [
108                'host' => $server,
109                'lag' => $fakeDispatchLag,
110                'type' => 'wikibase-queryservice',
111                'queryserviceLag' => $lag,
112            ];
113        }
114    }
115
116}