Skip to content

Instantly share code, notes, and snippets.

@antichris
Last active October 4, 2017 19:21
Show Gist options
  • Save antichris/1dd951752f3da125d382420be21d5b16 to your computer and use it in GitHub Desktop.
Save antichris/1dd951752f3da125d382420be21d5b16 to your computer and use it in GitHub Desktop.
An `mb_substr_replace()` implementation
<?php
/**
* Replace text within a portion of a multi-byte string
* <p>
* Performs a multi-byte safe <i>{@link substr_replace()}</i> operation replacing a copy of <i>string</i> delimited by
* the <i>start</i> and (optionally) <i>length</i> parameters with the string given in <i>replacement</i>.
*
* @see http://php.net/manual/en/function.substr-replace.php
* @see http://php.net/manual/en/function.mb-substr.php
*
* @param mixed $string The input string.
* <p>
* An array of strings can be provided, in which case the replacements will occur on each string in turn. In this case,
* the <i>replacement</i>, <i>start</i>, <i>length</i> and <i>encoding</i> parameters may be provided either as scalar
* values to be applied to each input string in turn, or as arrays, in which case the corresponding array element will
* be used for each input string.
*
* @param mixed $replacement The replacement string.
*
* @param mixed $start If <i>start</i> is positive, the replacing will begin at the <i>start</i>'th offset into
* <i>string</i>.
* <p>
* If <i>start</i> is negative, the replacing will begin at the <i>start</i>'th character from the end of <i>string</i>.
*
* @param mixed $length [optional]
* <p>
* If given and is positive, it represents the length of the portion of <i>string</i> which is to be replaced. If it is
* negative, it represents the number of characters from the end of <i>string</i> at which to stop replacing. If it is
* not given or equals to <b>NULL</b> or an empty string, then it will default to strlen( <i>string</i> ); i.e. end the
* replacing at the end of <i>string</i>. If <i>length</i> is zero then this function will have the effect of inserting
* <i>replacement</i> into <i>string</i> at the given <i>start</i> offset.
*
* @param mixed $encoding [optional]
* <p>
* The <i>encoding</i> parameter is the character encoding. If it is omitted, the internal character encoding value will
* be used.
*
* @return mixed The result string is returned. If <i>string</i> is an array then array is returned.
*/
function mb_substr_replace($string, $replacement, $start, $length = null, $encoding = null)
{
if (!$encoding) {
$encoding = mb_internal_encoding();
}
if (is_array($string)) {
$stringCount = count($string);
if (is_array($replacement)) {
if (count($replacement) < $stringCount) {
$replacement = array_pad($replacement, $stringCount, '');
}
} else {
$replacement = array_fill(0, $stringCount, $replacement);
}
if (is_array($start)) {
if (count($start) < $stringCount) {
$start = array_pad($start, $stringCount, 0);
}
} else {
$start = array_fill(0, $stringCount, $start);
}
if (is_array($length)) {
if (count($length) < $stringCount) {
$length = array_pad($length, $stringCount, null);
}
} else {
$length = array_fill(0, $stringCount, $length);
}
if (is_array($encoding)) {
if (count($encoding) < $stringCount) {
$encoding = array_pad($encoding, $stringCount, mb_internal_encoding());
}
} else {
$encoding = array_fill(0, $stringCount, $encoding);
}
return array_map(__METHOD__, $string, $replacement, $start, $length, $encoding);
}
$stringLength = mb_strlen($string, $encoding);
if ($start < 0) {
if (-$start < $stringLength) {
$startNormalized = $stringLength + $start;
} else {
$startNormalized = 0;
}
} else if ($start > $stringLength) {
$startNormalized = $stringLength;
} else {
$startNormalized = $start;
}
if ($length === null || $length === '') {
$start2 = $stringLength;
} else if ($length < 0) {
$start2 = $stringLength + $length;
if ($start2 < $startNormalized) {
$start2 = $startNormalized;
}
} else {
$start2 = $startNormalized + $length;
}
$leader = $startNormalized
? mb_substr($string, 0, $startNormalized, $encoding)
: '';
$trailer = $start2 < $stringLength
? mb_substr($string, $start2, null, $encoding)
: '';
return "{$leader}{$replacement}{$trailer}";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment