jenkins-bot has submitted this change and it was merged.

Change subject: Add String Functions (version 0.4.2)
......................................................................


Add String Functions (version 0.4.2)

* add $wgNamespacesWithFoxway
* add Settings.php
* fix for passByReference
* small optimization for FArray

Change-Id: Id3a7f6ed3303660cff3bd3c3a41ffd45fa887993
---
M Foxway.body.php
M Foxway.i18n.php
M Foxway.php
A Settings.php
M includes/Debug.php
M includes/Interpreter.php
M includes/Runtime.php
M includes/RuntimeDebug.php
M includes/functions/BaseFunction.php
M includes/functions/FArray.php
A includes/functions/FString.php
M tests/phpunit/includes/InterpreterTest.php
12 files changed, 575 insertions(+), 158 deletions(-)

Approvals:
  Pastakhov: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/Foxway.body.php b/Foxway.body.php
index 0013902..f707185 100644
--- a/Foxway.body.php
+++ b/Foxway.body.php
@@ -11,38 +11,12 @@
 
        static $frames=array();
 
-       /**
-        * 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) {
+               global $wgNamespacesWithFoxway;
+               if( $wgNamespacesWithFoxway !== true && 
empty($wgNamespacesWithFoxway[$frame->getTitle()->getNamespace()]) ) {
+                       return Html::element( 'span', array('class'=>'error'), 
wfMessage('foxway-disabled-for-namespace', 
$frame->getTitle()->getNsText())->escaped() );
+               }
+
                $is_debug = isset($args['debug']);
                $return = '';
 
@@ -56,9 +30,7 @@
                foreach ($result as &$value) {
                        if( $value instanceof Foxway\iRawOutput ) {
                                $value = (string)$value;
-                       }/*else{ // @todo ????
-                               $value = strtr( $value, array('&'=>'&amp;', 
'<'=>'&lt;') );
-                       }*/
+                       }
                }
 
                if( $is_debug ) {
@@ -66,7 +38,7 @@
                        $return .= self::insertNoWiki( $parser, 
array_shift($result) ) . "\n";
                }
 
