Pastakhov has submitted this change and it was merged.

Change subject: add class BaseHooks
......................................................................


add class BaseHooks

Change-Id: I3aa6723f9377a03732dfb262aa815a5c4caa9a42
---
M PhpTags.php
A includes/BaseHooks.php
M includes/ExceptionPhpTags.php
M includes/Runtime.php
M tests/phpunit/includes/RuntimeTest.php
5 files changed, 157 insertions(+), 97 deletions(-)

Approvals:
  Pastakhov: Verified; Looks good to me, approved



diff --git a/PhpTags.php b/PhpTags.php
index e00f77c..a911d05 100644
--- a/PhpTags.php
+++ b/PhpTags.php
@@ -73,6 +73,7 @@
 $wgAutoloadClasses['PhpTags\\ExceptionPhpTags']        = __DIR__ . 
'/includes/ExceptionPhpTags.php';
 $wgAutoloadClasses['PhpTags\\Compiler']                        = __DIR__ . 
'/includes/Compiler.php';
 $wgAutoloadClasses['PhpTags\\Runtime']                 = __DIR__ . 
'/includes/Runtime.php';
+$wgAutoloadClasses['PhpTags\\BaseHooks']               = __DIR__ . 
'/includes/BaseHooks.php';
 
 /**
  * Add files to phpunit test
diff --git a/includes/BaseHooks.php b/includes/BaseHooks.php
new file mode 100644
index 0000000..51aec92
--- /dev/null
+++ b/includes/BaseHooks.php
@@ -0,0 +1,84 @@
+<?php
+namespace PhpTags;
+
+define( 'PHPTAGS_HOOK_INVOKE', '=' );
+define( 'PHPTAGS_HOOK_VALUE_TYPE', 0 );
+define( 'PHPTAGS_HOOK_NEED_LINK', 1 );
+define( 'PHPTAGS_HOOK_DEFAULT_VALUE', 2 );
+define( 'PHPTAGS_HOOK_RETURNS_ON_FAIL', 1 );
+
+define( 'PHPTAGS_TYPE_ARRAY', 'a' );
+define( 'PHPTAGS_TYPE_INT', 'i' );
+
+/**
+ * This class is base for all constants, functions and objects hooks in the 
extension PhpTags
+ *
+ * @file BaseHooks.php
+ * @ingroup PhpTags
+ * @author Pavel Astakhov <pastak...@yandex.ru>
+ * @licence GNU General Public Licence 2.0 or later
+ */
+abstract class BaseHooks {
+       protected static $functions_definition = array();
+
+       abstract static function getClassName();
+
+       public static function onFunctionHook( $name, $params ) {
+               if ( !isset(static::$functions_definition[$name]) ) {
+                       return new ExceptionPhpTags( 
PHPTAGS_EXCEPTION_WARNING_INVALID_HOOK, array($name, static::getClassName()) );
+               }
+               $definition = static::$functions_definition[$name];
+               $args = array();
+               for ( $i=0, $c=count($params); $i < $c; $i++ ) {
+                       if ( !isset($definition[$i+1]) ) {
+                               Runtime::addException(
+                                               new ExceptionPhpTags( 
PHPTAGS_EXCEPTION_WARNING_WRONG_PARAMETER_COUNT, $name )
+                                       );
+                               return;
+                       }
+
+                       if ( $definition[$i+1][PHPTAGS_HOOK_NEED_LINK] ) {
+                               if ( $params[$i][PHPTAGS_STACK_COMMAND] != 
T_VARIABLE ) {
+                                       return new ExceptionPhpTags( 
PHPTAGS_EXCEPTION_FATAL_VALUE_PASSED_BY_REFERENCE );
+                               }
+                               $args[$i] = &$params[$i][PHPTAGS_STACK_RESULT];
+                       } else {
+                               $args[$i] = $params[$i][PHPTAGS_STACK_RESULT];
+                       }
+                       
+                       switch ( $definition[$i+1][PHPTAGS_HOOK_VALUE_TYPE] ) {
+                               case PHPTAGS_TYPE_ARRAY:
+                                       if ( !is_array($args[$i]) ) {
+                                               Runtime::addException(
+                                                               new 
ExceptionPhpTags( PHPTAGS_EXCEPTION_WARNING_EXPECTS_PARAMETER, array($name, 
$i+1, 'array', gettype($args[$i])) )
+                                                       );
+                                               return 
$definition[0][PHPTAGS_HOOK_RETURNS_ON_FAIL];
+                                       }
+                                       break;
+                               case PHPTAGS_TYPE_INT:
+                                       if ( is_object($args[$i]) ) {
+                                               Runtime::addException(
+                                                                // @todo 
unknown
+                                                               new 
ExceptionPhpTags( PHPTAGS_EXCEPTION_NOTICE_OBJECT_CONVERTED, array('unknown', 
'int') )
+                                                       );
+                                               unset( $args[$i] );
+                                               $args[$i] = 1;
+                                       }
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
+               while ( !isset($definition[PHPTAGS_HOOK_INVOKE][$i]) ) {
+                       if ( 
!isset($definition[$i+1][PHPTAGS_HOOK_DEFAULT_VALUE]) ) {
+                               Runtime::addException(
+                                               new ExceptionPhpTags( 
PHPTAGS_EXCEPTION_WARNING_WRONG_PARAMETER_COUNT, $name )
+                                       );
+                               return;
+                       }
+                       $args[$i] = 
$definition[$i+1][PHPTAGS_HOOK_DEFAULT_VALUE];
+                       $i++;
+               }
+               return call_user_func_array( 'static::' . 
$definition[PHPTAGS_HOOK_INVOKE][$i], $args );
+       }
+}
\ No newline at end of file
diff --git a/includes/ExceptionPhpTags.php b/includes/ExceptionPhpTags.php
index 1a2e6c1..28a4983 100644
--- a/includes/ExceptionPhpTags.php
+++ b/includes/ExceptionPhpTags.php
@@ -7,14 +7,22 @@
 define( 'PHPTAGS_EXCEPTION_NOTICE_UNINIT_STRING_OFFSET', 2002 ); // PHP 
Notice:  Uninitialized string offset: $1
 define( 'PHPTAGS_EXCEPTION_NOTICE_UNDEFINED_OFFSET', 2003 ); // PHP Notice:  
Undefined offset: 4 in Command line code on line 1
 define( 'PHPTAGS_EXCEPTION_NOTICE_UNDEFINED_CONSTANT', 2004 ); // PHP Notice:  
Use of undefined constant $1 - assumed '$1'
+define( 'PHPTAGS_EXCEPTION_NOTICE_OBJECT_CONVERTED', 2005 ); // PHP Notice:  
Object of class Exception could not be converted to int
 
 define( 'PHPTAGS_EXCEPTION_WARNING_DIVISION_BY_ZERO', 3001 ); // PHP Warning:  
Division by zero
 define( 'PHPTAGS_EXCEPTION_WARNING_SCALAR_VALUE_AS_ARRAY', 3002 ); // PHP 
Warning:  Cannot use a scalar value as an array
 define( 'PHPTAGS_EXCEPTION_WARNING_INVALID_ARGUMENT_FOR_FOREACH', 3003 ); // 
PHP Warning:  Invalid argument supplied for foreach()
 define( 'PHPTAGS_EXCEPTION_WARNING_RETURNED_INVALID_VALUE', 3004 );
+define( 'PHPTAGS_EXCEPTION_WARNING_INVALID_HOOK', 3005 );
+define( 'PHPTAGS_EXCEPTION_WARNING_EXPECTS_PARAMETER', 3006 ); // PHP Warning: 
 func() expects parameter 1 to be array, integer given
+define( 'PHPTAGS_EXCEPTION_WARNING_WRONG_PARAMETER_COUNT', 3007 ); // PHP 
Warning:  Wrong parameter count for $1()
 
 define( 'PHPTAGS_EXCEPTION_FATAL_CANNOT_USE_FOR_READING', 4001 ); // PHP Fatal 
error:  Cannot use [] for reading in Command line code on line 1
 define( 'PHPTAGS_EXCEPTION_FATAL_STRING_OFFSET_AS_ARRAY', 4002 ); // PHP Fatal 
error:  Cannot use string offset as an array
+define( 'PHPTAGS_EXCEPTION_FATAL_VALUE_PASSED_BY_REFERENCE', 4003 ); // PHP 
Fatal error:  Only variables can be passed by reference
+define( 'PHPTAGS_EXCEPTION_FATAL_CALL_TO_UNDEFINED_FUNCTION', 4004 ); // PHP 
Fatal error:  Call to undefined function $1()
+define( 'PHPTAGS_EXCEPTION_FATAL_NONEXISTENT_HOOK_CLASS', 4005 );
+define( 'PHPTAGS_EXCEPTION_FATAL_INVALID_HOOK_CLASS', 4006 );
 
 // pcre
 define( 'PHPTAGS_EXCEPTION_WARNING_WRONG_DELIMITER', 2009 ); // PHP Warning:  
preg_replace(): Delimiter must not be alphanumeric or backslash
@@ -28,7 +36,6 @@
 define( 'PHPTAGS_FATAL_UNABLE_CALL_TO_FUNCTION', 105 ); // 
$foxwayFunctions[$1][$2] is not callable
 define( 'PHPTAGS_FATAL_ERROR_CALL_TO_FUNCTION', 106 ); // Error in 
$foxwayFunctions[$1]
 define( 'PHPTAGS_WARNING_WRONG_PARAMETER_COUNT', 107 ); // PHP Warning:  Wrong 
parameter count for $1()
-define( 'PHPTAGS_FATAL_VALUE_PASSED_BY_REFERENCE', 108 ); // PHP Fatal error:  
Only variables can be passed by reference
 define( 'PHPTAGS_FATAL_CANNOT_UNSET_STRING_OFFSETS', 115 ); // PHP Fatal 
error:  Cannot unset string offsets
 
 // PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried 
to allocate 73 bytes)
@@ -102,7 +109,28 @@
                                // @todo
                                $message = "PHP Warning: constant, function or 
object '$params' returns an invalid value";
                                break;
-                       
+                       case PHPTAGS_EXCEPTION_FATAL_VALUE_PASSED_BY_REFERENCE:
+                               $message = "PHP Fatal error:  Only variables 
can be passed by reference";
+                               break;
+                       case PHPTAGS_EXCEPTION_WARNING_EXPECTS_PARAMETER:
+                               $message = "PHP Warning:  {$params[0]} expects 
parameter {$params[1]} to be {$params[2]}, {$params[3]} given";
+                               break;
+                       case PHPTAGS_EXCEPTION_NOTICE_OBJECT_CONVERTED:
+                               $message = "PHP Notice:  Object of class 
{$params[0]} could not be converted to {$params[1]}";
+                               break;
+                       case PHPTAGS_EXCEPTION_WARNING_WRONG_PARAMETER_COUNT:
+                               $message = "PHP Warning:  Wrong parameter count 
for $params()";
+                               break;
+                       case PHPTAGS_EXCEPTION_FATAL_CALL_TO_UNDEFINED_FUNCTION:
+                               $message = "PHP Fatal error:  Call to undefined 
function $params()";
+                               break;
+                       case PHPTAGS_EXCEPTION_FATAL_NONEXISTENT_HOOK_CLASS:
+                               $message = "PHP Fatal error:  For the function 
{$params[0]} was registered nonexistent hook class {$params[1]}";
+                               break;
+                       case PHPTAGS_EXCEPTION_FATAL_INVALID_HOOK_CLASS:
+                               $message = "PHP Fatal error:  For the function 
{$params[0]} was registered invalid hook class {$params[1]}";
+                               break;
+
                        // pcre
                        case PHPTAGS_EXCEPTION_WARNING_WRONG_DELIMITER:
                                $message = "PHP Warning:  preg_replace(): 
Delimiter must not be alphanumeric or backslash";
@@ -115,18 +143,13 @@
                                break;
 
 
-                       case PHPTAGS_FATAL_CALL_TO_UNDEFINED_FUNCTION:
-                               $message = "PHP Fatal error:  Call to undefined 
function $params()";
-                               break;
                        case PHPTAGS_FATAL_UNABLE_CALL_TO_FUNCTION:
                                $message = "PHP Fatal error:  
\$foxwayFunctions[{$params[0]}][{$params[1]}] is not callable";
                                break;
                        case PHPTAGS_FATAL_ERROR_CALL_TO_FUNCTION:
                                $message = "PHP Fatal error:  Error at 
\$foxwayFunctions[$params]";
                                break;
-                       case PHPTAGS_WARNING_WRONG_PARAMETER_COUNT:
-                               $message = "PHP Warning:  Wrong parameter count 
for $params()";
-                               break;
+
                        case PHPTAGS_FATAL_CANNOT_UNSET_STRING_OFFSETS:
                                $message = 'PHP Fatal error:  Cannot unset 
string offsets';
                                break;
diff --git a/includes/Runtime.php b/includes/Runtime.php
index 6b90976..0f27d9c 100644
--- a/includes/Runtime.php
+++ b/includes/Runtime.php
@@ -26,18 +26,19 @@
  */
 class Runtime {
 
-       static private $constantsValue = array();
-       static private $constantsHook = array();
-       static private $functionsHook = array();
-       static private $objectsHook = array();
+       private static $constantsValue = array();
+       private static $constantsHook = array();
+       private static $functionsHook = array();
+       private static $objectsHook = array();
 
        static public $time = 0;
        static public $permittedTime = true;
        protected static $startTime = array();
 
-       protected static $variables = array();
-       protected static $staticVariables = array();
-       protected static $globalVariables = array();
+       private static $variables = array();
+       private static $staticVariables = array();
+       private static $globalVariables = array();
+       private static $tmpException = array();
 
        /*public function startTime($scope) {
                self::$startTime[$scope] = microtime(true);
@@ -365,89 +366,38 @@
                                                $name = 
$value[PHPTAGS_STACK_PARAM];
                                                if ( 
isset($value[PHPTAGS_STACK_PARAM_2]) ) { // This is function or object
                                                        if ( 
is_array($value[PHPTAGS_STACK_PARAM_2]) ) { // This is function
-                                                               if ( 
isset(self::$functionsHook[$name]) ) {
-                                                                       
$function = &self::$functionsHook[$name];
-                                                                       $param 
= array();
-                                                                       foreach 
( $value[PHPTAGS_STACK_PARAM_2] as $val ) {
-                                                                               
if ( $val[PHPTAGS_STACK_COMMAND] == T_VARIABLE ) { // Example $foo
-                                                                               
        $ref = &$thisVariables[ $val[PHPTAGS_STACK_PARAM] ];
-                                                                               
        if ( isset($val[PHPTAGS_STACK_ARRAY_INDEX]) ) { // Example: $foo[1]
-                                                                               
                foreach ( $val[PHPTAGS_STACK_ARRAY_INDEX] as $v ) {
-                                                                               
                        if ( !isset($ref[ $v[PHPTAGS_STACK_RESULT] ]) ) {
-                                                                               
                                $ref[ $v[PHPTAGS_STACK_RESULT] ] = null;
-                                                                               
                                // @todo PHP Fatal error:  Only variables can 
be passed by reference
-                                                                               
                                if( is_string($ref) ) {
-                                                                               
                                        
//PHPTAGS_EXCEPTION_NOTICE_UNINIT_STRING_OFFSET $return[] = (string) new 
ExceptionPhpTags( (int)$v[PHPTAGS_STACK_RESULT] , 
PHPTAGS_NOTICE_UNINIT_STRING_OFFSET, $value[PHPTAGS_STACK_TOKEN_LINE], $place );
-                                                                               
                                }
-                                                                               
                        }
-                                                                               
                        $ref = &$ref[ $v[PHPTAGS_STACK_RESULT] ];
-                                                                               
                }
-                                                                               
        }
-                                                                               
        $param[] = &$ref;
-                                                                               
} else {
-                                                                               
        // @todo PHP Fatal error:  Only variables can be passed by reference
-                                                                               
        $param[] = $val[PHPTAGS_STACK_RESULT];
-                                                                               
}
-                                                                       }
-                                                                       $count 
= count( $param );
-                                                                       do {
-                                                                               
if( isset($function[$count]) ) {
-                                                                               
        $function = &$function[$count];
-                                                                               
        break;
-                                                                               
} else {
-                                                                               
        if ( isset($function[PHPTAGS_DEFAULT_VALUES]) ) { // Has default values
-                                                                               
                $param += $function[PHPTAGS_DEFAULT_VALUES];
-                                                                               
                $count = count( $param );
-                                                                               
                if( isset($function[$count]) ) {
-                                                                               
                        $function = &$function[$count];
-                                                                               
                        break;
-                                                                               
                }
-                                                                               
        }
-                                                                               
        if ( isset($function[PHPTAGS_MIN_VALUES]) ) {
-                                                                               
                if( $count >= $function[PHPTAGS_MIN_VALUES] && 
isset($function['']) ) {
-                                                                               
                        $function = &$function[''];
-                                                                               
                        $count = "''"; // it for error message
-                                                                               
                        break;
-                                                                               
                }
-                                                                               
        }
-                                                                               
}
-                                                                               
$return[] = (string) new ExceptionPhpTags( $name, 
PHPTAGS_WARNING_WRONG_PARAMETER_COUNT, $value[PHPTAGS_STACK_TOKEN_LINE], $place 
);
-                                                                               
$value[PHPTAGS_STACK_RESULT] = null;
-                                                                               
break 2; /**** EXIT ****/
-                                                                       } 
while( false );
+                                                               if ( 
!isset(self::$functionsHook[$name]) ) {
+                                                                       
$return[] = new ExceptionPhpTags( 
PHPTAGS_EXCEPTION_FATAL_CALL_TO_UNDEFINED_FUNCTION, $name, 
$value[PHPTAGS_STACK_TOKEN_LINE], $place );
+                                                                       return 
$return;
+                                                               }
+                                                               $hookClassName 
= self::$functionsHook[$name];
+                                                               if( 
!class_exists($hookClassName) ) {
+                                                                       
$return[] = new ExceptionPhpTags( 
PHPTAGS_EXCEPTION_FATAL_NONEXISTENT_HOOK_CLASS, array($name, $hookClassName), 
$value[PHPTAGS_STACK_TOKEN_LINE], $place );
+                                                                       return 
$return;
+                                                               }
+                                                               $classParens = 
class_parents( $hookClassName );
+                                                               if ( 
!isset($classParens['PhpTags\\BaseHooks']) ) {
+                                                                       
$return[] = new ExceptionPhpTags( PHPTAGS_EXCEPTION_FATAL_INVALID_HOOK_CLASS, 
array($name, $hookClassName), $value[PHPTAGS_STACK_TOKEN_LINE], $place );
+                                                                       return 
$return;
+                                                               }
 
-                                                                       if ( 
is_callable($function) ) {
-                                                                               
try {
-                                                                               
        wfSuppressWarnings();
-                                                                               
        $result = $function( $param, $transit );
-                                                                               
        if ( $result instanceof outPrint ) {
-                                                                               
                $value[PHPTAGS_STACK_RESULT] = $result->returnValue;
-                                                                               
                $return[] = $result;
-                                                                               
        } else {
-                                                                               
                $value[PHPTAGS_STACK_RESULT] = $result;
-                                                                               
        }
-                                                                               
        wfRestoreWarnings();
-                                                                               
} catch ( ExceptionPhpTags $e ) {
-                                                                               
        $e->tokenLine = $value[PHPTAGS_STACK_TOKEN_LINE];
-                                                                               
        $e->place = $place;
-                                                                               
        if ( is_array($e->params) ) {
-                                                                               
                array_unshift( $e->params, $name );
-                                                                               
        }
-                                                                               
        $return[] = $e;
-                                                                               
        $value[PHPTAGS_STACK_RESULT] = null;
-                                                                               
        break; /**** EXIT ****/
-                                                                               
} catch (Exception $e) {
-                                                                               
        $return[] = (string) new ExceptionPhpTags( $name, 
PHPTAGS_FATAL_ERROR_CALL_TO_FUNCTION, $value[PHPTAGS_STACK_TOKEN_LINE], $place 
);
-                                                                               
        $value[PHPTAGS_STACK_RESULT] = null;
-                                                                               
        break; /**** EXIT ****/
-                                                                               
}
-                                                                       } else {
-                                                                               
$return[] = (string) new ExceptionPhpTags( array($name, $count), 
PHPTAGS_FATAL_UNABLE_CALL_TO_FUNCTION, $value[PHPTAGS_STACK_TOKEN_LINE], $place 
);
-                                                                               
$value[PHPTAGS_STACK_RESULT] = null;
-                                                                               
break; /**** EXIT ****/
+                                                               try {
+                                                                       
wfSuppressWarnings();
+
+                                                                       
$value[PHPTAGS_STACK_RESULT] = $hookClassName::onFunctionHook( $name, 
$value[PHPTAGS_STACK_PARAM_2] );
+
+                                                                       
wfRestoreWarnings();
+                                                               } catch ( 
ExceptionPhpTags $e ) {
+                                                                       
$e->tokenLine = $value[PHPTAGS_STACK_TOKEN_LINE];
+                                                                       
$e->place = $place;
+                                                                       if ( 
is_array($e->params) ) {
+                                                                               
array_unshift( $e->params, $name );
                                                                        }
-                                                               } else {
-                                                                       
$return[] = (string) new ExceptionPhpTags( $name, 
PHPTAGS_FATAL_CALL_TO_UNDEFINED_FUNCTION, $value[PHPTAGS_STACK_TOKEN_LINE], 
$place );
+                                                                       
$return[] = $e;
+                                                                       
$value[PHPTAGS_STACK_RESULT] = null;
+                                                                       break; 
/**** EXIT ****/
+                                                               } catch 
(Exception $e) {
+                                                                       
$return[] = (string) new ExceptionPhpTags( $name, 
PHPTAGS_FATAL_ERROR_CALL_TO_FUNCTION, $value[PHPTAGS_STACK_TOKEN_LINE], $place 
);
                                                                        
$value[PHPTAGS_STACK_RESULT] = null;
                                                                        break; 
/**** EXIT ****/
                                                                }
@@ -736,5 +686,8 @@
        public static function setObjectsHook( $className, array $objectsName ) 
{
                self::$objectsHook += array_fill_keys( $objectsName, $className 
);
        }
+       public static function addException( ExceptionPhpTags $exception ) {
+               self::$tmpException[] = $exception;
+       }
 
 }
diff --git a/tests/phpunit/includes/RuntimeTest.php 
b/tests/phpunit/includes/RuntimeTest.php
index aff1d48..00e4698 100644
--- a/tests/phpunit/includes/RuntimeTest.php
+++ b/tests/phpunit/includes/RuntimeTest.php
@@ -2474,5 +2474,4 @@
                                );
        }
 
-
 }

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I3aa6723f9377a03732dfb262aa815a5c4caa9a42
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/PhpTags
Gerrit-Branch: master
Gerrit-Owner: Pastakhov <pastak...@yandex.ru>
Gerrit-Reviewer: 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