Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ $value = \TraderInteractive\Filter\Strings::redact('a string with some unwanted
assert($value === 'a string with some ******** *****');
```

#### Strings::stripControlCharacters

This filter will strip all ASCII control characters, plus the delete character, including tabs and newlines.
It will also strip unicode invisible formatting characters, private use characters, and unused code points.

The second, optional argument specifies a replacement string for the removed characters.

```php
$value = \TraderInteractive\Filter\Strings::stripControlCharacters("Hello\x00\tWorld\nTest\x7F");
assert($value === 'HelloWorldTest');
```

#### Strings::stripEmoji

This filter will strip emoji, pictographs, alphanumeric supplement characters and more from a given string.
Expand Down
21 changes: 21 additions & 0 deletions src/Filter/Strings.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,27 @@ public static function stripEmoji(string $value, string $replacement = ''): stri
return preg_replace($regexPatterns, $replacement, $value);
}

/**
* Strip control characters from a given string
*
* @param string $value The input string.
* @param string $replacement The string to replace the tags with. Defaults to an empty string.
*
* @return string;
*/
public static function stripControlCharacters(string $value, string $replacement = ''): string
{
$asciiControlCharacters = '\x00-\x1F\x7F';
$unicodeControlCharacters = '\p{C}';
$controlCharactersPattern = "/[{$asciiControlCharacters}{$unicodeControlCharacters}]/u";
$filtered = preg_replace($controlCharactersPattern, $replacement, $value);
if ($filtered === null) {
throw new FilterException("Unable to strip control characters from '{$value}'");
}

return $filtered;
}

private static function validateMinimumLength(int $minLength)
{
if ($minLength < 0) {
Expand Down
48 changes: 48 additions & 0 deletions tests/Filter/StringsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ public function provideRedactFailsOnBadInput() : array
* @param string $expectedValue The expected filtered value.
*
* @test
* @covers ::stripEmoji
* @dataProvider provideStripEmoji
*/
public function stripEmoji(string $input, string $expectedValue): void
Expand Down Expand Up @@ -591,4 +592,51 @@ public static function provideStripEmoji(): array
],
];
}

/**
* @param string $input The string value to be filtered.
* @param string $expectedValue The expected filtered value.
*
* @test
* @covers ::stripControlCharacters
* @dataProvider provideStripControlCharacters
*/
public function stripControlCharacters(string $input, string $expectedValue): void
{
$actualValue = Strings::stripControlCharacters($input);
$this->assertSame($expectedValue, $actualValue);
}

/**
* @return array
*/
public static function provideStripControlCharacters(): array
{
return [
'string contains no control characters' => [
'input' => 'a b c',
'expected' => 'a b c',
],
'Contains a null byte, tab, newline, and delete' => [
'input' => "Hello\x00\tWorld\nTest\x7F",
'expected' => 'HelloWorldTest',
],
'Contains a Zero-Width Space (\u{200B}) and a Soft Hyphen (\u{00AD})' => [
'input' => "Uni\u{200B}code\u{00AD}Text",
'expected' => 'UnicodeText',
],
];
}

/**
* @test
* @covers ::stripControlCharacters
*/
public function stripControlCharactersNonUtf8()
{
$windows1252String = "100 \x80";
$this->expectException(FilterException::class);
$this->expectExceptionMessage("Unable to strip control characters from '{$windows1252String}'");
Strings::stripControlCharacters($windows1252String);
}
}
Loading