-               return $return . self::insertGeneral( $parser, 
$parser->recursiveTagParse(implode('', $result),$frame) );
+               return $return . self::insertGeneral( $parser, 
$parser->recursiveTagParse(implode($result),$frame) );
        }
 
        /**
diff --git a/Foxway.i18n.php b/Foxway.i18n.php
index 124afe8..fdc0eb9 100644
--- a/Foxway.i18n.php
+++ b/Foxway.i18n.php
@@ -13,7 +13,8 @@
  * @author pastakhov
  */
 $messages['en'] = array(
-       'foxway-desc' => 'Allows to store an object-oriented data and 
implements its own runtime for PHP code on pages',
+       'foxway-desc' => 'Adds in the wikitext parser the ability to use the 
syntax and functions of PHP',
+       'foxway-disabled-for-namespace' => 'Extension foxway disabled for this 
namespace $1',
        'foxway-php-fatal-error-undefined-function' => 'PHP fatal error: Call 
to undefined function $1() on page $2 line $3.',
        'foxway-php-not-variable-passed-by-reference' => 'PHP fatal error: Only 
variables can be passed by reference, function $1() on page $2 line $3.',
        'foxway-php-syntax-error-unexpected' => 'PHP parse error: Syntax error, 
unexpected $1 in command line code on line $2.',
@@ -27,6 +28,8 @@
  */
 $messages['qqq'] = array(
        'foxway-desc' => 
'{{desc|name=Foxway|url=https://www.mediawiki.org/wiki/Extension:Foxway}}',
+       'foxway-disabled-for-namespace' => 'Error message when trying use this 
extension on the pages of the namespace where it is not permitted, parameters:
+* $1 - the namespace name',
        'foxway-php-fatal-error-undefined-function' => 'Error message, 
parameters:
 * $1 - user-specified function name
 * $2 - the name of the page on which the error occurred
diff --git a/Foxway.php b/Foxway.php
index 2ddd4b0..de30ac2 100644
--- a/Foxway.php
+++ b/Foxway.php
@@ -15,7 +15,7 @@
        die( 'This file is an extension to MediaWiki and thus not a valid entry 
point.' );
 }
 
-define( 'Foxway_VERSION' , '0.4.1' );
+define( 'Foxway_VERSION' , '0.4.2' );
 
 // Register this extension on Special:Version
 $wgExtensionCredits['parserhook'][] = array(
@@ -64,6 +64,7 @@
 
 $wgAutoloadClasses['Foxway\\BaseFunction']             = $dir . 
'/includes/functions/BaseFunction.php';
 $wgAutoloadClasses['Foxway\\FArray']                   = $dir . 
'/includes/functions/FArray.php';
+$wgAutoloadClasses['Foxway\\FString']                  = $dir . 
'/includes/functions/FString.php';
 $wgAutoloadClasses['Foxway\\FVariable']                        = $dir . 
'/includes/functions/FVariable.php';
 
 // Resources
@@ -85,6 +86,10 @@
                return true;
 };
 
+include_once 'Settings.php';
+
+// @todo Reverse shift ???
+// Do not change the value of this variable in LocalSettings.php!!!
 $wgFoxwayPassByReference = array(
        'settype' => 1,
        'unset' => -1,
@@ -111,101 +116,8 @@
        'rsort' => 1,
        'shuffle' => 1,
        'sort' => 1,
-);
-
-$wgFoxwayFunctions = array(
-       'FVariable' => array( // Variable handling Functions @see 
http://www.php.net/manual/en/ref.var.php
-               'boolval',
-               //'debug_zval_dump',
-               'doubleval',
-               'empty',
-               'floatval',
-               'get_defined_vars', //implemented in Runtime.php
-               //'get_resource_type',
-               'gettype',
-               //'import_request_variables', @todo  need hide not foxway Cookie
-               'intval',
-               'is_array',
-               'is_bool',
-               //'is_callable',
-               'is_double',
-               'is_float',
-               'is_int',
-               'is_integer',
-               'is_long',
-               'is_null',
-               'is_numeric',
-               //'is_object',
-               'is_real',
-               //'is_resource',
-               'is_scalar',
-               'is_string',
-               'isset',
-               'print_r',
-               //'serialize',
-               'settype',
-               'strval',
-               //'unserialize',
-               'unset',
-               'var_dump',
-               'var_export',
-       ),
-       'FArray' => array( // Array Functions @see 
http://www.php.net/manual/en/ref.array.php
-               'array_change_key_case',
-               'array_chunk',
-               //'array_column', @todo PHP 5 >= 5.5.0
-               'array_combine',
-               'array_count_values',
-               'array_diff_assoc',
-               'array_diff_key',
-               'array_diff',
-               'array_fill_keys',
-               'array_fill',
-               'array_flip',
-               'array_intersect_assoc',
-               'array_intersect_key',
-               'array_intersect',
-               'array_key_exists',
-               'array_keys',
-               'array_merge_recursive',
-               'array_merge',
-               'array_multisort',
-               'array_pad',
-               'array_pop',
-               'array_product',
-               'array_push',
-               'array_rand',
-               'array_replace_recursive',
-               'array_replace',
-               'array_reverse',
-               'array_search',
-               'array_shift',
-               'array_slice',
-               'array_splice',
-               'array_sum',
-               'array_unique',
-               'array_unshift',
-               'array_values',
-               'arsort',
-               'asort',
-               'count',
-               'current',
-               'each',
-               'end',
-               'in_array',
-               'key',
-               'krsort',
-               'ksort',
-               'natcasesort',
-               'natsort',
-               'next',
-               'pos',
-               'prev',
-               'range',
-               'reset',
-               'rsort',
-               'shuffle',
-               'sizeof',
-               'sort',
-       ),
+       'similar_text' => 4, // 0b100
+       'sscanf' => 2147483644, // 0b1111111111111111111111111111100
+       'str_ireplace' => 8, // 0b1000
+       'str_replace' => 8, // 0b1000
 );
diff --git a/Settings.php b/Settings.php
new file mode 100644
index 0000000..be813f8
--- /dev/null
+++ b/Settings.php
@@ -0,0 +1,324 @@
+<?php
+/**
+ * File defining the settings for the Foxway extension.
+ * More info can be found at https://www.mediawiki.org/wiki/Extension:Foxway
+ *
+ *                                               NOTICE:
+ * Changing one of these settings can be done by copieng or cutting it,
+ * and placing it in LocalSettings.php, AFTER the inclusion of Foxway.
+ *
+ * @file Settings.php
+ * @ingroup Foxway
+ * @author Pavel Astakhov <pastak...@yandex.ru>
+ */
+
+// 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.' );
+}
+
+// Default settings
+
+
+/**
+ * You can specify the namespaces in which is allowed to use the extension 
Foxway.
+ *
+ * Thus it is possible to give permission to use this extension is just a 
special user group, example:
+ * define("NS_PHP", 1000);
+ * define("NS_PHP_TALK", 1001);
+ * $wgExtraNamespaces[NS_PHP] = "PHP";
+ * $wgExtraNamespaces[NS_PHP_TALK] = "PHP_Talk";
+ *
+ * $wgNamespacesWithFoxway = array( NS_PHP );
+ * $wgNamespaceProtection[NS_PHP] = array( 'php_editor' );
+ * $wgGroupPermissions['sysop']['php_editor'] = true;
+ *
+ * @var array Namespaces in which is allowed to use the extension Foxway, 
boolean 'true' for unlimited
+ */
+$wgNamespacesWithFoxway = true;
+
+$wgFoxwayFunctions = array(
+       'FVariable' => array( // Variable handling Functions @see 
http://www.php.net/manual/en/ref.var.php
+               'boolval',
+               //'debug_zval_dump',
+               'doubleval',
+               'empty',
+               'floatval',
+               'get_defined_vars', //implemented in Runtime.php
+               //'get_resource_type',
+               'gettype',
+               //'import_request_variables', @todo  need hide not foxway Cookie
+               'intval',
+               'is_array',
+               'is_bool',
+               //'is_callable',
+               'is_double',
+               'is_float',
+               'is_int',
+               'is_integer',
+               'is_long',
+               'is_null',
+               'is_numeric',
+               //'is_object',
+               'is_real',
+               //'is_resource',
+               'is_scalar',
+               'is_string',
+               'isset',
+               'print_r',
+               //'serialize',
+               'settype',
+               'strval',
+               //'unserialize',
+               'unset',
+               'var_dump',
+               'var_export',
+       ),
+       'FArray' => array( // Array Functions @see 
http://www.php.net/manual/en/ref.array.php
+               'array_change_key_case',
+               'array_chunk',
+               //'array_column', @todo PHP 5 >= 5.5.0
+               'array_combine',
+               'array_count_values',
+               'array_diff_assoc',
+               'array_diff_key',
+               'array_diff',
+               'array_fill_keys',
+               'array_fill',
+               'array_flip',
+               'array_intersect_assoc',
+               'array_intersect_key',
+               'array_intersect',
+               'array_key_exists',
+               'array_keys',
+               'array_merge_recursive',
+               'array_merge',
+               'array_multisort',
+               'array_pad',
+               'array_pop',
+               'array_product',
+               'array_push',
+               'array_rand',
+               'array_replace_recursive',
+               'array_replace',
+               'array_reverse',
+               'array_search',
+               'array_shift',
+               'array_slice',
+               'array_splice',
+               'array_sum',
+               'array_unique',
+               'array_unshift',
+               'array_values',
+               'arsort',
+               'asort',
+               'count',
+               'current',
+               'each',
+               'end',
+               'in_array',
+               'key',
+               'krsort',
+               'ksort',
+               'natcasesort',
+               'natsort',
+               'next',
+               'pos',
+               'prev',
+               'range',
+               'reset',
+               'rsort',
+               'shuffle',
+               'sizeof',
+               'sort',
+       ),
+       'FString' => array( // String Functions @see 
http://www.php.net/manual/en/ref.strings.php
+               'addcslashes',
+               'addslashes',
+               'chop',
+               'chr',
+               'chunk_split',
+               'convert_cyr_string',
+               'convert_uudecode',
+               'convert_uuencode',
+               'count_chars',
+               'crc32',
+               'crypt',
+               'explode',
+               'html_entity_decode',
+               'htmlentities',
+               'htmlspecialchars_decode',
+               'htmlspecialchars',
+               'implode',
+               'join',
+               'lcfirst',
+               'levenshtein',
+               'ltrim',
+               'md5',
+               'metaphone',
+               'money_format',
+               'nl_langinfo',
+               'nl2br',
+               'number_format',
+               'ord',
+               'printf',
+               'quotemeta',
+               'rtrim',
+               'sha1',
+               'similar_text',
+               'soundex',
+               'sprintf',
+               'sscanf',
+               'str_ireplace',
+               'str_pad',
+               'str_repeat',
+               'str_replace',
+               'str_rot13',
+               'str_shuffle',
+               'str_split',
+               'str_word_count',
+               'strcasecmp',
+               'strchr',
+               'strcmp',
+               'strcspn',
+               'strip_tags',
+               'stripcslashes',
+               'stripos',
+               'stripslashes',
+               'stristr',
+               'strlen',
+               'strnatcasecmp',
+               'strnatcmp',
+               'strncmp',
+               'strpbrk',
+               'strpos',
+               'strrchr',
+               'strrev',
+               'strripos',
+               'strrpos',
+               'strspn',
+               'strstr',
+               'strtok',
+               'strtolower',
+               'strtoupper',
+               'strtr',
+               'substr_compare',
+               'substr_count',
+               'substr_replace',
+               'substr',
+               'trim',
+               'ucfirst',
+               'ucwords',
+               'vprintf',
+               'vsprintf',
+               'wordwrap',
+       ),
+);
+
+$wgFoxwayAllowedPHPConstants = array(
+       'CASE_UPPER',
+       'CASE_LOWER',
+       'SORT_ASC',
+       'SORT_DESC',
+       'SORT_REGULAR',
+       'SORT_NUMERIC',
+       'SORT_STRING',
+       'SORT_LOCALE_STRING',
+       'SORT_NATURAL', // PHP >= 5.4.0
+       'SORT_FLAG_CASE', // PHP >= 5.4.0
+       'COUNT_RECURSIVE',
+       'CRYPT_STD_DES',
+       'CRYPT_EXT_DES',
+       'CRYPT_MD5',
+       'CRYPT_BLOWFISH',
+       'CRYPT_SHA256',
+       'CRYPT_SHA512',
+       'ENT_COMPAT',
+       'ENT_QUOTES',
+       'ENT_NOQUOTES',
+       'ENT_HTML401', // PHP >= 5.4.0
+       'ENT_XML1', // PHP >= 5.4.0
+       'ENT_XHTML', // PHP >= 5.4.0
+       'ENT_HTML5', // PHP >= 5.4.0
+       'ENT_IGNORE',
+       'ENT_SUBSTITUTE', // PHP >= 5.4.0
+       'ENT_DISALLOWED', // PHP >= 5.4.0
+       'STR_PAD_RIGHT',
+       'STR_PAD_LEFT',
+       'STR_PAD_BOTH',
+       'ABDAY_1',
+       'ABDAY_2',
+       'ABDAY_3',
+       'ABDAY_4',
+       'ABDAY_5',
+       'ABDAY_6',
+       'ABDAY_7',
+       'DAY_1',
+       'DAY_2',
+       'DAY_3',
+       'DAY_4',
+       'DAY_5',
+       'DAY_6',
+       'DAY_7',
+       'ABMON_1',
+       'ABMON_2',
+       'ABMON_3',
+       'ABMON_4',
+       'ABMON_5',
+       'ABMON_6',
+       'ABMON_7',
+       'ABMON_8',
+       'ABMON_9',
+       'ABMON_10',
+       'ABMON_11',
+       'ABMON_12',
+       'MON_1',
+       'MON_2',
+       'MON_3',
+       'MON_4',
+       'MON_5',
+       'MON_6',
+       'MON_7',
+       'MON_8',
+       'MON_9',
+       'MON_10',
+       'MON_11',
+       'MON_12',
+       'AM_STR',
+       'PM_STR',
+       'D_T_FMT',
+       'D_FMT',
+       'T_FMT',
+       'T_FMT_AMPM',
+       'ERA',
+       'ERA_YEAR',
+       'ERA_D_T_FMT',
+       'ERA_D_FMT',
+       'ERA_T_FMT',
+       'INT_CURR_SYMBOL',
+       'CURRENCY_SYMBOL',
+       'CRNCYSTR',
+       'MON_DECIMAL_POINT',
+       'MON_THOUSANDS_SEP',
+       'MON_GROUPING',
+       'POSITIVE_SIGN',
+       'NEGATIVE_SIGN',
+       'INT_FRAC_DIGITS',
+       'FRAC_DIGITS',
+       'P_CS_PRECEDES',
+       'P_SEP_BY_SPACE',
+       'N_CS_PRECEDES',
+       'N_SEP_BY_SPACE',
+       'P_SIGN_POSN',
+       'N_SIGN_POSN',
+       'DECIMAL_POINT',
+       'RADIXCHAR',
+       'THOUSANDS_SEP',
+       'THOUSEP',
+       'GROUPING',
+       'YESEXPR',
+       'NOEXPR',
+       'YESSTR',
+       'NOSTR',
+       'CODESET',
+);
\ No newline at end of file
diff --git a/includes/Debug.php b/includes/Debug.php
index 25f7d23..437bfca 100644
--- a/includes/Debug.php
+++ b/includes/Debug.php
@@ -77,6 +77,7 @@
                        case T_BOOL_CAST: // (bool)
                        case T_UNSET_CAST: // (unset)
                        case T_ECHO:
+                       case T_PRINT:
                        case T_IF:
                        case T_ELSE:
                        case T_ELSEIF:
diff --git a/includes/Interpreter.php b/includes/Interpreter.php
index 57f0955..5dc21f0 100644
--- a/includes/Interpreter.php
+++ b/includes/Interpreter.php
@@ -116,6 +116,8 @@
        );
 
        public static function run($source, array $args=array(), $scope='', 
$is_debug=false) {
+               global $wgFoxwayAllowedPHPConstants;
+
                $tokens = self::getTokens($source);
 
                $return = array();
@@ -292,6 +294,10 @@
                                        $runtime->addCommand($id);
                                        $parenthesFlags = 
FOXWAY_ALLOW_LIST_PARAMS | FOXWAY_EXPECT_SEMICOLON;
                                        break;
+                               case T_PRINT:
+                                       $runtime->addCommand($id);
+                                       $parenthesFlags = 
FOXWAY_EXPECT_SEMICOLON;
+                                       break;
                                case T_CONSTANT_ENCAPSED_STRING:
                                        $is_apostrophe = substr($text, 0, 1) == 
'\'' ? true : false;
                                        $string = substr($text, 1, -1);
@@ -403,8 +409,8 @@
                                                        $debug[] = $token;
                                                }
                                                continue 2;
