r114738 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r114737‎ | r114738 | r114739 >
Date:12:02, 5 April 2012
Author:vvv
Status:deferred
Tags:
Comment:
Rename Scripting to Scribunto per Tim's suggestion.
Modified paths:
  • /trunk/extensions/Scribunto (added) (history)
  • /trunk/extensions/Scripting (deleted) (history)

Diff [purge]

Index: trunk/extensions/Scribunto/Scripting.i18n.php
@@ -0,0 +1,25 @@
 2+<?php
 3+/**
 4+ * Internationalisation file for extension Scripting.
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+$messages = array();
 11+
 12+/** English
 13+ * @author Victor Vasiliev
 14+ */
 15+$messages['en'] = array(
 16+ 'scripting-desc' => 'Framework for embedding scripting languages into MediaWiki pages',
 17+ 'scripting-codelocation' => 'in $1 at line $2',
 18+ 'scripting-luasandbox-error' => 'Lua error: $2',
 19+ 'scripting-common-toofewargs' => 'Lua error: Too few arguments to function $2',
 20+ 'scripting-common-nosuchmodule' => 'Script error: No such module',
 21+ 'scripting-luasandbox-noreturn' => 'Script error: The module did not return a value, it should return an export table.',
 22+ 'scripting-luasandbox-toomanyreturns' => 'Script error: The module returned multiple values, it should return an export table.',
 23+ 'scripting-luasandbox-notarrayreturn' => 'Script error: The module returned something other than a table, it should return an export table.',
 24+ 'scripting-common-nofunction' => 'Script error: You must specify a function to call.',
 25+ 'scripting-common-nosuchfunction' => 'Script error: The function you specified did not exist.',
 26+);
Property changes on: trunk/extensions/Scribunto/Scripting.i18n.php
___________________________________________________________________
Added: svn:eol-style
127 + native
Index: trunk/extensions/Scribunto/Scripting.namespaces.php
@@ -0,0 +1,8 @@
 2+<?php
 3+
 4+$namespaceNames = array();
 5+
 6+$namespaceNames['en'] = array(
 7+ NS_MODULE => 'Module',
 8+ NS_MODULE_TALK => 'Module_talk',
 9+);
Property changes on: trunk/extensions/Scribunto/Scripting.namespaces.php
___________________________________________________________________
Added: svn:eol-style
110 + native
Index: trunk/extensions/Scribunto/Scripting.magic.php
@@ -0,0 +1,9 @@
 2+<?php
 3+
 4+$magicWords = array();
 5+
 6+$magicWords['en'] = array(
 7+ 'invoke' => array( 0, 'invoke' ),
 8+ 'script' => array( 0, 'script' ),
 9+);
 10+
