Skip to content

Commit

Permalink
Merge pull request #42 from internalsystemerror/hotfix/string-casting
Browse files Browse the repository at this point in the history
Fix fatal errors due to strict types in string filters
  • Loading branch information
Ocramius authored Dec 23, 2021
2 parents 67d88c4 + a3f9227 commit 79e8baa
Show file tree
Hide file tree
Showing 77 changed files with 1,254 additions and 1,471 deletions.
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@
"forum": "https://discourse.laminas.dev"
},
"config": {
"sort-packages": true
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true,
"composer/package-versions-deprecated": true
}
},
"extra": {
"laminas": {
Expand Down
19 changes: 19 additions & 0 deletions src/AbstractFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
use Traversable;

use function array_key_exists;
use function array_map;
use function get_class;
use function gettype;
use function is_array;
use function is_object;
use function is_scalar;
use function method_exists;
use function sprintf;
use function str_replace;
Expand Down Expand Up @@ -103,4 +105,21 @@ protected static function isOptions($options)
{
return is_array($options) || $options instanceof Traversable;
}

/**
* @internal
*
* @param mixed $value
* @return mixed
*/
protected static function applyFilterOnlyToStringableValuesAndStringableArrayValues($value, callable $callback)
{
if (! is_array($value)) {
if (! is_scalar($value)) {
return $value;
}
return $callback((string) $value);
}
return $callback(array_map(fn($item) => is_scalar($item) ? (string) $item : $item, $value));
}
}
1 change: 1 addition & 0 deletions src/Encrypt/Openssl.php
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ private function freeKeyResources(array $keys): void
{
if (PHP_VERSION_ID < 80000) {
foreach ($keys as $key) {
// phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated
openssl_free_key($key);
}
}
Expand Down
23 changes: 18 additions & 5 deletions src/PregReplace.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

namespace Laminas\Filter;

use Closure;
use Traversable;

use function func_get_args;
use function get_class;
use function gettype;
use function is_array;
use function is_object;
use function is_scalar;
use function is_string;
use function iterator_to_array;
use function preg_match;
Expand Down Expand Up @@ -137,18 +137,31 @@ public function getReplacement()
*/
public function filter($value)
{
if (! is_scalar($value) && ! is_array($value)) {
return $value;
}
return self::applyFilterOnlyToStringableValuesAndStringableArrayValues(
$value,
Closure::fromCallable([$this, 'filterNormalizedValue'])
);
}

/**
* @param string|string[] $value
* @return string|string[]
*/
private function filterNormalizedValue($value)
{
if ($this->options['pattern'] === null) {
throw new Exception\RuntimeException(sprintf(
'Filter %s does not have a valid pattern set',
static::class
));
}

return preg_replace($this->options['pattern'], $this->options['replacement'], $value);
/** @var string|string[] $pattern */
$pattern = $this->options['pattern'];
/** @var string|string[] $replacement */
$replacement = $this->options['replacement'];

return preg_replace($pattern, $replacement, $value);
}

/**
Expand Down
23 changes: 16 additions & 7 deletions src/StripNewlines.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

namespace Laminas\Filter;

use function is_array;
use function is_scalar;
use Closure;

use function str_replace;

class StripNewlines extends AbstractFilter
Expand All @@ -15,14 +15,23 @@ class StripNewlines extends AbstractFilter
*
* Returns $value without newline control characters
*
* @param string|array $value
* @return string|array
* @param mixed $value
* @return mixed
*/
public function filter($value)
{
if (! is_scalar($value) && ! is_array($value)) {
return $value;
}
return self::applyFilterOnlyToStringableValuesAndStringableArrayValues(
$value,
Closure::fromCallable([$this, 'filterNormalizedValue'])
);
}

/**
* @param string|string[] $value
* @return string|string[]
*/
private function filterNormalizedValue($value)
{
return str_replace(["\n", "\r"], '', $value);
}
}
21 changes: 14 additions & 7 deletions src/Word/CamelCaseToSeparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,33 @@

namespace Laminas\Filter\Word;

use Closure;
use Laminas\Stdlib\StringUtils;

use function is_array;
use function is_scalar;
use function preg_replace;

class CamelCaseToSeparator extends AbstractSeparator
{
/**
* Defined by Laminas\Filter\Filter
*
* @param string|array $value
* @return string|array
* @param mixed $value
* @return mixed
*/
public function filter($value)
{
if (! is_scalar($value) && ! is_array($value)) {
return $value;
}
return self::applyFilterOnlyToStringableValuesAndStringableArrayValues(
$value,
Closure::fromCallable([$this, 'filterNormalizedValue'])
);
}

/**
* @param string|string[] $value
* @return string|string[]
*/
private function filterNormalizedValue($value)
{
if (StringUtils::hasPcreUnicodeSupport()) {
$pattern = ['#(?<=(?:\p{Lu}))(\p{Lu}\p{Ll})#', '#(?<=(?:\p{Ll}|\p{Nd}))(\p{Lu})#'];
$replacement = [$this->separator . '\1', $this->separator . '\1'];
Expand Down
22 changes: 15 additions & 7 deletions src/Word/DashToSeparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,32 @@

namespace Laminas\Filter\Word;

use function is_array;
use function is_scalar;
use Closure;

use function str_replace;

class DashToSeparator extends AbstractSeparator
{
/**
* Defined by Laminas\Filter\Filter
*
* @param string|array $value
* @return string|array
* @param mixed $value
* @return mixed
*/
public function filter($value)
{
if (! is_scalar($value) && ! is_array($value)) {
return $value;
}
return self::applyFilterOnlyToStringableValuesAndStringableArrayValues(
$value,
Closure::fromCallable([$this, 'filterNormalizedValue'])
);
}

/**
* @param string|string[] $value
* @return string|string[]
*/
private function filterNormalizedValue($value)
{
return str_replace('-', $this->separator, $value);
}
}
21 changes: 14 additions & 7 deletions src/Word/SeparatorToCamelCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

namespace Laminas\Filter\Word;

use Closure;
use Laminas\Stdlib\StringUtils;

use function extension_loaded;
use function is_array;
use function is_scalar;
use function preg_quote;
use function preg_replace_callback;

Expand All @@ -17,15 +16,23 @@ class SeparatorToCamelCase extends AbstractSeparator
/**
* Defined by Laminas\Filter\Filter
*
* @param string|array $value
* @return string|array
* @param mixed $value
* @return mixed
*/
public function filter($value)
{
if (! is_scalar($value) && ! is_array($value)) {
return $value;
}
return self::applyFilterOnlyToStringableValuesAndStringableArrayValues(
$value,
Closure::fromCallable([$this, 'filterNormalizedValue'])
);
}

/**
* @param string|string[] $value
* @return string|string[]
*/
private function filterNormalizedValue($value)
{
// a unicode safe way of converting characters to \x00\x00 notation
$pregQuotedSeparator = preg_quote($this->separator, '#');

Expand Down
28 changes: 19 additions & 9 deletions src/Word/SeparatorToSeparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

namespace Laminas\Filter\Word;

use Closure;
use Laminas\Filter\AbstractFilter;
use Laminas\Filter\Exception;

use function is_array;
use function is_scalar;
use function preg_quote;
use function preg_replace;

Expand Down Expand Up @@ -78,20 +77,31 @@ public function getReplacementSeparator()
*
* Returns the string $value, replacing the searched separators with the defined ones
*
* @param string|array $value
* @return string|array
* @param mixed $value
* @return mixed
*/
public function filter($value)
{
if (! is_scalar($value) && ! is_array($value)) {
return $value;
}
return self::applyFilterOnlyToStringableValuesAndStringableArrayValues(
$value,
Closure::fromCallable([$this, 'filterNormalizedValue'])
);
}

/**
* @param string|string[] $value
* @return string|string[]
*/
private function filterNormalizedValue($value)
{
if ($this->searchSeparator === null) {
throw new Exception\RuntimeException('You must provide a search separator for this filter to work.');
}

$pattern = '#' . preg_quote($this->searchSeparator, '#') . '#';
return preg_replace($pattern, $this->replacementSeparator, $value);
return preg_replace(
'#' . preg_quote($this->searchSeparator, '#') . '#',
$this->replacementSeparator,
$value
);
}
}
1 change: 1 addition & 0 deletions src/Word/UnderscoreToStudlyCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public function filter($value)
return $value;
}

/** @var string|array $value */
$value = parent::filter($value);
$lowerCaseFirst = 'lcfirst';

Expand Down
10 changes: 5 additions & 5 deletions test/AllowListTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ public function testConstructorOptions(): void
'strict' => true,
]);

$this->assertEquals(true, $filter->getStrict());
$this->assertEquals(['test', 1], $filter->getList());
$this->assertSame(true, $filter->getStrict());
$this->assertSame(['test', 1], $filter->getList());
}

