Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.15% covered (success)
98.15%
106 / 108
75.00% covered (warning)
75.00%
6 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
SkinComponentSearch
98.15% covered (success)
98.15%
106 / 108
75.00% covered (warning)
75.00%
6 / 8
14
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getMessageLocalizer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 msg
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getConfig
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 makeSearchInput
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 makeSearchButton
94.74% covered (success)
94.74%
18 / 19
0.00% covered (danger)
0.00%
0 / 1
5.00
 getSearchInputAttributes
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
2
 getTemplateData
98.41% covered (success)
98.41%
62 / 63
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Skin;
4
5use InvalidArgumentException;
6use MediaWiki\Config\Config;
7use MediaWiki\Html\Html;
8use MediaWiki\Linker\Linker;
9use MediaWiki\MainConfigNames;
10use MediaWiki\Message\Message;
11use MediaWiki\Title\Title;
12use MessageLocalizer;
13
14/**
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28 * http://www.gnu.org/copyleft/gpl.html
29 *
30 * @internal for use inside Skin and SkinTemplate classes only
31 */
32class SkinComponentSearch implements SkinComponent {
33    /** @var Config */
34    private $config;
35    /** @var MessageLocalizer */
36    private $localizer;
37    /** @var Title */
38    private $searchTitle;
39    /** @var array|null */
40    private $cachedData;
41
42    /**
43     * @param Config $config
44     * @param MessageLocalizer $localizer
45     * @param Title $searchTitle
46     */
47    public function __construct(
48        Config $config,
49        MessageLocalizer $localizer,
50        Title $searchTitle
51    ) {
52        $this->config = $config;
53        $this->localizer = $localizer;
54        $this->searchTitle = $searchTitle;
55        $this->cachedData = null;
56    }
57
58    /**
59     * @return MessageLocalizer
60     */
61    private function getMessageLocalizer(): MessageLocalizer {
62        return $this->localizer;
63    }
64
65    /**
66     * @param string $key
67     * @return Message
68     */
69    private function msg( string $key ): Message {
70        return $this->localizer->msg( $key );
71    }
72
73    /**
74     * @return Config
75     */
76    private function getConfig(): Config {
77        return $this->config;
78    }
79
80    /**
81     * @param array $attrs (optional) will be passed to tooltipAndAccesskeyAttribs
82     *  and decorate the resulting input
83     * @return string of HTML input
84     */
85    private function makeSearchInput( array $attrs = [] ) {
86        return Html::element( 'input', $this->getSearchInputAttributes( $attrs ) );
87    }
88
89    /**
90     * @param string $mode representing the type of button wanted
91     *  either `go` OR `fulltext`.
92     * @param array $attrs (optional)
93     * @return string of HTML button
94     */
95    private function makeSearchButton( string $mode, array $attrs = [] ) {
96        switch ( $mode ) {
97            case 'go':
98            case 'fulltext':
99                $realAttrs = [
100                    'type' => 'submit',
101                    'name' => $mode,
102                    'value' => $this->msg( $mode == 'go' ? 'searcharticle' : 'searchbutton' )->text(),
103                ];
104                $realAttrs = array_merge(
105                    $realAttrs,
106                    Linker::tooltipAndAccesskeyAttribs(
107                        "search-$mode",
108                        [],
109                        null,
110                        $this->getMessageLocalizer()
111                    ),
112                    $attrs
113                );
114                return Html::element( 'input', $realAttrs );
115            default:
116                throw new InvalidArgumentException( 'Unknown mode passed to ' . __METHOD__ );
117        }
118    }
119
120    /**
121     * @param array $attrs (optional) will be passed to tooltipAndAccesskeyAttribs
122     *  and decorate the resulting input
123     * @return array attributes of HTML input
124     */
125    private function getSearchInputAttributes( array $attrs = [] ) {
126        $autoCapHint = $this->getConfig()->get( MainConfigNames::CapitalLinks );
127        $realAttrs = [
128            'type' => 'search',
129            'name' => 'search',
130            'placeholder' => $this->msg( 'searchsuggest-search' )->text(),
131            'aria-label' => $this->msg( 'searchsuggest-search' )->text(),
132            // T251664: Disable autocapitalization of input
133            // method when using fully case-sensitive titles.
134            'autocapitalize' => $autoCapHint ? 'sentences' : 'none',
135        ];
136
137        return array_merge(
138            $realAttrs,
139            Linker::tooltipAndAccesskeyAttribs(
140                'search',
141                [],
142                null,
143                $this->getMessageLocalizer()
144            ),
145            $attrs
146        );
147    }
148
149    /**
150     * @inheritDoc
151     * Since 1.38:
152     * - string html-button-fulltext-attributes HTML attributes for usage on a button
153     *    that redirects user to a search page with the current query.
154     * - string html-button-go-attributes HTML attributes for usage on a search
155     *   button that redirects user to a title that matches the query.
156     * - string html-input-attributes HTML attributes for input on an input field
157     *    that is used to construct a search query.
158     * Since 1.35:
159     * - string form-action Where the form should post to e.g. /w/index.php
160     * - string html-button-search Search button with label
161     *    derived from `html-button-go-attributes`.
162     * - string html-button-search-fallback Search button with label
163     *    derived from `html-button-fulltext-attributes`.
164     * - string html-input An input element derived from `html-input-attributes`.
165     */
166    public function getTemplateData(): array {
167        // Optimization: Generate once.
168        if ( $this->cachedData ) {
169            return $this->cachedData;
170        }
171
172        $config = $this->getConfig();
173        $localizer = $this->getMessageLocalizer();
174        $searchButtonAttributes = [
175            'class' => 'searchButton'
176        ];
177        $fallbackButtonAttributes = [
178            'class' => 'searchButton mw-fallbackSearchButton'
179        ];
180        $buttonAttributes = [
181            'type' => 'submit',
182        ];
183
184        $searchTitle = $this->searchTitle;
185
186        $inputAttrs = $this->getSearchInputAttributes( [] );
187        $goButtonAttributes = $searchButtonAttributes + $buttonAttributes + [
188            'name' => 'go',
189        ] + Linker::tooltipAndAccesskeyAttribs(
190            'search-go',
191            [],
192            null,
193            $localizer
194        );
195        $fulltextButtonAttributes = $fallbackButtonAttributes + $buttonAttributes + [
196            'name' => 'fulltext'
197        ] + Linker::tooltipAndAccesskeyAttribs(
198            'search-fulltext',
199            [],
200            null,
201            $localizer
202        );
203
204        $this->cachedData = [
205            'search-special-page-title' => $searchTitle->getText(),
206            'form-action' => $config->get( MainConfigNames::Script ),
207            'html-button-search-fallback' => $this->makeSearchButton(
208                'fulltext',
209                $fallbackButtonAttributes + [
210                    'id' => 'mw-searchButton',
211                ]
212            ),
213            'html-button-search' => $this->makeSearchButton(
214                'go',
215                $searchButtonAttributes + [
216                    'id' => 'searchButton',
217                ]
218            ),
219            'html-input' => $this->makeSearchInput( [ 'id' => 'searchInput' ] ),
220            'msg-search' => $this->msg( 'search' )->text(),
221            'page-title' => $searchTitle->getPrefixedDBkey(),
222            'array-button-go-attributes' => $goButtonAttributes,
223            'html-button-go-attributes' => Html::expandAttributes(
224                $goButtonAttributes
225            ),
226            'array-button-fulltext-attributes' => $fulltextButtonAttributes,
227            'html-button-fulltext-attributes' => Html::expandAttributes(
228                $fulltextButtonAttributes
229            ),
230            'array-input-attributes' => $inputAttrs,
231            'html-input-attributes' => Html::expandAttributes(
232                $inputAttrs
233            ),
234        ];
235        return $this->cachedData;
236    }
237}