Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
20.00% covered (danger)
20.00%
5 / 25
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
HTMLReCaptchaNoCaptchaField
20.00% covered (danger)
20.00%
5 / 25
50.00% covered (danger)
50.00%
1 / 2
4.05
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 getInputHTML
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Extension\ConfirmEdit\ReCaptchaNoCaptcha;
4
5use MediaWiki\Html\Html;
6use MediaWiki\HTMLForm\HTMLFormField;
7
8/**
9 * Creates a ReCaptcha v2 widget. Does not return any data; handling the data submitted by the
10 * widget is callers' responsibility.
11 */
12class HTMLReCaptchaNoCaptchaField extends HTMLFormField {
13    /** @var string Public key parameter to be passed to ReCaptcha. */
14    protected $key;
15
16    /** @var string Error returned by ReCaptcha in the previous round. */
17    protected $error;
18
19    /**
20     * Parameters:
21     * - key: (string, required) ReCaptcha public key
22     * - error: (string) ReCaptcha error from previous round
23     * @param array $params
24     */
25    public function __construct( array $params ) {
26        $params += [ 'error' => null ];
27        parent::__construct( $params );
28
29        $this->key = $params['key'];
30        $this->error = $params['error'];
31
32        $this->mName = 'g-recaptcha-response';
33    }
34
35    /** @inheritDoc */
36    public function getInputHTML( $value ) {
37        $out = $this->mParent->getOutput();
38        $lang = htmlspecialchars( urlencode( $this->mParent->getLanguage()->getCode() ) );
39
40        // Insert reCAPTCHA script, in display language, if available.
41        // Language falls back to the browser's display language.
42        // See https://developers.google.com/recaptcha/docs/faq
43        $out->addHeadItem(
44            'g-recaptchascript',
45            "<script src=\"https://www.recaptcha.net/recaptcha/api.js?hl={$lang}\" async defer></script>"
46        );
47        ReCaptchaNoCaptcha::addCSPSources( $out->getCSP() );
48
49        $output = Html::element( 'div', [
50            'class' => [
51                'g-recaptcha',
52                'mw-confirmedit-captcha-fail' => (bool)$this->error,
53            ],
54            'data-sitekey' => $this->key,
55        ] );
56        $htmlUrlencoded = htmlspecialchars( urlencode( $this->key ) );
57        $output .= <<<HTML
58<noscript>
59  <div>
60    <div style="width: 302px; height: 422px; position: relative;">
61      <div style="width: 302px; height: 422px; position: absolute;">
62        <iframe
63            src="https://www.recaptcha.net/recaptcha/api/fallback?k={$htmlUrlencoded}&hl={$lang}"
64            frameborder="0" scrolling="no"
65            style="width: 302px; height:422px; border-style: none;">
66        </iframe>
67      </div>
68    </div>
69    <div style="width: 300px; height: 60px; border-style: none;
70                bottom: 12px; left: 25px; margin: 0px; padding: 0px; right: 25px;
71                background: #f9f9f9; border: 1px solid #c1c1c1; border-radius: 3px;">
72      <textarea id="g-recaptcha-response" name="g-recaptcha-response"
73                class="g-recaptcha-response"
74                style="width: 250px; height: 40px; border: 1px solid #c1c1c1;
75                       margin: 10px 25px; padding: 0px; resize: none;" >
76      </textarea>
77    </div>
78  </div>
79</noscript>
80HTML;
81        return $output;
82    }
83}