Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F2977
StringFunctions_new.patch
Public
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Authored By
•
bzimport
Nov 21 2014, 9:18 PM
2014-11-21 21:18:46 (UTC+0)
Size
26 KB
Referenced Files
None
Subscribers
None
StringFunctions_new.patch
View Options
Index: StringFunctions.body.php
===================================================================
--- StringFunctions.body.php (revision 0)
+++ StringFunctions.body.php (revision 0)
@@ -0,0 +1,297 @@
+<?php
+
+class StringFunctions {
+ static $markerRegex = false;
+
+ /* Called by ParserAfterStrip. Preloads the syntax for unique markers
+ so that we can avoid reconstructing it on every operation. */
+ static function loadRegex( &$parser ) {
+ wfProfileIn( __METHOD__ );
+
+ $prefix = preg_quote( $parser->mUniqPrefix, '/' );
+
+ if ( defined('Parser::MARKER_SUFFIX') )
+ $suffix = preg_quote( Parser::MARKER_SUFFIX, '/' );
+ elseif ( isset($parser->mMarkerSuffix) )
+ $suffix = preg_quote( $parser->mMarkerSuffix, '/' );
+ elseif ( defined('MW_PARSER_VERSION') && strcmp( MW_PARSER_VERSION, '1.6.1' ) > 0 )
+ $suffix = "QINU\x07";
+ else $suffix = 'QINU';
+
+ self::$markerRegex = '/' .$prefix. '(?:(?!' .$suffix. ').)*' . $suffix . '/us';
+
+ wfProfileOut( __METHOD__ );
+ return true;
+ }
+
+ // Removes unique markers from passed parameters.
+ private function killMarkers ( $text ) {
+ if( self::$markerRegex ) {
+ return preg_replace( self::$markerRegex , '' , $text );
+ } else {
+ return $text;
+ }
+ }
+
+ // Verifies parameter is less than max string length.
+ private function checkLength( $text ) {
+ global $wgStringFunctionsLimit;
+ return ( mb_strlen( $text ) < $wgStringFunctionsLimit );
+ }
+
+ // Generates error message. Called when string is too long.
+ private function tooLongError() {
+ global $wgStringFunctionsLimit;
+ return wfMsg( 'stringfunctions-toolong', $wgStringFunctionsLimit );
+ }
+
+ /**
+ * {{#len:string}}
+ */
+ function runLen ( &$parser, $inStr = '' ) {
+ wfProfileIn( __METHOD__ );
+
+ $inStr = $this->killMarkers( (string)$inStr );
+ $len = mb_strlen( $inStr );
+
+ wfProfileOut( __METHOD__ );
+ return $len;
+ }
+
+ /**
+ * {{#pos:value|key|offset}}
+ * Note: If the needle is an empty string, single space is used instead.
+ * Note: If the needle is not found, -1 is returned.
+ */
+ function runPos ( &$parser, $inStr = '', $inNeedle = '', $inOffset = 0 ) {
+ wfProfileIn( __METHOD__ );
+
+ $inStr = $this->killMarkers( (string)$inStr );
+ $inNeedle = $this->killMarkers( (string)$inNeedle );
+
+ if( !$this->checkLength( $inStr ) ||
+ !$this->checkLength( $inNeedle ) ) {
+ wfProfileOut( __METHOD__ );
+ return $this->tooLongError();
+ }
+
+ if( $inNeedle == '' ) { $inNeedle = ' '; }
+
+ $pos = mb_strpos( $inStr, $inNeedle, $inOffset );
+ if( $pos === false ) { $pos = -1; }
+
+ wfProfileOut( __METHOD__ );
+ return $pos;
+ }
+
+ /**
+ * {{#rpos:value|key}}
+ * Note: If the needle is an empty string, single space is used instead.
+ * Note: If the needle is not found, -1 is returned.
+ */
+ function runRPos ( &$parser, $inStr = '', $inNeedle = '' ) {
+ wfProfileIn( __METHOD__ );
+
+ $inStr = $this->killMarkers( (string)$inStr );
+ $inNeedle = $this->killMarkers( (string)$inNeedle );
+
+ if( !$this->checkLength( $inStr ) ||
+ !$this->checkLength( $inNeedle ) ) {
+ wfProfileOut( __METHOD__ );
+ return $this->tooLongError();
+ }
+
+ if( $inNeedle == '' ) { $inNeedle = ' '; }
+
+ $pos = mb_strrpos( $inStr, $inNeedle );
+ if( $pos === false ) { $pos = -1; }
+
+ wfProfileOut( __METHOD__ );
+ return $pos;
+ }
+
+ /**
+ * {{#sub:value|start|length}}
+ * Note: If length is zero, the rest of the input is returned.
+ */
+ function runSub ( &$parser, $inStr = '', $inStart = 0, $inLength = 0 ) {
+ wfProfileIn( __METHOD__ );
+
+ $inStr = $this->killMarkers( (string)$inStr );
+
+ if( !$this->checkLength( $inStr ) ) {
+ wfProfileOut( __METHOD__ );
+ return $this->tooLongError();
+ }
+
+ if ( intval($inLength) == 0 ) {
+ $result = mb_substr( $inStr, $inStart );
+ } else {
+ $result = mb_substr( $inStr, $inStart, $inLength );
+ }
+
+ wfProfileOut( __METHOD__ );
+ return $result;
+ }
+
+ /**
+ * {{#replace:value|from|to}}
+ * Note: If "from" is an empty string, single space is used instead.
+ */
+ function runReplace( &$parser, $inStr = '', $inReplaceFrom = '', $inReplaceTo = '' ) {
+ global $wgStringFunctionsLimit;
+ wfProfileIn( __METHOD__ );
+
+ $inStr = $this->killMarkers( (string)$inStr );
+ $inReplaceFrom = $this->killMarkers( (string)$inReplaceFrom );
+ $inReplaceTo = $this->killMarkers( (string)$inReplaceTo );
+
+ if( !$this->checkLength( $inStr ) ||
+ !$this->checkLength( $inReplaceFrom ) ||
+ !$this->checkLength( $inReplaceTo ) ) {
+ wfProfileOut( __METHOD__ );
+ return $this->tooLongError();
+ }
+
+ if( $inReplaceFrom == '' ) { $inReplaceFrom = ' '; }
+
+ // Precompute limit to avoid generating enormous string:
+ $diff = mb_strlen( $inReplaceTo ) - mb_strlen( $inReplaceFrom );
+ if( $diff > 0 ) {
+ $limit = ( ( $wgStringFunctionsLimit - mb_strlen( $inStr ) ) / $diff ) + 1;
+ } else {
+ $limit = -1;
+ }
+
+ $inReplaceFrom = preg_quote( $inReplaceFrom, '/' );
+ $inReplaceTo = preg_quote( $inReplaceTo, '/' );
+
+ $result = preg_replace( '/' . $inReplaceFrom . '/u', $inReplaceTo, $inStr, $limit);
+
+ if( !$this->checkLength( $result ) ) {
+ wfProfileOut( __METHOD__ );
+ return $this->tooLongError();
+ }
+
+ wfProfileOut( __METHOD__ );
+ return $result;
+ }
+
+
+ /**
+ * {{#explode:value|delimiter|position}}
+ * Note: Negative position can be used to specify tokens from the end.
+ * Note: If the divider is an empty string, single space is used instead.
+ * Note: Empty string is returned, if there is not enough exploded chunks.
+ */
+ function runExplode ( &$parser, $inStr = '', $inDiv = '', $inPos = 0 ) {
+ wfProfileIn( __METHOD__ );
+
+ $inStr = $this->killMarkers( (string)$inStr );
+ $inDiv = $this->killMarkers( (string)$inDiv );
+
+ if( $inDiv == '' ) { $inDiv = ' '; }
+
+ $inStr = preg_quote( $inStr, '/' );
+ $inDiv = preg_quote( $inDiv, '/' );
+
+ if( !$this->checkLength( $inStr ) ||
+ !$this->checkLength( $inDiv ) ) {
+ wfProfileOut( __METHOD__ );
+ return $this->tooLongError();
+ }
+
+ $matches = preg_split( '/'.$inDiv.'/u', $inStr );
+
+ if( $inPos >= 0 && isset( $matches[$inPos] ) ) {
+ $result = $matches[$inPos];
+ } elseif ( $inPos < 0 && isset( $matches[count($matches) + $inPos] ) ) {
+ $result = $matches[count($matches) + $inPos];
+ } else {
+ $result = '';
+ }
+
+ wfProfileOut( __METHOD__ );
+ return $result;
+ }
+}
+
+
+/*
+ The following section reimplements the necessary multi-byte
+ string functions if they are not present. This removes multi-byte
+ support as a requirement for this extension; however, these
+ substitutes are very inefficient. True multi-byte support is
+ recommended.
+
+ In addition, please note that the only parameters implemented below
+ are the ones necessary for this extension.
+*/
+
+if( !function_exists( 'mb_strlen' ) ) {
+
+ function mb_strlen( $text ) {
+ if( $text == '' ) { return 0; }
+
+ $ar = array();
+ preg_match_all('/./us', $text, $ar );
+ return count($ar[0]);
+ }
+
+}
+
+if( !function_exists( 'mb_strpos' ) ) {
+
+ function mb_strpos( $haystack, $needle, $offset = 0 ) {
+ $needle = preg_quote( $needle, '/' );
+
+ $ar = array();
+ preg_match( '/'.$needle.'/u', $haystack, $ar, PREG_OFFSET_CAPTURE, $offset );
+
+ if( isset( $ar[0][1] ) ) {
+ return $ar[0][1];
+ } else {
+ return false;
+ }
+ }
+
+}
+
+if( !function_exists( 'mb_strrpos' ) ) {
+
+ function mb_strrpos( $haystack, $needle, $offset = 0 ) {
+ $needle = preg_quote( $needle, '/' );
+
+ $ar = array();
+ preg_match_all( '/'.$needle.'/u', $haystack, $ar, PREG_OFFSET_CAPTURE, $offset );
+
+ if( isset( $ar[0] ) && count( $ar[0] ) > 0 &&
+ isset( $ar[0][count($ar[0])-1][1] ) ) {
+ return $ar[0][count($ar[0])-1][1];
+ } else {
+ return false;
+ }
+ }
+}
+
+if( !function_exists( 'mb_substr' ) ) {
+
+ function mb_substr( $text, $start, $length = 0 ) {
+ if( $text == '' ) { return ''; }
+
+ $ar = array();
+ preg_match_all('/./us', $text, $ar );
+
+ $res = '';
+
+ if( $length == 0 ) { $length = count($ar[0]); }
+
+ while( $length > 0 && isset( $ar[0][$start] ) ) {
+ $res .= $ar[0][$start];
+ $start++;
+ $length--;
+ }
+
+ return $res;
+ }
+}
Property changes on: StringFunctions.body.php
___________________________________________________________________
Added: svn:eol-style
+ native
Index: StringFunctions.i18n.php
===================================================================
--- StringFunctions.i18n.php (revision 49027)
+++ StringFunctions.i18n.php (working copy)
@@ -14,6 +14,7 @@
*/
$messages['en'] = array(
'stringfunctions-desc' => 'Enhances the parser with string functions',
+ 'stringfunctions-toolong' => '<span class="error">String is exceeds $1 character limit.</span>',
);
/** Message documentation (Message documentation)
Index: StringFunctions.php
===================================================================
--- StringFunctions.php (revision 49027)
+++ StringFunctions.php (working copy)
@@ -1,75 +1,82 @@
<?php
/*
- Defines a subset of parser functions that operate with strings.
+ This extension defines a set of parser functions for operating on UTF-8 strings.
- {{#len:value}}
- Returns the length of the given value.
- See: http://php.net/manual/function.strlen.php
+ == Functions ==
+ {{#len:string}}
- {{#pos:value|key|offset}}
+ Returns the length of the given "string".
- Returns the first position of key inside the given value, or an empty string.
- If offset is defined, this method will not search the first offset characters.
- See: http://php.net/manual/function.strpos.php
+ {{#pos:string|key|offset}}
- {{#rpos:value|key}}
+ Returns the first position of "key" inside the given "string" or -1 if not found.
+ If "offset" is defined, this method will not search the first "offset" characters.
- Returns the last position of key inside the given value, or -1 if the key is
- not found. When using this to search for the last delimiter, add +1 to the
- result to retreive position after the last delimiter. This also works when
- the delimiter is not found, because "-1 + 1" is zero, which is the beginning
- of the given value.
- See: http://php.net/manual/function.strrpos.php
+ {{#rpos:string|key}}
- {{#sub:value|start|length}}
+ Returns the last position of "key" inside the given "string", or -1 if the key is
+ not found.
- Returns a substring of the given value with the given starting position and
- length. If length is omitted, this returns the rest of the string.
- See: http://php.net/manual/function.substr.php
+ {{#sub:string|start|length}}
- {{#pad:value|length|with|direction}}
+ Returns a substring of the given "string" with the given "start" position and
+ "length". If "length" is omitted, this returns the rest of the string.
- Returns the value padded to the certain length with the given with string.
- If the with string is not given, spaces are used for padding. The direction
- may be specified as: 'left', 'center' or 'right'.
- See: http://php.net/manual/function.str-pad.php
+ {{#replace:string|from|to}}
- {{#replace:value|from|to}}
+ Returns the given "string" with all occurences of "from" replaced with "to".
- Returns the given value with all occurences of 'from' replaced with 'to'.
- See: http://php.net/manual/function.str-replace.php
+ {{#explode:string|delimiter|position}}
- {{#explode:value|delimiter|position}}
+ Splits the given "string" into pieces by the given "delimiter" and returns the
+ "position" piece. Empty string is returned if there are not enough pieces. The
+ first piece is assigned "position" zero. If "position" is negative, counts pieces
+ from the end instead of the beginning.
- Splits the given value into pieces by the given delimiter and returns the
- position-th piece. Empty string is returned if there are not enough pieces.
- Note: Pieces are counted from 0.
- Note: A negative value can be used to count pieces from the end, instead of
- counting from the beginning. The last piece is at position -1.
- See: http://php.net/manual/function.explode.php
+
+ == Limitations ==
+ This extension has a defined upper limit to the size of the string it will operate
+ on. This can be controlled by adjusting the value of $wgStringFunctionsLimit.
+ When passed a string longer than this maximum the function will return an error
+ message.
- {{#urlencode:value}}
+
+ In order to operate correctly, this extension must remove certain tags if they occur
+ in the passed parameters, including <nowiki>, <gallery>, <math>, and certain others.
+ If passed to a string function these elements are treated as having zero length.
- URL-encodes the given value.
- See: http://php.net/manual/function.urlencode.php
+ Due to the design of the parser all parameters are passed through a trim function
+ that removes whitespace on both ends before being recieved by the StringFunctions.
+ Parameters consisting entirely of whitespace will be reduced to the empty string, "".
+ For the purposes of operating, functions recieving an empty string will assume the
+ intended parameter is a single space " ".
+ In addition, it is possible to exploit the tag behavior described above to force the
+ preservation of whitespace. In particular, passing a string like:
+ "<nowiki></nowiki> BOB <nowiki></nowiki>" will be recieved as " BOB ", with the
+ whitespace at both ends preserved even though the <nowiki> tags have been stripped.
- {{#urldecode:value}}
+
+ This extension requires PHP's Perl Compatible Regular Expressions (PCRE) be available.
+ In addition, it makes use of PHP's multi-byte string functions if they are available.
+ If multi-byte string function are not available this behavior is simulated through
+ much slower regex. Hence the presence of multi-byte string functions is strongly
+ recommended.
- URL-decodes the given value.
- See: http://php.net/manual/function.urldecode.php
+ == Copyright ==
- Copyright (c) 2008 Ross McClure & Juraj Simlovic
+ Copyright (c) 2008-2009 Robert Rohde, Ross McClure, and Juraj Simlovic
+ http://en.wikipedia.org/wiki/User:Dragons_flight
http://www.mediawiki.org/wiki/User:Algorithm
http://www.mediawiki.org/wiki/User:jsimlo
@@ -96,379 +103,48 @@
*/
-$wgExtensionCredits['parserhook'][] = array(
+$wgStringFunctionsLimit = 1000;
+
+$wgExtensionCredits['validextensionclass'][] = array(
'name' => 'StringFunctions',
- 'version' => '2.0.3', // Nov 30, 2008
+ 'version' => '3.0.0', // March 30, 2009
'description' => 'Enhances parser with string functions',
'descriptionmsg' => 'stringfunctions-desc',
- 'author' => array('Ross McClure', 'Juraj Simlovic'),
+ 'author' => array('Robert Rohde', 'Ross McClure', 'Juraj Simlovic'),
'url' => 'http://www.mediawiki.org/wiki/Extension:StringFunctions',
);
-$dir = dirname( __FILE__ ) . '/';
-$wgExtensionMessagesFiles['StringFunctions'] = $dir . 'StringFunctions.i18n.php';
+$wgAutoloadClasses['StringFunctions'] =
+ dirname( __FILE__ ) . '/StringFunctions.body.php';
+$wgExtensionMessagesFiles['StringFunctions'] =
+ dirname( __FILE__ ) . '/StringFunctions.i18n.php';
$wgExtensionFunctions[] = 'wfStringFunctions';
$wgHooks['LanguageGetMagic'][] = 'wfStringFunctionsLanguageGetMagic';
+$wgHooks['ParserAfterStrip'][] = 'StringFunctions::loadRegex';
function wfStringFunctions ( ) {
- global $wgParser, $wgExtStringFunctions;
- global $wgStringFunctionsLimitSearch;
- global $wgStringFunctionsLimitReplace;
- global $wgStringFunctionsLimitPad;
+ global $wgParser, $wgStringFunctions;
- $wgExtStringFunctions = new ExtStringFunctions ( );
- $wgStringFunctionsLimitSearch = 30;
- $wgStringFunctionsLimitReplace = 30;
- $wgStringFunctionsLimitPad = 100;
+ $wgStringFunctions = new StringFunctions ( );
- $wgParser->setFunctionHook('len', array(&$wgExtStringFunctions,'runLen' ));
- $wgParser->setFunctionHook('pos', array(&$wgExtStringFunctions,'runPos' ));
- $wgParser->setFunctionHook('rpos', array(&$wgExtStringFunctions,'runRPos' ));
- $wgParser->setFunctionHook('sub', array(&$wgExtStringFunctions,'runSub' ));
- $wgParser->setFunctionHook('pad', array(&$wgExtStringFunctions,'runPad' ));
- $wgParser->setFunctionHook('replace', array(&$wgExtStringFunctions,'runReplace' ));
- $wgParser->setFunctionHook('explode', array(&$wgExtStringFunctions,'runExplode' ));
- $wgParser->setFunctionHook('urlencode',array(&$wgExtStringFunctions,'runUrlEncode'));
- $wgParser->setFunctionHook('urldecode',array(&$wgExtStringFunctions,'runUrlDecode'));
+ $wgParser->setFunctionHook('len', array(&$wgStringFunctions,'runLen' ));
+ $wgParser->setFunctionHook('pos', array(&$wgStringFunctions,'runPos' ));
+ $wgParser->setFunctionHook('rpos', array(&$wgStringFunctions,'runRPos' ));
+ $wgParser->setFunctionHook('sub', array(&$wgStringFunctions,'runSub' ));
+ $wgParser->setFunctionHook('replace', array(&$wgStringFunctions,'runReplace' ));
+ $wgParser->setFunctionHook('explode', array(&$wgStringFunctions,'runExplode' ));
}
function wfStringFunctionsLanguageGetMagic( &$magicWords, $langCode = "en" ) {
- switch ( $langCode ) {
- default:
- $magicWords['len'] = array ( 0, 'len' );
- $magicWords['pos'] = array ( 0, 'pos' );
- $magicWords['rpos'] = array ( 0, 'rpos' );
- $magicWords['sub'] = array ( 0, 'sub' );
- $magicWords['pad'] = array ( 0, 'pad' );
- $magicWords['replace'] = array ( 0, 'replace' );
- $magicWords['explode'] = array ( 0, 'explode' );
- $magicWords['urlencode'] = array ( 0, 'urlencode' );
- $magicWords['urldecode'] = array ( 0, 'urldecode' );
- }
+
+ $magicWords['len'] = array ( 0, 'len' );
+ $magicWords['pos'] = array ( 0, 'pos' );
+ $magicWords['rpos'] = array ( 0, 'rpos' );
+ $magicWords['sub'] = array ( 0, 'sub' );
+ $magicWords['replace'] = array ( 0, 'replace' );
+ $magicWords['explode'] = array ( 0, 'explode' );
+
return true;
-}
-
-class ExtStringFunctions {
-
- /**
- * Returns part of the perl regexp pattern that matches a marker.
- * Unfortunatelly, we are still backward-supporting old versions.
- */
- function mwMarkerRE ( &$parser )
- {
- if ( defined('Parser::MARKER_SUFFIX') )
- $suffix = preg_quote( Parser::MARKER_SUFFIX, '/' );
- elseif ( isset($parser->mMarkerSuffix) )
- $suffix = preg_quote( $parser->mMarkerSuffix, '/' );
- elseif ( defined('MW_PARSER_VERSION') && strcmp( MW_PARSER_VERSION, '1.6.1' ) > 0 )
- $suffix = "QINU\x07";
- else $suffix = 'QINU';
-
- return preg_quote( $parser->mUniqPrefix, '/' ) . '.*?' . $suffix;
- }
-
- /**
- * {{#len:value}}
- *
- * Main idea: Count multibytes. Find markers. Substract.
- */
- function runLen ( &$parser, $inStr = '' ) {
-
- $len = mb_strlen ( (string)$inStr );
-
- $count = preg_match_all (
- '/' . $this->mwMarkerRE($parser) . '/',
- (string) $inStr, $matches
- );
-
- foreach ($matches[0] as $match)
- $len -= strlen ($match) - 1;
-
- return $len;
- }
-
- /**
- * Splits the string into its component parts using preg_match_all().
- * $chars is set to the resulting array of multibyte characters.
- * Returns count($chars).
- */
- function mwSplit ( &$parser, $str, &$chars ) {
- # Get marker prefix & suffix
- $prefix = preg_quote( $parser->mUniqPrefix, '/' );
- if ( defined('Parser::MARKER_SUFFIX') )
- $suffix = preg_quote( Parser::MARKER_SUFFIX, '/' );
- elseif ( isset($parser->mMarkerSuffix) )
- $suffix = preg_quote( $parser->mMarkerSuffix, '/' );
- elseif ( defined('MW_PARSER_VERSION') && strcmp( MW_PARSER_VERSION, '1.6.1' ) > 0 )
- $suffix = "QINU\x07";
- else $suffix = 'QINU';
-
- # Treat strip markers as single multibyte characters
- $count = preg_match_all('/' . $prefix . '.*?' . $suffix . '|./su', $str, $arr);
- $chars = $arr[0];
- return $count;
- }
-
- /**
- * {{#pos:value|key|offset}}
- * Note: If the needle is an empty string, single space is used instead.
- * Note: If the needle is not found, empty string is returned.
- * Note: The needle is limited to specific length.
- */
- function runPos ( &$parser, $inStr = '', $inNeedle = '', $inOffset = 0 ) {
- global $wgStringFunctionsLimitSearch;
-
- if ( $inNeedle === '' ) {
- # empty needle
- $needle = array(' ');
- $nSize = 1;
- } else {
- # convert needle
- $nSize = $this->mwSplit ( $parser, $inNeedle, $needle );
-
- if ( $nSize > $wgStringFunctionsLimitSearch ) {
- $nSize = $wgStringFunctionsLimitSearch;
- $needle = array_slice ( $needle, 0, $nSize );
- }
- }
-
- # convert string
- $size = $this->mwSplit( $parser, $inStr, $chars ) - $nSize;
- $inOffset = max ( intval($inOffset), 0 );
-
- # find needle
- for ( $i = $inOffset; $i <= $size; $i++ ) {
- if ( $chars[$i] !== $needle[0] ) continue;
- for ( $j = 1; ; $j++ ) {
- if ( $j >= $nSize ) return $i;
- if ( $chars[$i + $j] !== $needle[$j] ) break;
- }
- }
-
- # return empty string upon not found
- return '';
- }
-
- /**
- * {{#rpos:value|key}}
- * Note: If the needle is an empty string, single space is used instead.
- * Note: If the needle is not found, -1 is returned.
- * Note: The needle is limited to specific length.
- */
- function runRPos ( &$parser, $inStr = '', $inNeedle = '' ) {
- global $wgStringFunctionsLimitSearch;
-
- if ( $inNeedle === '' ) {
- # empty needle
- $needle = array(' ');
- $nSize = 1;
- } else {
- # convert needle
- $nSize = $this->mwSplit ( $parser, $inNeedle, $needle );
-
- if ( $nSize > $wgStringFunctionsLimitSearch ) {
- $nSize = $wgStringFunctionsLimitSearch;
- $needle = array_slice ( $needle, 0, $nSize );
- }
- }
-
- # convert string
- $size = $this->mwSplit( $parser, $inStr, $chars ) - $nSize;
-
- # find needle
- for ( $i = $size; $i >= 0; $i-- ) {
- if ( $chars[$i] !== $needle[0] ) continue;
- for ( $j = 1; ; $j++ ) {
- if ( $j >= $nSize ) return $i;
- if ( $chars[$i + $j] !== $needle[$j] ) break;
- }
- }
-
- # return -1 upon not found
- return "-1";
- }
-
- /**
- * {{#sub:value|start|length}}
- * Note: If length is zero, the rest of the input is returned.
- */
- function runSub ( &$parser, $inStr = '', $inStart = 0, $inLength = 0 ) {
- # convert string
- $this->mwSplit( $parser, $inStr, $chars );
-
- # zero length
- if ( intval($inLength) == 0 )
- return join('', array_slice( $chars, intval($inStart) ));
-
- # non-zero length
- return join('', array_slice( $chars, intval($inStart), intval($inLength) ));
- }
-
- /**
- * {{#pad:value|length|with|direction}}
- * Note: Length of the resulting string is limited.
- */
- function runPad( &$parser, $inStr = '', $inLen = 0, $inWith = '', $inDirection = '' ) {
- global $wgStringFunctionsLimitPad;
-
- # direction
- switch ( strtolower ( $inDirection ) ) {
- case 'center':
- $direction = STR_PAD_BOTH;
- break;
- case 'right':
- $direction = STR_PAD_RIGHT;
- break;
- case 'left':
- default:
- $direction = STR_PAD_LEFT;
- break;
- }
-
- # prevent markers in padding
- $a = explode ( $parser->mUniqPrefix, $inWith, 2 );
- if ( $a[0] === '' )
- $inWith = ' ';
- else $inWith = $a[0];
-
- # limit pad length
- $inLen = intval ( $inLen );
- if ($wgStringFunctionsLimitPad > 0)
- $inLen = min ( $inLen, $wgStringFunctionsLimitPad );
-
- # adjust for multibyte strings
- $inLen += strlen( $inStr ) - $this->mwSplit( $parser, $inStr, $a );
-
- # pad
- return str_pad ( $inStr, $inLen, $inWith, $direction );
- }
-
- /**
- * {{#replace:value|from|to}}
- * Note: If the needle is an empty string, single space is used instead.
- * Note: The needle is limited to specific length.
- * Note: The product is limited to specific length.
- */
- function runReplace( &$parser, $inStr = '', $inReplaceFrom = '', $inReplaceTo = '' ) {
- global $wgStringFunctionsLimitSearch, $wgStringFunctionsLimitReplace;
-
- if ( $inReplaceFrom === '' ) {
- # empty needle
- $needle = array(' ');
- $nSize = 1;
- } else {
- # convert needle
- $nSize = $this->mwSplit ( $parser, $inReplaceFrom, $needle );
- if ( $nSize > $wgStringFunctionsLimitSearch ) {
- $nSize = $wgStringFunctionsLimitSearch;
- $needle = array_slice ( $needle, 0, $nSize );
- }
- }
-
- # convert product
- $pSize = $this->mwSplit ( $parser, $inReplaceTo, $product );
- if ( $pSize > $wgStringFunctionsLimitReplace ) {
- $pSize = $wgStringFunctionsLimitReplace;
- $product = array_slice ( $product, 0, $pSize );
- }
-
- # remove markers in product
- for( $i = 0; $i < $pSize; $i++ ) {
- if( strlen( $product[$i] ) > 6 ) $product[$i] = ' ';
- }
-
- # convert string
- $size = $this->mwSplit ( $parser, $inStr, $chars ) - $nSize;
-
- # replace
- for ( $i = 0; $i <= $size; $i++ ) {
- if ( $chars[$i] !== $needle[0] ) continue;
- for ( $j = 1; ; $j++ ) {
- if ( $j >= $nSize ) {
- array_splice ( $chars, $i, $j, $product );
- $size += ( $pSize - $nSize );
- $i += ( $pSize - 1 );
- break;
- }
- if ( $chars[$i + $j] !== $needle[$j] ) break;
- }
- }
- return join('', $chars);
- }
-
- /**
- * {{#explode:value|delimiter|position}}
- * Note: Negative position can be used to specify tokens from the end.
- * Note: If the divider is an empty string, single space is used instead.
- * Note: The divider is limited to specific length.
- * Note: Empty string is returned, if there is not enough exploded chunks.
- */
- function runExplode ( &$parser, $inStr = '', $inDiv = '', $inPos = 0 ) {
- global $wgStringFunctionsLimitSearch;
-
- if ( $inDiv === '' ) {
- # empty divider
- $div = array(' ');
- $dSize = 1;
- } else {
- # convert divider
- $dSize = $this->mwSplit ( $parser, $inDiv, $div );
- if ( $dSize > $wgStringFunctionsLimitSearch ) {
- $dSize = $wgStringFunctionsLimitSearch;
- $div = array_slice ( $div, 0, $dSize );
- }
- }
-
- # convert string
- $size = $this->mwSplit ( $parser, $inStr, $chars ) - $dSize;
-
- # explode
- $inPos = intval ( $inPos );
- $tokens = array();
- $start = 0;
- for ( $i = 0; $i <= $size; $i++ ) {
- if ( $chars[$i] !== $div[0] ) continue;
- for ( $j = 1; ; $j++ ) {
- if ( $j >= $dSize ) {
- if ( $inPos > 0 ) $inPos--;
- else {
- $tokens[] = join('', array_slice($chars, $start, ($i - $start)));
- if ( $inPos == 0 ) return $tokens[0];
- }
- $start = $i + $j;
- $i = $start - 1;
- break;
- }
- if ( $chars[$i + $j] !== $div[$j] ) break;
- }
- }
- $tokens[] = join('', array_slice( $chars, $start ));
-
- # negative $inPos
- if ( $inPos < 0 ) $inPos += count ( $tokens );
-
- # out of range
- if ( !isset ( $tokens[$inPos] ) ) return "";
-
- # in range
- return $tokens[$inPos];
- }
-
- /**
- * {{#urlencode:value}}
- */
- function runUrlEncode ( &$parser, $inStr = '' ) {
- # encode
- return urlencode ( $inStr );
- }
-
- /**
- * {{#urldecode:value}}
- */
- function runUrlDecode ( &$parser, $inStr = '' ) {
- # decode
- return urldecode ( $inStr );
- }
-}
+}
\ No newline at end of file
File Metadata
Details
Attached
Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2547
Default Alt Text
StringFunctions_new.patch (26 KB)
Attached To
Mode
T8455: Set $wgPFEnableStringFunctions = true on WMF wikis
Attached
Detach File
Event Timeline
Log In to Comment