Pastakhov has uploaded a new change for review.

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

Change subject: add possibility to set property value (v 2.7.0)
......................................................................

add possibility to set property value (v 2.7.0)

* add PHPTAGS_STACK_HOOK_TYPE
* add function Compiler::stepFunction()
* add function Compiler::stepFunctionFromVariable()
* refactoring function Hooks::callHook()

Change-Id: I5ef1406b51e137b96359a3403b06f512578a5e82
---
M PhpTags.php
M includes/Compiler.php
M includes/Hooks.php
M includes/PhpTagsException.php
M includes/Runtime.php
5 files changed, 260 insertions(+), 84 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/PhpTags 
refs/changes/10/148610/1

diff --git a/PhpTags.php b/PhpTags.php
index 658bd21..007896f 100644
--- a/PhpTags.php
+++ b/PhpTags.php
@@ -16,8 +16,8 @@
 }
 
 define( 'PHPTAGS_MAJOR_VERSION', 2 );
-define( 'PHPTAGS_MINOR_VERSION', 6 );
-define( 'PHPTAGS_RELEASE_VERSION', 2 );
+define( 'PHPTAGS_MINOR_VERSION', 7 );
+define( 'PHPTAGS_RELEASE_VERSION', 0 );
 define( 'PHPTAGS_VERSION', PHPTAGS_MAJOR_VERSION . '.' . PHPTAGS_MINOR_VERSION 
. '.' . PHPTAGS_RELEASE_VERSION );
 
 define( 'PHPTAGS_HOOK_RELEASE', 4 );
diff --git a/includes/Compiler.php b/includes/Compiler.php
index b44a0eb..70734ae 100644
--- a/includes/Compiler.php
+++ b/includes/Compiler.php
@@ -345,16 +345,19 @@
                        } else {
                                $ref = false;
                        }