Property changes on: trunk/extensions/Scribunto/Scripting.magic.php
___________________________________________________________________
Added: svn:eol-style
111 + native
Index: trunk/extensions/Scribunto/Scripting.php
@@ -0,0 +1,102 @@
 2+<?php
 3+/**
 4+ * Wikitext scripting infrastructure for MediaWiki.
 5+ * Copyright (C) 2009-2012 Victor Vasiliev <vasilvv@gmail.com>
 6+ * http://www.mediawiki.org/
 7+ *
 8+ * This program is free software; you can redistribute it and/or modify
 9+ * it under the terms of the GNU General Public License as published by
 10+ * the Free Software Foundation; either version 2 of the License, or
 11+ * (at your option) any later version.
 12+ *
 13+ * This program is distributed in the hope that it will be useful,
 14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 16+ * GNU General Public License for more details.
 17+ *
 18+ * You should have received a copy of the GNU General Public License along
 19+ * with this program; if not, write to the Free Software Foundation, Inc.,
 20+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 21+ * http://www.gnu.org/copyleft/gpl.html
 22+ */
 23+
 24+if( !defined( 'MEDIAWIKI' ) )
 25+ die();
 26+
 27+$wgExtensionCredits['parserhook']['Scripting'] = array(
 28+ 'path' => __FILE__,
 29+ 'name' => 'Scripting',
 30+ 'author' => 'Victor Vasiliev',
 31+ 'descriptionmsg' => 'scripting-desc',
 32+ 'url' => 'https://www.mediawiki.org/wiki/Extension:Scripting',
 33+);
 34+
 35+$dir = dirname(__FILE__) . '/';
 36+$wgExtensionMessagesFiles['Scripting'] = $dir . 'Scripting.i18n.php';
 37+$wgExtensionMessagesFiles['ScriptingMagic'] = $dir . 'Scripting.magic.php';
 38+$wgExtensionMessagesFiles['ScriptingNamespaces'] = $dir . 'Scripting.namespaces.php';
 39+
 40+$wgAutoloadClasses['ScriptingEngineBase'] = $dir.'common/Base.php';
 41+$wgAutoloadClasses['ScriptingModuleBase'] = $dir.'common/Base.php';
 42+$wgAutoloadClasses['ScriptingFunctionBase'] = $dir.'common/Base.php';
 43+$wgAutoloadClasses['ScriptingHooks'] = $dir.'common/Hooks.php';
 44+$wgAutoloadClasses['ScriptingException'] = $dir.'common/Common.php';
 45+$wgAutoloadClasses['Scripting'] = $dir.'common/Common.php';
 46+
 47+$wgHooks['ParserFirstCallInit'][] = 'ScriptingHooks::setupParserHook';
 48+$wgHooks['ParserLimitReport'][] = 'ScriptingHooks::reportLimits';
 49+$wgHooks['ParserClearState'][] = 'ScriptingHooks::clearState';
 50+
 51+$wgHooks['CanonicalNamespaces'][] = 'ScriptingHooks::addCanonicalNamespaces';
 52+$wgHooks['ArticleViewCustom'][] = 'ScriptingHooks::handleScriptView';
 53+$wgHooks['TitleIsWikitextPage'][] = 'ScriptingHooks::isWikitextPage';
 54+$wgHooks['CodeEditorGetPageLanguage'][] = 'ScriptingHooks::getCodeLanguage';
 55+$wgHooks['EditFilter'][] = 'ScriptingHooks::validateScript';
 56+
 57+/***** Individual engines and their configurations *****/
 58+
 59+$wgAutoloadClasses['LuaSandboxEngine'] = $dir.'engines/LuaSandbox/Engine.php';
 60+
 61+/***** Configuration *****/
 62+
 63+/**
 64+ * The name of the default scripting engine.
 65+ */
 66+$wgScriptingDefaultEngine = 'luasandbox';
 67+
 68+/**
 69+ * Configuration for each scripting engine
 70+ */
 71+$wgScriptingEngineConf = array(
 72+ 'luasandbox' => array(
 73+ 'class' => 'LuaSandboxEngine',
 74+ 'memoryLimit' => 50 * 1024 * 1024,
 75+ 'cpuLimit' => 7,
 76+ ),
 77+);
 78+
 79+/**
 80+ * Script namespace numbers.
 81+ */
 82+$wgScriptingNamespaceNumbers = array(
 83+ 'Module' => 20,
 84+ 'Module_talk' => 21,
 85+);
 86+
 87+/**
 88+ * Turn on to true if SyntaxHighlight_GeSHi extension is enabled.
 89+ */
 90+$wgScriptingUseGeSHi = false;
 91+
 92+/**
 93+ * Turn on to true if CodeEditor extension is enabled.
 94+ */
 95+$wgScriptingUseCodeEditor = false;
 96+
 97+function efDefineScriptingNamespace() {
 98+ global $wgScriptingNamespaceNumbers;
 99+ define( 'NS_MODULE', $wgScriptingNamespaceNumbers['Module'] );
 100+ define( 'NS_MODULE_TALK', $wgScriptingNamespaceNumbers['Module_talk'] );
 101+}
 102+
 103+$wgExtensionFunctions[] = 'efDefineScriptingNamespace';
