Index: trunk/extensions/Scripting/i18n/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/Scripting/i18n/Namespaces.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 10 | + native |
Index: trunk/extensions/Scripting/i18n/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/Scripting/i18n/Magic.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 11 | + native |
Index: trunk/extensions/Scripting/i18n/Messages.php |
— | — | @@ -0,0 +1,18 @@ |
| 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 | + |
| 18 | + 'scripting-exception-luasandbox-error' => 'Lua error: $1', |
| 19 | +); |
Property changes on: trunk/extensions/Scripting/i18n/Messages.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 20 | + native |
Index: trunk/extensions/Scripting/scripting.sql |
— | — | @@ -0,0 +1,16 @@ |
| 2 | +-- |
| 3 | +-- Track script inclusions. |
| 4 | +-- |
| 5 | +CREATE TABLE /*_*/scriptlinks ( |
| 6 | + -- Key to the page_id of the page containing the link. |
| 7 | + sl_from int unsigned NOT NULL default 0, |
| 8 | + |
| 9 | + -- Key to page_title of the target page. |
| 10 | + -- The target page may or may not exist, and due to renames |
| 11 | + -- and deletions may refer to different page records as time |
| 12 | + -- goes by. |
| 13 | + sl_to varchar(255) binary NOT NULL default '' |
| 14 | +) /*$wgDBTableOptions*/; |
| 15 | + |
| 16 | +CREATE UNIQUE INDEX /*i*/sl_from ON /*_*/scriptlinks (sl_from,sl_to); |
| 17 | +CREATE UNIQUE INDEX /*i*/sl_title ON /*_*/scriptlinks (sl_to,sl_from); |
Property changes on: trunk/extensions/Scripting/scripting.sql |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 18 | + native |
Index: trunk/extensions/Scripting/Scripting.i18n.php |
Property changes on: trunk/extensions/Scripting/Scripting.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
2 | 19 | + native |
Index: trunk/extensions/Scripting/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 . 'i18n/Messages.php'; |
| 37 | +$wgExtensionMessagesFiles['ScriptingMagic'] = $dir . 'i18n/Magic.php'; |
| 38 | +$wgExtensionMessagesFiles['ScriptingNamespaces'] = $dir . 'i18n/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['ScriptLinksUpdateHooks'] = $dir.'common/LinkUpdates.php'; |
| 45 | +$wgAutoloadClasses['ScriptingException'] = $dir.'common/Common.php'; |
| 46 | +$wgAutoloadClasses['Scripting'] = $dir.'common/Common.php'; |
| 47 | + |
| 48 | +$wgHooks['ParserFirstCallInit'][] = 'ScriptingHooks::setupParserHook'; |
| 49 | +$wgHooks['ParserLimitReport'][] = 'ScriptingHooks::reportLimits'; |
| 50 | +$wgHooks['ParserClearState'][] = 'ScriptingHooks::clearState'; |
| 51 | +$wgHooks['ParserTestTables'][] = 'ScriptingHooks::addTestTables'; |
| 52 | + |
| 53 | +$wgHooks['CanonicalNamespaces'][] = 'ScriptingHooks::addCanonicalNamespaces'; |
| 54 | +$wgHooks['ArticleViewCustom'][] = 'ScriptingHooks::handleScriptView'; |
| 55 | +$wgHooks['TitleIsWikitextPage'][] = 'ScriptingHooks::isWikitextPage'; |
| 56 | +$wgHooks['EditFilter'][] = 'ScriptingHooks::validateScript'; |
| 57 | + |
| 58 | +$wgHooks['LinksUpdate'][] = 'ScriptLinksUpdateHooks::updateLinks'; |
| 59 | +$wgHooks['ArticleEditUpdates'][] = 'ScriptLinksUpdateHooks::purgeCache'; |
| 60 | +$wgHooks['ParserAfterTidy'][] = 'ScriptLinksUpdateHooks::appendToOutput'; |
| 61 | +$wgHooks['BacklinkCacheGetPrefix'][] = 'ScriptLinksUpdateHooks::getBacklinkCachePrefix'; |
| 62 | +$wgHooks['BacklinkCacheGetConditions'][] = 'ScriptLinksUpdateHooks::getBacklinkCacheConditions'; |
| 63 | + |
| 64 | +/***** Individual engines and their configurations *****/ |
| 65 | + |
| 66 | +/** |
| 67 | + * Available scripting engines. |
| 68 | + */ |
| 69 | +$wgScriptingEngines = array( |
| 70 | + 'luasandbox' => 'LuaSandboxEngine', |
| 71 | +); |
| 72 | + |
| 73 | +$wgAutoloadClasses['LuaSandboxEngine'] = $dir.'engines/LuaSandbox/Engine.php'; |
| 74 | + |
| 75 | +/***** Configuration *****/ |
| 76 | + |
| 77 | +/** |
| 78 | + * The name of the scripting engine. |
| 79 | + */ |
| 80 | +$wgScriptingEngine = false; |
| 81 | + |
| 82 | + |
| 83 | +$wgScriptingEngineConf = array(); |
| 84 | + |
| 85 | +/** |
| 86 | + * Script namespace numbers. Should be redefined before |
| 87 | + * the inlcusion of the extension. |
| 88 | + */ |
| 89 | +if( !isset( $wgScriptingNamespaceNumbers ) ) { |
| 90 | + $wgScriptingNamespaceNumbers = array( |
| 91 | + 'Module' => 20, |
| 92 | + 'Module_talk' => 21, |
| 93 | + ); |
| 94 | +} |
| 95 | + |
| 96 | +/** |
| 97 | + * Turn on to true if you have linked or copied wikiscripts.php and |
| 98 | + * SyntaxHighlight_GeSHi extension is enabled. |
| 99 | + */ |
| 100 | +$wgScriptingUseGeSHi = false; |
| 101 | + |
| 102 | +define( 'NS_MODULE', $wgScriptingNamespaceNumbers['Module'] ); |
| 103 | +define( 'NS_MODULE_TALK', $wgScriptingNamespaceNumbers['Module_talk'] ); |
Property changes on: trunk/extensions/Scripting/Scripting.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 104 | + native |
Index: trunk/extensions/Scripting/common/Base.php |
— | — | @@ -0,0 +1,251 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Wikitext scripting infrastructure for MediaWiki: base classes. |
| 6 | + * Copyright (C) 2012 Victor Vasiliev <vasilvv@gmail.com> et al |
| 7 | + * Based on MediaWiki file LinksUpdate.php |
| 8 | + * http://www.mediawiki.org/ |
| 9 | + * |
| 10 | + * This program is free software; you can redistribute it and/or modify |
| 11 | + * it under the terms of the GNU General Public License as published by |
| 12 | + * the Free Software Foundation; either version 2 of the License, or |
| 13 | + * (at your option) any later version. |
| 14 | + * |
| 15 | + * This program is distributed in the hope that it will be useful, |
| 16 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | + * GNU General Public License for more details. |
| 19 | + * |
| 20 | + * You should have received a copy of the GNU General Public License along |
| 21 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 22 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 23 | + * http://www.gnu.org/copyleft/gpl.html |
| 24 | + */ |
| 25 | + |
| 26 | +/** |
| 27 | + * Base class for all scripting engines. Includes all code |
| 28 | + * not related to particular modules, like tracking links between |
| 29 | + * modules or loading module texts. |
| 30 | + */ |
| 31 | +abstract class ScriptingEngineBase { |
| 32 | + protected |
| 33 | + $mParser, |
| 34 | + $mModules = array(), |
| 35 | + $mModuleTitles = array(), |
| 36 | + $mLoaded = false; |
| 37 | + |
| 38 | + /** |
| 39 | + * Required for the lazy-loading of the engine. Should have a sentinel |
| 40 | + * inside checking whether it is already loaded. |
| 41 | + */ |
| 42 | + abstract public function load(); |
| 43 | + |
| 44 | + /** |
| 45 | + * Returns the name of your module class. |
| 46 | + */ |
| 47 | + abstract protected function getModuleClassName(); |
| 48 | + |
| 49 | + /** |
| 50 | + * Returns the default options of the engine. |
| 51 | + */ |
| 52 | + abstract public function getDefaultOptions(); |
| 53 | + |
| 54 | + /** |
| 55 | + * Is called by setOptions() in order to notify the engine |
| 56 | + * that the options were changed. |
| 57 | + */ |
| 58 | + protected function updateOptions() { /* No-op */ } |
| 59 | + |
| 60 | + /** |
| 61 | + * Constructor. |
| 62 | + * |
| 63 | + * @param $parser Parser Wikitext parser |
| 64 | + */ |
| 65 | + public final function __construct( $parser ) { |
| 66 | + $this->mParser = $parser; |
| 67 | + } |
| 68 | + |
| 69 | + /** |
| 70 | + * Loads the module either from instance cache or from the actual revision. |
| 71 | + * Does not initialize the module, i.e. do not expect it to complain if the module |
| 72 | + * text is garbage or has syntax error. Returns a module or throws an exception. |
| 73 | + * |
| 74 | + * @param $title Title/string The title or the name of the module. |
| 75 | + * @param $source string Source of the module |
| 76 | + * @return ScriptingEngineModule |
| 77 | + */ |
| 78 | + public function getModule( $title, $source = Scripting::Local ) { |
| 79 | + // Convert string to title |
| 80 | + if( !$title instanceof Title ) { |
| 81 | + $titleobj = Title::newFromText( (string)$title, NS_MODULE ); |
| 82 | + if( !$titleobj || $titleobj->getNamespace() != NS_MODULE ) { |
| 83 | + throw new ScriptingException( 'badtitle', 'common' ); // scripting-exceptions-common-badtitle |
| 84 | + } |
| 85 | + $title = $titleobj; |
| 86 | + } |
| 87 | + |
| 88 | + // Check if it is already loaded |
| 89 | + $key = $title->getPrefixedText(); |
| 90 | + if( !isset( $this->mModules[$key] ) ) { |
| 91 | + // Fetch the text |
| 92 | + $rev = $this->getModuleRev( $title, $source ); |
| 93 | + if( !$rev ) { |
| 94 | + throw new ScriptingException( 'nosuchmodule', 'common' ); // scripting-exceptions-common-nosuchmodule |
| 95 | + } |
| 96 | + if( $rev->getTitle()->getNamespace() != NS_MODULE ) { |
| 97 | + throw new ScriptingException( 'badnamespace', 'common' ); // scripting-exceptions-common-badnamespace |
| 98 | + } |
| 99 | + |
| 100 | + // Create the class |
| 101 | + $class = $this->getModuleClassName(); |
| 102 | + $this->mModules[$key] = new $class( $this, $title, $rev->getText(), $rev->getID(), $source ); |
| 103 | + $this->mModuleTitles[] = $title; |
| 104 | + } |
| 105 | + return $this->mModules[$key]; |
| 106 | + } |
| 107 | + |
| 108 | + /** |
| 109 | + * Fetches the revision for given module title. |
| 110 | + */ |
| 111 | + private function getModuleRev( $title, $source ) { |
| 112 | + if( $source != Scripting::Local ) { |
| 113 | + throw new MWException( 'Non-local scripts are not supported at this point' ); |
| 114 | + } |
| 115 | + |
| 116 | + $rev = Revision::newFromTitle( $title ); |
| 117 | + if( $rev && $real = Title::newFromRedirect( $rev->getText() ) ) { |
| 118 | + $rev = Revision::newFromTitle( $real ); |
| 119 | + } |
| 120 | + return $rev; |
| 121 | + } |
| 122 | + |
| 123 | + /** |
| 124 | + * Sets the engine-specific options from $wgScriptingEngineConf. |
| 125 | + */ |
| 126 | + function setOptions( $options ) { |
| 127 | + $this->mOptions = array_merge( $this->getDefaultOptions(), $options ); |
| 128 | + $this->updateOptions(); |
| 129 | + } |
| 130 | + |
| 131 | + /** |
| 132 | + * Validates the script and returns an array of the syntax erros for the |
| 133 | + * given code. |
| 134 | + * |
| 135 | + * @param $code Code to validate |
| 136 | + * @param $title Title of the code page |
| 137 | + * @return array |
| 138 | + */ |
| 139 | + function validate( $code, $title ) { |
| 140 | + $class = $this->getModuleClassName(); |
| 141 | + $module = new $class( $this, $title, $code, 0, Scripting::Local ); |
| 142 | + |
| 143 | + try { |
| 144 | + $module->initialize(); |
| 145 | + } catch( ScriptingException $e ) { |
| 146 | + return array( $e->getMessage() ); |
| 147 | + } |
| 148 | + |
| 149 | + return array(); |
| 150 | + } |
| 151 | + |
| 152 | + /** |
| 153 | + * Allows the engine to append their information to the limits |
| 154 | + * report. |
| 155 | + */ |
| 156 | + public function getLimitsReport() { |
| 157 | + /* No-op by default */ |
| 158 | + return ''; |
| 159 | + } |
| 160 | + |
| 161 | + /** |
| 162 | + * Returns the titles of all the modules used by this instance of the |
| 163 | + * engine. |
| 164 | + */ |
| 165 | + public function getUsedModules() { |
| 166 | + return $this->mModuleTitles; |
| 167 | + } |
| 168 | + |
| 169 | + /** |
| 170 | + * Invalidates the cache of the given module by its title. Should be |
| 171 | + * redefined if the engine uses any form of bytecode or other cache. |
| 172 | + */ |
| 173 | + function invalidateModuleCache( $title ) { |
| 174 | + /* No-op by default */ |
| 175 | + } |
| 176 | + |
| 177 | + /** |
| 178 | + * Get the language code for GeSHi syntax highlighter. |
| 179 | + */ |
| 180 | + function getGeSHiLangauge() { |
| 181 | + return false; |
| 182 | + } |
| 183 | +} |
| 184 | + |
| 185 | +/** |
| 186 | + * Class that represents a module. Responsible for initial module parsing |
| 187 | + * and maintaining the contents of the module. |
| 188 | + */ |
| 189 | +abstract class ScriptingModuleBase { |
| 190 | + var $mEngine, $mTitle, $mCode, $mRevisionID, $mSource; |
| 191 | + |
| 192 | + public final function __construct( $engine, $title, $code, $revisionID, $source ) { |
| 193 | + $this->mEngine = $engine; |
| 194 | + $this->mTitle = $title; |
| 195 | + $this->mCode = $code; |
| 196 | + $this->mRevisionID = $revisionID; |
| 197 | + $this->mSource = $source; |
| 198 | + } |
| 199 | + |
| 200 | + /** Accessors **/ |
| 201 | + public function getEngine() { return $this->mEngine; } |
| 202 | + public function getTitle() { return $this->mTitle; } |
| 203 | + public function getCode() { return $this->mCode; } |
| 204 | + public function getRevisionID() { return $this->mRevisionID; } |
| 205 | + public function getSource() { return $this->mSource; } |
| 206 | + |
| 207 | + /** |
| 208 | + * Initialize the module. That means parse it and load the |
| 209 | + * functions/constants/whatever into the object. |
| 210 | + * |
| 211 | + * Protection of double-initialization is the responsibility of this method. |
| 212 | + */ |
| 213 | + abstract function initialize(); |
| 214 | + |
| 215 | + /** |
| 216 | + * Returns the object for a given function. Should return null if it does not exist. |
| 217 | + * |
| 218 | + * @return ScriptingFunctionBase or null |
| 219 | + */ |
| 220 | + abstract function getFunction( $name ); |
| 221 | + |
| 222 | + /** |
| 223 | + * Returns the list of the functions in the module. |
| 224 | + * |
| 225 | + * @return array(string) |
| 226 | + */ |
| 227 | + abstract function getFunctions(); |
| 228 | +} |
| 229 | + |
| 230 | +abstract class ScriptingFunctionBase { |
| 231 | + protected $mName, $mContents, $mModule, $mEngine; |
| 232 | + |
| 233 | + public final function __construct( $name, $contents, $module, $engine ) { |
| 234 | + $this->mName = $name; |
| 235 | + $this->mContents = $contents; |
| 236 | + $this->mModule = $module; |
| 237 | + $this->mEngine = $engine; |
| 238 | + } |
| 239 | + |
| 240 | + /** |
| 241 | + * Calls the function. Returns its first result or null if no result. |
| 242 | + * |
| 243 | + * @param $args array Arguments to the function |
| 244 | + * @param $frame PPFrame |
| 245 | + */ |
| 246 | + abstract public function call( $args, $frame ); |
| 247 | + |
| 248 | + /** Accessors **/ |
| 249 | + public function getName() { return $this->mName; } |
| 250 | + public function getModule() { return $this->mModule; } |
| 251 | + public function getEngine() { return $this->mEngine; } |
| 252 | +} |
Property changes on: trunk/extensions/Scripting/common/Base.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 253 | + native |
Index: trunk/extensions/Scripting/common/Hooks.php |
— | — | @@ -0,0 +1,224 @@ |
| 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 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 interpreter is to be reset. |
| 40 | + * |
| 41 | + * @static |
| 42 | + * @param $parser Parser |
| 43 | + * @return bool |
| 44 | + */ |
| 45 | + public static function clearState( &$parser ) { |
| 46 | + Scripting::resetEngine( $parser ); |
| 47 | + return true; |
| 48 | + } |
| 49 | + |
| 50 | + /** |
| 51 | + * Adds scriptlinks table to parser tests. |
| 52 | + */ |
| 53 | + public static function addTestTables( &$tables ) { |
| 54 | + $tables[] = 'scriptlinks'; |
| 55 | + return true; |
| 56 | + } |
| 57 | + |
| 58 | + /** |
| 59 | + * Handles the {{#invoke:module|func}} construction. |
| 60 | + * |
| 61 | + * @static |
| 62 | + * @param $parser Parser |
| 63 | + * @param $frame |
| 64 | + * @param $args |
| 65 | + * @return string |
| 66 | + */ |
| 67 | + public static function callHook( &$parser, $frame, $args ) { |
| 68 | + if( count( $args ) < 2 ) { |
| 69 | + throw new ScriptingException( 'nofunction', 'common' ); // scripting-exceptions-common-nofunction |
| 70 | + } |
| 71 | + |
| 72 | + $module = $parser->mStripState->unstripBoth( array_shift( $args ) ); |
| 73 | + $function = $frame->expand( array_shift( $args ) ); |
| 74 | + return self::doRunHook( $parser, $frame, $module, $function, $args ); |
| 75 | + } |
| 76 | + |
| 77 | + /** |
| 78 | + * Handles the transclusion of the script ({{script:module}} hook). |
| 79 | + * |
| 80 | + * @static |
| 81 | + * @param $parser Parser |
| 82 | + * @param $frame |
| 83 | + * @param $args |
| 84 | + * @return string |
| 85 | + */ |
| 86 | + public static function transcludeHook( &$parser, $frame, $args ) { |
| 87 | + $module = $parser->mStripState->unstripBoth( array_shift( $args ) ); |
| 88 | + return self::doRunHook( $parser, $frame, $module, 'main', $args ); |
| 89 | + } |
| 90 | + |
| 91 | + private static function doRunHook( &$parser, $frame, $module, $function, $args ) { |
| 92 | + wfProfileIn( __METHOD__ ); |
| 93 | + |
| 94 | + try { |
| 95 | + $engine = Scripting::getEngine( $parser ); |
| 96 | + |
| 97 | + foreach( $args as &$arg ) { |
| 98 | + $arg = $frame->expand( $arg ); |
| 99 | + } |
| 100 | + |
| 101 | + $module = $engine->getModule( $module, Scripting::Local ); |
| 102 | + |
| 103 | + $functionObj = $module->getFunction( $function ); |
| 104 | + if( !$functionObj ) { |
| 105 | + throw new ScriptingException( 'nosuchfunction', 'common' ); // scripting-exceptions-common-nosuchfunction |
| 106 | + } |
| 107 | + |
| 108 | + $result = $functionObj->call( $args, $frame ); |
| 109 | + |
| 110 | + wfProfileOut( __METHOD__ ); |
| 111 | + return trim( $result ); |
| 112 | + } catch( ScriptingException $e ) { |
| 113 | + $msg = $e->getMessage(); |
| 114 | + wfProfileOut( __METHOD__ ); |
| 115 | + return "<strong class=\"error\">{$msg}</strong>"; |
| 116 | + } |
| 117 | + } |
| 118 | + |
| 119 | + /** |
| 120 | + * Overrides the standard view for modules. Enables syntax highlighting when |
| 121 | + * possible. |
| 122 | + * |
| 123 | + * @static |
| 124 | + * @param $text |
| 125 | + * @param $title Title |
| 126 | + * @param $output OutputPage |
| 127 | + * @return bool |
| 128 | + */ |
| 129 | + public static function handleScriptView( $text, $title, $output ) { |
| 130 | + global $wgScriptingUseGeSHi, $wgParser; |
| 131 | + |
| 132 | + if( $title->getNamespace() == NS_MODULE ) { |
| 133 | + $engine = Scripting::getEngine( $wgParser ); |
| 134 | + $language = $engine->getGeSHiLangauge(); |
| 135 | + |
| 136 | + if( $wgScriptingUseGeSHi && $language ) { |
| 137 | + $geshi = SyntaxHighlight_GeSHi::prepare( $text, $language ); |
| 138 | + $geshi->set_language( $language ); |
| 139 | + if( $geshi instanceof GeSHi && !$geshi->error() ) { |
| 140 | + $code = $geshi->parse_code(); |
| 141 | + if( $code ) { |
| 142 | + $output->addHeadItem( "source-{$language}", SyntaxHighlight_GeSHi::buildHeadItem( $geshi ) ); |
| 143 | + $output->addHTML( "<div dir=\"ltr\">{$code}</div>" ); |
| 144 | + return false; |
| 145 | + } |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | + // No GeSHi, or GeSHi can't parse it, use plain <pre> |
| 150 | + $output->addHTML( "<pre class=\"mw-code mw-script\" dir=\"ltr\">\n" ); |
| 151 | + $output->addHTML( htmlspecialchars( $text ) ); |
| 152 | + $output->addHTML( "\n</pre>\n" ); |
| 153 | + return false; |
| 154 | + } else { |
| 155 | + return true; |
| 156 | + } |
| 157 | + } |
| 158 | + |
| 159 | + /** |
| 160 | + * Indicates that modules are not wikitext. |
| 161 | + */ |
| 162 | + public static function isWikitextPage( $title, &$result ) { |
| 163 | + if( $title->getNamespace() == NS_MODULE ) { |
| 164 | + $result = false; |
| 165 | + return false; |
| 166 | + } |
| 167 | + return true; |
| 168 | + } |
| 169 | + |
| 170 | + /** |
| 171 | + * Adds report of number of evaluations by the single wikitext page. |
| 172 | + * |
| 173 | + * @static |
| 174 | + * @param $parser Parser |
| 175 | + * @param $report |
| 176 | + * @return bool |
| 177 | + */ |
| 178 | + public static function reportLimits( $parser, &$report ) { |
| 179 | + # FIXME |
| 180 | + global $wgScriptsLimits; |
| 181 | + $engine = Scripting::getEngine( $parser ); |
| 182 | + $report .= $engine->getLimitsReport(); |
| 183 | + return true; |
| 184 | + } |
| 185 | + |
| 186 | + /** |
| 187 | + * Adds the module namespaces. |
| 188 | + */ |
| 189 | + public static function addCanonicalNamespaces( &$list ) { |
| 190 | + $list[NS_MODULE] = 'Module'; |
| 191 | + $list[NS_MODULE_TALK] = 'Module_talk'; |
| 192 | + return true; |
| 193 | + } |
| 194 | + |
| 195 | + public static function validateScript( $editor, $text, $section, &$error ) { |
| 196 | + global $wgUser, $wgParser; |
| 197 | + $title = $editor->mTitle; |
| 198 | + |
| 199 | + if( $title->getNamespace() == NS_MODULE ) { |
| 200 | + $engine = Scripting::getEngine( $wgParser ); |
| 201 | + $errors = $engine->validate( $text, $title ); |
| 202 | + if( !$errors ) { |
| 203 | + return true; |
| 204 | + } |
| 205 | + |
| 206 | + $errmsg = wfMsgExt( 'scripting-error', array( 'parsemag' ), array( count( $errors ) ) ); |
| 207 | + if( count( $errors ) == 1 ) { |
| 208 | + $errlines = ': ' . wfEscapeWikiText( $errors[0] ); |
| 209 | + } else { |
| 210 | + $errlines = '* ' . implode( "\n* ", array_map( 'wfEscapeWikiText', $errors ) ); |
| 211 | + } |
| 212 | + $error = <<<HTML |
| 213 | +<div class="errorbox"> |
| 214 | +{$errmsg} |
| 215 | +{$errlines} |
| 216 | +</div> |
| 217 | +<br clear="all" /> |
| 218 | +HTML; |
| 219 | + |
| 220 | + return true; |
| 221 | + } |
| 222 | + |
| 223 | + return true; |
| 224 | + } |
| 225 | +} |
Property changes on: trunk/extensions/Scripting/common/Hooks.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 226 | + native |
Index: trunk/extensions/Scripting/common/LinkUpdates.php |
— | — | @@ -0,0 +1,201 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Wikitext scripting infrastructure for MediaWiki: link updating code |
| 5 | + * Copyright (C) 2011-2012 Victor Vasiliev <vasilvv@gmail.com> et al |
| 6 | + * Based on MediaWiki file LinksUpdate.php |
| 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 | +if( !defined( 'MEDIAWIKI' ) ) |
| 26 | + die(); |
| 27 | + |
| 28 | + |
| 29 | +/** |
| 30 | + * Class that contains hooks related to tracking links to scripts and invalidating |
| 31 | + * pages on script change. |
| 32 | + */ |
| 33 | +class ScriptLinksUpdateHooks { |
| 34 | + /** |
| 35 | + * Appends script links to the output. |
| 36 | + */ |
| 37 | + public static function appendToOutput( &$parser, &$text ) { |
| 38 | + if( isset( $parser->scripting_engine ) ) { |
| 39 | + $parser->mOutput->scripting_links = $parser->scripting_engine->getUsedModules(); |
| 40 | + } |
| 41 | + return true; |
| 42 | + } |
| 43 | + |
| 44 | + /** |
| 45 | + * Runs the link updater. |
| 46 | + */ |
| 47 | + public static function updateLinks( &$update ) { |
| 48 | + $output = $update->mParserOutput; |
| 49 | + if( isset( $output->scripting_links ) ) { |
| 50 | + $new = $output->scripting_links; |
| 51 | + } else { |
| 52 | + $new = array(); |
| 53 | + } |
| 54 | + |
| 55 | + $isupdate = new ScriptLinksUpdate( $update, $new ); |
| 56 | + $isupdate->run(); |
| 57 | + return true; |
| 58 | + } |
| 59 | + |
| 60 | + /** |
| 61 | + * Purges cache for all the pages where the script is used. |
| 62 | + */ |
| 63 | + public static function purgeCache( &$article, &$editInfo, $changed ) { |
| 64 | + global $wgDeferredUpdateList, $wgParser; |
| 65 | + |
| 66 | + if( $article->mTitle->getNamespace() == NS_MODULE ) { |
| 67 | + // Invalidate the script cache |
| 68 | + $engine = Scripting::getEngine( $wgParser ); |
| 69 | + $engine->invalidateModuleCache( $article->mTitle ); |
| 70 | + |
| 71 | + // Invalidate caches of articles which include the script |
| 72 | + $wgDeferredUpdateList[] = new HTMLCacheUpdate( $article->mTitle, 'scriptlinks' ); |
| 73 | + } |
| 74 | + |
| 75 | + return true; |
| 76 | + } |
| 77 | + |
| 78 | + /** |
| 79 | + * Adds scriptlinks to the list of tables supported by BacklinkCache. |
| 80 | + */ |
| 81 | + public static function getBacklinkCachePrefix( $table, &$prefix ) { |
| 82 | + if( $table == 'scriptlinks' ) { |
| 83 | + $prefix = 'sl'; |
| 84 | + return false; |
| 85 | + } else { |
| 86 | + return true; |
| 87 | + } |
| 88 | + } |
| 89 | + |
| 90 | + /** |
| 91 | + * Adds scriptlinks to the list of tables supported by BacklinkCache. |
| 92 | + */ |
| 93 | + public static function getBacklinkCacheConditions( $table, $title, &$conds ) { |
| 94 | + if( $table == 'scriptlinks' ) { |
| 95 | + $conds = array( |
| 96 | + 'sl_to' => $title->getDBkey(), |
| 97 | + 'page_id=sl_from' |
| 98 | + ); |
| 99 | + return false; |
| 100 | + } else { |
| 101 | + return true; |
| 102 | + } |
| 103 | + } |
| 104 | +} |
| 105 | + |
| 106 | +/** |
| 107 | + * A class that updates links on scripts like phase3/includes/LinksUpdate.php does that |
| 108 | + * with templates. |
| 109 | + */ |
| 110 | +class ScriptLinksUpdate { |
| 111 | + var $mUpdate, $mId, $mNew; |
| 112 | + |
| 113 | + public function __construct( $update, $new ) { |
| 114 | + $this->mUpdate = $update; |
| 115 | + $this->mId = $update->mId; |
| 116 | + $this->mNew = $new; |
| 117 | + } |
| 118 | + |
| 119 | + public function run() { |
| 120 | + global $wgUseDumbLinkUpdate; |
| 121 | + |
| 122 | + wfProfileIn( __METHOD__ ); |
| 123 | + |
| 124 | + if( $wgUseDumbLinkUpdate ) { |
| 125 | + $this->mUpdate->dumbTableUpdate( 'scriptlinks', $this->getScriptInsertions(), 'sl_from' ); |
| 126 | + } else { |
| 127 | + $existing = $this->getExistingScripts(); |
| 128 | + $this->mUpdate->incrTableUpdate( 'scriptlinks', 'sl', $this->getScriptDeletions( $existing ), |
| 129 | + $this->getScriptInsertions( $existing ) ); |
| 130 | + } |
| 131 | + |
| 132 | + if( $this->mUpdate->mRecursive && $this->mUpdate->mTitle->getNamespace() == NS_MODULE ) { |
| 133 | + $this->queueRecursiveJobs(); |
| 134 | + } |
| 135 | + |
| 136 | + wfProfileOut( __METHOD__ ); |
| 137 | + } |
| 138 | + |
| 139 | + protected function getExistingScripts() { |
| 140 | + $result = array(); |
| 141 | + |
| 142 | + $res = $this->mUpdate->mDb->select( 'scriptlinks', array( 'sl_to' ), |
| 143 | + array( 'sl_from' => $this->mId ), __METHOD__, $this->mUpdate->mOptions ); |
| 144 | + foreach ( $res as $row ) { |
| 145 | + $result[] = $row->sl_to; |
| 146 | + } |
| 147 | + |
| 148 | + return $result; |
| 149 | + } |
| 150 | + |
| 151 | + protected function getScriptInsertions( $existing = array() ) { |
| 152 | + $result = array(); |
| 153 | + |
| 154 | + foreach( array_diff( $this->mNew, $existing ) as $module ) { |
| 155 | + $result[] = array( |
| 156 | + 'sl_from' => $this->mId, |
| 157 | + 'sl_to' => $module, |
| 158 | + ); |
| 159 | + } |
| 160 | + |
| 161 | + return $result; |
| 162 | + } |
| 163 | + |
| 164 | + protected function getScriptDeletions( $existing = array() ) { |
| 165 | + $result = array(); |
| 166 | + |
| 167 | + foreach( array_diff( $existing, $this->mNew ) as $module ) { |
| 168 | + $result[] = array( |
| 169 | + 'sl_from' => $this->mId, |
| 170 | + 'sl_to' => $module, |
| 171 | + ); |
| 172 | + } |
| 173 | + |
| 174 | + return $result; |
| 175 | + } |
| 176 | + |
| 177 | + protected function queueRecursiveJobs() { |
| 178 | + global $wgUpdateRowsPerJob; |
| 179 | + wfProfileIn( __METHOD__ ); |
| 180 | + |
| 181 | + $cache = $this->mUpdate->mTitle->getBacklinkCache(); |
| 182 | + $batches = $cache->partition( 'scriptlinks', $wgUpdateRowsPerJob ); |
| 183 | + if ( !$batches ) { |
| 184 | + wfProfileOut( __METHOD__ ); |
| 185 | + return; |
| 186 | + } |
| 187 | + $jobs = array(); |
| 188 | + foreach ( $batches as $batch ) { |
| 189 | + list( $start, $end ) = $batch; |
| 190 | + $params = array( |
| 191 | + 'table' => 'scriptlinks', |
| 192 | + 'start' => $start, |
| 193 | + 'end' => $end, |
| 194 | + ); |
| 195 | + $jobs[] = new RefreshLinksJob2( $this->mUpdate->mTitle, $params ); |
| 196 | + } |
| 197 | + Job::batchInsert( $jobs ); |
| 198 | + |
| 199 | + wfProfileOut( __METHOD__ ); |
| 200 | + } |
| 201 | +} |
| 202 | + |
Property changes on: trunk/extensions/Scripting/common/LinkUpdates.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 203 | + native |
Index: trunk/extensions/Scripting/common/Common.php |
— | — | @@ -0,0 +1,63 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Generic scripting functions. |
| 6 | + */ |
| 7 | +class Scripting { |
| 8 | + const Local = 'local'; |
| 9 | + |
| 10 | + protected static function getEngineClass() { |
| 11 | + global $wgScriptingEngine, $wgScriptingEngines; |
| 12 | + |
| 13 | + if( !$wgScriptingEngine ) { |
| 14 | + throw new MWException( 'Scripting extension is enabled but $wgScriptingEngine is not set' ); |
| 15 | + } |
| 16 | + |
| 17 | + if( !isset( $wgScriptingEngines[$wgScriptingEngine] ) ) { |
| 18 | + throw new MWException( 'Invalid scripting engine is specified in $wgScriptingEngine' ); |
| 19 | + } |
| 20 | + |
| 21 | + return $wgScriptingEngines[$wgScriptingEngine]; |
| 22 | + } |
| 23 | + |
| 24 | + public static function getEngine( $parser ) { |
| 25 | + global $wgScriptingEngineConf; |
| 26 | + |
| 27 | + if( !isset( $parser->scripting_engine ) || !$parser->scripting_engine ) { |
| 28 | + $class = self::getEngineClass(); |
| 29 | + $parser->scripting_engine = new $class( $parser ); |
| 30 | + $parser->scripting_engine->setOptions( $wgScriptingEngineConf ); |
| 31 | + } |
| 32 | + return $parser->scripting_engine; |
| 33 | + } |
| 34 | + |
| 35 | + public static function resetEngine( $parser ) { |
| 36 | + $parser->scripting_engine = null; |
| 37 | + } |
| 38 | +} |
| 39 | + |
| 40 | +/** |
| 41 | + * Exceptions which represents user-originating error in the script. |
| 42 | + * Please do not use it for internal errors like "oh god, this should have never happened". |
| 43 | + * Use casual MWException for that. |
| 44 | + */ |
| 45 | +class ScriptingException extends MWException { |
| 46 | + function __construct( $exceptionID, $engine, $module = null, $line = null, $params = array() ) { |
| 47 | + if( $module ) { |
| 48 | + $codelocation = wfMsg( 'scripting-codelocation', $module, $line ); |
| 49 | + $msg = wfMsgExt( "scripting-exception-{$engine}-{$exceptionID}", array(), array_merge( array( $codelocation ), $params ) ); |
| 50 | + } else { |
| 51 | + $msg = wfMsgExt( "scripting-exception-{$engine}-{$exceptionID}", array(), $params ); |
| 52 | + } |
| 53 | + parent::__construct( $msg ); |
| 54 | + |
| 55 | + $this->mExceptionID = $exceptionID; |
| 56 | + $this->mLine = $line; |
| 57 | + $this->mModule = $module; |
| 58 | + $this->mParams = $params; |
| 59 | + } |
| 60 | + |
| 61 | + public function getExceptionID() { |
| 62 | + return $this->mExceptionID; |
| 63 | + } |
| 64 | +} |
Property changes on: trunk/extensions/Scripting/common/Common.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 65 | + native |
Index: trunk/extensions/Scripting/engines/LuaSandbox/Engine.php |
— | — | @@ -0,0 +1,140 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class LuaSandboxEngine extends ScriptingEngineBase { |
| 5 | + public $mSandbox; |
| 6 | + |
| 7 | + public function load() { |
| 8 | + if( $this->mLoaded ) |
| 9 | + return; |
| 10 | + |
| 11 | + if( !class_exists('luasandbox') ) { |
| 12 | + throw new MWException( 'luasandbox PHP extension is not installed' ); |
| 13 | + } |
| 14 | + |
| 15 | + $this->mSandbox = new LuaSandbox; |
| 16 | + $this->mSandbox->setMemoryLimit( $this->mOptions['memoryLimit'] ); |
| 17 | + $this->mSandbox->setCPULimit( $this->mOptions['maxCPU'] ); |
| 18 | + $this->mSandbox->registerLibrary( 'mw', array( 'import' => array( $this, 'importModule' ) ) ); |
| 19 | + |
| 20 | + $this->mLoaded = true; |
| 21 | + } |
| 22 | + |
| 23 | + protected function updateOptions() { |
| 24 | + if( $this->mLoaded ) { |
| 25 | + $this->mSandbox->setMemoryLimit( $this->mOptions['memoryLimit'] ); |
| 26 | + $this->mSandbox->setCPULimit( $this->mOptions['maxCPU'] ); |
| 27 | + } |
| 28 | + } |
| 29 | + |
| 30 | + protected function getModuleClassName() { |
| 31 | + return 'LuaSandboxEngineModule'; |
| 32 | + } |
| 33 | + |
| 34 | + public function getDefaultOptions() { |
| 35 | + return array( |
| 36 | + 'memoryLimit' => 50 * 1024 * 1024, |
| 37 | + 'maxCPU' => 7, |
| 38 | + ); |
| 39 | + } |
| 40 | + |
| 41 | + public function getGeSHiLangauge() { |
| 42 | + return 'lua'; |
| 43 | + } |
| 44 | + |
| 45 | + public function getLimitsReport() { |
| 46 | + $this->load(); |
| 47 | + |
| 48 | + $usage = $this->mSandbox->getMemoryUsage(); |
| 49 | + if( $usage < 8 * 1024 ) { |
| 50 | + $usageStr = $usage . " bytes"; |
| 51 | + } elseif( $usage < 8 * 1024 * 1024 ) { |
| 52 | + $usageStr = round( $usage / 1024, 2 ) . " kilobytes"; |
| 53 | + } else { |
| 54 | + $usageStr = round( $usage / 1024 / 1024, 2 ) . " megabytes"; |
| 55 | + } |
| 56 | + |
| 57 | + return "Lua scripts memory usage: {$usageStr}\n"; |
| 58 | + } |
| 59 | + |
| 60 | + function importModule() { |
| 61 | + // FIXME: luasandbox segfaults on exceptions |
| 62 | + try { |
| 63 | + $args = func_get_args(); |
| 64 | + if( count( $args ) < 1 ) { |
| 65 | + // FIXME: LuaSandbox PHP extension should provide proper context |
| 66 | + throw new ScriptingException( 'toofewargs', 'common', null, null, array( 'mw.import' ) ); |
| 67 | + } |
| 68 | + |
| 69 | + $module = $this->getModule( $args[0] ); |
| 70 | + $module->initialize(); |
| 71 | + return $module->mContents; |
| 72 | + } catch( ScriptingException $e ) { |
| 73 | + return null; |
| 74 | + } |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +class LuaSandboxEngineModule extends ScriptingModuleBase { |
| 79 | + protected $mInitialized; |
| 80 | + |
| 81 | + function initialize() { |
| 82 | + if( $this->mInitialized ) |
| 83 | + return; |
| 84 | + $this->mEngine->load(); |
| 85 | + |
| 86 | + // FIXME: caching? |
| 87 | + |
| 88 | + try { |
| 89 | + $this->mBody = $this->mEngine->mSandbox->loadString( $this->mCode ); |
| 90 | + $output = $this->mBody->call(); |
| 91 | + } catch( LuaSandboxError $e ) { |
| 92 | + throw new ScriptingException( 'error', 'luasandbox', null, null, array( $e->getMessage() ) ); |
| 93 | + } |
| 94 | + |
| 95 | + if( !$output ) { |
| 96 | + throw new ScriptingException( 'noreturn', 'luasandbox' ); |
| 97 | + } |
| 98 | + if( count( $output ) > 2 ) { |
| 99 | + throw new ScriptingException( 'toomanyreturns', 'luasandbox' ); |
| 100 | + } |
| 101 | + if( !is_array( $output[0] ) ) { |
| 102 | + throw new ScriptingException( 'notarrayreturn', 'luasandbox' ); |
| 103 | + } |
| 104 | + |
| 105 | + $this->mContents = $output[0]; |
| 106 | + $this->mFunctions = array(); |
| 107 | + foreach( $this->mContents as $key => $content ) { |
| 108 | + if( $content instanceof LuaSandboxFunction ) |
| 109 | + $this->mFunctions[] = $key; |
| 110 | + } |
| 111 | + |
| 112 | + $this->mInitialized = true; |
| 113 | + } |
| 114 | + |
| 115 | + function getFunction( $name ) { |
| 116 | + $this->initialize(); |
| 117 | + |
| 118 | + if( isset( $this->mContents[$name] ) ) { |
| 119 | + return new LuaSandboxEngineFunction( $name, $this->mContents[$name], $this, $this->mEngine ); |
| 120 | + } else { |
| 121 | + return null; |
| 122 | + } |
| 123 | + } |
| 124 | + |
| 125 | + function getFunctions() { |
| 126 | + $this->initialize(); |
| 127 | + return $this->mFunctions; |
| 128 | + } |
| 129 | +} |
| 130 | + |
| 131 | +class LuaSandboxEngineFunction extends ScriptingFunctionBase { |
| 132 | + public function call( $args, $frame ) { |
| 133 | + try { |
| 134 | + $result = call_user_func_array( array( $this->mContents, 'call' ), $args ); |
| 135 | + } catch( LuaSandboxError $e ) { |
| 136 | + throw new ScriptingException( 'error', 'luasandbox', null, null, array( $e->getMessage() ) ); |
| 137 | + } |
| 138 | + |
| 139 | + return implode( '', $result ); |
| 140 | + } |
| 141 | +} |
Property changes on: trunk/extensions/Scripting/engines/LuaSandbox/Engine.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 142 | + native |