2013-02-20 22:00:42 +00:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Scribunto Content Model
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @ingroup Extensions
|
|
|
|
* @ingroup Scribunto
|
|
|
|
*
|
|
|
|
* @author Brad Jorsch <bjorsch@wikimedia.org>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents the content of a Scribunto script page
|
|
|
|
*/
|
|
|
|
class ScribuntoContent extends TextContent {
|
|
|
|
|
|
|
|
function __construct( $text ) {
|
2014-09-16 03:25:53 +00:00
|
|
|
parent::__construct( $text, CONTENT_MODEL_SCRIBUNTO );
|
2013-02-20 22:00:42 +00:00
|
|
|
}
|
|
|
|
|
2016-09-13 23:41:13 +00:00
|
|
|
/**
|
|
|
|
* Checks whether the script is valid
|
|
|
|
*
|
|
|
|
* @param Title $title
|
|
|
|
* @return Status
|
|
|
|
*/
|
|
|
|
public function validate( Title $title ) {
|
|
|
|
$engine = Scribunto::newDefaultEngine();
|
|
|
|
$engine->setTitle( $title );
|
|
|
|
return $engine->validate( $this->getNativeData(), $title->getPrefixedDBkey() );
|
|
|
|
}
|
|
|
|
|
|
|
|
public function prepareSave( WikiPage $page, $flags, $parentRevId, User $user ) {
|
|
|
|
return $this->validate( $page->getTitle() );
|
|
|
|
}
|
|
|
|
|
2013-02-20 22:00:42 +00:00
|
|
|
/**
|
|
|
|
* Parse the Content object and generate a ParserOutput from the result.
|
|
|
|
*
|
2017-09-24 17:38:14 +00:00
|
|
|
* @param Title $title The page title to use as a context for rendering
|
|
|
|
* @param null|int $revId The revision being rendered (optional)
|
|
|
|
* @param null|ParserOptions $options Any parser options
|
|
|
|
* @param bool $generateHtml Whether to generate HTML (default: true).
|
|
|
|
* @param ParserOutput &$output ParserOutput representing the HTML form of the text.
|
2013-02-20 22:00:42 +00:00
|
|
|
* @return ParserOutput
|
|
|
|
*/
|
2016-05-17 14:52:05 +00:00
|
|
|
protected function fillParserOutput(
|
|
|
|
Title $title, $revId, ParserOptions $options, $generateHtml, ParserOutput &$output
|
|
|
|
) {
|
2014-07-03 18:50:50 +00:00
|
|
|
global $wgParser, $wgScribuntoUseGeSHi, $wgUseSiteCss;
|
2013-02-20 22:00:42 +00:00
|
|
|
|
|
|
|
$text = $this->getNativeData();
|
|
|
|
|
|
|
|
// Get documentation, if any
|
|
|
|
$output = new ParserOutput();
|
2013-03-08 17:01:50 +00:00
|
|
|
$doc = Scribunto::getDocPage( $title );
|
2013-02-20 22:00:42 +00:00
|
|
|
if ( $doc ) {
|
|
|
|
$msg = wfMessage(
|
2013-03-08 17:01:50 +00:00
|
|
|
$doc->exists() ? 'scribunto-doc-page-show' : 'scribunto-doc-page-does-not-exist',
|
2013-02-20 22:00:42 +00:00
|
|
|
$doc->getPrefixedText()
|
|
|
|
)->inContentLanguage();
|
2014-05-08 08:24:08 +00:00
|
|
|
|
2013-02-20 22:00:42 +00:00
|
|
|
if ( !$msg->isDisabled() ) {
|
|
|
|
// We need the ParserOutput for categories and such, so we
|
|
|
|
// can't use $msg->parse().
|
2013-05-29 15:08:31 +00:00
|
|
|
$docViewLang = $doc->getPageViewLanguage();
|
2014-05-08 08:24:08 +00:00
|
|
|
$dir = $docViewLang->getDir();
|
|
|
|
|
|
|
|
// Code is forced to be ltr, but the documentation can be rtl.
|
|
|
|
// Correct direction class is needed for correct formatting.
|
|
|
|
// The possible classes are
|
|
|
|
// mw-content-ltr or mw-content-rtl
|
|
|
|
$dirClass = "mw-content-$dir";
|
|
|
|
|
|
|
|
$docWikitext = Html::rawElement(
|
|
|
|
'div',
|
2017-06-15 17:19:00 +00:00
|
|
|
[
|
2014-05-08 08:24:08 +00:00
|
|
|
'lang' => $docViewLang->getHtmlCode(),
|
|
|
|
'dir' => $dir,
|
|
|
|
'class' => $dirClass,
|
2017-06-15 17:19:00 +00:00
|
|
|
],
|
2014-05-08 08:24:08 +00:00
|
|
|
// Line breaks are needed so that wikitext would be
|
|
|
|
// appropriately isolated for correct parsing. See Bug 60664.
|
|
|
|
"\n" . $msg->plain() . "\n"
|
|
|
|
);
|
|
|
|
|
2013-05-29 15:08:31 +00:00
|
|
|
if ( !$options ) {
|
|
|
|
// NOTE: use canonical options per default to produce cacheable output
|
|
|
|
$options = ContentHandler::getForTitle( $doc )->makeParserOptions( 'canonical' );
|
|
|
|
} else {
|
|
|
|
if ( $options->getTargetLanguage() === null ) {
|
|
|
|
$options->setTargetLanguage( $doc->getPageLanguage() );
|
|
|
|
}
|
|
|
|
}
|
2014-05-08 08:24:08 +00:00
|
|
|
|
2013-05-29 15:08:31 +00:00
|
|
|
$output = $wgParser->parse( $docWikitext, $title, $options, true, true, $revId );
|
2013-02-20 22:00:42 +00:00
|
|
|
}
|
|
|
|
|
2013-03-08 17:01:50 +00:00
|
|
|
// Mark the doc page as a transclusion, so we get purged when it
|
|
|
|
// changes.
|
2013-02-20 22:00:42 +00:00
|
|
|
$output->addTemplate( $doc, $doc->getArticleID(), $doc->getLatestRevID() );
|
|
|
|
}
|
|
|
|
|
2013-12-06 17:51:09 +00:00
|
|
|
// Validate the script, and include an error message and tracking
|
|
|
|
// category if it's invalid
|
2016-09-13 23:41:13 +00:00
|
|
|
$status = $this->validate( $title );
|
2015-06-21 04:38:39 +00:00
|
|
|
if ( !$status->isOK() ) {
|
2018-01-10 14:19:13 +00:00
|
|
|
$output->setText( $output->getRawText() .
|
2017-06-15 17:19:00 +00:00
|
|
|
Html::rawElement( 'div', [ 'class' => 'errorbox' ],
|
2013-12-06 17:51:09 +00:00
|
|
|
$status->getHTML( 'scribunto-error-short', 'scribunto-error-long' )
|
|
|
|
)
|
|
|
|
);
|
2016-09-14 18:52:43 +00:00
|
|
|
$output->addTrackingCategory( 'scribunto-module-with-errors-category', $title );
|
2013-12-06 17:51:09 +00:00
|
|
|
}
|
|
|
|
|
2013-02-20 22:00:42 +00:00
|
|
|
if ( !$generateHtml ) {
|
|
|
|
// We don't need the actual HTML
|
|
|
|
$output->setText( '' );
|
|
|
|
return $output;
|
|
|
|
}
|
|
|
|
|
2016-09-13 23:41:13 +00:00
|
|
|
$engine = Scribunto::newDefaultEngine();
|
|
|
|
$engine->setTitle( $title );
|
|
|
|
|
2013-02-20 22:00:42 +00:00
|
|
|
// Add HTML for the actual script
|
|
|
|
$language = $engine->getGeSHiLanguage();
|
2015-06-21 04:38:39 +00:00
|
|
|
if ( $wgScribuntoUseGeSHi && $language ) {
|
2013-02-20 22:00:42 +00:00
|
|
|
$geshi = SyntaxHighlight_GeSHi::prepare( $text, $language );
|
|
|
|
$geshi->set_language( $language );
|
2015-06-21 04:38:39 +00:00
|
|
|
if ( $geshi instanceof GeSHi && !$geshi->error() ) {
|
2013-02-20 22:00:42 +00:00
|
|
|
$code = $geshi->parse_code();
|
2015-06-21 04:38:39 +00:00
|
|
|
if ( $code ) {
|
2014-07-03 18:50:50 +00:00
|
|
|
// @todo Once we drop support for old versions of
|
|
|
|
// Extension:SyntaxHighlight_GeSHi, drop the ugly test and
|
|
|
|
// the BC case.
|
|
|
|
global $wgAutoloadClasses;
|
|
|
|
if ( isset( $wgAutoloadClasses['ResourceLoaderGeSHiModule'] ) ) {
|
|
|
|
$output->addModuleStyles( "ext.geshi.language.$language" );
|
|
|
|
} else {
|
|
|
|
// Backwards compatibility
|
|
|
|
$output->addHeadItem( SyntaxHighlight_GeSHi::buildHeadItem( $geshi ), "source-{$language}" );
|
|
|
|
}
|
|
|
|
if ( $wgUseSiteCss ) {
|
|
|
|
$output->addModuleStyles( 'ext.geshi.local' );
|
|
|
|
}
|
2018-01-10 14:19:13 +00:00
|
|
|
$output->setText( $output->getRawText() . $code );
|
2013-02-20 22:00:42 +00:00
|
|
|
return $output;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// No GeSHi, or GeSHi can't parse it, use plain <pre>
|
2018-01-10 14:19:13 +00:00
|
|
|
$output->setText( $output->getRawText() .
|
2014-09-22 02:51:26 +00:00
|
|
|
"<pre class='mw-code mw-script' dir='ltr'>\n" .
|
2013-02-20 22:00:42 +00:00
|
|
|
htmlspecialchars( $text ) .
|
|
|
|
"\n</pre>\n"
|
|
|
|
);
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
}
|
|
|
|
}
|