-                       $this->stack[] = array(
+                       $hookCheckParam = array(
                                PHPTAGS_STACK_COMMAND => 
PHPTAGS_T_HOOK_CHECK_PARAM,
                                PHPTAGS_STACK_PARAM_3 => &$ref,
-                               PHPTAGS_STACK_PARAM => $functionName,
+                               PHPTAGS_STACK_PARAM => false, // $functionName
                                PHPTAGS_STACK_PARAM_2 => 
$value[PHPTAGS_STACK_COMMAND] == PHPTAGS_T_VARIABLE,
                                PHPTAGS_STACK_AIM => $i,
                                PHPTAGS_STACK_RESULT => &$result,
                                PHPTAGS_STACK_TOKEN_LINE => $this->tokenLine,
                        );
-                       unset( $ref );
+                       $func = $functionName; // clone the function name for 
use in the next loop
+                       $this->addValueIntoStack( $func, $hookCheckParam, 
PHPTAGS_STACK_PARAM );
+                       $this->stack[] =& $hookCheckParam;
+                       unset( $ref, $hookCheckParam, $func );
 
                        if ( current($this->tokens) != ',' ) {
                                break;
@@ -494,8 +497,9 @@
 
                                        $this->stepUP();
 
-                                       $result = array( // define hook as the 
constant
+                                       $result = array( // define blank hook 
as the constant
                                                PHPTAGS_STACK_COMMAND => 
PHPTAGS_T_HOOK,
+                                               PHPTAGS_STACK_HOOK_TYPE => 
PHPTAGS_HOOK_GET_CONSTANT,
                                                PHPTAGS_STACK_PARAM => $text,  
// function or method
                                                PHPTAGS_STACK_PARAM_2 => false, 
// &$functionParameters
                                                PHPTAGS_STACK_PARAM_3 => false, 
// false or &object
@@ -505,29 +509,15 @@
                                        );
 
                                        if ( $this->id == '(' ) { // it is 
function
-                                               $this->stepUP();
-
-                                               if ( $owner !== false ) { // it 
is object
-                                                       
$this->addValueIntoStack( $owner[0], $result, PHPTAGS_STACK_PARAM_3 );
-                                                       $functionParameters =& 
$this->getFunctionParameters( $text, array( &$result ) );
-                                               } else { // it is function
-                                                       $functionParameters =& 
$this->getFunctionParameters( $text );
-                                               }
-
-                                               $result[PHPTAGS_STACK_PARAM_2] 
=& $functionParameters; // now, hook is function
-
-                                               if ( $this->id != ')' ) {
-                                                       // PHP Parse error:  
syntax error, unexpected $tmp_id, expecting ')'
-                                                       throw new 
PhpTagsException( PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( 
$this->id, "')'" ), $this->tokenLine, $this->place );
-                                               }
-                                               $this->stepUP();
+                                               $this->stepFunction( $result, 
array(PHPTAGS_STACK_COMMAND=>false, PHPTAGS_STACK_RESULT=>$text), $owner );
                                        } elseif ( $owner !== false ) { // it 
is an objects property. Example: it's 'bar' for FOO::bar
+                                               
$result[PHPTAGS_STACK_HOOK_TYPE] = $owner[1] === true ? 
PHPTAGS_HOOK_GET_STATIC_PROPERTY : PHPTAGS_HOOK_GET_OBJECT_PROPERTY;
                                                $this->addValueIntoStack( 
$owner[0], $result, PHPTAGS_STACK_PARAM_3 );
                                        } elseif ( $this->id == T_DOUBLE_COLON 
) { // it is static constant or method of an object. Examples: FOO::property or 
FOO::method()
                                                $result[PHPTAGS_STACK_COMMAND] 
= false;
                                                $result[PHPTAGS_STACK_RESULT] = 
$text;
 
-                                               $result = & 
$this->stepMethodChaining( $result );
+                                               $result = & 
$this->stepMethodChaining( $result, true );
                                        }
 
                                        return $result;
@@ -560,9 +550,12 @@
                                $cannotRead = false;
 
                                $variable = array( 
PHPTAGS_STACK_COMMAND=>PHPTAGS_T_VARIABLE, PHPTAGS_STACK_PARAM=>substr($text, 
1), PHPTAGS_STACK_PARAM_2=>null, PHPTAGS_STACK_RESULT=>null, 
PHPTAGS_STACK_TOKEN_LINE=>$this->tokenLine, PHPTAGS_STACK_DEBUG=>$text );
-
                                $this->stepUP();
-                               if ( $this->id == '[' ) { // There is array 
index
+
+checkOperators:
+                               if ( $this->id == '(' ) { // it is function
+                                       $variable =& 
$this->stepFunctionFromVariable( $variable, $text, $owner );
+                               } elseif ( $this->id == '[' ) { // There is 
array index
                                        $variable[PHPTAGS_STACK_ARRAY_INDEX] = 
array();
                                        $i = 0;
                                        do { // Example: $foo[
@@ -593,41 +586,101 @@
                                                // PHP Parse error:  syntax 
error, unexpected $id
                                                throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id ), 
$this->tokenLine, $this->place );
                                        }
-                                       $return = array(
-                                               PHPTAGS_STACK_COMMAND => 
self::$runtimeOperators[$id],
-                                               PHPTAGS_STACK_PARAM => 
$variable,
-                                               PHPTAGS_STACK_PARAM_2 => null,
-                                               PHPTAGS_STACK_RESULT => null,
-                                               PHPTAGS_STACK_TOKEN_LINE => 
$this->tokenLine,
-                                               PHPTAGS_STACK_DEBUG => $text,
-                                       );
-                                       $this->addValueIntoStack( $val, 
$return, PHPTAGS_STACK_PARAM_2 );
-                                       return $return; // *********** EXIT 
***********
+                                       if ( $owner === false && 
$variable[PHPTAGS_STACK_COMMAND] == PHPTAGS_T_VARIABLE ) {
+                                               $return = array(
+                                                       PHPTAGS_STACK_COMMAND 
=> self::$runtimeOperators[$id],
+                                                       PHPTAGS_STACK_PARAM => 
$variable,
+                                                       PHPTAGS_STACK_PARAM_2 
=> null,
+                                                       PHPTAGS_STACK_RESULT => 
null,
+                                                       
PHPTAGS_STACK_TOKEN_LINE => $this->tokenLine,
+                                                       PHPTAGS_STACK_DEBUG => 
$text,
+                                               );
+                                               $this->addValueIntoStack( $val, 
$return, PHPTAGS_STACK_PARAM_2 );
+                                               return $return; // *********** 
EXIT ***********
+                                       } elseif ( $owner === false ) {
+                                               // 
$variable[PHPTAGS_STACK_COMMAND] == PHPTAGS_T_HOOK
+                                               switch ( 
$variable[PHPTAGS_STACK_HOOK_TYPE] ) {
+                                                       case 
PHPTAGS_HOOK_GET_OBJECT_PROPERTY: // Example: $foo = new FOO(); $foo->bar =
+                                                               
$variable[PHPTAGS_STACK_HOOK_TYPE] = PHPTAGS_HOOK_SET_OBJECT_PROPERTY;
+                                                               break;
+                                                       case 
PHPTAGS_HOOK_GET_STATIC_PROPERTY: // Example: $foo = new FOO(); $foo::bar =
+                                                               
$variable[PHPTAGS_STACK_HOOK_TYPE] = PHPTAGS_HOOK_SET_STATIC_PROPERTY;
+                                                               break;
+                                                       default :  // Example: 
FOO->$bar() =
+                                                               // PHP Parse 
error:  syntax error, unexpected $id
+                                                               throw new 
PhpTagsException( PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( 
$this->id ), $this->tokenLine, $this->place );
+                                               }
+                                               $this->addValueIntoStack( $val, 
$variable, PHPTAGS_STACK_PARAM_2 );
+                                               return $variable; // 
*********** EXIT ***********
+                                       } else { // Property name as variable. 
Example: $foo = new FOO(); $bar='anyproperty'; $foo->$bar =
+                                               $return = array( // define hook
+                                                       PHPTAGS_STACK_COMMAND 
=> PHPTAGS_T_HOOK,
+                                                       PHPTAGS_STACK_HOOK_TYPE 
=> $owner[1] === true ? PHPTAGS_HOOK_SET_STATIC_PROPERTY : 
PHPTAGS_HOOK_SET_OBJECT_PROPERTY,
+                                                       PHPTAGS_STACK_PARAM => 
false,  // function or method
+                                                       PHPTAGS_STACK_PARAM_2 
=> false, // &$functionParameters
+                                                       PHPTAGS_STACK_PARAM_3 
=> false, // false or &object
+                                                       PHPTAGS_STACK_RESULT => 
null,
+                                                       
PHPTAGS_STACK_TOKEN_LINE => $this->tokenLine,
+                                                       PHPTAGS_STACK_DEBUG => 
$text,
+                                               );
+                                               $this->addValueIntoStack( 
$variable, $return, PHPTAGS_STACK_PARAM ); // property name
+                                               $this->addValueIntoStack( $val, 
$return, PHPTAGS_STACK_PARAM_2 ); // value
+                                               $this->addValueIntoStack( 
$owner[0], $return, PHPTAGS_STACK_PARAM_3 ); // object
+                                               return $return;
+                                       }
                                } elseif ( $id == T_INC || $id == T_DEC ) {
-                                       $variable = array(
-                                               PHPTAGS_STACK_COMMAND => 
self::$runtimeOperators[$id],
-                                               PHPTAGS_STACK_PARAM => 
$variable,
-                                               PHPTAGS_STACK_PARAM_2 => true, 
// Example: $foo++
-                                               PHPTAGS_STACK_RESULT => null,
-                                               PHPTAGS_STACK_TOKEN_LINE => 
$this->tokenLine,
-                                               PHPTAGS_STACK_DEBUG => $text,
-                                       );
-                                       $this->stepUP();
-                               } elseif ( $cannotRead ) {
+                                       if ( $variable[PHPTAGS_STACK_COMMAND] 
== PHPTAGS_T_VARIABLE ) {
+                                               $variable = array(
+                                                       PHPTAGS_STACK_COMMAND 
=> self::$runtimeOperators[$id],
+                                                       PHPTAGS_STACK_PARAM => 
$variable,
+                                                       PHPTAGS_STACK_PARAM_2 
=> true, // Example: $foo++
+                                                       PHPTAGS_STACK_RESULT => 
null,
+                                                       
PHPTAGS_STACK_TOKEN_LINE => $this->tokenLine,
+                                                       PHPTAGS_STACK_DEBUG => 
$text,
+                                               );
+                                               $this->stepUP();
+                                       } else { // 
$variable[PHPTAGS_STACK_COMMAND] == PHPTAGS_T_HOOK Example: FOO->$bar()++
+                                               // PHP Parse error:  syntax 
error, unexpected $id
+                                               throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id ), 
$this->tokenLine, $this->place );
+                                       }
+                               } elseif ( $cannotRead ) { // Example: echo 
$foo[];
                                        // PHP Fatal error:  Cannot use [] for 
reading
                                        throw new PhpTagsException( 
PhpTagsException::FATAL_CANNOT_USE_FOR_READING, null, $this->tokenLine, 
$this->place );
-                               } elseif ( $owner === false && ($id == 
T_OBJECT_OPERATOR || $id == T_DOUBLE_COLON) ) { // Example: $foo->
+                               } elseif ( $owner !== false ) {
+                                       if ( $variable[PHPTAGS_STACK_COMMAND] 
== PHPTAGS_T_HOOK ) { // Example: $bar = 'anymethod'; echo $foo->$bar();
+                                               return $variable;
+                                       } // Example: $bar = 'anyproperty'; 
echo $foo->$bar
+                                       $return = array( // define hook
+                                               PHPTAGS_STACK_COMMAND => 
PHPTAGS_T_HOOK,
+                                               PHPTAGS_STACK_HOOK_TYPE => 
$owner[1] === true ? PHPTAGS_HOOK_GET_STATIC_PROPERTY : 
PHPTAGS_HOOK_GET_OBJECT_PROPERTY,
+                                               PHPTAGS_STACK_PARAM => false,  
// function or method
+                                               PHPTAGS_STACK_PARAM_2 => false, 
// &$functionParameters
+                                               PHPTAGS_STACK_PARAM_3 => false, 
// false or &object
+                                               PHPTAGS_STACK_RESULT => null,
+                                               PHPTAGS_STACK_TOKEN_LINE => 
$this->tokenLine,
+                                               PHPTAGS_STACK_DEBUG => $text,
+                                       );
+                                       $this->addValueIntoStack( $variable, 
$return, PHPTAGS_STACK_PARAM ); // property name
+                                       $this->addValueIntoStack( $owner[0], 
$return, PHPTAGS_STACK_PARAM_3 ); // object
+
+                                       $id = $this->id;
+                                       if ( $id == T_OBJECT_OPERATOR || $id == 
T_DOUBLE_COLON ) {
+                                               $return =& 
$this->stepMethodChaining( $return, $id == T_DOUBLE_COLON );
+                                       }
+                                       return $return;
+                               } elseif ( $id == T_OBJECT_OPERATOR || $id == 
T_DOUBLE_COLON ) { // Example: $foo->
                                        $this->stepUP();
-                                       $val =& $this->stepValue( 
array(&$variable) );
-                                       if ( $val == false || 
$val[PHPTAGS_STACK_COMMAND] != PHPTAGS_T_HOOK ) { // Example: $foo->;
+                                       $variable =& $this->stepValue( 
array(&$variable, $id == T_DOUBLE_COLON) );
+                                       if ( $variable == false || 
$variable[PHPTAGS_STACK_COMMAND] != PHPTAGS_T_HOOK ) { // Example: $foo->;
                                                // PHP Parse error:  syntax 
error, unexpected $id
                                                throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id ), 
$this->tokenLine, $this->place );
                                        }
 
