* http://www.mediawiki.org/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * http://www.gnu.org/copyleft/gpl.html */ /** * Hooks for the Scribunto extension. */ class ScribuntoHooks { /** * Get software information for Special:Version * @param &$software array * @return bool */ public static function getSoftwareInfo( &$software ) { $engine = Scribunto::newDefaultEngine(); $engine->setTitle( Title::makeTitle( NS_SPECIAL, 'Version' ) ); $engine->getSoftwareInfo( $software ); return true; } /** * Register parser hooks. * @param $parser Parser * @return bool */ public static function setupParserHook( &$parser ) { $parser->setFunctionHook( 'invoke', 'ScribuntoHooks::invokeHook', SFH_OBJECT_ARGS ); return true; } /** * Called when the interpreter is to be reset. * * @param $parser Parser * @return bool */ public static function clearState( &$parser ) { Scribunto::resetParserEngine( $parser ); return true; } /** * Called when the parser is cloned * * @param $parser Parser * @return bool */ public static function parserCloned( $parser ) { $parser->scribunto_engine = null; return true; } /** * Hook function for {{#invoke:module|func}} * * @param $parser Parser * @param $frame PPFrame * @param $args array * @throws MWException * @throws ScribuntoException * @return string */ public static function invokeHook( &$parser, $frame, $args ) { if ( !@constant( get_class( $frame ) . '::SUPPORTS_INDEX_OFFSET' ) ) { throw new MWException( 'Scribunto needs MediaWiki 1.20 or later (Preprocessor::SUPPORTS_INDEX_OFFSET)' ); } wfProfileIn( __METHOD__ ); try { if ( count( $args ) < 2 ) { throw new ScribuntoException( 'scribunto-common-nofunction' ); } $moduleName = trim( $frame->expand( $args[0] ) ); $engine = Scribunto::getParserEngine( $parser ); $title = Title::makeTitleSafe( NS_MODULE, $moduleName ); if ( !$title || Scribunto::isDocPage( $title ) ) { throw new ScribuntoException( 'scribunto-common-nosuchmodule' ); } $module = $engine->fetchModuleFromParser( $title ); if ( !$module ) { throw new ScribuntoException( 'scribunto-common-nosuchmodule' ); } $functionName = trim( $frame->expand( $args[1] ) ); unset( $args[0] ); unset( $args[1] ); $childFrame = $frame->newChild( $args, $title, 1 ); $result = $module->invoke( $functionName, $childFrame ); $result = UtfNormal::cleanUp( strval( $result ) ); wfProfileOut( __METHOD__ ); return $result; } catch( ScribuntoException $e ) { $trace = $e->getScriptTraceHtml( array( 'msgOptions' => array( 'content' ) ) ); $html = Html::element( 'p', array(), $e->getMessage() ); if ( $trace !== false ) { $html .= Html::element( 'p', array(), wfMessage( 'scribunto-common-backtrace' )->inContentLanguage()->text() ) . $trace; } $out = $parser->getOutput(); if ( !isset( $out->scribunto_errors ) ) { $out->addOutputHook( 'ScribuntoError' ); $out->scribunto_errors = array(); $parser->addTrackingCategory( 'scribunto-common-error-category' ); } $out->scribunto_errors[] = $html; $id = 'mw-scribunto-error-' . ( count( $out->scribunto_errors ) - 1 ); $parserError = wfMessage( 'scribunto-parser-error' )->inContentLanguage()->text() . $parser->insertStripItem( '' ); wfProfileOut( __METHOD__ ); // #iferror-compatible error element return "" . $parserError. ""; } } /** * @param $title Title * @param $lang string * @return bool */ public static function getCodeLanguage( $title, &$lang ) { global $wgScribuntoUseCodeEditor; if( $wgScribuntoUseCodeEditor && $title->getNamespace() == NS_MODULE && !Scribunto::isDocPage( $title ) ) { $engine = Scribunto::newDefaultEngine(); if( $engine->getCodeEditorLanguage() ) { $lang = $engine->getCodeEditorLanguage(); return false; } } return true; } /** * Set the Scribunto content handler for modules * @param $title Title * @param &$model string * @return bool */ public static function contentHandlerDefaultModelFor( $title, &$model ) { if( $title->getNamespace() == NS_MODULE && !Scribunto::isDocPage( $title ) ) { $model = 'Scribunto'; return false; } return true; } /** * Adds report of number of evaluations by the single wikitext page. * * @param $parser Parser * @param $report * @return bool */ public static function reportLimits( $parser, &$report ) { if ( Scribunto::isParserEnginePresent( $parser ) ) { $engine = Scribunto::getParserEngine( $parser ); $report .= $engine->getLimitReport(); } return true; } /** * Adds the module namespaces. */ public static function addCanonicalNamespaces( &$list ) { $list[NS_MODULE] = 'Module'; $list[NS_MODULE_TALK] = 'Module_talk'; return true; } /** * EditPageBeforeEditChecks hook * @param $editor EditPage * @param $checkboxes Checkbox array * @param $tabindex Current tabindex */ public static function beforeEditChecks( &$editor, &$checkboxes, &$tabindex ) { if ( $editor->getTitle()->getNamespace() !== NS_MODULE ) { return true; } if ( Scribunto::isDocPage( $editor->getTitle() ) ) { return true; } $req = RequestContext::getMain()->getRequest(); $name = 'scribunto_ignore_errors'; $attribs = array( 'tabindex' => ++$tabindex, 'id' => "mw-$name", ); $checkboxes['scribunto'] = Xml::check( $name, $req->getCheck( $name ), $attribs ) . ' ' . Xml::label( wfMessage( 'scribunto-ignore-errors' )->text(), "mw-$name" ); // While we're here, lets set up the edit module global $wgOut; $wgOut->addModules( 'ext.scribunto.edit' ); $editor->editFormTextAfterTools = '
'; return true; } /** * EditPageBeforeEditButtons hook * @param $editor EditPage * @param $buttons Button array * @param $tabindex Current tabindex */ public static function beforeEditButtons( &$editor, &$buttons, &$tabindex ) { if ( $editor->getTitle()->getNamespace() !== NS_MODULE ) { return true; } if ( Scribunto::isDocPage( $editor->getTitle() ) ) { return true; } unset( $buttons['preview'] ); return true; } /** * @param $editor EditPage * @param $text string * @param $error * @param $summary * @return bool */ public static function validateScript( $editor, $text, &$error, $summary ) { global $wgOut; $title = $editor->getTitle(); if( $title->getNamespace() != NS_MODULE ) { return true; } if ( Scribunto::isDocPage( $title ) ) { return true; } $req = RequestContext::getMain()->getRequest(); if ( $req->getBool( 'scribunto_ignore_errors' ) ) { return true; } $engine = Scribunto::newDefaultEngine(); $engine->setTitle( $title ); $status = $engine->validate( $text, $title->getPrefixedDBkey() ); if( $status->isOK() ) { return true; } $errmsg = $status->getWikiText( 'scribunto-error-short', 'scribunto-error-long' ); $error = <<