Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
39.06% covered (danger)
39.06%
25 / 64
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
SkinMustache
39.06% covered (danger)
39.06%
25 / 64
0.00% covered (danger)
0.00%
0 / 5
51.24
0.00% covered (danger)
0.00%
0 / 1
 getTemplateParser
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 createTempUserBannerHTML
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
12
 generateHTML
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
2
 doEditSectionLinksHTML
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 getTemplateData
92.59% covered (success)
92.59%
25 / 27
0.00% covered (danger)
0.00%
0 / 1
5.01
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21use MediaWiki\Html\Html;
22use MediaWiki\Html\TemplateParser;
23use MediaWiki\Skin\SkinComponentTempUserBanner;
24use MediaWiki\Skin\SkinComponentUtils;
25use MediaWiki\Title\Title;
26
27/**
28 * Generic template for use with Mustache templates.
29 * @since 1.35
30 */
31class SkinMustache extends SkinTemplate {
32    /**
33     * @var TemplateParser|null
34     */
35    private $templateParser = null;
36
37    /**
38     * Get the template parser, it will be lazily created if not already set.
39     * The template directory is defined in the skin options passed to
40     * the class constructor.
41     *
42     * @return TemplateParser
43     */
44    protected function getTemplateParser() {
45        if ( $this->templateParser === null ) {
46            $this->templateParser = new TemplateParser( $this->options['templateDirectory'] );
47            // For table of contents rendering.
48            $this->templateParser->enableRecursivePartials( true );
49        }
50        return $this->templateParser;
51    }
52
53    /**
54     * Creates a banner notifying IP masked users (temporary accounts)
55     * That they are editing via a temporary account.
56     *
57     * @return string
58     */
59    private function createTempUserBannerHTML() {
60        $isSupportedSkin = $this->getOptions()['tempUserBanner'];
61        $isTempUser = $this->getUser()->isTemp();
62
63        if ( !$isSupportedSkin || !$isTempUser ) {
64            return '';
65        }
66
67        $returntoParam = SkinComponentUtils::getReturnToParam(
68            $this->getTitle(),
69            $this->getRequest(),
70            $this->getAuthority()
71        );
72
73        $tempUserBanner = new SkinComponentTempUserBanner(
74            $returntoParam,
75            $this->getContext(),
76            $this->getUser(),
77        );
78        return $tempUserBanner->getTemplateData()['html'];
79    }
80
81    /**
82     * @inheritDoc
83     * Render the associated template. The master template is assumed
84     * to be 'skin' unless `template` has been passed in the skin options
85     * to the constructor.
86     */
87    public function generateHTML() {
88        $this->setupTemplateContext();
89        $out = $this->getOutput();
90        $tp = $this->getTemplateParser();
91        $template = $this->options['template'] ?? 'skin';
92        $data = $this->getTemplateData();
93        $tempUserBannerHTML = $this->createTempUserBannerHTML();
94
95        // T259955: OutputPage::headElement must be called last (after getTemplateData)
96        // as it calls OutputPage::getRlClient, which freezes the ResourceLoader
97        // modules queue for the current page load.
98        $html = $out->headElement( $this );
99
100        $html .= $tempUserBannerHTML;
101
102        $html .= $tp->processTemplate( $template, $data );
103        $html .= $out->tailElement( $this );
104        return $html;
105    }
106
107    /**
108     * @inheritDoc
109     */
110    protected function doEditSectionLinksHTML( array $links, Language $lang ) {
111        $template = $this->getOptions()['templateSectionLinks'] ?? null;
112        if ( !$template ) {
113            return parent::doEditSectionLinksHTML( $links, $lang );
114        }
115        return $this->getTemplateParser()->processTemplate( $template, [
116            'class' => 'mw-editsection',
117            'array-links' => $links
118        ] );
119    }
120
121    /**
122     * @inheritDoc
123     * @return array Data specific for a mustache template. See parent function for common data.
124     */
125    public function getTemplateData() {
126        $out = $this->getOutput();
127        $printSource = Html::rawElement(
128            'div',
129            [
130                'class' => 'printfooter',
131                'data-nosnippet' => ''
132            ] + $this->getUserLanguageAttributes(),
133            $this->printSource()
134        );
135        $bodyContent = $out->getHTML() . "\n" . $printSource;
136
137        $newTalksHtml = $this->getNewtalks() ?: null;
138
139        $data = parent::getTemplateData() + [
140            // Array objects
141            'array-indicators' => $this->getIndicatorsData( $out->getIndicators() ),
142            // HTML strings
143            'html-site-notice' => $this->getSiteNotice() ?: null,
144            'html-user-message' => $newTalksHtml ?
145                Html::rawElement( 'div', [ 'class' => 'usermessage' ], $newTalksHtml ) : null,
146            'html-subtitle' => $this->prepareSubtitle(),
147            'html-body-content' => $this->wrapHTML( $out->getTitle(), $bodyContent ),
148            'html-categories' => $this->getCategories(),
149            'html-after-content' => $this->afterContentHook(),
150            'html-undelete-link' => $this->prepareUndeleteLink(),
151            'html-user-language-attributes' => $this->prepareUserLanguageAttributes(),
152
153            // links
154            'link-mainpage' => Title::newMainPage()->getLocalURL(),
155        ];
156
157        foreach ( $this->options['messages'] ?? [] as $message ) {
158            $data["msg-{$message}"] = $this->msg( $message )->text();
159        }
160        return $data;
161    }
162}