Property changes on: trunk/extensions/Scribunto/Scripting.php
___________________________________________________________________
Added: svn:eol-style
1104 + native
Index: trunk/extensions/Scribunto/common/Base.php
@@ -0,0 +1,183 @@
 2+<?php
 3+
 4+/**
 5+ * Wikitext scripting infrastructure for MediaWiki: base classes.
 6+ * Copyright (C) 2012 Victor Vasiliev <vasilvv@gmail.com> et al
 7+ * http://www.mediawiki.org/
 8+ *
 9+ * This program is free software; you can redistribute it and/or modify
 10+ * it under the terms of the GNU General Public License as published by
 11+ * the Free Software Foundation; either version 2 of the License, or
 12+ * (at your option) any later version.
 13+ *
 14+ * This program is distributed in the hope that it will be useful,
 15+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 17+ * GNU General Public License for more details.
 18+ *
 19+ * You should have received a copy of the GNU General Public License along
 20+ * with this program; if not, write to the Free Software Foundation, Inc.,
 21+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 22+ * http://www.gnu.org/copyleft/gpl.html
 23+ */
 24+
 25+/**
 26+ * Base class for all scripting engines. Includes all code
 27+ * not related to particular modules, like tracking links between
 28+ * modules or loading module texts.
 29+ */
 30+abstract class ScriptingEngineBase {
 31+ protected
 32+ $parser,
 33+ $options,
 34+ $modules = array();
 35+
 36+ /**
 37+ * Creates a new module object within this engine
 38+ */
 39+ abstract protected function newModule( $text, $chunkName );
 40+
 41+ /**
 42+ * Constructor.
 43+ *
 44+ * @param $options Associative array of options:
 45+ * - parser: A Parser object
 46+ */
 47+ public function __construct( $options ) {
 48+ $this->options = $options;
 49+ if ( isset( $options['parser'] ) ) {
 50+ $this->parser = $options['parser'];
 51+ }
 52+ }
 53+
 54+ /**
 55+ * Load a module from some parser-defined template loading mechanism and
 56+ * register a parser output dependency.
 57+ *
 58+ * Does not initialize the module, i.e. do not expect it to complain if the module
 59+ * text is garbage or has syntax error. Returns a module or throws an exception.
 60+ *
 61+ * @param $title The title of the module
 62+ * @return ScriptingEngineModule
 63+ */
 64+ function fetchModuleFromParser( Title $title ) {
 65+ list( $text, $finalTitle ) = $this->parser->fetchTemplateAndTitle( $title );
 66+ if ( $text === false ) {
 67+ throw new ScriptingException( 'scripting-common-nosuchmodule' );
 68+ }
 69+
 70+ $key = $finalTitle->getPrefixedDBkey();
 71+ if ( !isset( $this->modules[$key] ) ) {
 72+ $this->modules[$key] = $this->newModule( $text, $key );
 73+ }
 74+ return $this->modules[$key];
 75+ }
 76+
 77+ /**
 78+ * Validates the script and returns an array of the syntax errors for the
 79+ * given code.
 80+ *
 81+ * @param $code Code to validate
 82+ * @param $title Title of the code page
 83+ * @return array
 84+ */
 85+ function validate( $text, $chunkName = false ) {
 86+ $module = $this->newModule( $text, $chunkName );
 87+
 88+ try {
 89+ $module->initialize();
 90+ } catch( ScriptingException $e ) {
 91+ return array( $e->getMessage() );
 92+ }
 93+
 94+ return array();
 95+ }
 96+
 97+ /**
 98+ * Allows the engine to append their information to the limits
 99+ * report.
 100+ */
 101+ public function getLimitsReport() {
 102+ /* No-op by default */
 103+ return '';
 104+ }
 105+
 106+ /**
 107+ * Get the language for GeSHi syntax highlighter.
 108+ */
 109+ function getGeSHiLanguage() {
 110+ return false;
 111+ }
 112+
 113+ /**
 114+ * Get the language for Ace code editor.
 115+ */
 116+ function getCodeEditorLanguage() {
 117+ return false;
 118+ }
 119+}
 120+
 121+/**
 122+ * Class that represents a module. Responsible for initial module parsing
 123+ * and maintaining the contents of the module.
 124+ */
 125+abstract class ScriptingModuleBase {
 126+ var $engine, $code, $chunkName;
 127+
 128+ public function __construct( $engine, $code, $chunkName ) {
 129+ $this->engine = $engine;
 130+ $this->code = $code;
 131+ $this->chunkName = $chunkName;
 132+ }
 133+
 134+ /** Accessors **/
 135+ public function getEngine() { return $this->engine; }
 136+ public function getCode() { return $this->code; }
 137+ public function getChunkName() { return $this->chunkName; }
 138+
 139+ /**
 140+ * Initialize the module. That means parse it and load the
 141+ * functions/constants/whatever into the object.
 142+ *
 143+ * Protection of double-initialization is the responsibility of this method.
 144+ */
 145+ abstract function initialize();
 146+
 147+ /**
 148+ * Returns the object for a given function. Should return null if it does not exist.
 149+ *
 150+ * @return ScriptingFunctionBase or null
 151+ */
 152+ abstract function getFunction( $name );
 153+
 154+ /**
 155+ * Returns the list of the functions in the module.
 156+ *
 157+ * @return array(string)
 158+ */
 159+ abstract function getFunctions();
 160+}
 161+
 162+abstract class ScriptingFunctionBase {
 163+ protected $mName, $mContents, $mModule, $mEngine;
 164+
 165+ public function __construct( $module, $name, $contents ) {
 166+ $this->name = $name;
 167+ $this->contents = $contents;
 168+ $this->module = $module;
 169+ $this->engine = $module->getEngine();
 170+ }
 171+
 172+ /**
 173+ * Calls the function. Returns its first result or null if no result.
 174+ *
 175+ * @param $args array Arguments to the function
 176+ * @param $frame PPFrame
 177+ */
 178+ abstract public function call( $args, $frame );
 179+
 180+ /** Accessors **/
 181+ public function getName() { return $this->name; }
 182+ public function getModule() { return $this->module; }
 183+ public function getEngine() { return $this->engine; }
 184+}
