45 return mb_check_encoding( (
string)$value,
'UTF-8' );
60 $subject, $nested =
false ) {
64 $encStart = preg_quote( $startDelim,
'!' );
65 $encEnd = preg_quote( $endDelim,
'!' );
66 $encSep = preg_quote( $separator,
'!' );
67 $len = strlen( $subject );
73 "!$encStart|$encEnd|$encSep!S", $subject, $m,
74 PREG_OFFSET_CAPTURE, $inputPos
79 $inputPos = $matchPos + strlen( $match );
80 if ( $match === $separator ) {
83 $subject, $lastPos, $matchPos - $lastPos
87 } elseif ( $match === $startDelim ) {
88 if ( $depth === 0 || $nested ) {
95 $exploded[] = substr( $subject, $lastPos );
98 return new ArrayIterator( $exploded );
119 $segments =
explode( $startDelim, $subject );
120 $output = array_shift( $segments );
121 foreach ( $segments as
$s ) {
122 $endDelimPos = strpos( $s, $endDelim );
123 if ( $endDelimPos ===
false ) {
124 $output .= $startDelim .
$s;
126 $output .= $replace . substr( $s, $endDelimPos + strlen( $endDelim ) );
158 $subject, $flags =
'' 165 $encStart = preg_quote( $startDelim,
'!' );
166 $encEnd = preg_quote( $endDelim,
'!' );
167 $strcmp = strpos( $flags,
'i' ) ===
false ?
'strcmp' :
'strcasecmp';
168 $endLength = strlen( $endDelim );
171 while ( $inputPos < strlen( $subject ) &&
172 preg_match(
"!($encStart)|($encEnd)!S$flags", $subject, $m, PREG_OFFSET_CAPTURE, $inputPos )
174 $tokenOffset = $m[0][1];
175 if ( $m[1][0] !=
'' ) {
177 $strcmp( $endDelim, substr( $subject, $tokenOffset, $endLength ) ) == 0
179 # An end match is present at the same location 181 $tokenLength = $endLength;
183 $tokenType =
'start';
184 $tokenLength = strlen( $m[0][0] );
186 } elseif ( $m[2][0] !=
'' ) {
188 $tokenLength = strlen( $m[0][0] );
193 if ( $tokenType ==
'start' ) {
194 # Only move the start position if we haven't already found a start 195 # This means that START START END matches outer pair 196 if ( !$foundStart ) {
198 $inputPos = $tokenOffset + $tokenLength;
199 # Write out the non-matching section 200 $output .= substr( $subject, $outputPos, $tokenOffset - $outputPos );
201 $outputPos = $tokenOffset;
202 $contentPos = $inputPos;
205 # Move the input position past the *first character* of START, 206 # to protect against missing END when it overlaps with START 207 $inputPos = $tokenOffset + 1;
209 } elseif ( $tokenType ==
'end' ) {
212 $output .= $callback( [
213 substr( $subject, $outputPos, $tokenOffset + $tokenLength - $outputPos ),
214 substr( $subject, $contentPos, $tokenOffset - $contentPos )
218 # Non-matching end, write it out 219 $output .= substr( $subject, $inputPos, $tokenOffset + $tokenLength - $outputPos );
221 $inputPos = $outputPos = $tokenOffset + $tokenLength;
226 if ( $outputPos < strlen( $subject ) ) {
227 $output .= substr( $subject, $outputPos );
248 static function delimiterReplace( $startDelim, $endDelim, $replace, $subject, $flags =
'' ) {
249 return self::delimiterReplaceCallback(
250 $startDelim, $endDelim,
251 function ( array
$matches ) use ( $replace ) {
252 return strtr( $replace, [
'$0' => $matches[0],
'$1' => $matches[1] ] );
266 $placeholder =
"\x00";
269 $text = str_replace( $placeholder,
'', $text );
272 $cleaned = self::delimiterReplaceCallback(
274 function ( array
$matches ) use ( $separator, $placeholder ) {
275 return str_replace( $separator, $placeholder, $matches[0] );
281 $items =
explode( $separator, $cleaned );
282 foreach ( $items as $i => $str ) {
283 $items[$i] = str_replace( $placeholder, $separator, $str );
298 $placeholder =
"\x00";
301 $text = str_replace( $placeholder,
'', $text );
304 $cleaned = self::delimiterReplaceCallback(
306 function ( array
$matches ) use ( $search, $placeholder ) {
307 return str_replace( $search, $placeholder, $matches[0] );
313 $cleaned = str_replace( $search, $replace, $cleaned );
314 $text = str_replace( $placeholder, $search, $cleaned );
329 AtEase::suppressWarnings();
331 $isValid = preg_match( $string,
'' );
332 AtEase::restoreWarnings();
333 return $isValid !==
false;
344 $string = str_replace(
'\\',
'\\\\', $string );
345 $string = str_replace(
'$',
'\\$', $string );
356 static function explode( $separator, $subject ) {
357 if ( substr_count( $subject, $separator ) > 1000 ) {
360 return new ArrayIterator(
explode( $separator, $subject ) );
static isUtf8( $value)
Test whether a string is valid UTF-8.
static isValidPCRERegex( $string)
Utility function to check if the given string is a valid PCRE regex.
static escapeRegexReplacement( $string)
Escape a string to make it suitable for inclusion in a preg_replace() replacement parameter...
static replaceMarkup( $search, $replace, $text)
More or less "markup-safe" str_replace() Ignores any instances of the separator inside <...
static hungryDelimiterReplace( $startDelim, $endDelim, $replace, $subject)
Perform an operation equivalent to preg_replace()
A collection of static methods to play with strings.
static delimiterReplaceCallback( $startDelim, $endDelim, $callback, $subject, $flags='')
Perform an operation equivalent to preg_replace_callback()
static explode( $separator, $subject)
Workalike for explode() with limited memory usage.
An iterator which works exactly like:
static explodeMarkup( $separator, $text)
More or less "markup-safe" explode() Ignores any instances of the separator inside <...
static delimiterExplode( $startDelim, $endDelim, $separator, $subject, $nested=false)
Explode a string, but ignore any instances of the separator inside the given start and end delimiters...
static delimiterReplace( $startDelim, $endDelim, $replace, $subject, $flags='')
Perform an operation equivalent to preg_replace() with flags.