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 $this->parent->request
135 );
136
137 return implode( "\n", $styles );
138 }
139
145 private function getCssUrl() {
146 return Html::linkedStyle( $this->parent->getUrl( [ 'css' => 1 ] ) );
147 }
148
149 public function flush() {
150 if ( !$this->headerDone ) {
151 $this->outputHeader();
152 }
153 if ( !$this->redirectTarget && strlen( $this->contents ) ) {
154 echo $this->contents;
155 flush();
156 $this->contents = '';
157 }
158 }
159
164 private function getLanguage() {
165 return RequestContext::getMain()->getLanguage();
166 }
167
171 public function getHeadAttribs() {
172 return [
173 'dir' => $this->getLanguage()->getDir(),
174 'lang' => $this->getLanguage()->getHtmlCode(),
175 ];
176 }
177
183 public function headerDone() {
184 return $this->headerDone;
185 }
186
187 public function outputHeader() {
188 $this->headerDone = true;
189 $this->parent->request->response()->header( 'Content-Type: text/html; charset=utf-8' );
190 $this->parent->request->response()->header( 'X-Frame-Options: DENY' );
191
192 $cspPolicy = "default-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'none';" .
193 " script-src 'self' 'nonce-" . $this->getCSPNonce() . "';" .
194 " img-src 'self'; frame-src 'self'; base-uri 'none'";
195
196 $this->parent->request->response()->header( 'Content-Security-Policy: ' . $cspPolicy );
197
198 if ( $this->redirectTarget ) {
199 $this->parent->request->response()->header( 'Location: ' . $this->redirectTarget );
200
201 return;
202 }
203?>
204<?php echo Html::htmlHeader( $this->getHeadAttribs() ); ?>
205
206<head>
207 <meta name="robots" content="noindex, nofollow" />
208 <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
209 <title><?php $this->outputTitle(); ?></title>
210 <?php echo $this->getCodex() . "\n"; ?>
211 <?php echo $this->getCssUrl() . "\n"; ?>
212 <?php echo $this->getJQuery() . "\n"; ?>
213 <?php echo Html::linkedScript( 'config.js' ) . "\n"; ?>
214</head>
215
216<?php echo Html::openElement( 'body', [ 'class' => $this->getLanguage()->getDir() ] ) . "\n"; ?>
217<div id="mw-page-base"></div>
218<div id="mw-head-base"></div>
219<div id="content" class="mw-body" role="main">
220<div id="bodyContent" class="mw-body-content">
221
222<h1><?php $this->outputTitle(); ?></h1>
223<?php
224 }
225
226 public function outputFooter() {
227?>
228
229</div></div>
230
231<aside id="mw-panel">
232 <div class="portal" id="p-logo">
233 <a href="https://www.mediawiki.org/" title="Main Page"></a>
234 </div>
235<?php
236 // @phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact
237 $message = wfMessage( 'config-sidebar' )->plain();
238 // Section 1: External links
239 // @todo FIXME: Migrate to plain link label messages (T227297).
240 foreach ( explode( '----', $message ) as $section ) {
241 echo '<div class="portal"><div class="body">';
242 echo $this->parent->parse( $section, true );
243 echo '</div></div>';
244 }
245 // Section 2: Installer pages
246 echo '<div class="portal"><div class="body"><ul>';
247 foreach ( [
248 'config-sidebar-relnotes' => 'ReleaseNotes',
249 'config-sidebar-license' => 'Copying',
250 'config-sidebar-upgrade' => 'UpgradeDoc',
251 ] as $msgKey => $pageName ) {
252 echo $this->parent->makeLinkItem(
253 $this->parent->getDocUrl( $pageName ),
254 wfMessage( $msgKey )->text()
255 );
256 }
257 echo '</ul></div></div>';
258 // @phpcs:enable
259?>
260</aside>
261
262<?php
263 echo Html::closeElement( 'body' ) . Html::closeElement( 'html' );
264 }
265
266 public function outputTitle() {
267 echo wfMessage( 'config-title', MW_VERSION )->escaped();
268 }
269
273 public function getJQuery() {
274 return Html::linkedScript( "../resources/lib/jquery/jquery.js" );
275 }
276
280 public function getCodex() {
281 return Html::linkedStyle( "../resources/lib/codex/codex.style.css" );
282 }
283
290 public function getCSPNonce() {
291 static $nonce;
292 if ( $nonce === null ) {
293 // Spec says at least 16 bytes. Do 18 so it encodes evenly in base64
294 $nonce = base64_encode( random_bytes( 18 ) );
295 }
296 return $nonce;
297 }
298}
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:32
ResourceLoader is a loading system for JavaScript and CSS resources.
Module for skin stylesheets.