Property changes on: trunk/extensions/Scribunto/common/Base.php
___________________________________________________________________
Added: svn:eol-style
1185 + native
Index: trunk/extensions/Scribunto/common/Hooks.php
@@ -0,0 +1,240 @@
 2+<?php
 3+/**
 4+ * Wikitext scripting infrastructure for MediaWiki: hooks.
 5+ * Copyright (C) 2009-2012 Victor Vasiliev <vasilvv@gmail.com>
 6+ * http://www.mediawiki.org/
 7+ *
 8+ * This program is free software; you can redistribute it and/or modify
 9+ * it under the terms of the GNU General Public License as published by
 10+ * the Free Software Foundation; either version 2 of the License, or
 11+ * (at your option) any later version.
 12+ *
 13+ * This program is distributed in the hope that it will be useful,
 14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 16+ * GNU General Public License for more details.
 17+ *
 18+ * You should have received a copy of the GNU General Public License along
 19+ * with this program; if not, write to the Free Software Foundation, Inc.,
 20+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 21+ * http://www.gnu.org/copyleft/gpl.html
 22+ */
 23+
 24+/**
 25+ * Hooks for the Scripting extension.
 26+ */
 27+class ScriptingHooks {
 28+ /**
 29+ * Register parser hooks.
 30+ * @param $parser Parser
 31+ */
 32+ public static function setupParserHook( &$parser ) {
 33+ $parser->setFunctionHook( 'invoke', 'ScriptingHooks::callHook', SFH_OBJECT_ARGS );
 34+ $parser->setFunctionHook( 'script', 'ScriptingHooks::transcludeHook', SFH_NO_HASH | SFH_OBJECT_ARGS );
 35+ return true;
 36+ }
 37+
 38+ /**
 39+ * Called when the interpreter is to be reset.
 40+ *
 41+ * @static
 42+ * @param $parser Parser
 43+ * @return bool
 44+ */
 45+ public static function clearState( &$parser ) {
 46+ Scripting::resetParserEngine( $parser );
 47+ return true;
 48+ }
 49+
 50+ /**
 51+ * Hook function for {{#invoke:module|func}}
 52+ *
 53+ * @param $parser Parser
 54+ * @param $frame PPFrame
 55+ * @param $args array
 56+ * @return string
 57+ */
 58+ public static function callHook( &$parser, $frame, $args ) {
 59+ if( count( $args ) < 2 ) {
 60+ throw new ScriptingException( 'scripting-common-nofunction' );
 61+ }
 62+
 63+ $module = $parser->mStripState->unstripBoth( array_shift( $args ) );
 64+ $function = $frame->expand( array_shift( $args ) );
 65+ return self::doRunHook( $parser, $frame, $module, $function, $args );
 66+ }
 67+
 68+ /**
 69+ * Hook function for {{script:module}}
 70+ *
 71+ * @param $parser Parser
 72+ * @param $frame PPFrame
 73+ * @param $args
 74+ * @return string
 75+ */
 76+ public static function transcludeHook( &$parser, $frame, $args ) {
 77+ $module = $parser->mStripState->unstripBoth( array_shift( $args ) );
 78+ return self::doRunHook( $parser, $frame, $module, 'main', $args );
 79+ }
 80+
 81+ /**
 82+ * @param $parser Parser
 83+ * @param $frame PPFrame
 84+ * @param $moduleName
 85+ * @param $functionName
 86+ * @param $args
 87+ * @return string
 88+ * @throws ScriptingException
 89+ */
 90+ private static function doRunHook( $parser, $frame, $moduleName, $functionName, $args ) {
 91+ wfProfileIn( __METHOD__ );
 92+
 93+ try {
 94+ $engine = Scripting::getParserEngine( $parser );
 95+ $title = Title::makeTitleSafe( NS_MODULE, $moduleName );
 96+ if ( !$title ) {
 97+ throw new ScriptingException( 'scripting-common-nosuchmodule' );
 98+ }
 99+ $module = $engine->fetchModuleFromParser( $title );
 100+
 101+ $functionObj = $module->getFunction( $functionName );
 102+ if( !$functionObj ) {
 103+ throw new ScriptingException( 'scripting-common-nosuchfunction' );
 104+ }
 105+
 106+ foreach( $args as &$arg ) {
 107+ $arg = $frame->expand( $arg );
 108+ }
 109+
 110+ $result = $functionObj->call( $args, $frame );
 111+
 112+ wfProfileOut( __METHOD__ );
 113+ return trim( strval( $result ) );
 114+ } catch( ScriptingException $e ) {
 115+ $msg = $e->getMessage();
 116+ wfProfileOut( __METHOD__ );
 117+ return "<strong class=\"error\">{$msg}</strong>";
 118+ }
 119+ }
 120+
 121+ /**
 122+ * Overrides the standard view for modules. Enables syntax highlighting when
 123+ * possible.
 124+ *
 125+ * @param $text string
 126+ * @param $title Title
 127+ * @param $output OutputPage
 128+ * @return bool
 129+ */
 130+ public static function handleScriptView( $text, $title, $output ) {
 131+ global $wgScriptingUseGeSHi;
 132+
 133+ if( $title->getNamespace() == NS_MODULE ) {
 134+ $engine = Scripting::newDefaultEngine();
 135+ $language = $engine->getGeSHiLanguage();
 136+
 137+ if( $wgScriptingUseGeSHi && $language ) {
 138+ $geshi = SyntaxHighlight_GeSHi::prepare( $text, $language );
 139+ $geshi->set_language( $language );
 140+ if( $geshi instanceof GeSHi && !$geshi->error() ) {
 141+ $code = $geshi->parse_code();
 142+ if( $code ) {
 143+ $output->addHeadItem( "source-{$language}", SyntaxHighlight_GeSHi::buildHeadItem( $geshi ) );
 144+ $output->addHTML( "<div dir=\"ltr\">{$code}</div>" );
 145+ return false;
 146+ }
 147+ }
 148+ }
 149+
 150+ // No GeSHi, or GeSHi can't parse it, use plain <pre>
 151+ $output->addHTML( "<pre class=\"mw-code mw-script\" dir=\"ltr\">\n" );
 152+ $output->addHTML( htmlspecialchars( $text ) );
 153+ $output->addHTML( "\n</pre>\n" );
 154+ return false;
 155+ } else {
 156+ return true;
 157+ }
 158+ }
 159+
 160+ public static function getCodeLanguage( $title, &$lang ) {
 161+ global $wgScriptingUseCodeEditor;
 162+ if( $wgScriptingUseCodeEditor && $title->getNamespace() == NS_MODULE ) {
 163+ $engine = Scripting::newDefaultEngine();
 164+ if( $engine->getCodeEditorLanguage() ) {
 165+ $lang = $engine->getCodeEditorLanguage();
 166+ return false;
 167+ }
 168+ }
 169+
 170+ return true;
 171+ }
 172+
 173+ /**
 174+ * Indicates that modules are not wikitext.
 175+ * @param $title Title
 176+ * @param $result
 177+ * @return bool
 178+ */
 179+ public static function isWikitextPage( $title, &$result ) {
 180+ if( $title->getNamespace() == NS_MODULE ) {
 181+ $result = false;
 182+ return false;
 183+ }
 184+ return true;
 185+ }
 186+
 187+ /**
 188+ * Adds report of number of evaluations by the single wikitext page.
 189+ *
 190+ * @param $parser Parser
 191+ * @param $report
 192+ * @return bool
 193+ */
 194+ public static function reportLimits( $parser, &$report ) {
 195+ # FIXME
 196+ global $wgScriptsLimits;
 197+ $engine = Scripting::getParserEngine( $parser );
 198+ $report .= $engine->getLimitReport();
 199+ return true;
 200+ }
 201+
 202+ /**
 203+ * Adds the module namespaces.
 204+ */
 205+ public static function addCanonicalNamespaces( &$list ) {
 206+ $list[NS_MODULE] = 'Module';
 207+ $list[NS_MODULE_TALK] = 'Module_talk';
 208+ return true;
 209+ }
 210+
 211+ public static function validateScript( $editor, $text, $section, &$error ) {
 212+ global $wgUser;
 213+ $title = $editor->mTitle;
 214+
 215+ if( $title->getNamespace() == NS_MODULE ) {
 216+ $engine = Scripting::newDefaultEngine();
 217+ $errors = $engine->validate( $text, $title->getPrefixedDBkey() );
 218+ if( !$errors ) {
 219+ return true;
 220+ }
 221+
 222+ $errmsg = wfMsgExt( 'scripting-error', array( 'parsemag' ), array( count( $errors ) ) );
 223+ if( count( $errors ) == 1 ) {
 224+ $errlines = ': ' . wfEscapeWikiText( $errors[0] );
 225+ } else {
 226+ $errlines = '* ' . implode( "\n* ", array_map( 'wfEscapeWikiText', $errors ) );
 227+ }
 228+ $error = <<<HTML
 229+<div class="errorbox">
 230+{$errmsg}
 231+{$errlines}
 232+</div>
 233+<br clear="all" />
 234+HTML;
 235+
 236+ return true;
 237+ }
 238+
 239+ return true;
 240+ }
 241+}
