MediaWiki master
WebInstallerOutput.php
Go to the documentation of this file.
1<?php
2
9namespace MediaWiki\Installer;
10
11use LogicException;
19
33
39 public $parent;
40
45 private $contents = '';
46
51 private $headerDone = false;
52
57
58 public function __construct( WebInstaller $parent ) {
59 $this->parent = $parent;
60 }
61
65 public function addHTML( $html ) {
66 $this->contents .= $html;
67 $this->flush();
68 }
69
74 public function addWikiTextAsInterface( $text ) {
75 $this->addHTML( $this->parent->parse( $text ) );
76 }
77
81 public function addHTMLNoFlush( $html ) {
82 $this->contents .= $html;
83 }
84
88 public function redirect( $url ) {
89 if ( $this->headerDone ) {
90 throw new LogicException( __METHOD__ . ' called after sending headers' );
91 }
92 $this->redirectTarget = $url;
93 }
94
95 public function output() {
96 $this->flush();
97
98 if ( !$this->redirectTarget ) {
99 $this->outputFooter();
100 }
101 }
102
108 public function getCSS() {
109 $resourceLoader = MediaWikiServices::getInstance()->getResourceLoader();
110
111 $rlContext = new RL\Context( $resourceLoader, new FauxRequest( [
112 'debug' => 'true',
113 'lang' => $this->getLanguage()->getCode(),
114 'only' => 'styles',
115 ] ) );
116
117 $module = new RL\SkinModule( [
118 'features' => [
119 'elements',
120 'interface-message-box'
121 ],
122 'styles' => [
123 'mw-config/config.css',
124 ],
125 ] );
126 $module->setConfig( $resourceLoader->getConfig() );
127
128 // Based on MediaWiki\ResourceLoader\FileModule::getStyles, without the DB query
129 $styles = ResourceLoader::makeCombinedStyles(
130 $module->readStyleFiles(
131 $module->getStyleFiles( $rlContext ),
132 $rlContext
133 )
134 );
135
136 return implode( "\n", $styles );
137 }
138
144 private function getCssUrl() {
145 return Html::linkedStyle( $this->parent->getUrl( [ 'css' => 1 ] ) );
146 }
147
148 public function flush() {
149 if ( !$this->headerDone ) {
150 $this->outputHeader();
151 }
152 if ( !$this->redirectTarget && strlen( $this->contents ) ) {
153 echo $this->contents;
154 flush();
155 $this->contents = '';
156 }
157 }
158
163 private function getLanguage() {
164 return RequestContext::getMain()->getLanguage();
165 }
166
170 public function getHeadAttribs() {
171 return [
172 'dir' => $this->getLanguage()->getDir(),
173 'lang' => $this->getLanguage()->getHtmlCode(),
174 ];
175 }
176
182 public function headerDone() {
183 return $this->headerDone;
184 }
185
186 public function outputHeader() {
187 $this->headerDone = true;
188 $this->parent->request->response()->header( 'Content-Type: text/html; charset=utf-8' );
189 $this->parent->request->response()->header( 'X-Frame-Options: DENY' );
190
191 $cspPolicy = "default-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'none';" .
192 " script-src 'self' 'nonce-" . $this->getCSPNonce() . "';" .
193 " img-src 'self'; frame-src 'self'; base-uri 'none'";
194
195 $this->parent->request->response()->header( 'Content-Security-Policy: ' . $cspPolicy );
196
197 if ( $this->redirectTarget ) {
198 $this->parent->request->response()->header( 'Location: ' . $this->redirectTarget );
199
200 return;
201 }
202?>
203<?php echo Html::htmlHeader( $this->getHeadAttribs() ); ?>
204
205<head>
206 <meta name="robots" content="noindex, nofollow" />
207 <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
208 <title><?php $this->outputTitle(); ?></title>
209 <?php echo $this->getCodex() . "\n"; ?>
210 <?php echo $this->getCssUrl() . "\n"; ?>
211 <?php echo $this->getJQuery() . "\n"; ?>
212 <?php echo Html::linkedScript( 'config.js' ) . "\n"; ?>
213</head>
214
215<?php echo Html::openElement( 'body', [ 'class' => $this->getLanguage()->getDir() ] ) . "\n"; ?>
216<div id="mw-page-base"></div>
217<div id="mw-head-base"></div>
218<div id="content" class="mw-body" role="main">
219<div id="bodyContent" class="mw-body-content">
220
221<h1><?php $this->outputTitle(); ?></h1>
222<?php
223 }
224
225 public function outputFooter() {
226?>
227
228</div></div>
229
230<aside id="mw-panel">
231 <div class="portal" id="p-logo">
232 <a href="https://www.mediawiki.org/" title="Main Page"></a>
233 </div>
234<?php
235 // @phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact
236 $message = wfMessage( 'config-sidebar' )->plain();
237 // Section 1: External links
238 // @todo FIXME: Migrate to plain link label messages (T227297).
239 foreach ( explode( '----', $message ) as $section ) {
240 echo '<div class="portal"><div class="body">';
241 echo $this->parent->parse( $section, true );
242 echo '</div></div>';
243 }
244 // Section 2: Installer pages
245 echo '<div class="portal"><div class="body"><ul>';
246 foreach ( [
247 'config-sidebar-relnotes' => 'ReleaseNotes',
248 'config-sidebar-license' => 'Copying',
249 'config-sidebar-upgrade' => 'UpgradeDoc',
250 ] as $msgKey => $pageName ) {
251 echo $this->parent->makeLinkItem(
252 $this->parent->getDocUrl( $pageName ),
253 wfMessage( $msgKey )->text()
254 );
255 }
256 echo '</ul></div></div>';
257 // @phpcs:enable
258?>
259</aside>
260
261<?php
262 echo Html::closeElement( 'body' ) . Html::closeElement( 'html' );
263 }
264
265 public function outputTitle() {
266 echo wfMessage( 'config-title', MW_VERSION )->escaped();
267 }
268
272 public function getJQuery() {
273 return Html::linkedScript( "../resources/lib/jquery/jquery.js" );
274 }
275
279 public function getCodex() {
280 return Html::linkedStyle( "../resources/lib/codex/codex.style.css" );
281 }
282
289 public function getCSPNonce() {
290 static $nonce;
291 if ( $nonce === null ) {
292 // Spec says at least 16 bytes. Do 18 so it encodes evenly in base64
293 $nonce = base64_encode( random_bytes( 18 ) );
294 }
295 return $nonce;
296 }
297}
const MW_VERSION
The running version of MediaWiki.
Definition Defines.php:23
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Group all the pieces relevant to the context of a request into one instance.
This class is a collection of static functions that serve two purposes:
Definition Html.php:44
Output class modelled on OutputPage.
getCSPNonce()
Get the nonce for use with inline scripts.
headerDone()
Get whether the header has been output.
getCSS()
Get the stylesheet of the MediaWiki skin.
WebInstaller $parent
The WebInstaller object this WebInstallerOutput is used by.
Class for the core installer web interface.
Base class for language-specific code.
Definition Language.php:65
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
WebRequest clone which takes values from a provided array.
Context object that contains information about the state of a specific ResourceLoader web request.
Definition Context.php:35
ResourceLoader is a loading system for JavaScript and CSS resources.
Module for skin stylesheets.