Skip to content

Commit f69eace

Browse files
Merge pull request #210 from cleverage/199
#199 - Fix PregFilterTransformer
2 parents d139690 + d215e35 commit f69eace

4 files changed

Lines changed: 116 additions & 4 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Latest
1010
* [#194](https://github.com/cleverage/process-bundle/issues/194) Fix ProcessLauncherTask: the `process_options` normalizer returned an array despite its scalar return type, so the task always failed with a `TypeError`. Update documentation, add tests.
1111
* [#189](https://github.com/cleverage/process-bundle/issues/189) Fix EventDispatcherTask: dispatch the event under the `event_name` option (regression since v4.0). `event_name` is now optional: when `null` (default), the event is dispatched under its class name. Update documentation, add tests.
1212
* [#198](https://github.com/cleverage/process-bundle/issues/198) Fix DateParserTransformer: a `\DateTimeImmutable` input is converted to a `\DateTime` instead of throwing a `TypeError`. Update documentation, add tests.
13+
* [#199](https://github.com/cleverage/process-bundle/issues/199) Fix PregFilterTransformer: an array `replacement` is no longer cast to the string `"Array"`, and requires an array `pattern`. Update documentation, add tests.
1314

1415
## Deprecated
1516
* [#189](https://github.com/cleverage/process-bundle/issues/189) EventDispatcherTask: when `event_name` is set, listening to `CleverAge\ProcessBundle\Event\EventDispatcherTaskEvent` is deprecated (the event is still dispatched under its class name, with an `E_USER_DEPRECATED` error, if it has listeners). Listen to the configured `event_name` instead: the BC layer will be removed in v6.0.

‎docs/reference/transformers/preg_filter_transformer.md‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Options
2727
| Code | Type | Required | Default | Description |
2828
|---------------|-----------------|:--------:|---------|-------------------------------------------------------------------------------------------------------|
2929
| `pattern` | `string\|array` | **X** | | Pattern, or list of patterns, to search |
30-
| `replacement` | `string\|array` | **X** | | Replacement string. The value is cast to string, so an array is not supported in practice (see Notes) |
30+
| `replacement` | `string\|array` | **X** | | Replacement string, or list of replacements (only when `pattern` is an array) |
3131

3232
Examples
3333
--------
@@ -39,6 +39,15 @@ preg_filter:
3939
replacement: ''
4040
```
4141
42+
* Replace several patterns at once: each pattern is replaced by the replacement at the same position
43+
44+
```yaml
45+
# Transformer options level
46+
preg_filter:
47+
pattern: ['/a/', '/b/']
48+
replacement: ['1', '2']
49+
```
50+
4251
* Reformat a date, `null` if the input does not match
4352

4453
```yaml
@@ -51,5 +60,6 @@ preg_filter:
5160
Notes
5261
-----
5362

54-
Although `replacement` accepts an `array`, it is cast to string before calling `preg_filter()`, which results in the
55-
literal `Array` (and a PHP warning).
63+
An array `replacement` requires an array `pattern` (as in `preg_filter()`): otherwise an `InvalidOptionsException` is
64+
thrown when resolving the options. If `replacement` has fewer elements than `pattern`, the missing replacements are
65+
empty strings.

‎src/Transformer/PregFilterTransformer.php‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
namespace CleverAge\ProcessBundle\Transformer;
1515

16+
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
17+
use Symfony\Component\OptionsResolver\Options;
1618
use Symfony\Component\OptionsResolver\OptionsResolver;
1719

1820
class PregFilterTransformer implements ConfigurableTransformerInterface
@@ -22,7 +24,7 @@ public function transform(mixed $value, array $options = []): array|string|null
2224
$pattern = $options['pattern'];
2325
$replacement = $options['replacement'];
2426

25-
return preg_filter($pattern, (string) $replacement, (string) $value);
27+
return preg_filter($pattern, $replacement, (string) $value);
2628
}
2729

2830
/**
@@ -38,5 +40,15 @@ public function configureOptions(OptionsResolver $resolver): void
3840
$resolver->setRequired(['pattern', 'replacement']);
3941
$resolver->setAllowedTypes('pattern', ['string', 'array']);
4042
$resolver->setAllowedTypes('replacement', ['string', 'array']);
43+
$resolver->setNormalizer(
44+
'replacement',
45+
static function (Options $options, string|array $value): string|array {
46+
if (\is_array($value) && !\is_array($options['pattern'])) {
47+
throw new InvalidOptionsException('The "replacement" option can only be an array when the "pattern" option is an array');
48+
}
49+
50+
return $value;
51+
}
52+
);
4153
}
4254
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the CleverAge/ProcessBundle package.
7+
*
8+
* Copyright (c) Clever-Age
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace CleverAge\ProcessBundle\Tests\Transformer;
15+
16+
use CleverAge\ProcessBundle\Transformer\PregFilterTransformer;
17+
use PHPUnit\Framework\TestCase;
18+
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
19+
use Symfony\Component\OptionsResolver\OptionsResolver;
20+
21+
#[\PHPUnit\Framework\Attributes\CoversClass(PregFilterTransformer::class)]
22+
#[\PHPUnit\Framework\Attributes\CoversMethod(PregFilterTransformer::class, 'transform')]
23+
#[\PHPUnit\Framework\Attributes\CoversMethod(PregFilterTransformer::class, 'configureOptions')]
24+
#[\PHPUnit\Framework\Attributes\CoversMethod(PregFilterTransformer::class, 'getCode')]
25+
class PregFilterTransformerTest extends TestCase
26+
{
27+
public function testTransformWithStringReplacement(): void
28+
{
29+
$transformer = new PregFilterTransformer();
30+
$options = $this->resolveOptions($transformer, [
31+
'pattern' => '/^(\d{2})\/(\d{2})\/(\d{4})$/',
32+
'replacement' => '$3-$2-$1',
33+
]);
34+
35+
$this->assertSame('2019-12-02', $transformer->transform('02/12/2019', $options));
36+
}
37+
38+
public function testTransformReturnsNullWhenPatternDoesNotMatch(): void
39+
{
40+
$transformer = new PregFilterTransformer();
41+
$options = $this->resolveOptions($transformer, [
42+
'pattern' => '/^\d+$/',
43+
'replacement' => 'number',
44+
]);
45+
46+
$this->assertNull($transformer->transform('abc', $options));
47+
}
48+
49+
public function testTransformWithArrayReplacement(): void
50+
{
51+
$transformer = new PregFilterTransformer();
52+
$options = $this->resolveOptions($transformer, [
53+
'pattern' => ['/a/', '/b/'],
54+
'replacement' => ['1', '2'],
55+
]);
56+
57+
$this->assertSame('12c', $transformer->transform('abc', $options));
58+
}
59+
60+
public function testArrayReplacementRequiresArrayPattern(): void
61+
{
62+
$transformer = new PregFilterTransformer();
63+
64+
$this->expectException(InvalidOptionsException::class);
65+
66+
$this->resolveOptions($transformer, [
67+
'pattern' => '/a/',
68+
'replacement' => ['1', '2'],
69+
]);
70+
}
71+
72+
public function testGetCode(): void
73+
{
74+
$this->assertSame('preg_filter', (new PregFilterTransformer())->getCode());
75+
}
76+
77+
/**
78+
* @param array<string, mixed> $options
79+
*
80+
* @return array<string, mixed>
81+
*/
82+
private function resolveOptions(PregFilterTransformer $transformer, array $options): array
83+
{
84+
$resolver = new OptionsResolver();
85+
$transformer->configureOptions($resolver);
86+
87+
return $resolver->resolve($options);
88+
}
89+
}

0 commit comments

Comments
 (0)