-                                       } elseif( 
isset(self::$PHPConstants[$text]) ) {
-                                               $runtime->addParamValue( 
self::$PHPConstants[$text] );
+                                       } elseif( in_array($text, 
$wgFoxwayAllowedPHPConstants) && defined($text) ) {
+                                               $runtime->addParamValue( 
constant($text) );
                                        } else {
                                                $return[] = new 
ErrorMessage(__LINE__, $tokenLine, E_PARSE, $id);
                                                break 2;
@@ -443,6 +449,7 @@
                                        }
                                        switch ($command) {
                                                case T_ECHO:
+                                               case T_PRINT:
                                                        $return = 
array_merge($return, $result);
                                                        break;
                                                case T_IF:
@@ -554,6 +561,7 @@
                                        }
                                        // break is not necessary here
                                case T_ECHO:
+                               case T_PRINT:
                                case ',':
                                case T_CONCAT_EQUAL:    // .=
                                case T_PLUS_EQUAL:              // +=
@@ -960,19 +968,5 @@
                }
                return (float)( substr($string, 0, $epos) * pow(10, 
substr($string, $epos+1)) );
        }
-
-       private static $PHPConstants = array(
-               'CASE_UPPER' => CASE_UPPER,
-               'CASE_LOWER' => CASE_LOWER,
-               'SORT_ASC' => SORT_ASC,
-               'SORT_DESC' => SORT_DESC,
-               'SORT_REGULAR' => SORT_REGULAR,
-               'SORT_NUMERIC' => SORT_NUMERIC,
-               'SORT_STRING' => SORT_STRING,
-               'SORT_LOCALE_STRING' => SORT_LOCALE_STRING,
-               //'SORT_NATURAL' => SORT_NATURAL, // @todo PHP >= 5.4.0
-               //'SORT_FLAG_CASE' => SORT_FLAG_CASE, // @todo PHP >= 5.4.0
-               'COUNT_RECURSIVE' => COUNT_RECURSIVE,
-       );
 
 }