Property changes on: trunk/extensions/Scribunto/common/Hooks.php
___________________________________________________________________
Added: svn:eol-style
1242 + native
Index: trunk/extensions/Scribunto/common/Common.php
@@ -0,0 +1,85 @@
 2+<?php
 3+
 4+/**
 5+ * Generic scripting functions.
 6+ */
 7+class Scripting {
 8+ const LOCAL = 'local';
 9+
 10+ /**
 11+ * Create a new engine object with specified parameters.
 12+ */
 13+ public static function newEngine( $options ) {
 14+ $class = $options['class'];
 15+ return new $class( $options );
 16+ }
 17+
 18+ /**
 19+ * Create a new engine object with default parameters
 20+ * @param $extraOptions Extra options to pass to the constructor, in addition to the configured options
 21+ */
 22+ public static function newDefaultEngine( $extraOptions = array() ) {
 23+ global $wgScriptingDefaultEngine, $wgScriptingEngineConf;
 24+ if( !$wgScriptingDefaultEngine ) {
 25+ throw new MWException( 'Scripting extension is enabled but $wgScriptingDefaultEngine is not set' );
 26+ }
 27+
 28+ if( !isset( $wgScriptingEngineConf[$wgScriptingDefaultEngine] ) ) {
 29+ throw new MWException( 'Invalid scripting engine is specified in $wgScriptingDefaultEngine' );
 30+ }
 31+ $options = $extraOptions + $wgScriptingEngineConf[$wgScriptingDefaultEngine];
 32+ return self::newEngine( $options );
 33+ }
 34+
 35+ /**
 36+ * Get an engine instance for the given parser, and cache it in the parser
 37+ * so that subsequent calls to this function for the same parser will return
 38+ * the same engine.
 39+ *
 40+ * @param Parser $parser
 41+ */
 42+ public static function getParserEngine( $parser ) {
 43+ if( !isset( $parser->scripting_engine ) || !$parser->scripting_engine ) {
 44+ $parser->scripting_engine = self::newDefaultEngine( array( 'parser' => $parser ) );
 45+ }
 46+ return $parser->scripting_engine;
 47+ }
 48+
 49+ /**
 50+ * Remove the current engine instance from the parser
 51+ */
 52+ public static function resetParserEngine( $parser ) {
 53+ $parser->scripting_engine = null;
 54+ }
 55+}
 56+
 57+/**
 58+ * An exception class which represents an error in the script. This does not
 59+ * normally abort the request, instead it is caught and shown to the user.
 60+ */
 61+class ScriptingException extends MWException {
 62+ var $messageName, $params;
 63+
 64+ function __construct( $messageName, $params = array() ) {
 65+ if ( isset( $params['args'] ) ) {
 66+ $args = $params['args'];
 67+ } else {
 68+ $args = array();
 69+ }
 70+ if ( isset( $params['module'] ) && isset( $params['line'] ) ) {
 71+ $codelocation = wfMsg( 'scripting-codelocation', $params['module'], $params['line'] );
 72+ } else {
 73+ $codelocation = '[UNKNOWN]'; // should never happen
 74+ }
 75+ array_unshift( $args, $codelocation );
 76+ $msg = wfMsgExt( $messageName, array(), $args );
 77+ parent::__construct( $msg );
 78+
 79+ $this->messageName = $messageName;
 80+ $this->params = $params;
 81+ }
 82+
 83+ public function getMessageName() {
 84+ return $this->messageName;
 85+ }
 86+}
