Pastakhov has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/56366


Change subject: Add php interpreter and runtime (version 0.0.1)
......................................................................

Add php interpreter and runtime (version 0.0.1)

works only command 'echo' with strings and variables.

Change-Id: I062ac9e6084e4afec15c82ae655d943ca217ed45
---
A Foxway.body.php
A Foxway.i18n.magic.php
A Foxway.i18n.php
A Foxway.php
A includes/Interpreter.php
A includes/Runtime.php
6 files changed, 504 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Foxway 
refs/changes/66/56366/1

diff --git a/Foxway.body.php b/Foxway.body.php
new file mode 100644
index 0000000..0867415
--- /dev/null
+++ b/Foxway.body.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Main class of Foxway extension.
+ *
+ * @file Foxway.body.php
+ * @ingroup Foxway
+ * @author Pavel Astakhov <[email protected]>
+ * @licence GNU General Public Licence 2.0 or later
+ */
+class Foxway {
+
+       /**
+        * Render function used in hook ParserFirstCallInit
+        *
+        * @param Parser $parser
+        * @return string
+        */
+       public static function renderParserFunction(Parser &$parser) {
+               $params = func_get_args();
+               array_shift( $params );
+
+               if( count($params) < 2 ) {
+                       return '<span class="error">' . wfMessage( 
'foxway-not-enough-parameters' )->escaped() . '</span>';
+               }
+
+               $action = strtolower( $params[0] );
+               switch ($action) {
+                       case 'set':
+                               $matches = array();
+                               if( 
preg_match('/^\s*([^=]+)\s*=\s*(.+)\s*$/si', $params[1], &$matches) ) {
+                               $propertyName = $matches[1];
+                               $propertyValue = $matches[2];
+                               return \Foxway\ORM::SetProperty($propertyName, 
$propertyValue);
+                               break;
+                       }
+                               break;
+                       default:
+                               return '<span class="error">' . wfMessage( 
'foxway-unknown-action', $action )->escaped() . '</span>';
+                               break;
+               }
+       }
+
+       public static function render($input, array $args, Parser $parser, 
PPFrame $frame) {
+               return Foxway\Interpreter::run($input);
+       }
+}
\ No newline at end of file
diff --git a/Foxway.i18n.magic.php b/Foxway.i18n.magic.php
new file mode 100644
index 0000000..b29eb7b
--- /dev/null
+++ b/Foxway.i18n.magic.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Internationalization file for the magic word of the Foxway extension.
+ *
+ * @file Foxway.i18n.magic.php
+ * @ingroup Foxway
+ * @author Pavel Astakhov <[email protected]>
+ */
+
+$magicWords = array();
+
+/** English
+ * @author pastakhov
+ */
+$magicWords['en'] = array(
+       'foxway' => array( 0, 'foxway' ),
+);
diff --git a/Foxway.i18n.php b/Foxway.i18n.php
new file mode 100644
index 0000000..d915ab0
--- /dev/null
+++ b/Foxway.i18n.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Internationalization file for the messages of the Foxway extension.
+ *
+ * @file Foxway.i18n.php
+ * @ingroup Foxway
+ * @author Pavel Astakhov <[email protected]>
+ */
+
+$messages = array();
+
+/** English
+ * @author pastakhov
+ */
+$messages['en'] = array(
+       'foxway-desc' => 'Allows to store an object-oriented data and 
implements its own runtime for php code on wikipage',
+       'foxway-php-syntax-error-unexpected' => 'PHP Parse error: syntax error, 
unexpected "$1" in Command line code on line $2'
+);
+
+/** Message documentation (Message documentation)
+ * @author pastakhov
+ */
+$messages['qqq'] = array(
+       'foxway-desc' => 
'{{desc|name=Foxway|url=http://www.mediawiki.org/wiki/Extension:Foxway}}',
+       'foxway-php-syntax-error-unexpected' => 'Error message, parameters:
+* $1 - user-specified string
+* $2 - the line number where the error occurred',
+);
diff --git a/Foxway.php b/Foxway.php
new file mode 100644
index 0000000..4131a57
--- /dev/null
+++ b/Foxway.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Foxway - An extension that allows to store an object-oriented data and 
implements its own runtime for php code on wikipage
+ *
+ * @link https://www.mediawiki.org/wiki/Extension:Foxway Documentation
+ * @file Foxway.php
+ * @defgroup Foxway
+ * @ingroup Extensions
+ * @author Pavel Astakhov <[email protected]>
+ * @licence GNU General Public Licence 2.0 or later
+ */
+
+// Check to see if we are being called as an extension or directly
+if ( !defined( 'MEDIAWIKI' ) ) {
+       die( 'This file is an extension to MediaWiki and thus not a valid entry 
point.' );
+}
+
+define( 'Foxway_VERSION' , '0.0.1' );
+
+// Register this extension on Special:Version
+$wgExtensionCredits['parserhook'][] = array(
+       'path'                          => __FILE__,
+       'name'                          => 'Foxway',
+       'version'                       => Foxway_VERSION,
+       'url'                           => 
'https://www.mediawiki.org/wiki/Extension:Foxway',
+       'author'                        => array( '[[mw:User:Pastakhov|Pavel 
Astakhov]]' ),
+       'descriptionmsg'        => 'foxway-desc'
+);
+
+// Tell the whereabouts of files
+$dir = __DIR__;
+
+// Allow translations for this extension
+$wgExtensionMessagesFiles['Foxway'] =          $dir . '/Foxway.i18n.php';
+$wgExtensionMessagesFiles['FoxwayMagic'] =     $dir . '/Foxway.i18n.magic.php';
+
+// Include the settings file.
+//require_once $dir . '/Settings.php';
+
+// Specify the function that will initialize the parser function.
+/**
+ * @codeCoverageIgnore
+ */
+$wgHooks['ParserFirstCallInit'][] = function( Parser &$parser ) {
+   //$parser->setFunctionHook( 'foxway', 'Foxway::renderParserFunction' );
+   $parser->setHook( 'foxway', 'Foxway::render' );
+   return true;
+};
+
+//Preparing classes for autoloading
+$wgAutoloadClasses['Foxway']                           = $dir . 
'/Foxway.body.php';
+
+$wgAutoloadClasses['Foxway\\Interpreter']      = $dir . 
'/includes/Interpreter.php';
+//$wgAutoloadClasses['Foxway\\ORM']                    = $dir . 
'/includes/ORM.php';
+$wgAutoloadClasses['Foxway\\Runtime']          = $dir . 
'/includes/Runtime.php';
+
+//$wgAutoloadClasses['Foxway\\BaseValue']              = $dir . 
'/includes/ORMValues/BaseValue.php';
+//$wgAutoloadClasses['Foxway\\ValueNumber']    = $dir . 
'/includes/ORMValues/ValueNumber.php';
+
+/******** DB UPDATING ********/
+
+# Schema changes
+$wgHooks['LoadExtensionSchemaUpdates'][] = function( DatabaseUpdater $updater 
) {
+       $dirsql = __DIR__ . '/sql';
+
+       //$updater->addExtensionTable( 'foxway_properties', 
"$dirsql/foxway_properties.sql" );
+       //$updater->addExtensionTable( 'foxway_links', 
"$dirsql/foxway_links.sql" );
+
+       return true;
+};
+
diff --git a/includes/Interpreter.php b/includes/Interpreter.php
new file mode 100644
index 0000000..322a215
--- /dev/null
+++ b/includes/Interpreter.php
@@ -0,0 +1,211 @@
+<?php
+namespace Foxway;
+/**
+ * Interpreter class of Foxway extension.
+ *
+ * @file Interpreter.php
+ * @ingroup Foxway
+ * @author Pavel Astakhov <[email protected]>
+ * @licence GNU General Public Licence 2.0 or later
+ */
+class Interpreter {
+
+       private static $skipTokenIds = array(
+               T_WHITESPACE,
+               T_COMMENT,
+               T_DOC_COMMENT,
+       );
+
+       public static function run($source, $is_debug = true) {
+               $tokens = token_get_all("<?php $source ?>");
+               $return = "";
+               $debug = array();
+               $expected = false;
+               $expectListParams = false;
+               $expectCurlyClose = false;
+               $line = 1;
+               $runtime = new Runtime();
+
+               foreach ($tokens as $token) {
+                       if ( is_string($token) ) {
+                               $id = $token;
+                               if($is_debug) {
+                                       $debug[] = $token;
+                               }
+                       } else {
+                               list($id, $text, $line) = $token;
+                       }
+
+                       if( $expected && in_array($id, self::$skipTokenIds) === 
false && in_array($id, $expected) === false) {
+                               $id_str = is_string($id) ? $id : 
token_name($id);
+                               $return .= '<br><span class="error">' . 
wfMessage( 'foxway-php-syntax-error-unexpected', $id_str, $line )->escaped() . 
'</span>';
+                               break;
+                       }
+
+                       switch ($id) {
+                               case T_COMMENT:
+                               case T_DOC_COMMENT:
+                                       if($is_debug) {
+                                               $debug[] = '<span 
style="color:#969696" title="'. token_name($id) . '">' . str_replace("\n", "<br 
/>\n", htmlspecialchars($text) ) . '</span>';
+                                       }
+                                       break;
+                               case T_WHITESPACE:
+                                       if($is_debug) {
+                                               $debug[] = str_replace("\n", 
"<br />\n", $text);
+                                       }
+                                       break;
+                               case '"':
+                                       if($is_debug) {
+                                               array_pop($debug);
+                                               $debug[] = '<span 
style="color:#CE7B00">"</span>';
+                                       }
+                                       break;
+                               case ';':
+                                       $return .= 
$runtime->getCommandResult($debug);
+                                       $expectListParams = false;
+                                       $expected = false;
+                                       break;
+                               case '=':
+                                       $runtime->setVariableOperator('=');
+                                       $expected = array(
+                                               T_CONSTANT_ENCAPSED_STRING,
+                                               T_ENCAPSED_AND_WHITESPACE,
+                                               T_VARIABLE,
+                                               T_CURLY_OPEN,
+                                               '"',
+                                               ';',
+                                               );
+                                       break;
+                               case '.':
+                                       $expected = array(
+                                               T_CONSTANT_ENCAPSED_STRING,
+                                               T_ENCAPSED_AND_WHITESPACE,
+                                               T_VARIABLE,
+                                               T_CURLY_OPEN,
+                                               '"',
+                                               ';',
+                                               );
+                                               $runtime->addOperator('.');
+                                       break;
+                               case ',':
+                                       $expected = array(
+                                               T_CONSTANT_ENCAPSED_STRING,
+                                               T_ENCAPSED_AND_WHITESPACE,
+                                               T_VARIABLE,
+                                               T_CURLY_OPEN,
+                                               '"',
+                                               // ';',
+                                               );
+                                       break;
+                               case '}':
+                                       if( $expectCurlyClose ) {
+                                               $expectCurlyClose = false;
+                                               $expected = array(
+                                                       
T_CONSTANT_ENCAPSED_STRING,
+                                                       
T_ENCAPSED_AND_WHITESPACE,
+                                                       T_VARIABLE,
+                                                       T_CURLY_OPEN,
+                                                       '"',
+                                                       ';',
+                                                       );
+                                       } else {
+                                               $return .= '<br><span 
class="error">' . wfMessage( 'foxway-php-syntax-error-unexpected', '}', $line 
)->escaped() . '</span>';
+                                               break 2;
+                                       }
+                                       break;
+                               case T_ECHO:
+                                       if($is_debug) {
+                                               $i = array_push($debug, 
$text)-1;
+                                       } else {
+                                               $i = false;
+                                       }
+                                       $runtime->addCommand('echo', $i);
+                                       //@todo:
+                                       /*$expected = array(
+                                               T_START_HEREDOC,
+                                               T_DNUMBER,
+                                               T_LNUMBER,
+                                               T_STRING_CAST,
+                                               T_INT_CAST,
+                                               T_FUNCTION,
+                                               );*/
+                                       $expectListParams = true;
+                                       $expected = array(
+                                               T_CONSTANT_ENCAPSED_STRING,
+                                               T_ENCAPSED_AND_WHITESPACE,
+                                               T_VARIABLE,
+                                               T_CURLY_OPEN,
+                                               '"',
+                                               ';',
+                                               );
+                                       break;
+                               case T_CONSTANT_ENCAPSED_STRING:
+                                       if($is_debug) {
+                                               $debug[] = '<span 
style="color:#CE7B00" title="'. token_name($id) . '">' . 
htmlspecialchars($text) . '</span>';
+                                       }
+                                       $runtime->addParam( substr($text, 1, 
-1) );
+                                       $expected = array(
+                                               ';',
+                                               '.',
+                                               );
+                                       if($expectListParams){
+                                               $expected[] = ',';
+                                       }
+                                       break;
+                               case T_ENCAPSED_AND_WHITESPACE:
+                                       if($is_debug) {
+                                               $debug[] = '<span 
style="color:#CE7B00" title="'. token_name($id) . '">' . 
htmlspecialchars($text) . '</span>';
+                                       }
+                                       $runtime->addParam( $text );
+                                       $runtime->addOperator('.');
+                                       break;
+                               case T_VARIABLE:
+                                       if( $expected && in_array(T_VARIABLE, 
$expected) ) {
+                                               $value = $runtime->getVariable( 
substr($text, 1) );
+                                               $runtime->addParam($value);
+                                               if( $expectCurlyClose ) {
+                                                       $expected = array(
+                                                               '}',
+                                                               );
+                                               }
+                                               if($is_debug) {
+                                                       if( is_null($value) ) {
+                                                               $debug[] = 
'<span style="color:red" title="'.token_name($id).' = '.htmlspecialchars( 
var_export($value, true) ).'">' . $text . '</span>';
+                                                       } else {
+                                                               $debug[] = 
'<span style="color:#6D3206" title="'.token_name($id).' = '.htmlspecialchars( 
var_export($value, true) ).'">' . $text . '</span>';
+                                                       }
+                                               }
+                                       } else {
+                                               if($is_debug) {
+                                                       $i = array_push($debug, 
$text)-1;
+                                               } else {
+                                                       $i = false;
+                                               }
+                                               $runtime->setVariable($text, 
$i);
+                                               $expected = array('=');
+                                       }
+                                       break;
+                               case T_CURLY_OPEN:
+                                       if($is_debug) {
+                                               $debug[] = '{';
+                                       }
+                                       $expectCurlyClose = true;
+                                       $expected = array(
+                                               T_VARIABLE,
+                                               );
+                                       break;
+                               default:
+                                       if($is_debug) {
+                                               $debug[] = '<span title="'. 
token_name($id) . '">' . htmlspecialchars($text) . '</span>';
+                                       }
+                                       break;
+                       }
+               }
+
+               if( $is_debug ) {
+                       $return = implode('', $debug) . '<HR>' . $return;
+               }
+               return $return;
+       }
+
+}
diff --git a/includes/Runtime.php b/includes/Runtime.php
new file mode 100644
index 0000000..d06671e
--- /dev/null
+++ b/includes/Runtime.php
@@ -0,0 +1,131 @@
+<?php
+namespace Foxway;
+/**
+ * Runtime class of Foxway extension.
+ *
+ * @file Runtime.php
+ * @ingroup Foxway
+ * @author Pavel Astakhov <[email protected]>
+ * @licence GNU General Public Licence 2.0 or later
+ */
+class Runtime {
+
+       private $lastCommand = false;
+       private $lastDebug = false;
+       private $lastParam = null;
+       private $listParams = array();
+       private $lastOperator = false;
+       private $lastVariable = false;
+       private $listVariables = array();
+       private $lastVariableOperator = false;
+
+       private $stack = array();
+       private static $variables = array();
+
+       private function pushStack() {
+               $this->stack[] = array($this->lastCommand, $this->lastDebug, 
$this->lastParam, $this->listParams, $this->lastOperator, $this->lastVariable, 
$this->listVariables, $this->lastVariableOperator);
+       }
+
+       public function popStack() {
+               if( count($this->stack) == 0 ) {
+                       $this->lastCommand = false;
+                       $this->lastDebug = false;
+                       $this->lastParam = null;
+                       $this->listParams = array();
+                       $this->lastOperator = false;
+                       $this->lastVariable = false;
+                       $this->listVariables = array();
+                       $this->lastVariableOperator = false;
+               } else {
+                       list($this->lastCommand, $this->lastDebug, 
$this->lastParam, $this->listParams, $this->lastOperator, $this->lastVariable, 
$this->listVariables, $this->lastVariableOperator) = array_pop($this->stack);
+               }
+       }
+
+       public function addCommand( $name, $debug ) {
+               if( $this->lastCommand ) {
+                       $this->pushStack();
+               }
+               $this->lastCommand = $name;
+               $this->lastDebug = $debug;
+       }
+
+       public function addParam( $param ) {
+               if( $this->lastOperator ) {
+                       switch ( $this->lastOperator ) {
+                               case '.':
+                                       $this->lastParam = $this->lastParam . 
$param;
+                                       $this->lastOperator = false;
+                                       break;
+                               default:
+                                       // TODO
+                                       \MWDebug::log( 'Error! Unknown operator 
"' . htmlspecialchars($this->lastOperator) . '" in ' . __METHOD__ );
+                                       break;
+                       }
+               } else {
+                       if( !is_null($this->lastParam) ) {
+                               $this->listParams[] = $this->lastParam;
+                       }
+                       $this->lastParam = $param;
+               }
+       }
+
+       public function addOperator( $operator ) {
+               $this->lastOperator = $operator;
+       }
+
+       public function getCommandResult( &$debug ) {
+               $this->listParams[] = $this->lastParam;
+               $return = null;
+
+               switch ($this->lastCommand) {
+                       case 'echo':
+                               $return = implode('', $this->listParams);
+                               if( $this->lastDebug !== false ) {
+                                       $debug[$this->lastDebug] = '<span 
style="color:#0000E6" title="'. token_name(T_ECHO) . ' do ' . 
htmlspecialchars($return) . '">' . $debug[$this->lastDebug] . '</span>';
+                               }
+                               break;
+                       default:
+                               $lastCommand = $this->lastCommand;
+                               if( substr($lastCommand, 0, 1) == '$' ) {
+                                       switch ($this->lastVariableOperator) {
+                                               case '=':
+                                                       if( $this->lastDebug 
!== false ) {
+                                                               
$debug[$this->lastDebug] = '<span style="color:#6D3206" 
title="'.token_name(T_VARIABLE).' set '.htmlspecialchars( 
var_export($this->lastParam, true) ).'">' . $lastCommand . '</span>';
+                                                       }
+                                                       self::$variables[ 
substr($lastCommand, 1) ] = $this->lastParam;
+                                                       break;
+                                               default:
+                                                       // TODO exception
+                                                       $return = 'Error! 
Unknown operator "' . htmlspecialchars($this->lastVariableOperator) . '" in ' . 
__METHOD__;
+                                                       \MWDebug::log($return);
+                                                       break;
+                                       }
+
+                               } else {
+                                       // TODO exception
+                                       $return = 'Error in ' . __METHOD__;
+                               }
+                               break;
+               }
+               $this->popStack();
+               return $return;
+       }
+
+       public function setVariable( $name, $debug ) {
+               $this->addCommand($name, $debug);
+       }
+
+       public function setVariableOperator( $operator ) {
+               $this->lastVariableOperator = $operator;
+       }
+
+       public function getVariable( $name ) {
+               if( isset(self::$variables[$name]) ) {
+                       return self::$variables[$name];
+               } else {
+                       //TODO THROW
+                       return null;
+               }
+       }
+
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/56366
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I062ac9e6084e4afec15c82ae655d943ca217ed45
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Foxway
Gerrit-Branch: master
Gerrit-Owner: Pastakhov <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to