Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 44 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
MissingExtensionException | |
0.00% |
0 / 44 |
|
0.00% |
0 / 5 |
210 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
renderHtml | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
20 | |||
renderText | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
render | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
getMWLogo | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
20 |
1 | <?php |
2 | use MediaWiki\Html\TemplateParser; |
3 | |
4 | /** |
5 | * Thrown when ExtensionRegistry cannot open the extension.json or skin.json file. |
6 | * |
7 | * We handle this case specially, because it is one of the more |
8 | * common errors a new MW sysadmin is likely to encounter and we |
9 | * want their initial experience to be good. wfLoadExtension() |
10 | * generally happens before MWExceptionRenderer gets installed |
11 | * so we cannot use that. |
12 | * |
13 | * @ingroup ExtensionRegistry |
14 | * @internal |
15 | */ |
16 | class MissingExtensionException extends Exception { |
17 | private bool $isSkin; |
18 | private string $extName = 'unknown'; |
19 | private string $path; |
20 | private string $error; |
21 | |
22 | /** |
23 | * @param string $path Path of file that cannot be read |
24 | * @param string $error Text of error mtime gave |
25 | */ |
26 | public function __construct( string $path, string $error ) { |
27 | $this->isSkin = str_ends_with( $path, "/skin.json" ); |
28 | $m = []; |
29 | preg_match( "!/([^/]*)/[^/]*.json$!", $path, $m ); |
30 | if ( $m ) { |
31 | $this->extName = $m[1]; |
32 | } |
33 | $this->path = $path; |
34 | $this->error = $error; |
35 | |
36 | parent::__construct( "Error Loading extension. Unable to open file $path: $error" ); |
37 | } |
38 | |
39 | /** |
40 | * Output error message as html. |
41 | * |
42 | * Avoid relying on MW stuff, as it might not be setup yet. |
43 | * We don't bother translating, as the user may not have even set lang yet. |
44 | * |
45 | */ |
46 | private function renderHtml() { |
47 | if ( !headers_sent() ) { |
48 | HttpStatus::header( 500 ); |
49 | header( 'Content-Type: text/html; charset=UTF-8' ); |
50 | } |
51 | |
52 | $templateParser = new TemplateParser( null, new EmptyBagOStuff() ); |
53 | |
54 | try { |
55 | echo $templateParser->processTemplate( |
56 | 'ExtensionConfigError', |
57 | [ |
58 | 'version' => MW_VERSION, |
59 | 'path' => $this->path, |
60 | 'type' => $this->isSkin ? 'skin' : 'extension', |
61 | 'error' => $this->error, |
62 | 'extName' => $this->extName, |
63 | 'trace' => $this->getTraceAsString(), |
64 | 'mwLogo' => $this->getMWLogo(), |
65 | ] |
66 | ); |
67 | } catch ( Exception $e ) { |
68 | echo 'Error: ' . htmlspecialchars( $e->getMessage() ); |
69 | } |
70 | } |
71 | |
72 | /** |
73 | * Render the error for CLI |
74 | */ |
75 | private function renderText() { |
76 | $type = $this->isSkin ? 'skin' : 'extension'; |
77 | echo "Error: The $this->extName $type cannot be loaded. " |
78 | . "Check that all of its files are installed properly.\n\n"; |
79 | echo $this->getTraceAsString(); |
80 | echo "\n"; |
81 | } |
82 | |
83 | /** |
84 | * Output an error response and exit. |
85 | * |
86 | * @return never |
87 | */ |
88 | public function render() { |
89 | if ( wfIsCli() ) { |
90 | $this->renderText(); |
91 | } else { |
92 | $this->renderHtml(); |
93 | } |
94 | // Make sure that the error gets into logs. |
95 | // This will also stop execution. |
96 | trigger_error( $this->getMessage(), E_USER_ERROR ); |
97 | } |
98 | |
99 | /** |
100 | * Get the url for the MW logo |
101 | * |
102 | * @return string |
103 | */ |
104 | private function getMWLogo() { |
105 | global $wgResourceBasePath; |
106 | $suffix = "/resources/assets/mediawiki.png"; |
107 | if ( $wgResourceBasePath !== null ) { |
108 | // We are early in setup, so we can't rely on this. |
109 | return $wgResourceBasePath . $suffix; |
110 | } |
111 | $path = '/'; |
112 | foreach ( array_filter( explode( '/', $_SERVER['PHP_SELF'] ) ) as $part ) { |
113 | if ( !preg_match( '/\.php$/', $part ) ) { |
114 | $path .= "$part/"; |
115 | } else { |
116 | break; |
117 | } |
118 | } |
119 | |
120 | return $path . $suffix; |
121 | } |
122 | } |