MediaWiki REL1_37
SpecialExpandTemplates.php
Go to the documentation of this file.
1<?php
26
34
36 protected $generateXML;
37
40
42 protected $removeComments;
43
45 protected $removeNowiki;
46
48 private const MAX_INCLUDE_SIZE = 50000000;
49
51 private $parser;
52
55
57 private $tidy;
58
64 public function __construct(
68 ) {
69 parent::__construct( 'ExpandTemplates' );
70 $this->parser = $parser;
71 $this->userOptionsLookup = $userOptionsLookup;
72 $this->tidy = $tidy;
73 }
74
79 public function execute( $subpage ) {
80 $this->setHeaders();
81 $this->addHelpLink( 'Help:ExpandTemplates' );
82
83 $request = $this->getRequest();
84 $titleStr = $request->getText( 'wpContextTitle' );
85 $title = Title::newFromText( $titleStr );
86
87 if ( !$title ) {
88 $title = $this->getPageTitle();
89 }
90 $input = $request->getText( 'wpInput' );
91 $this->generateXML = $request->getBool( 'wpGenerateXml' );
92 $this->generateRawHtml = $request->getBool( 'wpGenerateRawHtml' );
93
94 if ( strlen( $input ) ) {
95 $this->removeComments = $request->getBool( 'wpRemoveComments', false );
96 $this->removeNowiki = $request->getBool( 'wpRemoveNowiki', false );
97 $options = ParserOptions::newFromContext( $this->getContext() );
98 $options->setRemoveComments( $this->removeComments );
99 $options->setMaxIncludeSize( self::MAX_INCLUDE_SIZE );
100
101 if ( $this->generateXML ) {
102 $this->parser->startExternalParse( $title, $options, Parser::OT_PREPROCESS );
103 $dom = $this->parser->preprocessToDom( $input );
104
105 if ( method_exists( $dom, 'saveXML' ) ) {
106 // @phan-suppress-next-line PhanUndeclaredMethod
107 $xml = $dom->saveXML();
108 } else {
109 // @phan-suppress-next-line PhanUndeclaredMethod
110 $xml = $dom->__toString();
111 }
112 }
113
114 $output = $this->parser->preprocess( $input, $title, $options );
115 } else {
116 $this->removeComments = $request->getBool( 'wpRemoveComments', true );
117 $this->removeNowiki = $request->getBool( 'wpRemoveNowiki', false );
118 $output = false;
119 }
120
121 $out = $this->getOutput();
122
123 $this->makeForm( $titleStr, $input );
124
125 if ( $output !== false ) {
126 if ( $this->generateXML && strlen( $output ) > 0 ) {
127 $out->addHTML( $this->makeOutput( $xml, 'expand_templates_xml_output' ) );
128 }
129
130 $tmp = $this->makeOutput( $output );
131
132 if ( $this->removeNowiki ) {
133 $tmp = preg_replace(
134 [ '_&lt;nowiki&gt;_', '_&lt;/nowiki&gt;_', '_&lt;nowiki */&gt;_' ],
135 '',
136 $tmp
137 );
138 }
139
140 $config = $this->getConfig();
141
142 $tmp = $this->tidy->tidy( $tmp );
143
144 $out->addHTML( $tmp );
145
146 $pout = $this->generateHtml( $title, $output );
147 $rawhtml = $pout->getText();
148 if ( $this->generateRawHtml && strlen( $rawhtml ) > 0 ) {
149 // @phan-suppress-next-line SecurityCheck-DoubleEscaped Wanted here to display the html
150 $out->addHTML( $this->makeOutput( $rawhtml, 'expand_templates_html_output' ) );
151 }
152
153 $this->showHtmlPreview( $title, $pout, $out );
154 }
155 }
156
165 public function onSubmitInput( array $values ) {
166 $status = Status::newGood();
167 if ( !strlen( $values['input'] ) ) {
168 $status = Status::newFatal( 'expand_templates_input_missing' );
169 }
170 return $status;
171 }
172
179 private function makeForm( $title, $input ) {
180 $fields = [
181 'contexttitle' => [
182 'type' => 'text',
183 'label' => $this->msg( 'expand_templates_title' )->plain(),
184 'name' => 'wpContextTitle',
185 'id' => 'contexttitle',
186 'size' => 60,
187 'default' => $title,
188 'autofocus' => true,
189 ],
190 'input' => [
191 'type' => 'textarea',
192 'name' => 'wpInput',
193 'label' => $this->msg( 'expand_templates_input' )->text(),
194 'rows' => 10,
195 'default' => $input,
196 'id' => 'input',
197 'useeditfont' => true,
198 ],
199 'removecomments' => [
200 'type' => 'check',
201 'label' => $this->msg( 'expand_templates_remove_comments' )->text(),
202 'name' => 'wpRemoveComments',
203 'id' => 'removecomments',
204 'default' => $this->removeComments,
205 ],
206 'removenowiki' => [
207 'type' => 'check',
208 'label' => $this->msg( 'expand_templates_remove_nowiki' )->text(),
209 'name' => 'wpRemoveNowiki',
210 'id' => 'removenowiki',
211 'default' => $this->removeNowiki,
212 ],
213 'generate_xml' => [
214 'type' => 'check',
215 'label' => $this->msg( 'expand_templates_generate_xml' )->text(),
216 'name' => 'wpGenerateXml',
217 'id' => 'generate_xml',
218 'default' => $this->generateXML,
219 ],
220 'generate_rawhtml' => [
221 'type' => 'check',
222 'label' => $this->msg( 'expand_templates_generate_rawhtml' )->text(),
223 'name' => 'wpGenerateRawHtml',
224 'id' => 'generate_rawhtml',
225 'default' => $this->generateRawHtml,
226 ],
227 ];
228
229 $form = HTMLForm::factory( 'ooui', $fields, $this->getContext() );
230 $form
231 ->setSubmitTextMsg( 'expand_templates_ok' )
232 ->setWrapperLegendMsg( 'expandtemplates' )
233 ->setHeaderText( $this->msg( 'expand_templates_intro' )->parse() )
234 ->setSubmitCallback( [ $this, 'onSubmitInput' ] )
235 ->showAlways();
236 }
237
245 private function makeOutput( $output, $heading = 'expand_templates_output' ) {
246 $out = "<h2>" . $this->msg( $heading )->escaped() . "</h2>\n";
247 $out .= Xml::textarea(
248 'output',
249 $output,
250 10,
251 10,
252 [
253 'id' => 'output',
254 'readonly' => 'readonly',
255 'class' => 'mw-editfont-' . $this->userOptionsLookup->getOption( $this->getUser(), 'editfont' )
256 ]
257 );
258
259 return $out;
260 }
261
269 private function generateHtml( Title $title, $text ) {
270 $popts = ParserOptions::newFromContext( $this->getContext() );
271 $popts->setTargetLanguage( $title->getPageLanguage() );
272 return $this->parser->parse( $text, $title, $popts );
273 }
274
282 private function showHtmlPreview( Title $title, ParserOutput $pout, OutputPage $out ) {
283 $lang = $title->getPageViewLanguage();
284 $out->addHTML( "<h2>" . $this->msg( 'expand_templates_preview' )->escaped() . "</h2>\n" );
285
286 if ( $this->getConfig()->get( 'RawHtml' ) ) {
287 $request = $this->getRequest();
288 $user = $this->getUser();
289
290 // To prevent cross-site scripting attacks, don't show the preview if raw HTML is
291 // allowed and a valid edit token is not provided (T73111). However, MediaWiki
292 // does not currently provide logged-out users with CSRF protection; in that case,
293 // do not show the preview unless anonymous editing is allowed.
294 if ( $user->isAnon() && !$this->getAuthority()->isAllowed( 'edit' ) ) {
295 $error = [ 'expand_templates_preview_fail_html_anon' ];
296 } elseif ( !$user->matchEditToken( $request->getVal( 'wpEditToken' ), '', $request ) ) {
297 $error = [ 'expand_templates_preview_fail_html' ];
298 } else {
299 $error = false;
300 }
301
302 if ( $error ) {
303 $out->wrapWikiMsg( "<div class='previewnote errorbox'>\n$1\n</div>", $error );
304 return;
305 }
306 }
307
308 $out->addHTML( Html::openElement( 'div', [
309 'class' => 'mw-content-' . $lang->getDir(),
310 'dir' => $lang->getDir(),
311 'lang' => $lang->getHtmlCode(),
312 ] ) );
313 $out->addParserOutputContent( $pout );
314 $out->addHTML( Html::closeElement( 'div' ) );
315 $out->setCategoryLinks( $pout->getCategories() );
316 }
317
318 protected function getGroupName() {
319 return 'wiki';
320 }
321}
Base class for HTML cleanup utilities.
Provides access to user options.
This is one of the Core classes and should be read at least once by any new developers.
setCategoryLinks(array $categories)
Reset the category links (but not the category list) and add $categories.
wrapWikiMsg( $wrap,... $msgSpecs)
This function takes a number of message/argument specifications, wraps them in some overall structure...
addParserOutputContent(ParserOutput $parserOutput, $poOptions=[])
Add the HTML and enhancements for it (like ResourceLoader modules) associated with a ParserOutput obj...
addHTML( $text)
Append $text to the body HTML.
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
Definition Parser.php:91
const OT_PREPROCESS
Definition Parser.php:127
A special page that expands submitted templates, parser functions, and variables, allowing easier deb...
bool $generateRawHtml
Whether or not to show the raw HTML code.
__construct(Parser $parser, UserOptionsLookup $userOptionsLookup, TidyDriverBase $tidy)
bool $removeComments
Whether or not to remove comments in the expanded wikitext.
UserOptionsLookup $userOptionsLookup
onSubmitInput(array $values)
Callback for the HTMLForm used in self::makeForm.
bool $generateXML
Whether or not to show the XML parse tree.
makeForm( $title, $input)
Generate a form allowing users to enter information.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
showHtmlPreview(Title $title, ParserOutput $pout, OutputPage $out)
Wraps the provided html code in a div and outputs it to the page.
generateHtml(Title $title, $text)
Renders the supplied wikitext as html.
makeOutput( $output, $heading='expand_templates_output')
Generate a nice little box with a heading for output.
execute( $subpage)
Show the special page.
bool $removeNowiki
Whether or not to remove <nowiki> tags in the expanded wikitext.
Parent class for all special pages.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getOutput()
Get the OutputPage being used for this instance.
getUser()
Shortcut to get the User executing this instance.
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getConfig()
Shortcut to get main config object.
getRequest()
Get the WebRequest being used for this instance.
getPageTitle( $subpage=false)
Get a self-referential title object.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Represents a title within MediaWiki.
Definition Title.php:48
if(!isset( $args[0])) $lang