Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 45
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
Hooks
0.00% covered (danger)
0.00%
0 / 45
0.00% covered (danger)
0.00%
0 / 7
600
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 onWebRequestPathInfoRouter
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 onRegistration
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 onBeforePageDisplay
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
20
 onSidebarBeforeOutput
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
56
 onSkinTemplateNavigation__Universal
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 getFullUrl
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * Hooks for setting up UrlShortener
4 *
5 * @file
6 * @ingroup Extensions
7 * @author Yuvi Panda, http://yuvi.in
8 * @copyright © 2014 Yuvaraj Pandian (yuvipanda@gmail.com)
9 * @license Apache-2.0
10 */
11
12namespace MediaWiki\Extension\UrlShortener;
13
14use MediaWiki\Config\ConfigException;
15use MediaWiki\Config\ConfigFactory;
16use MediaWiki\Hook\BeforePageDisplayHook;
17use MediaWiki\Hook\SidebarBeforeOutputHook;
18use MediaWiki\Hook\SkinTemplateNavigation__UniversalHook;
19use MediaWiki\Hook\WebRequestPathInfoRouterHook;
20use MediaWiki\Output\OutputPage;
21use MediaWiki\Request\PathRouter;
22use MediaWiki\SpecialPage\SpecialPage;
23use MobileContext;
24use Skin;
25use SkinTemplate;
26
27class Hooks implements
28    WebRequestPathInfoRouterHook,
29    BeforePageDisplayHook,
30    SidebarBeforeOutputHook,
31    SkinTemplateNavigation__UniversalHook
32{
33    private bool $enableSidebar;
34    private bool $enableQrCode;
35    private bool $readOnly;
36    /** @var string|false */
37    private $urlTemplate;
38    /** @phan-suppress-next-line PhanUndeclaredTypeProperty */
39    private ?MobileContext $mobileContext;
40
41    public function __construct(
42        ConfigFactory $configFactory,
43        // @phan-suppress-next-line PhanUndeclaredTypeParameter
44        ?MobileContext $mobileContext
45    ) {
46        $config = $configFactory->makeConfig( 'urlshortener' );
47        $this->enableSidebar = $config->get( 'UrlShortenerEnableSidebar' );
48        $this->enableQrCode = $config->get( 'UrlShortenerEnableQrCode' );
49        $this->readOnly = $config->get( 'UrlShortenerReadOnly' );
50        $this->urlTemplate = $config->get( 'UrlShortenerTemplate' );
51        $this->mobileContext = $mobileContext;
52    }
53
54    /**
55     * @param PathRouter $router
56     *
57     * Adds UrlShortener rules to the URL router.
58     */
59    public function onWebRequestPathInfoRouter( $router ) {
60        // If a template is set, and it is not the root, register it
61        if ( $this->urlTemplate && $this->urlTemplate !== '/$1' ) {
62            $router->add( $this->urlTemplate,
63                [ 'title' => SpecialPage::getTitleFor( 'UrlRedirector', '$1' )->getPrefixedText() ]
64            );
65        }
66    }
67
68    public static function onRegistration() {
69        global $wgUrlShortenerIdSet, $wgUrlShortenerIdMapping, $wgUrlShortenerAltPrefix;
70
71        if ( strpos( $wgUrlShortenerIdSet, $wgUrlShortenerAltPrefix ) !== false ) {
72            throw new ConfigException( 'UrlShortenerAltPrefix cannot be contained in UrlShortenerIdSet' );
73        }
74        if ( isset( $wgUrlShortenerIdMapping[ $wgUrlShortenerAltPrefix ] ) ) {
75            throw new ConfigException( 'UrlShortenerAltPrefix cannot be contained in UrlShortenerIdMapping' );
76        }
77    }
78
79    /**
80     * Load toolbar module for the sidebar link
81     *
82     * @param OutputPage $out
83     * @param Skin $skin
84     */
85    public function onBeforePageDisplay( $out, $skin ): void {
86        if ( $this->readOnly || !$this->enableSidebar || $skin->getTitle()->isSpecial( 'UrlShortener' ) ) {
87            return;
88        }
89
90        $out->addModules( 'ext.urlShortener.toolbar' );
91    }
92
93    /**
94     * Adds a link to the toolbox to Special:UrlShortener
95     *
96     * @param Skin $skin
97     * @param array &$sidebar
98     */
99    public function onSidebarBeforeOutput( $skin, &$sidebar ): void {
100        if ( $this->readOnly || ( !$this->enableSidebar && !$this->enableQrCode ) ) {
101            return;
102        }
103
104        $fullURL = self::getFullUrl( $skin );
105        if ( $this->enableSidebar && !$skin->getTitle()->isSpecial( 'UrlShortener' ) ) {
106            // Append link to generate short URL
107            $sidebar['TOOLBOX']['urlshortener'] = [
108                'id' => 't-urlshortener',
109                'href' => SpecialPage::getTitleFor( 'UrlShortener' )->getLocalURL( [ 'url' => $fullURL ] ),
110                'text' => $skin->msg( 'urlshortener-toolbox' )->text(),
111            ];
112        }
113
114        if ( $this->enableQrCode ) {
115            // Append link to download QR code
116            $sidebar['TOOLBOX']['urlshortener-qrcode'] = [
117                'id' => 't-urlshortener-qrcode',
118                'href' => SpecialPage::getTitleFor( 'QrCode' )->getLocalURL( [ 'url' => $fullURL ] ),
119                'text' => $skin->msg( 'urlshortener-toolbox-qrcode' )->text(),
120            ];
121        }
122    }
123
124    /**
125     * Display the "Download QR code" link in the Minerva overflow menu.
126     *
127     * @param SkinTemplate $sktemplate
128     * @param array &$links
129     * @phpcs:disable MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName
130     */
131    public function onSkinTemplateNavigation__Universal( $sktemplate, &$links ): void {
132        // @phan-suppress-next-line PhanUndeclaredClassMethod
133        if ( $this->enableQrCode && $this->mobileContext && $this->mobileContext->shouldDisplayMobileView() ) {
134            $fullURL = self::getFullUrl( $sktemplate );
135            $links['actions']['qrcode'] = [
136                'icon' => 'qrCode',
137                // Needs its own selector to avoid styling clashes.
138                'class' => 'ext-urlshortener-qrcode-download-minerva',
139                'href' => SpecialPage::getTitleFor( 'QrCode' )->getLocalURL( [ 'url' => $fullURL ] ),
140                'text' => $sktemplate->msg( 'urlshortener-toolbox-qrcode' )->plain(),
141            ];
142        }
143    }
144
145    /**
146     * @param Skin $skin
147     * @return string
148     */
149    private static function getFullUrl( Skin $skin ): string {
150        $query = $skin->getRequest()->getQueryValues();
151        if ( isset( $query['title'] ) ) {
152            // We already know the title
153            unset( $query['title'] );
154        }
155
156        return $skin->getTitle()->getFullURL( $query, false, PROTO_CANONICAL );
157    }
158}