diff --git a/includes/Runtime.php b/includes/Runtime.php
index 564bb39..a85826a 100644
--- a/includes/Runtime.php
+++ b/includes/Runtime.php
@@ -209,9 +209,6 @@
                                }else{
                                        $this->listParams[] = 
$this->lastParam->getValue();
                                }
-                               if( $this->passByReference > 0 ) {
-                                       $this->passByReference <<= 1;
-                               }
                        }
                        $this->lastParam = $this->listParams;
                }
@@ -231,7 +228,7 @@
                                                $this->listParams[] = 
$this->lastParam->getValue();
                                        }
                                        if( $this->passByReference > 0 ) {
-                                               $this->passByReference <<= 1;
+                                               $this->passByReference >>= 1;
                                        }
                                }
                                $this->lastParam = null;
@@ -259,6 +256,7 @@
                                switch ($this->lastCommand) {
                                        case false:
                                        case T_ECHO:
+                                       case T_PRINT:
                                                break 2;
                                        case T_IF:
                                                $this->lastCommand = false;
@@ -484,6 +482,7 @@
                // Remember the child class RuntimeDebug
                switch ($this->lastCommand) {
                        case T_ECHO:
+                       case T_PRINT:
                                $return = array( T_ECHO, $this->listParams );
                                break;
                        case false:
diff --git a/includes/RuntimeDebug.php b/includes/RuntimeDebug.php
index a6e66f5..75cb095 100644
--- a/includes/RuntimeDebug.php
+++ b/includes/RuntimeDebug.php
@@ -102,6 +102,7 @@
                                case false:
                                case T_ARRAY:
                                case T_ECHO:
+                               case T_PRINT:
                                        break;
                                case T_IF:
                                        $this->debug[] = 
self::getHTMLForCommand(T_IF) .
@@ -121,6 +122,7 @@
 
                switch ($lastCommand) {
                        case T_ECHO:
+                       case T_PRINT:
                                $this->debug[] = 
self::getHTMLForCommand($lastCommand) . '&nbsp;' . implode(', ', 
$this->savedListParams) . ';';
                                $this->debug[] = implode('', $return[1]);
                                break;
@@ -199,6 +201,9 @@
                        case T_ECHO:
                                $return = \Html::element('span', 
array('class'=>'foxway_construct'), 'echo');
                                break;
+                       case T_PRINT:
+                               $return = \Html::element('span', 
array('class'=>'foxway_construct'), 'print');
+                               break;
                        case T_IF:
                                $return = \Html::element('span', 
array('class'=>'foxway_construct'), 'if');
                                break;
diff --git a/includes/functions/BaseFunction.php 
b/includes/functions/BaseFunction.php
index e5bea8b..2bbcdd4 100644
--- a/includes/functions/BaseFunction.php
+++ b/includes/functions/BaseFunction.php
@@ -1,6 +1,6 @@
 <?php
 namespace Foxway;
-define('FOXWAY_MAX_PAST_PARAM', 16);
+define('FOXWAY_MAX_PAST_PARAM', 16); // Max 31 ?
 
 /**
  * BaseFunction base class for functions classes of Foxway extension.
diff --git a/includes/functions/FArray.php b/includes/functions/FArray.php
index 154e2f7..20290cc 100644
--- a/includes/functions/FArray.php
+++ b/includes/functions/FArray.php
@@ -90,12 +90,16 @@
        );
 
        public static function __callStatic($name, $arguments) {
+               global $wgFoxwayPassByReference;
+
                if( isset(self::$listFunction[$name]) ) {
                        $funcData = &self::$listFunction[$name];
                        $refarg = &$arguments[0];
-                       foreach ($refarg as $key => &$value) {
-                               if( $value instanceof RValue ) {
-                                       $refarg[$key] = &$value->getReference();
+                       if( isset($wgFoxwayPassByReference[$funcData[0]]) ) {
+                               foreach ($refarg as $key => &$value) {
+                                       if( $value instanceof RValue ) {
+                                               $refarg[$key] = 
&$value->getReference();
+                                       }
                                }
                        }
                        $c = count($refarg);
diff --git a/includes/functions/FString.php b/includes/functions/FString.php
new file mode 100644
index 0000000..2e983ff
--- /dev/null
+++ b/includes/functions/FString.php
@@ -0,0 +1,196 @@
+<?php
+namespace Foxway;
+/**
+ * FString class implements String Functions for Foxway extension.
+ *
+ * @file FString.php
+ * @ingroup Foxway
+ * @author Pavel Astakhov <pastak...@yandex.ru>
+ * @licence GNU General Public Licence 2.0 or later
+ */
+class FString extends BaseFunction {
+       protected static $listFunction = array(
+               'f_addcslashes' => array('addcslashes', 2, 2),
+               'f_addslashes' => array('addslashes', 1, 1),
+               //'f_bin2hex' => array('bin2hex', 1, 1),
+               'f_chop' => array('rtrim', 1, 2), //chop — Alias of rtrim()
+               'f_chr' => array('chr', 1, 1),
+               'f_chunk_split' => array('chunk_split', 1, 3),
+               'f_convert_cyr_string' => array('convert_cyr_string', 3, 3),
+               'f_convert_uudecode' => array('convert_uudecode', 1, 1),
+               'f_convert_uuencode' => array('convert_uuencode', 1, 1),
+               'f_count_chars' => array('count_chars', 1, 2),
+               'f_crc32' => array('crc32', 1, 1),
+               'f_crypt' => array('crypt', 1, 2),
+               'f_explode' => array('explode', 2, 3),
+               // ### fprintf — Write a formatted string to a stream ###
+               //'f_get_html_translation_table' => 
array('get_html_translation_table', 0, 3),
+               //'f_hebrev' => array('hebrev', 1, 2),
+               //'f_hebrevc' => array('hebrevc', 1, 2),
+               //'f_hex2bin' => array('hex2bin', 1, 1), PHP >= 5.4.0
+               'f_html_entity_decode' => array('html_entity_decode', 1, 3),
+               'f_htmlentities' => array('htmlentities', 1, 4),
+               'f_htmlspecialchars_decode' => array('htmlspecialchars_decode', 
1, 2),
+               'f_htmlspecialchars' => array('htmlspecialchars', 1, 4),
+               'f_implode' => array('implode', 1, 2),
+               'f_join' => array('implode', 1, 2), //join — Alias of implode()
+               'f_lcfirst' => array('lcfirst', 1, 1),
+               //'levenshtein', @see self::f_levenshtein
+               //'localeconv' @todo get info from MW
+               'f_ltrim' => array('ltrim', 1, 2), //@todo check exsample
+               // ### md5_ file
+               'f_md5' => array('md5', 1, 2),
+               'f_metaphone' => array('metaphone', 1, 2),
+               'f_money_format' => array('money_format', 2, 2), // @todo need 
setlocale
+               'f_nl_langinfo' => array('nl_langinfo', 1, 1), // @todo need 
setlocale
+               'f_nl2br' => array('nl2br', 1, 2),
+               // 'number_format' @see self::number_format
+               'f_ord' => array('ord', 1, 1),
+               // @todo parse_str
+               // 'print' implemented in Runtime.php
+               //'f_printf', @see self::f_printf
+               //'f_quoted_printable_decode' => 
array('quoted_printable_decode', 1, 1),
+               //'f_quoted_printable_encode' => 
array('quoted_printable_encode', 1, 1),
+               'f_quotemeta' => array('quotemeta', 1, 1),
+               'f_rtrim' => array('rtrim', 1, 2),
+               // setlocale @todo need check for security
+               // ### sha1_file
+               'f_sha1' => array('sha1', 1, 2),
+               'f_similar_text' => array('similar_text', 2, 3),
+               'f_soundex' => array('soundex', 1, 1),
+               'f_sprintf' => array('sprintf', 1, FOXWAY_MAX_PAST_PARAM),
+               'f_sscanf' => array('sscanf', 2, FOXWAY_MAX_PAST_PARAM),
+               //str_getcsv
+               'f_str_ireplace' => array('str_ireplace', 3, 4),
+               'f_str_pad' => array('str_pad', 2, 4),
+               'f_str_repeat' => array('str_repeat', 2, 2),
+               'f_str_replace' => array('str_replace', 3, 4),
+               'f_str_rot13' => array('str_rot13', 1, 1),
+               'f_str_shuffle' => array('str_shuffle', 1, 1),
+               'f_str_split' => array('str_split', 1, 2),
+               'f_str_word_count' => array('str_word_count', 1, 3),
+               'f_strcasecmp' => array('strcasecmp', 2, 2),
+               'f_strchr' => array('strstr', 2, 3), //strchr — Alias of 
strstr()
+               'f_strcmp' => array('strcmp', 2, 2),
+               // strcoll function is not binary safe.
+               'f_strcspn' => array('strcspn', 2, 4),
+               'f_strip_tags' => array('strip_tags', 1, 2),
+               'f_stripcslashes' => array('stripcslashes', 1, 1),
+               'f_stripos' => array('stripos', 2, 3),
+               'f_stripslashes' => array('stripslashes', 1, 1),
+               'f_stristr' => array('stristr', 2, 3),
+               'f_strlen' => array('strlen', 1, 1),
+               'f_strnatcasecmp' => array('strnatcasecmp', 2, 2),
+               'f_strnatcmp' => array('strnatcmp', 2, 2),
+               'f_strncasecmp' => array('strncasecmp', 3, 3),
+               'f_strncmp' => array('strncmp', 3, 3),
+               'f_strpbrk' => array('strpbrk', 2, 2),
+               'f_strpos' => array('strpos', 2, 3),
+               'f_strrchr' => array('strrchr', 2, 2),
+               'f_strrev' => array('strrev', 1, 1),
+               'f_strripos' => array('strripos', 2, 3),
+               'f_strrpos' => array('strrpos', 2, 3),
+               'f_strspn' => array('strspn', 2, 4),
+               'f_strstr' => array('strstr', 2, 3),
+               'f_strtok' => array('strtok', 1, 2),
+               'f_strtolower' => array('strtolower', 1, 1),
+               'f_strtoupper' => array('strtoupper', 1, 1),
+               'f_strtr' => array('strtr', 2, 3),
+               'f_substr_compare' => array('substr_compare', 3, 5),
+               'f_substr_count' => array('substr_count', 2, 4),
+               'f_substr_replace' => array('substr_replace', 3, 4),
+               'f_substr' => array('substr', 2, 3),
+               'f_trim' => array('trim', 1, 2),
+               'f_ucfirst' => array('ucfirst', 1, 1),
+               'f_ucwords' => array('ucwords', 1, 1),
+               // ### vfprintf — Write a formatted string to a stream
+               // 'f_vprintf', @see self::f_vprintf
+               'f_vsprintf' => array('vsprintf', 2, 2),
+               'f_wordwrap' => array('wordwrap', 1, 4),
+
+       );
+
+       public static function __callStatic($name, $arguments) {
+               global $wgFoxwayPassByReference;
+
+               if( isset(self::$listFunction[$name]) ) {
+                       $funcData = &self::$listFunction[$name];
+                       $refarg = &$arguments[0];
+                       if( isset($wgFoxwayPassByReference[$funcData[0]]) ) {
+                               foreach ($refarg as $key => &$value) {
+                                       if( $value instanceof RValue ) {
+                                               $refarg[$key] = 
&$value->getReference();
+                                       }
+                               }
+                       }
+                       $c = count($refarg);
+                       if( $c >= $funcData[1] && $c <= $funcData[2] ) {
+                               return new RValue( 
call_user_func_array($funcData[0], $refarg) );
+                       }else{
+                               return self::wrongParameterCount($name, 
__LINE__);
+                       }
+               } else {
+                       return self::callUnknownMethod($name, __LINE__);
+               }
+       }
+
+       /**
+        * Output a formatted string
+        * @param array $arguments
+        * @return \Foxway\RValue
+        */
+       public static function f_printf($arguments) {
+               if( count($arguments) == 0 ) {
+                       return self::wrongParameterCount( __FUNCTION__, 
__LINE__ );
+               }
+               ob_start();
+               call_user_func_array('printf', $arguments);
+               return new ROutput( null, ob_get_clean(), 'pre' );
+       }
+
+       /**
+        * Calculate Levenshtein distance between two strings
+        * @param array $arguments
+        * @return \Foxway\RValue
+        */
+       public static function f_levenshtein($arguments) {
+               switch ( count($arguments) ) {
+                       case 2:
+                       case 5:
+                               return new RValue( 
call_user_func_array('levenshtein', $arguments) );
+                               break;
+               }
+               return self::wrongParameterCount( __FUNCTION__, __LINE__ );
+       }
+
+       /**
+        * Calculate Levenshtein distance between two strings
+        * @param array $arguments
+        * @return \Foxway\RValue
+        */
+       public static function f_number_format($arguments) {
+               switch ( count($arguments) ) {
+                       case 1:
+                       case 2:
+                       case 4:
+                               return new RValue( 
call_user_func_array('number_format', $arguments) );
+                               break;
+               }
+               return self::wrongParameterCount( __FUNCTION__, __LINE__ );
+       }
+
+       /**
+        * Output a formatted string
+        * @param array $arguments
+        * @return \Foxway\RValue
+        */
+       public static function f_vprintf($arguments) {
+               if( count($arguments) != 2 ) {
+                       return self::wrongParameterCount( __FUNCTION__, 
__LINE__ );
+               }
+               ob_start();
+               call_user_func_array('vprintf', $arguments);
+               return new ROutput( null, ob_get_clean(), 'pre' );
+       }
+
+}
diff --git a/tests/phpunit/includes/InterpreterTest.php 
b/tests/phpunit/includes/InterpreterTest.php
index cddfa50..35e549f 100644
--- a/tests/phpunit/includes/InterpreterTest.php
+++ b/tests/phpunit/includes/InterpreterTest.php
@@ -1995,6 +1995,13 @@
                                );
        }
 
+       public function testRun_RString_similar_text() {
+               $this->assertEquals(
+                               Interpreter::run('$var_1 = "PHP IS GREAT"; 
$var_2 = "WITH MYSQL"; similar_text($var_1, $var_2, $percent); echo $percent;'),
+                               array('27.272727272727')
+                               );
+       }
+
 }
 
 // @todo echo is_scalar(array("foo","bar") ? "true" : "false"; // most return 
error

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Id3a7f6ed3303660cff3bd3c3a41ffd45fa887993
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/Foxway
Gerrit-Branch: master
Gerrit-Owner: Pastakhov <pastak...@yandex.ru>
Gerrit-Reviewer: Pastakhov <pastak...@yandex.ru>
Gerrit-Reviewer: jenkins-bot

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

Reply via email to