Property changes on: trunk/extensions/Scribunto/common/Common.php
___________________________________________________________________
Added: svn:eol-style
187 + native
Index: trunk/extensions/Scribunto/engines/LuaSandbox/Engine.php
@@ -0,0 +1,149 @@
 2+<?php
 3+
 4+class LuaSandboxEngine extends ScriptingEngineBase {
 5+ public $sandbox, $options, $loaded = false;
 6+
 7+ public function newModule( $text, $chunkName ) {
 8+ return new LuaSandboxEngineModule( $this, $text, $chunkName );
 9+ }
 10+
 11+ public function load() {
 12+ if( $this->loaded ) {
 13+ return;
 14+ }
 15+
 16+ if( !MWInit::classExists( 'luasandbox' ) ) {
 17+ throw new MWException( 'luasandbox PHP extension is not installed' );
 18+ }
 19+
 20+ $this->sandbox = new LuaSandbox;
 21+ $this->sandbox->setMemoryLimit( $this->options['memoryLimit'] );
 22+ $this->sandbox->setCPULimit( $this->options['cpuLimit'] );
 23+ $this->sandbox->registerLibrary( 'mw', array( 'import' => array( $this, 'importModule' ) ) );
 24+
 25+ $this->loaded = true;
 26+ }
 27+
 28+ protected function getModuleClassName() {
 29+ return 'LuaSandboxEngineModule';
 30+ }
 31+
 32+ public function getGeSHiLanguage() {
 33+ return 'lua';
 34+ }
 35+
 36+ public function getCodeEditorLanguage() {
 37+ return 'lua';
 38+ }
 39+
 40+ public function getLimitReport() {
 41+ $this->load();
 42+
 43+ $usage = $this->sandbox->getMemoryUsage();
 44+ if( $usage < 8 * 1024 ) {
 45+ $usageStr = $usage . " bytes";
 46+ } elseif( $usage < 8 * 1024 * 1024 ) {
 47+ $usageStr = round( $usage / 1024, 2 ) . " kilobytes";
 48+ } else {
 49+ $usageStr = round( $usage / 1024 / 1024, 2 ) . " megabytes";
 50+ }
 51+
 52+ return "Lua scripts memory usage: {$usageStr}\n";
 53+ }
 54+
 55+ function importModule() {
 56+ $args = func_get_args();
 57+ if( count( $args ) < 1 ) {
 58+ // FIXME: LuaSandbox PHP extension should provide proper context
 59+ throw new ScriptingException( 'scripting-common-toofewargs',
 60+ array( 'args' => array( 'mw.import' ) ) );
 61+ }
 62+
 63+ $title = Title::makeTitleSafe( NS_MODULE, $args[0] );
 64+ if ( !$title ) {
 65+ throw new ScriptingException( 'scripting-common-nosuchmodule' );
 66+ }
 67+ $module = $this->fetchModuleFromParser( $title );
 68+ return $module->getContents();
 69+ }
 70+}
 71+
 72+class LuaSandboxEngineModule extends ScriptingModuleBase {
 73+ protected $initialized;
 74+
 75+ function initialize() {
 76+ if( $this->initialized ) {
 77+ return;
 78+ }
 79+ $this->engine->load();
 80+
 81+ // FIXME: caching?
 82+
 83+ try {
 84+ $this->body = $this->engine->sandbox->loadString(
 85+ $this->code,
 86+ // Prepending an "@" to the chunk name makes Lua think it is a file name
 87+ '@' . $this->chunkName );
 88+ $output = $this->body->call();
 89+ } catch( LuaSandboxError $e ) {
 90+ throw new ScriptingException( 'scripting-luasandbox-error',
 91+ array( 'args' => array( $e->getMessage() ) ) );
 92+ }
 93+
 94+ if( !$output ) {
 95+ throw new ScriptingException( 'scripting-luasandbox-noreturn' );
 96+ }
 97+ if( count( $output ) > 2 ) {
 98+ throw new ScriptingException( 'scripting-luasandbox-toomanyreturns' );
 99+ }
 100+ if( !is_array( $output[0] ) ) {
 101+ throw new ScriptingException( 'scripting-luasandbox-notarrayreturn' );
 102+ }
 103+
 104+ $this->contents = $output[0];
 105+ $this->functions = array();
 106+ foreach( $this->contents as $key => $content ) {
 107+ if( $content instanceof LuaSandboxFunction )
 108+ $this->functions[] = $key;
 109+ }
 110+
 111+ $this->initialized = true;
 112+ }
 113+
 114+ function getFunction( $name ) {
 115+ $this->initialize();
 116+
 117+ if( isset( $this->contents[$name] ) ) {
 118+ return new LuaSandboxEngineFunction( $this, $name, $this->contents[$name] );
 119+ } else {
 120+ return null;
 121+ }
 122+ }
 123+
 124+ function getFunctions() {
 125+ $this->initialize();
 126+ return $this->functions;
 127+ }
 128+
 129+ function getContents() {
 130+ $this->initialize();
 131+ return $this->contents;
 132+ }
 133+}
 134+
 135+class LuaSandboxEngineFunction extends ScriptingFunctionBase {
 136+ public function call( $args, $frame ) {
 137+ try {
 138+ $result = call_user_func_array( array( $this->contents, 'call' ), $args );
 139+ } catch( LuaSandboxError $e ) {
 140+ throw new ScriptingException( 'scripting-luasandbox-error',
 141+ array( 'args' => array( $e->getMessage() ) ) );
 142+ }
 143+
 144+ if ( isset( $result[0] ) ) {
 145+ return $result[0];
 146+ } else {
 147+ return null;
 148+ }
 149+ }
 150+}
Property changes on: trunk/extensions/Scribunto/engines/LuaSandbox/Engine.php
___________________________________________________________________
Added: svn:eol-style
1151 + native

Status & tagging log