-                                       if ( $this->id == T_OBJECT_OPERATOR || 
$this->id == T_DOUBLE_COLON ) {
-                                               $val = & 
$this->stepMethodChaining( $val );
+                                       $id = $this->id;
+                                       if ( $id == T_OBJECT_OPERATOR || $id == 
T_DOUBLE_COLON ) {
+                                               $variable =& 
$this->stepMethodChaining( $variable, $id == T_DOUBLE_COLON );
                                        }
-                                       return $val;
+                                       goto checkOperators;
                                }
                                return $variable; // *********** EXIT 
***********
                        case T_INC:
@@ -826,7 +879,10 @@
                                }
                                if ( $this->id == '(' ) { // it has parameters
                                        $this->stepUP();
-                                       $objectParameters =& 
$this->getFunctionParameters( PHPTAGS_METHOD_CONSTRUCTOR, array( &$result ) );
+                                       $objectParameters =& 
$this->getFunctionParameters(
+                                                       array( 
PHPTAGS_STACK_COMMAND => false, PHPTAGS_STACK_RESULT => 
PHPTAGS_METHOD_CONSTRUCTOR),
+                                                       array( &$result )
+                                               );
                                        if ( $this->id != ')' ) {
                                                // PHP Parse error:  syntax 
error, unexpected $tmp_id, expecting ')'
                                                throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id, "')'" ), 
$this->tokenLine, $this->place );
@@ -1388,16 +1444,16 @@
                return true;
        }
 