public function testConstructorDefaults(): void
{
$filter = new AllowListFilter();

$this->assertEquals(false, $filter->getStrict());
$this->assertEquals([], $filter->getList());
$this->assertSame(false, $filter->getStrict());
$this->assertSame([], $filter->getList());
}

public function testWithPluginManager(): void
Expand All @@ -59,7 +59,7 @@ public function testTraversableConvertsToArray(): void
$filter = new AllowListFilter([
'list' => $obj,
]);
$this->assertEquals($array, $filter->getList());
$this->assertSame($array, $filter->getList());
}

public function testSetStrictShouldCastToBoolean(): void
Expand Down
11 changes: 4 additions & 7 deletions test/BaseNameTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,16 @@ class BaseNameTest extends TestCase
{
/**
* Ensures that the filter follows expected behavior
*
* @return void
*/
public function testBasic()
public function testBasic(): void
{
$filter = new BaseNameFilter();
$valuesExpected = [
'/path/to/filename' => 'filename',
'/path/to/filename.ext' => 'filename.ext',
];
foreach ($valuesExpected as $input => $output) {
$this->assertEquals($output, $filter($input));
$this->assertSame($output, $filter($input));
}
}

Expand All @@ -43,12 +41,11 @@ public function returnUnfilteredDataProvider()

/**
* @dataProvider returnUnfilteredDataProvider
* @return void
*/
public function testReturnUnfiltered($input)
public function testReturnUnfiltered($input): void
{
$filter = new BaseNameFilter();

$this->assertEquals($input, $filter($input));
$this->assertSame($input, $filter($input));
}
}
Loading

0 comments on commit 79e8baa

Please sign in to comment.