MediaWiki  master
SpecialExpandTemplates.php
Go to the documentation of this file.
1 <?php
25 
33 
35  protected $generateXML;
36 
38  protected $generateRawHtml;
39 
41  protected $removeComments;
42 
44  protected $removeNowiki;
45 
47  const MAX_INCLUDE_SIZE = 50000000;
48 
49  function __construct() {
50  parent::__construct( 'ExpandTemplates' );
51  }
52 
57  function execute( $subpage ) {
58  $this->setHeaders();
59  $this->addHelpLink( 'Help:ExpandTemplates' );
60 
61  $request = $this->getRequest();
62  $titleStr = $request->getText( 'wpContextTitle' );
63  $title = Title::newFromText( $titleStr );
64 
65  if ( !$title ) {
66  $title = $this->getPageTitle();
67  }
68  $input = $request->getText( 'wpInput' );
69  $this->generateXML = $request->getBool( 'wpGenerateXml' );
70  $this->generateRawHtml = $request->getBool( 'wpGenerateRawHtml' );
71 
72  if ( strlen( $input ) ) {
73  $this->removeComments = $request->getBool( 'wpRemoveComments', false );
74  $this->removeNowiki = $request->getBool( 'wpRemoveNowiki', false );
75  $options = ParserOptions::newFromContext( $this->getContext() );
76  $options->setRemoveComments( $this->removeComments );
77  $options->setTidy( true );
78  $options->setMaxIncludeSize( self::MAX_INCLUDE_SIZE );
79 
80  $parser = MediaWikiServices::getInstance()->getParser();
81  if ( $this->generateXML ) {
82  $parser->startExternalParse( $title, $options, Parser::OT_PREPROCESS );
83  $dom = $parser->preprocessToDom( $input );
84 
85  if ( method_exists( $dom, 'saveXML' ) ) {
86  // @phan-suppress-next-line PhanUndeclaredMethod
87  $xml = $dom->saveXML();
88  } else {
89  // @phan-suppress-next-line PhanUndeclaredMethod
90  $xml = $dom->__toString();
91  }
92  }
93 
94  $output = $parser->preprocess( $input, $title, $options );
95  } else {
96  $this->removeComments = $request->getBool( 'wpRemoveComments', true );
97  $this->removeNowiki = $request->getBool( 'wpRemoveNowiki', false );
98  $output = false;
99  }
100 
101  $out = $this->getOutput();
102 
103  $this->makeForm( $titleStr, $input );
104 
105  if ( $output !== false ) {
106  if ( $this->generateXML && strlen( $output ) > 0 ) {
107  $out->addHTML( $this->makeOutput( $xml, 'expand_templates_xml_output' ) );
108  }
109 
110  $tmp = $this->makeOutput( $output );
111 
112  if ( $this->removeNowiki ) {
113  $tmp = preg_replace(
114  [ '_&lt;nowiki&gt;_', '_&lt;/nowiki&gt;_', '_&lt;nowiki */&gt;_' ],
115  '',
116  $tmp
117  );
118  }
119 
120  $config = $this->getConfig();
121  if ( MWTidy::isEnabled() && $options->getTidy() ) {
122  $tmp = MWTidy::tidy( $tmp );
123  } else {
124  wfDeprecated( 'disabling tidy', '1.33' );
125  }
126 
127  $out->addHTML( $tmp );
128 
129  $pout = $this->generateHtml( $title, $output );
130  $rawhtml = $pout->getText();
131  if ( $this->generateRawHtml && strlen( $rawhtml ) > 0 ) {
132  $out->addHTML( $this->makeOutput( $rawhtml, 'expand_templates_html_output' ) );
133  }
134 
135  $this->showHtmlPreview( $title, $pout, $out );
136  }
137  }
138 
147  public function onSubmitInput( array $values ) {
148  $status = Status::newGood();
149  if ( !strlen( $values['input'] ) ) {
150  $status = Status::newFatal( 'expand_templates_input_missing' );
151  }
152  return $status;
153  }
154 
161  private function makeForm( $title, $input ) {
162  $fields = [
163  'contexttitle' => [
164  'type' => 'text',
165  'label' => $this->msg( 'expand_templates_title' )->plain(),
166  'name' => 'wpContextTitle',
167  'id' => 'contexttitle',
168  'size' => 60,
169  'default' => $title,
170  'autofocus' => true,
171  ],
172  'input' => [
173  'type' => 'textarea',
174  'name' => 'wpInput',
175  'label' => $this->msg( 'expand_templates_input' )->text(),
176  'rows' => 10,
177  'default' => $input,
178  'id' => 'input',
179  'useeditfont' => true,
180  ],
181  'removecomments' => [
182  'type' => 'check',
183  'label' => $this->msg( 'expand_templates_remove_comments' )->text(),
184  'name' => 'wpRemoveComments',
185  'id' => 'removecomments',
186  'default' => $this->removeComments,
187  ],
188  'removenowiki' => [
189  'type' => 'check',
190  'label' => $this->msg( 'expand_templates_remove_nowiki' )->text(),
191  'name' => 'wpRemoveNowiki',
192  'id' => 'removenowiki',
193  'default' => $this->removeNowiki,
194  ],
195  'generate_xml' => [
196  'type' => 'check',
197  'label' => $this->msg( 'expand_templates_generate_xml' )->text(),
198  'name' => 'wpGenerateXml',
199  'id' => 'generate_xml',
200  'default' => $this->generateXML,
201  ],
202  'generate_rawhtml' => [
203  'type' => 'check',
204  'label' => $this->msg( 'expand_templates_generate_rawhtml' )->text(),
205  'name' => 'wpGenerateRawHtml',
206  'id' => 'generate_rawhtml',
207  'default' => $this->generateRawHtml,
208  ],
209  ];
210 
211  $form = HTMLForm::factory( 'ooui', $fields, $this->getContext() );
212  $form
213  ->setSubmitTextMsg( 'expand_templates_ok' )
214  ->setWrapperLegendMsg( 'expandtemplates' )
215  ->setHeaderText( $this->msg( 'expand_templates_intro' )->parse() )
216  ->setSubmitCallback( [ $this, 'onSubmitInput' ] )
217  ->showAlways();
218  }
219 
227  private function makeOutput( $output, $heading = 'expand_templates_output' ) {
228  $out = "<h2>" . $this->msg( $heading )->escaped() . "</h2>\n";
229  $out .= Xml::textarea(
230  'output',
231  $output,
232  10,
233  10,
234  [
235  'id' => 'output',
236  'readonly' => 'readonly',
237  'class' => 'mw-editfont-' . $this->getUser()->getOption( 'editfont' )
238  ]
239  );
240 
241  return $out;
242  }
243 
251  private function generateHtml( Title $title, $text ) {
252  $popts = ParserOptions::newFromContext( $this->getContext() );
253  $popts->setTargetLanguage( $title->getPageLanguage() );
254  return MediaWikiServices::getInstance()->getParser()->parse( $text, $title, $popts );
255  }
256 
264  private function showHtmlPreview( Title $title, ParserOutput $pout, OutputPage $out ) {
265  $lang = $title->getPageViewLanguage();
266  $out->addHTML( "<h2>" . $this->msg( 'expand_templates_preview' )->escaped() . "</h2>\n" );
267 
268  if ( $this->getConfig()->get( 'RawHtml' ) ) {
269  $request = $this->getRequest();
270  $user = $this->getUser();
271 
272  // To prevent cross-site scripting attacks, don't show the preview if raw HTML is
273  // allowed and a valid edit token is not provided (T73111). However, MediaWiki
274  // does not currently provide logged-out users with CSRF protection; in that case,
275  // do not show the preview unless anonymous editing is allowed.
276  if ( $user->isAnon() && !MediaWikiServices::getInstance()
277  ->getPermissionManager()
278  ->userHasRight( $user, 'edit' )
279  ) {
280  $error = [ 'expand_templates_preview_fail_html_anon' ];
281  } elseif ( !$user->matchEditToken( $request->getVal( 'wpEditToken' ), '', $request ) ) {
282  $error = [ 'expand_templates_preview_fail_html' ];
283  } else {
284  $error = false;
285  }
286 
287  if ( $error ) {
288  $out->wrapWikiMsg( "<div class='previewnote errorbox'>\n$1\n</div>", $error );
289  return;
290  }
291  }
292 
293  $out->addHTML( Html::openElement( 'div', [
294  'class' => 'mw-content-' . $lang->getDir(),
295  'dir' => $lang->getDir(),
296  'lang' => $lang->getHtmlCode(),
297  ] ) );
298  $out->addParserOutputContent( $pout );
299  $out->addHTML( Html::closeElement( 'div' ) );
300  $out->setCategoryLinks( $pout->getCategories() );
301  }
302 
303  protected function getGroupName() {
304  return 'wiki';
305  }
306 }
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:69
static newFromContext(IContextSource $context)
Get a ParserOptions object from a IContextSource object.
static tidy( $text)
Interface with Remex tidy.
Definition: MWTidy.php:42
execute( $subpage)
Show the special page.
getContext()
Gets the context this SpecialPage is executed in.
showHtmlPreview(Title $title, ParserOutput $pout, OutputPage $out)
Wraps the provided html code in a div and outputs it to the page.
static isEnabled()
Definition: MWTidy.php:54
bool $generateXML
Whether or not to show the XML parse tree.
if(!isset( $args[0])) $lang
static openElement( $element, $attribs=[])
Identical to rawElement(), but has no third parameter and omits the end tag (and the self-closing &#39;/&#39;...
Definition: Html.php:251
makeOutput( $output, $heading='expand_templates_output')
Generate a nice little box with a heading for output.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
wrapWikiMsg( $wrap,... $msgSpecs)
This function takes a number of message/argument specifications, wraps them in some overall structure...
getOutput()
Get the OutputPage being used for this instance.
onSubmitInput(array $values)
Callback for the HTMLForm used in self::makeForm.
bool $generateRawHtml
Whether or not to show the raw HTML code.
setCategoryLinks(array $categories)
Reset the category links (but not the category list) and add $categories.
const OT_PREPROCESS
Definition: Parser.php:117
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
static factory( $displayFormat,... $arguments)
Construct a HTMLForm object for given display type.
Definition: HTMLForm.php:307
A special page that expands submitted templates, parser functions, and variables, allowing easier deb...
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:315
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes! ...
bool $removeNowiki
Whether or not to remove <nowiki> tags in the expanded wikitext.
makeForm( $title, $input)
Generate a form allowing users to enter information.
generateHtml(Title $title, $text)
Renders the supplied wikitext as html.
static textarea( $name, $content, $cols=40, $rows=5, $attribs=[])
Shortcut for creating textareas.
Definition: Xml.php:635
getPageViewLanguage()
Get the language in which the content of this page is written when viewed by user.
Definition: Title.php:4666
addParserOutputContent(ParserOutput $parserOutput, $poOptions=[])
Add the HTML and enhancements for it (like ResourceLoader modules) associated with a ParserOutput obj...
getUser()
Shortcut to get the User executing this instance.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
getPageLanguage()
Get the language in which the content of this page is written in wikitext.
Definition: Title.php:4628
getConfig()
Shortcut to get main config object.
bool $removeComments
Whether or not to remove comments in the expanded wikitext.
addHTML( $text)
Append $text to the body HTML.
getRequest()
Get the WebRequest being used for this instance.
getPageTitle( $subpage=false)
Get a self-referential title object.
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:319