Fix #20032: Added mask method for string masking with multibyte support

This commit is contained in:
Saleh Hashemi
2023-10-25 20:17:03 +03:30
committed by GitHub
parent 778d708c4f
commit e2773e4524
3 changed files with 64 additions and 0 deletions

View File

@ -11,6 +11,8 @@ Yii Framework 2 Change Log
- Bug #20002: Fixed superfluous query on HEAD request in serializer (xicond) - Bug #20002: Fixed superfluous query on HEAD request in serializer (xicond)
- Enh #12743: Added new methods `BaseActiveRecord::loadRelations()` and `BaseActiveRecord::loadRelationsFor()` to eager load related models for existing primary model instances (PowerGamer1) - Enh #12743: Added new methods `BaseActiveRecord::loadRelations()` and `BaseActiveRecord::loadRelationsFor()` to eager load related models for existing primary model instances (PowerGamer1)
- Enh #20030: Improve performance of handling `ErrorHandler::$memoryReserveSize` (antonshevelev, rob006) - Enh #20030: Improve performance of handling `ErrorHandler::$memoryReserveSize` (antonshevelev, rob006)
- Enh #20032: Added `mask` method for string masking with multibyte support (salehhashemi1992)
2.0.49.2 October 12, 2023 2.0.49.2 October 12, 2023
------------------------- -------------------------

View File

@ -497,4 +497,34 @@ class BaseStringHelper
return implode('', $parts); return implode('', $parts);
} }
/**
* Masks a portion of a string with a repeated character.
* This method is multibyte-safe.
*
* @param string $string The input string.
* @param int $start The starting position from where to begin masking.
* This can be a positive or negative integer.
* Positive values count from the beginning,
* negative values count from the end of the string.
* @param int $length The length of the section to be masked.
* The masking will start from the $start position
* and continue for $length characters.
* @param string $mask The character to use for masking. The default is '*'.
* @return string The masked string.
*/
public static function mask($string, $start, $length, $mask = '*') {
$strLength = mb_strlen($string, 'UTF-8');
// Return original string if start position is out of bounds
if ($start >= $strLength || $start < -$strLength) {
return $string;
}
$masked = mb_substr($string, 0, $start, 'UTF-8');
$masked .= str_repeat($mask, abs($length));
$masked .= mb_substr($string, $start + abs($length), null, 'UTF-8');
return $masked;
}
} }

View File

@ -474,4 +474,36 @@ class StringHelperTest extends TestCase
['', ''], ['', ''],
]; ];
} }
public function testMask()
{
// Standard masking
$this->assertSame('12******90', StringHelper::mask('1234567890', 2, 6));
$this->assertSame('a********j', StringHelper::mask('abcdefghij', 1, 8));
$this->assertSame('*************', StringHelper::mask('Hello, World!', 0, 13));
$this->assertSame('************!', StringHelper::mask('Hello, World!', 0, 12));
$this->assertSame('Hello, *orld!', StringHelper::mask('Hello, World!', 7, 1));
$this->assertSame('Saleh Hashemi', StringHelper::mask('Saleh Hashemi', 0, 0));
// Different Mask Character
$this->assertSame('12######90', StringHelper::mask('1234567890', 2, 6, '#'));
// Positions outside the string
$this->assertSame('1234567890', StringHelper::mask('1234567890', 20, 6));
$this->assertSame('1234567890', StringHelper::mask('1234567890', -20, 6));
// Negative values for start
$this->assertSame('1234****90', StringHelper::mask('1234567890', -6, 4));
// type-related edge case
$this->assertSame('1234****90', StringHelper::mask(1234567890, -6, 4));
// Multibyte characters
$this->assertSame('你**', StringHelper::mask('你好吗', 1, 2));
$this->assertSame('你好吗', StringHelper::mask('你好吗', 4, 2));
// Special characters
$this->assertSame('em**l@email.com', StringHelper::mask('email@email.com', 2, 2));
$this->assertSame('******email.com', StringHelper::mask('email@email.com', 0, 6));
}
} }