MediaWiki master
PHPVersionCheck.php
Go to the documentation of this file.
1<?php
7// phpcs:disable Generic.Arrays.DisallowLongArraySyntax,PSR2.Classes.PropertyDeclaration,MediaWiki.Usage.DirUsage
8// phpcs:disable Squiz.Scope.MemberVarScope.Missing,Squiz.Scope.MethodScope.Missing
9// phpcs:disable MediaWiki.Usage.StaticClosure.StaticClosure
23 var $mwVersion = '1.46';
24
27 'mb_substr' => 'mbstring',
28 'xml_parser_create' => 'xml',
29 'ctype_digit' => 'ctype',
30 'json_decode' => 'json',
31 'iconv' => 'iconv',
32 'mime_content_type' => 'fileinfo',
33 'intl_is_failure' => 'intl',
34 );
35
39 var $format = 'text';
40
44 var $scriptPath = '/';
45
51 function setFormat( $format ) {
52 $this->format = $format;
53 }
54
61 $this->scriptPath = $scriptPath;
62 }
63
68 // This value should match the PHP version specified in composer.json,
69 // .phan/config.php, and ScopeStructureTest.php
70 $minimumVersion = '8.2.0';
71
85 $knownBad = array(
86 );
87
88 $passes = version_compare( PHP_VERSION, $minimumVersion, '>=' );
89
90 $versionString = "PHP $minimumVersion or higher";
91
92 // Left as a programmatic check to make it easier to update.
93 if ( count( $knownBad ) ) {
94 $versionString .= ' (and not ' . implode( ', ', array_values( $knownBad ) ) . ')';
95
96 foreach ( $knownBad as $range ) {
97 // As we don't have composer at this point, we have to do our own version range checking.
98 if ( strpos( $range, '-' ) ) {
99 $passes = $passes && !(
100 version_compare( PHP_VERSION, trim( strstr( $range, '-', true ) ), '>=' )
101 && version_compare( PHP_VERSION, trim( substr( strstr( $range, '-', false ), 1 ) ), '<' )
102 );
103 } else {
104 $passes = $passes && version_compare( PHP_VERSION, trim( $range ), '<>' );
105 }
106 }
107 }
108
109 if ( !$passes ) {
110 $cliText = "Error: You are using an unsupported PHP version (PHP " . PHP_VERSION . ").\n"
111 . "MediaWiki $this->mwVersion needs $versionString.\n\nCheck if you might have a newer "
112 . "PHP executable with a different name.\n\n";
113
114 $web = array();
115 $web['intro'] = "MediaWiki $this->mwVersion requires $versionString; you are using PHP "
116 . PHP_VERSION . ".";
117
118 $web['longTitle'] = "Supported PHP versions";
119 // phpcs:disable Generic.Files.LineLength
120 $web['longHtml'] = <<<HTML
121 <p>
122 Please consider <a href="https://www.php.net/downloads.php">upgrading your copy of PHP</a>.
123 PHP versions less than v8.2.0 are no longer <a href="https://www.php.net/supported-versions.php">supported</a>
124 by the PHP Group and will not receive security or bugfix updates.
125 </p>
126 <p>
127 If for some reason you are unable to upgrade your PHP version, you will need to
128 <a href="https://www.mediawiki.org/wiki/Download">download</a> an older version of
129 MediaWiki from our website. See our
130 <a href="https://www.mediawiki.org/wiki/Compatibility#PHP">compatibility page</a>
131 for details of which versions are compatible with prior versions of PHP.
132 </p>
133HTML;
134 // phpcs:enable Generic.Files.LineLength
135 $this->triggerError(
136 $web,
137 $cliText
138 );
139 }
140 }
141
146 if ( !file_exists( dirname( __FILE__ ) . '/../vendor/autoload.php' ) ) {
147 $cliText = "Error: You are missing some dependencies. \n"
148 . "MediaWiki has dependencies that need to be installed via Composer\n"
149 . "or from a separate repository. Please see\n"
150 . "https://www.mediawiki.org/wiki/Download_from_Git#Fetch_external_libraries\n"
151 . "for help with installing them.";
152
153 $web = array();
154 $web['intro'] = "Installing some dependencies is required.";
155 $web['longTitle'] = 'Dependencies';
156 // phpcs:disable Generic.Files.LineLength
157 $web['longHtml'] = <<<HTML
158 <p>
159 MediaWiki has dependencies that need to be installed via Composer
160 or from a separate repository. Please see the
161 <a href="https://www.mediawiki.org/wiki/Download_from_Git#Fetch_external_libraries">instructions
162 for installing external libraries</a> on MediaWiki.org.
163 </p>
164HTML;
165 // phpcs:enable Generic.Files.LineLength
166
167 $this->triggerError( $web, $cliText );
168 }
169 }
170
175 $missingExtensions = array();
176 foreach ( $this->functionsExtensionsMapping as $function => $extension ) {
177 if ( !function_exists( $function ) ) {
178 $missingExtensions[] = array( $extension );
179 }
180 }
181
182 // Special case: either of those is required, but only on 32-bit systems (T391169)
183 if ( PHP_INT_SIZE < 8 && !extension_loaded( 'gmp' ) && !extension_loaded( 'bcmath' ) ) {
184 $missingExtensions[] = array( 'bcmath', 'gmp' );
185 }
186
187 if ( $missingExtensions ) {
188 $missingExtText = '';
189 $missingExtHtml = '';
190 $baseUrl = 'https://www.php.net';
191 foreach ( $missingExtensions as $extNames ) {
192 $plaintextLinks = array();
193 $htmlLinks = array();
194 foreach ( $extNames as $ext ) {
195 $plaintextLinks[] = "$ext <$baseUrl/$ext>";
196 $htmlLinks[] = "<b>$ext</b> (<a href=\"$baseUrl/$ext\">more information</a>)";
197 }
198
199 $missingExtText .= ' * ' . implode( ' or ', $plaintextLinks ) . "\n";
200 $missingExtHtml .= "<li>" . implode( ' or ', $htmlLinks ) . "</li>";
201 }
202
203 $cliText = "Error: Missing one or more required PHP extensions. Please see\n"
204 . "https://www.mediawiki.org/wiki/Manual:Installation_requirements#PHP\n"
205 . "for help with installing them.\n"
206 . "Please install or enable:\n" . $missingExtText;
207
208 $web = array();
209 $web['intro'] = "Installing some PHP extensions is required.";
210 $web['longTitle'] = 'Required PHP extensions';
211 $web['longHtml'] = <<<HTML
212 <p>
213 You are missing one or more extensions to PHP that MediaWiki requires to run. Please see the
214 <a href="https://www.mediawiki.org/wiki/Manual:Installation_requirements#PHP">PHP
215 installation requirements</a> on MediaWiki.org.
216 </p>
217 <p>Please install or enable:</p>
218 <ul>
219 $missingExtHtml
220 </ul>
221HTML;
222
223 $this->triggerError( $web, $cliText );
224 }
225 }
226
230 function outputHTMLHeader() {
231 $protocol = isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
232
233 header( "$protocol 500 MediaWiki configuration Error" );
234 // Don't cache error pages! They cause no end of trouble...
235 header( 'Cache-Control: no-cache' );
236 }
237
246 function getIndexErrorOutput( $introText, $longTitle, $longHtml ) {
247 $encLogo =
248 htmlspecialchars( str_replace( '//', '/', $this->scriptPath . '/' ) .
249 'resources/assets/mediawiki.png' );
250
251 $introHtml = htmlspecialchars( $introText );
252 $longTitleHtml = htmlspecialchars( $longTitle );
253
254 header( 'Content-type: text/html; charset=UTF-8' );
255
256 $finalOutput = <<<HTML
257<!DOCTYPE html>
258<html lang="en" dir="ltr">
259 <head>
260 <meta charset="UTF-8" />
261 <title>MediaWiki {$this->mwVersion}</title>
262 <style media="screen">
263 body {
264 color: #000;
265 background-color: #fff;
266 font-family: sans-serif;
267 padding: 2em;
268 text-align: center;
269 }
270 p, img, h1, h2, ul {
271 text-align: left;
272 margin: 0.5em 0 1em;
273 }
274 h1 {
275 font-size: 120%;
276 }
277 h2 {
278 font-size: 110%;
279 }
280 </style>
281 </head>
282 <body>
283 <img src="{$encLogo}" alt="The MediaWiki logo" />
284 <h1>MediaWiki {$this->mwVersion} internal error</h1>
285 <p>
286 {$introHtml}
287 </p>
288 <h2>{$longTitleHtml}</h2>
289 {$longHtml}
290 </body>
291</html>
292HTML;
293
294 return $finalOutput;
295 }
296
311 function triggerError( $web, $cliText ) {
312 if ( $this->format === 'html' ) {
313 // Used by index.php and mw-config/index.php
314 $this->outputHTMLHeader();
315 $finalOutput = $this->getIndexErrorOutput(
316 $web['intro'],
317 $web['longTitle'],
318 $web['longHtml']
319 );
320 } else {
321 // Used by Maintenance.php (CLI)
322 $finalOutput = $cliText;
323 }
324
325 echo "$finalOutput\n";
326 die( 1 );
327 }
328}
329
337function wfEntryPointCheck( $format = 'text', $scriptPath = '/' ) {
338 $phpVersionCheck = new PHPVersionCheck();
339 $phpVersionCheck->setFormat( $format );
340 $phpVersionCheck->setScriptPath( $scriptPath );
341 $phpVersionCheck->checkRequiredPHPVersion();
342 $phpVersionCheck->checkVendorExistence();
343 $phpVersionCheck->checkExtensionExistence();
344}
wfEntryPointCheck( $format='text', $scriptPath='/')
Check PHP version and that external dependencies are installed, and display an informative error if e...
Check PHP Version, as well as for composer dependencies in entry points, and display something vaguel...
setFormat( $format)
Set the format used for errors.
string $mwVersion
The number of the MediaWiki version used.
outputHTMLHeader()
Output headers that prevents error pages to be cached.
setScriptPath( $scriptPath)
Set the script path used for images in HTML-formatted errors.
triggerError( $web, $cliText)
Display something vaguely comprehensible in the event of a totally unrecoverable error.
getIndexErrorOutput( $introText, $longTitle, $longHtml)
Returns an error page, which is suitable for output to the end user via a web browser.
checkExtensionExistence()
Displays an error, if a PHP extension does not exist.
checkRequiredPHPVersion()
Displays an error, if the installed PHP version does not meet the minimum requirement.
string[] $functionsExtensionsMapping
A mapping of PHP functions to PHP extensions.
checkVendorExistence()
Displays an error, if the vendor/autoload.php file could not be found.
string $format
The format used for errors.
Helper trait for implementations \DAO.