Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 79
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
HTMLButtonField
0.00% covered (danger)
0.00%
0 / 78
0.00% covered (danger)
0.00%
0 / 7
650
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
72
 getInputHTML
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
30
 getInputOOUI
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
 getInputCodex
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
30
 needsLabel
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 validate
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isBadIE
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace MediaWiki\HTMLForm\Field;
4
5use MediaWiki\Context\RequestContext;
6use MediaWiki\Html\Html;
7use MediaWiki\HTMLForm\HTMLFormField;
8use MediaWiki\HTMLForm\VFormHTMLForm;
9use Message;
10
11/**
12 * Adds a generic button inline to the form. Does not do anything, you must add
13 * click handling code in JavaScript. Use a HTMLSubmitField if you merely
14 * wish to add a submit button to a form.
15 *
16 * Additional recognized configuration parameters include:
17 * - flags: OOUI flags for the button, see OOUI\FlaggedElement
18 * - buttonlabel-message: Message to use for the button display text, instead
19 *   of the value from 'default'. Overrides 'buttonlabel' and 'buttonlabel-raw'.
20 * - buttonlabel: Text to display for the button display text, instead
21 *   of the value from 'default'. Overrides 'buttonlabel-raw'.
22 * - buttonlabel-raw: HTMLto display for the button display text, instead
23 *   of the value from 'default'.
24 * - formnovalidate: Set to true if clicking this button should suppress
25 *   client-side form validation. Used in HTMLFormFieldCloner for add/remove
26 *   buttons.
27 *
28 * @stable to extend
29 * @since 1.22
30 */
31class HTMLButtonField extends HTMLFormField {
32    protected $buttonType = 'button';
33    protected $buttonLabel = null;
34
35    /** @var array Flags to add to OOUI Button widget */
36    protected $mFlags = [];
37
38    protected $mFormnovalidate = false;
39
40    /**
41     * @stable to call
42     * @inheritDoc
43     */
44    public function __construct( $info ) {
45        $info['nodata'] = true;
46
47        $this->setShowEmptyLabel( false );
48
49        parent::__construct( $info );
50
51        if ( isset( $info['flags'] ) ) {
52            $this->mFlags = $info['flags'];
53        }
54
55        if ( isset( $info['formnovalidate'] ) ) {
56            $this->mFormnovalidate = $info['formnovalidate'];
57        }
58
59        # Generate the label from a message, if possible
60        if ( isset( $info['buttonlabel-message'] ) ) {
61            $this->buttonLabel = $this->getMessage( $info['buttonlabel-message'] )->parse();
62        } elseif ( isset( $info['buttonlabel'] ) ) {
63            if ( $info['buttonlabel'] === '&#160;' || $info['buttonlabel'] === "\u{00A0}" ) {
64                // Apparently some things set &nbsp directly and in an odd format
65                $this->buttonLabel = "\u{00A0}";
66            } else {
67                $this->buttonLabel = htmlspecialchars( $info['buttonlabel'] );
68            }
69        } elseif ( isset( $info['buttonlabel-raw'] ) ) {
70            $this->buttonLabel = $info['buttonlabel-raw'];
71        }
72    }
73
74    public function getInputHTML( $value ) {
75        $flags = '';
76        $prefix = 'mw-htmlform-';
77        if ( $this->mParent instanceof VFormHTMLForm ) {
78            $prefix = 'mw-ui-';
79            // add mw-ui-button separately, so the descriptor doesn't need to set it
80            $flags .= ' ' . $prefix . 'button';
81        }
82        foreach ( $this->mFlags as $flag ) {
83            $flags .= ' ' . $prefix . $flag;
84        }
85        $attr = [
86            'class' => 'mw-htmlform-submit ' . $this->mClass . $flags,
87            'id' => $this->mID,
88            'type' => $this->buttonType,
89            'name' => $this->mName,
90            'value' => $this->getDefault(),
91            'formnovalidate' => $this->mFormnovalidate,
92        ] + $this->getAttributes( [ 'disabled', 'tabindex' ] );
93
94        if ( $this->isBadIE() ) {
95            return Html::element( 'input', $attr );
96        } else {
97            return Html::rawElement( 'button', $attr,
98                $this->buttonLabel ?: htmlspecialchars( $this->getDefault() ) );
99        }
100    }
101
102    /**
103     * Get the OOUI widget for this field.
104     * @stable to override
105     * @param string $value
106     * @return \OOUI\ButtonInputWidget
107     */
108    public function getInputOOUI( $value ) {
109        return new \OOUI\ButtonInputWidget( [
110            'name' => $this->mName,
111            'value' => $this->getDefault(),
112            'label' => !$this->isBadIE() && $this->buttonLabel
113                ? new \OOUI\HtmlSnippet( $this->buttonLabel )
114                : $this->getDefault(),
115            'type' => $this->buttonType,
116            'classes' => [ 'mw-htmlform-submit', $this->mClass ],
117            'id' => $this->mID,
118            'flags' => $this->mFlags,
119            'useInputTag' => $this->isBadIE(),
120        ] + \OOUI\Element::configFromHtmlAttributes(
121            $this->getAttributes( [ 'disabled', 'tabindex' ] )
122        ) );
123    }
124
125    public function getInputCodex( $value, $hasErrors ) {
126        $flags = [];
127        $flagClassMap = [
128            'progressive' => 'cdx-button--action-progressive',
129            'destructive' => 'cdx-button--action-destructive',
130            'primary' => 'cdx-button--weight-primary',
131            'quiet' => 'cdx-button--weight-quiet',
132        ];
133
134        foreach ( $this->mFlags as $flag ) {
135            if ( isset( $flagClassMap[$flag] ) ) {
136                $flags[] = $flagClassMap[$flag];
137            }
138        }
139
140        $buttonClasses = [ 'mw-htmlform-submit', 'cdx-button', $this->mClass ];
141        $buttonClassesAndFlags = array_merge( $buttonClasses, $flags );
142        $attr = [
143            'class' => $buttonClassesAndFlags,
144            'id' => $this->mID,
145            'type' => $this->buttonType,
146            'name' => $this->mName,
147            'value' => $this->getDefault(),
148            'formnovalidate' => $this->mFormnovalidate,
149        ] + $this->getAttributes( [ 'disabled', 'tabindex' ] );
150
151        if ( $this->isBadIE() ) {
152            return Html::element( 'input', $attr );
153        } else {
154            return Html::rawElement( 'button', $attr,
155                $this->buttonLabel ?: htmlspecialchars( $this->getDefault() ) );
156        }
157    }
158
159    /**
160     * @inheritDoc
161     * @stable to override
162     */
163    protected function needsLabel() {
164        return false;
165    }
166
167    /**
168     * Button cannot be invalid
169     * @stable to override
170     *
171     * @param string $value
172     * @param array $alldata
173     *
174     * @return bool|string|Message
175     */
176    public function validate( $value, $alldata ) {
177        return true;
178    }
179
180    /**
181     * IE<8 has bugs with <button>, so we'll need to avoid them.
182     * @return bool Whether the request is from a bad version of IE
183     */
184    private function isBadIE() {
185        $request = $this->mParent
186            ? $this->mParent->getRequest()
187            : RequestContext::getMain()->getRequest();
188        return (bool)preg_match( '/MSIE [1-7]\./i', $request->getHeader( 'User-Agent' ) );
189    }
190}
191
192/** @deprecated class alias since 1.42 */
193class_alias( HTMLButtonField::class, 'HTMLButtonField' );