X-Git-Url: https://git.cyclocoop.org/admin/?a=blobdiff_plain;f=includes%2Flibs%2FStringUtils.php;h=cffb5a39457a2b4f09a35e8aa1e8ed9716c13622;hb=12601ff7d2796752404bfb331fccc41083d31f9f;hp=6b10c0998b8b6572b59600531c59ef4c398eb072;hpb=cc28eaeb0930c2d876ee6205de035a12e142d38f;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/libs/StringUtils.php b/includes/libs/StringUtils.php index 6b10c0998b..cffb5a3945 100644 --- a/includes/libs/StringUtils.php +++ b/includes/libs/StringUtils.php @@ -54,6 +54,59 @@ class StringUtils { ( $newPHP || preg_match( "/\xf4[\x90-\xbf]|[\xf5-\xff]/S", $value ) === 0 ); } + /** + * Explode a string, but ignore any instances of the separator inside + * the given start and end delimiters, which may optionally nest. + * The delimiters are literal strings, not regular expressions. + * @param string $startDelim Start delimiter + * @param string $endDelim End delimiter + * @param string $separator Separator string for the explode. + * @param string $subject Subject string to explode. + * @param bool $nested True iff the delimiters are allowed to nest. + * @return ArrayIterator + */ + static function delimiterExplode( $startDelim, $endDelim, $separator, + $subject, $nested = false ) { + $inputPos = 0; + $lastPos = 0; + $depth = 0; + $encStart = preg_quote( $startDelim, '!' ); + $encEnd = preg_quote( $endDelim, '!' ); + $encSep = preg_quote( $separator, '!' ); + $len = strlen( $subject ); + $m = []; + $exploded = []; + while ( + $inputPos < $len && + preg_match( + "!$encStart|$encEnd|$encSep!S", $subject, $m, + PREG_OFFSET_CAPTURE, $inputPos + ) + ) { + $match = $m[0][0]; + $matchPos = $m[0][1]; + $inputPos = $matchPos + strlen( $match ); + if ( $match === $separator ) { + if ( $depth === 0 ) { + $exploded[] = substr( + $subject, $lastPos, $matchPos - $lastPos + ); + $lastPos = $inputPos; + } + } elseif ( $match === $startDelim ) { + if ( $depth === 0 || $nested ) { + $depth++; + } + } else { + $depth--; + } + } + $exploded[] = substr( $subject, $lastPos ); + // This method could be rewritten in the future to avoid creating an + // intermediate array, since the return type is just an iterator. + return new ArrayIterator( $exploded ); + } + /** * Perform an operation equivalent to `preg_replace()` * @@ -115,6 +168,7 @@ class StringUtils { ) { $inputPos = 0; $outputPos = 0; + $contentPos = 0; $output = ''; $foundStart = false; $encStart = preg_quote( $startDelim, '!' );