-       private function & stepMethodChaining( &$result ) {
+       private function & stepMethodChaining( &$result, $isStatic ) {
                do {
                        $this->stepUP();
-                       $val =& $this->stepValue( array(&$result) );
+                       $val =& $this->stepValue( array(&$result, $isStatic) );
                        if ( $val == false ) { // Example: FOO::bar-> ;
                                // PHP Parse error:  syntax error, unexpected 
$id
                                throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id ), 
$this->tokenLine, $this->place );
                        }
                        switch ( $val[PHPTAGS_STACK_COMMAND] ) {
-                               case PHPTAGS_T_HOOK: // Example: FOO::bar->too
+                               case PHPTAGS_T_HOOK: // Examples: FOO::bar->too
                                        $result =& $val;
                                        break;
                                case PHPTAGS_T_VARIABLE: // Example: 
FOO::bar->$variable
@@ -1422,34 +1478,99 @@
                return $result;
        }
 
-       private function addValueIntoStack( &$value, &$result, $aim, $doit = 
false ) {
+       /**
+        * This function adds $value to the $aim in $command
+        * If $value has a variable then it will be added to stack
+        * If the values of the command are scalar then command can be processed
+        * and if $doit is TRUE then the command will be processed
+        * and in this case the function returns TRUE otherwise FALSE.
+        * @param array $value Array with PHPTAGS_STACK_COMMAND
+        * @param array $command Array with $aim
+        * @param string $aim The aim in $command
+        * @param boolean $doit Process the command if possible
+        * @return boolean Returns TRUE, if the command was processed
+        */
+       private function addValueIntoStack( &$value, &$command, $aim, $doit = 
false ) {
                if ( $value[PHPTAGS_STACK_COMMAND] == PHPTAGS_T_VARIABLE ) {
-                       $value[PHPTAGS_STACK_PARAM_2] =& $result;
+                       $value[PHPTAGS_STACK_PARAM_2] =& $command;
                        $value[PHPTAGS_STACK_AIM] = $aim;
                } else {
-                       $result[$aim] =& $value[PHPTAGS_STACK_RESULT];
+                       $command[$aim] =& $value[PHPTAGS_STACK_RESULT];
                }
 
-               if ( $value[PHPTAGS_STACK_COMMAND] ) {
-                       $this->stack[] =& $value;
-               } elseif( $value[PHPTAGS_STACK_COMMAND] === null ) {
-                       // The values of the operator have no command
+               if ( $value[PHPTAGS_STACK_COMMAND] === null ) {
+                       // The values of the command are scalar
                        if ( $doit ) {
-                               $tmp = array( PHPTAGS_STACK_COMMAND => 
PHPTAGS_T_RETURN, PHPTAGS_STACK_PARAM => &$result[PHPTAGS_STACK_RESULT] );
-                               $runtimeReturn = Runtime::run( array($result, 
$tmp),    array('PhpTags\\Compiler') );
+                               $tmp = array( PHPTAGS_STACK_COMMAND => 
PHPTAGS_T_RETURN, PHPTAGS_STACK_PARAM => &$command[PHPTAGS_STACK_RESULT] );
+                               $runtimeReturn = Runtime::run( array($command, 
$tmp),   array('PhpTags\\Compiler') );
                                if ( $runtimeReturn instanceof PhpTagsException 
) {
                                        return false;
                                }
-                               $result = array(
+                               $command = array(
                                        PHPTAGS_STACK_COMMAND => null, // Mark 
the operator as the already processed.
                                        PHPTAGS_STACK_RESULT => $runtimeReturn,
                                );
                        }
                        return true;
+               } elseif ( $value[PHPTAGS_STACK_COMMAND] !== false ) {
+                       $this->stack[] =& $value;
                }
 
                return false;
        }
 
+       /**
+        * Returns Hook as function() or $object->method()
+        * @param array $hook The blank hook
+        * @param array $funcName The function name
+        * @param mixed $owner Object as array or FALSE for function
+        * @return array Hook
+        * @throws PhpTagsException
+        */
+       private function & stepFunction( &$hook, $funcName, $owner ) {
+               $this->stepUP();
+
+               if ( $owner !== false ) { // $owner is object
+                       $hook[PHPTAGS_STACK_HOOK_TYPE] = $owner[1] === true ? 
PHPTAGS_HOOK_STATIC_METHOD : PHPTAGS_HOOK_OBJECT_METHOD;
+                       $this->addValueIntoStack( $owner[0], $hook, 
PHPTAGS_STACK_PARAM_3 );
+                       $hook[PHPTAGS_STACK_PARAM_2] =& 
$this->getFunctionParameters( $funcName, array( &$hook ) );
+               } else { // it is function
+                       $hook[PHPTAGS_STACK_HOOK_TYPE] = PHPTAGS_HOOK_FUNCTION;
+                       $hook[PHPTAGS_STACK_PARAM_2] =& 
$this->getFunctionParameters( $funcName );
+               }
+
+               if ( $this->id != ')' ) {
+                       // PHP Parse error:  syntax error, unexpected $tmp_id, 
expecting ')'
+                       throw new PhpTagsException( 
PhpTagsException::PARSE_SYNTAX_ERROR_UNEXPECTED, array( $this->id, "')'" ), 
$this->tokenLine, $this->place );
+               }
+               $this->stepUP();
+               return $hook;
+       }
+
+       /**
+        * Returns Hook as $function() or objects->$method() where name will be 
received from variable
+        * @param array $variable The variable as function or method name
+        * @param string $text Text of variable for debug
+        * @param mixed $owner Object as array or FALSE for function
+        * @return array Hook
+        * @throws PhpTagsException
+        */
+       public function & stepFunctionFromVariable( $variable, $text, $owner ) {
+               $hook = array( // define the blank hook
+                       PHPTAGS_STACK_COMMAND => PHPTAGS_T_HOOK,
+                       PHPTAGS_STACK_HOOK_TYPE => false,
+                       PHPTAGS_STACK_PARAM => false, // function or method 
name from $variable
+                       PHPTAGS_STACK_PARAM_2 => false, // &$functionParameters
+                       PHPTAGS_STACK_PARAM_3 => false, // false or &object
+                       PHPTAGS_STACK_RESULT => null,
+                       PHPTAGS_STACK_TOKEN_LINE => $this->tokenLine,
+                       PHPTAGS_STACK_DEBUG => $text,
+               );
+
+               $return =& $this->stepFunction( $hook, $variable, $owner );
+               $this->addValueIntoStack( $variable, $return, 
PHPTAGS_STACK_PARAM ); // Add function or method name to hook
+               return $return;
+       }
+
 }
 
diff --git a/includes/Hooks.php b/includes/Hooks.php
index 837b4b4..20aaf77 100644
--- a/includes/Hooks.php
+++ b/includes/Hooks.php
@@ -140,28 +140,33 @@
        }
 
        /**
-        * Call a hook like as constant or function or object's method of 
PhpTags
+        * Call a hook of PhpTags
+        * @param int $type Hook type
         * @param mixed $arguments Array or boolean false for the constants
         * @param mixed $name Name of constant or function or method
         * @param mixed $object boolean false for the functions or the object 
or object's name
         * @return mixed
         * @throws PhpTagsException
         */
-       public static function callHook( $arguments, $name, $object ) {
-               // it is a constant or a function or a method of an object
-               if ( $arguments === false ) { // it is a constant or a property 
of an object
-                       if ( $object === false ) { // it is a constant
-                               return self::callConstant( $name );
-                       } else { // it is a property of an object
-                               return self::callObjectsProperty( $name, 
$object );
-                       }
+       public static function callHook( $type, $arguments, $name, $object ) {
+               switch ( $type ) {
+                       case PHPTAGS_HOOK_GET_CONSTANT: // Hook is a constant. 
Example: echo M_PI;
+                               return self::callGetConstant( $name );
+                       case PHPTAGS_HOOK_FUNCTION: // Hook is a function. 
Example: echo foo();
+                               return self::callFunction( $arguments, $name );
+                       case PHPTAGS_HOOK_GET_STATIC_PROPERTY: // Hook is a 
static property of a method. Example: echo FOO::bar;
+                               return self::callGetStaticProperty( $name, 
$object );
+                       case PHPTAGS_HOOK_GET_OBJECT_PROPERTY: // Hook is a 
property of a method. Example: $foo = new Foo(); echo $foo->bar;
+                               return self::callGetObjectsProperty( $name, 
$object );
+                       case PHPTAGS_HOOK_SET_STATIC_PROPERTY: // Example 
FOO::bar = true;
+                               return self::callSetStaticProperty( $name, 
$object, $arguments );
+                       case PHPTAGS_HOOK_SET_OBJECT_PROPERTY: // Example: $foo 
= new Foo(); $foo->bar = true;
+                               return self::callSetObjectsProperty( $name, 
$object, $arguments );
+                       case PHPTAGS_HOOK_STATIC_METHOD: // Example: FOO::bar()
+                               return self::callStaticMethod( $arguments, 
$name, $object );
+                       case PHPTAGS_HOOK_OBJECT_METHOD: // Example: $foo = new 
Foo(); $foo->bar();
+                               return self::callObjectsMethod( $arguments, 
$name, $object );
                }
-               // it is a function or a method of an object
-               if ( $object === false ) { // it is a function
-                       return self::callFunction( $arguments, $name );
-               }
-               // it is a method of an object
-               return self::callObjectsMethod( $arguments, $name, $object );
        }
 
        /**
@@ -169,7 +174,7 @@
         * @param string $name Name of the constant
         * @return mixed
         */
-       private static function callConstant( $name ) {
+       private static function callGetConstant( $name ) {
                static $constants = array(); // cache of called constants
 
                if ( isset ( self::$constants[$name] ) ) {
@@ -221,7 +226,13 @@
                                return;
                        }
                }
-               // it is calling of static method
+               Runtime::$transit[PHPTAGS_TRANSIT_EXCEPTION][] = new 
PhpTagsException( PhpTagsException::FATAL_CALL_FUNCTION_ON_NON_OBJECT, $name );
+       }
+
+       private static function callStaticMethod( $arguments, $name, $object ) {
+               if ( $object instanceof GenericObject ) {
+                       $object = $object->getName();
+               }
                $className = self::getClassNameByObjectName( $object );
                if ( true === $className::checkArguments( $object, $name, 
$arguments ) ) {
                        $arguments[] = $object;
@@ -236,15 +247,36 @@
         * @return mixed
         * @throws PhpTagsException
         */
-       public static function callObjectsProperty( $name, $object ) {
+       public static function callGetObjectsProperty( $name, $object ) {
                if ( $object instanceof GenericObject ) {
                        return call_user_func( array($object, "p_$name") );
                }
-               // it is calling of static property
+               Runtime::$transit[PHPTAGS_TRANSIT_EXCEPTION][] = new 
PhpTagsException( PhpTagsException::NOTICE_GET_PROPERTY_OF_NON_OBJECT, null );
+       }
+
+       public static function callGetStaticProperty( $name, $object ) {
+               if ( $object instanceof GenericObject ) {
+                       $object = $object->getName();
+               }
                $className = self::getClassNameByObjectName( $object );
                return call_user_func( array($className, "c_$name"), $object );
        }
 
+       public static function callSetObjectsProperty( $name, $object, $value ) 
{
+               if ( $object instanceof GenericObject ) {
+                       return call_user_func( array($object, "b_$name"), 
$value );
+               }
+               Runtime::$transit[PHPTAGS_TRANSIT_EXCEPTION][] = new 
PhpTagsException( PhpTagsException::WARNING_ATTEMPT_TO_ASSIGN_PROPERTY, null );
+       }
+
+       public static function callSetStaticProperty( $name, $object, $value ) {
+               if ( $object instanceof GenericObject ) {
+                       $object = $object->getName();
+               }
+               $className = self::getClassNameByObjectName( $object );
+               return call_user_func( array($className, "k_$name"), $object, 
$value );
+       }
+
        public static function createObject( $arguments, $name, $showException 
= true ) {
                $className = self::getClassNameByObjectName( $name );
                $object = new $className( $name );
diff --git a/includes/PhpTagsException.php b/includes/PhpTagsException.php
index aa714cf..6ee01ec 100644
--- a/includes/PhpTagsException.php
+++ b/includes/PhpTagsException.php
@@ -150,6 +150,15 @@
                        case self::FATAL_CALLED_MANY_EXPENSIVE_FUNCTION:
                                $message = "Too many expensive function calls, 
last is $arguments";
                                break;
+                       case self::NOTICE_GET_PROPERTY_OF_NON_OBJECT:
+                               $message = 'Trying to get property of 
non-object';
+                               break;
+                       case self::WARNING_ATTEMPT_TO_ASSIGN_PROPERTY:
+                               $message = 'Attempt to assign property of 
non-object';
+                               break;
+                       case self::FATAL_CALL_FUNCTION_ON_NON_OBJECT;
+                               $message = "Call to a member function 
$arguments() on a non-object";
+                               break;
                        default:
                                $message = "Undefined error, code 
{$this->code}";
                                $this->code = self::EXCEPTION_FATAL * 1000;
@@ -191,6 +200,7 @@
        const NOTICE_UNDEFINED_PROPERTY = 2006;  // PHP Notice:  Undefined 
property: DateInterval::$rsss
        const NOTICE_UNDEFINED_CLASS_CONSTANT = 2007;  // PHP Fatal error:  
Undefined class constant 'EXCLUDE_START_DATEqqqq'
        const NOTICE_OBJECT_CONVERTED = 2008;  // PHP Notice:  Object of class 
Exception could not be converted to int
+       const NOTICE_GET_PROPERTY_OF_NON_OBJECT = 2009; // PHP Notice:  Trying 
to get property of non-object
 
        const EXCEPTION_WARNING = 3;
        const WARNING_DIVISION_BY_ZERO = 3001;  // PHP Warning:  Division by 
zero
@@ -203,6 +213,7 @@
        const WARNING_EXPECTS_EXACTLY_PARAMETER = 3009;  // PHP Warning:  
date_format() expects exactly 1 parameter, 3 given
        const WARNING_EXPECTS_AT_LEAST_PARAMETERS = 3010;
        const WARNING_EXPECTS_AT_LEAST_PARAMETER = 3011;  // PHP Warning:  
sprintf() expects at least 1 parameter, 0 given
+       const WARNING_ATTEMPT_TO_ASSIGN_PROPERTY = 3012; // PHP Warning:  
Attempt to assign property of non-object
 
        const WARNING_CALLFUNCTION_INVALID_HOOK = 3900;
        const WARNING_CALLCONSTANT_INVALID_HOOK = 3901;
@@ -226,6 +237,7 @@
        const FATAL_INVALID_CONSTANT_CLASS = 4016;
        const FATAL_CANNOT_UNSET_STRING_OFFSETS = 4017; // PHP Fatal error:  
Cannot unset string offsets
        const FATAL_CALLED_MANY_EXPENSIVE_FUNCTION = 4018;
+       const FATAL_CALL_FUNCTION_ON_NON_OBJECT = 4019; // PHP Fatal error:  
Call to a member function doo() on a non-object
 
        const EXCEPTION_CATCHABLE_FATAL = 5;
        const FATAL_OBJECT_COULD_NOT_BE_CONVERTED = 5001;  //PHP Catchable 
fatal error:  Object of class stdClass could not be converted to string
diff --git a/includes/Runtime.php b/includes/Runtime.php
index cdc4644..7b8b2d3 100644
--- a/includes/Runtime.php
+++ b/includes/Runtime.php
@@ -13,6 +13,16 @@
 define( 'PHPTAGS_STACK_ARRAY_INDEX', 'a' );
 define( 'PHPTAGS_STACK_DEBUG', '#' );
 define( 'PHPTAGS_STACK_AIM', '*' );
+define( 'PHPTAGS_STACK_HOOK_TYPE', 'h' );
+
+define( 'PHPTAGS_HOOK_GET_CONSTANT', '_' );
+define( 'PHPTAGS_HOOK_FUNCTION', 'f' );
+define( 'PHPTAGS_HOOK_GET_STATIC_PROPERTY', 'c' );
+define( 'PHPTAGS_HOOK_GET_OBJECT_PROPERTY', 'p' );
+define( 'PHPTAGS_HOOK_SET_STATIC_PROPERTY', 'k' );
+define( 'PHPTAGS_HOOK_SET_OBJECT_PROPERTY', 'b' );
+define( 'PHPTAGS_HOOK_STATIC_METHOD', 's' );
+define( 'PHPTAGS_HOOK_OBJECT_METHOD', 'm' );
 
 define( 'PHPTAGS_OBJECT_DEFINITION', 0 );
 define( 'PHPTAGS_METHOD_CONSTRUCTOR', 1 );
@@ -438,6 +448,7 @@
                                                        break;
                                                case PHPTAGS_T_HOOK:
                                                        $result = 
Hooks::callHook(
+                                                                       
$value[PHPTAGS_STACK_HOOK_TYPE],
                                                                        
$value[PHPTAGS_STACK_PARAM_2], // arguments
                                                                        
$value[PHPTAGS_STACK_PARAM], // name of function or method
                                                                        
$value[PHPTAGS_STACK_PARAM_3] // $object or false

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I5ef1406b51e137b96359a3403b06f512578a5e82
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/PhpTags
Gerrit-Branch: master
Gerrit-Owner: Pastakhov <pastak...@yandex.ru>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to