Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 78
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialQrCode
0.00% covered (danger)
0.00%
0 / 78
0.00% covered (danger)
0.00%
0 / 8
182
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 alterForm
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getFormFields
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
2
 onSubmit
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
12
 isListed
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 getQrCodeHtml
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
2
 getDownloadButton
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * A special page that creates QR codes from allowed URLs
4 *
5 * @file
6 * @ingroup Extensions
7 * @license Apache-2.0
8 */
9
10namespace MediaWiki\Extension\UrlShortener;
11
12use HTMLForm;
13use MediaWiki\Config\ConfigFactory;
14use MediaWiki\Html\Html;
15use Status;
16
17class SpecialQrCode extends SpecialUrlShortener {
18
19    private int $shortenLimit;
20
21    /**
22     * @param ConfigFactory $configFactory
23     */
24    public function __construct( ConfigFactory $configFactory ) {
25        $config = $configFactory->makeConfig( 'urlshortener' );
26        $this->shortenLimit = $config->get( 'UrlShortenerQrCodeShortenLimit' );
27        parent::__construct( 'QrCode' );
28    }
29
30    /**
31     * @param string|null $par
32     */
33    public function execute( $par ) {
34        if ( !$this->getConfig()->get( 'UrlShortenerEnableQrCode' ) ) {
35            $this->setHeaders();
36            $this->getOutput()->addWikiMsg( 'urlshortener-qrcode-disabled' );
37            return;
38        }
39        parent::execute( $par );
40        $this->addHelpLink( 'Help:QrCode' );
41    }
42
43    /**
44     * @param HTMLForm $form
45     * @param string $module
46     */
47    protected function alterForm( HTMLForm $form, string $module = 'ext.urlShortener.special' ) {
48        parent::alterForm( $form, 'ext.urlShortener.qrCode.special' );
49
50        // @phan-suppress-next-line PhanRedundantCondition
51        if ( isset( $this->resultStatus ) ) {
52            // We have to use Html::rawElement() because we need to link to a data URI,
53            // which is disallowed by OOUI\Tag::isSafeUrl().
54            // @phan-suppress-next-line SecurityCheck-XSS
55            $form->addPostHtml( $this->getQrCodeHtml() );
56            // Closes the .ext-urlshortener-container element opened in parent::alterForm()
57            $form->addPostHtml( Html::closeElement( 'div' ) );
58        }
59    }
60
61    /**
62     * Generate the form used to input the URL to shorten.
63     * @return array A form definition that can be used by HTMLForm
64     */
65    protected function getFormFields() {
66        return [
67            'url' => [
68                'validation-callback' => [ $this, 'validateURL' ],
69                'required' => true,
70                'type' => 'textwithbutton',
71                'inputtype' => 'url',
72                'buttontype' => 'submit',
73                'buttondefault' => $this->msg( 'urlshortener-qrcode-form-submit' )->text(),
74                'buttonflags' => [ 'primary', 'progressive' ],
75                'buttonid' => 'mw-urlshortener-submit',
76                'name' => 'url',
77                'label-message' => 'urlshortener-qrcode-url-label',
78                'autofocus' => true,
79                'id' => 'ext-urlshortener-url-input',
80                'help' => $this->getApprovedDomainsMessage()->parse(),
81                'placeholder' => $this->msg( 'urlshortener-url-input-label' )->text(),
82            ],
83        ];
84    }
85
86    /**
87     * Process the form on POST submission.
88     *
89     * Creates the short URL and displays it back to the user.
90     *
91     * @param array $data
92     * @return bool|Status True for success, false for didn't-try, Status (with errors) on failure
93     */
94    public function onSubmit( array $data ) {
95        $out = $this->getOutput();
96        $out->enableOOUI();
97        $out->addModuleStyles( [
98            'codex-styles',
99            'ext.urlShortener.qrCode.special.styles'
100        ] );
101        if ( $data['url'] === null ) {
102            return false;
103        }
104        $status = UrlShortenerUtils::getQrCode(
105            $data['url'],
106            $this->shortenLimit,
107            $this->getUser(),
108            true
109        );
110        if ( !$status->isOK() ) {
111            return $status;
112        }
113        $this->setShortenedUrlResultField( $status->getValue() );
114        $this->resultStatus = $status;
115        return true;
116    }
117
118    /**
119     * Don't list this page if in read only mode or QR Codes are not enabled.
120     *
121     * @return bool
122     */
123    public function isListed() {
124        return parent::isListed() && $this->getConfig()->get( 'UrlShortenerEnableQrCode' );
125    }
126
127    /**
128     * Create the QR Code based on the url
129     *
130     * @return string
131     */
132    private function getQrCodeHtml(): string {
133        $qrCodeUri = $this->resultStatus->getValue()['qrcode'];
134        $qrCodeImage = Html::element( 'img', [
135            'src' => $qrCodeUri
136        ] );
137        $qrCodeNode = Html::rawElement( 'div', [
138            'class' => 'ext-urlshortener-qrcode'
139        ], $qrCodeImage );
140        return Html::rawElement(
141            'div',
142            [ 'class' => 'ext-urlshortener-qrcode-container' ],
143            $qrCodeNode . $this->getDownloadButton( $qrCodeUri )
144        );
145    }
146
147    /**
148     * @param string $qrCodeUri
149     * @return string
150     */
151    private function getDownloadButton( string $qrCodeUri ): string {
152        $downloadIcon = Html::element( 'span', [
153            'class' => 'cdx-icon cdx-icon--medium'
154        ] );
155        $classes = [
156            'ext-urlshortener-download-qr-button',
157            'cdx-button',
158            'cdx-button--fake-button',
159            'cdx-button--fake-button--enabled'
160        ];
161        $content = $downloadIcon . $this->msg( 'urlshortener-toolbox-qrcode' )->text();
162        return Html::rawElement( 'a', [
163            'class' => implode( ' ', $classes ),
164            'href' => $qrCodeUri,
165            'download' => 'qrcode.svg'
166        ], $content );
167    }
168}