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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Latest
* [#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.
* [#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.
* [#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.
* [#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.

## Deprecated
* [#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.
Expand Down
16 changes: 13 additions & 3 deletions docs/reference/transformers/preg_filter_transformer.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Options
| Code | Type | Required | Default | Description |
|---------------|-----------------|:--------:|---------|-------------------------------------------------------------------------------------------------------|
| `pattern` | `string\|array` | **X** | | Pattern, or list of patterns, to search |
| `replacement` | `string\|array` | **X** | | Replacement string. The value is cast to string, so an array is not supported in practice (see Notes) |
| `replacement` | `string\|array` | **X** | | Replacement string, or list of replacements (only when `pattern` is an array) |

Examples
--------
Expand All @@ -39,6 +39,15 @@ preg_filter:
replacement: ''
```

* Replace several patterns at once: each pattern is replaced by the replacement at the same position

```yaml
# Transformer options level
preg_filter:
pattern: ['/a/', '/b/']
replacement: ['1', '2']
```

* Reformat a date, `null` if the input does not match

```yaml
Expand All @@ -51,5 +60,6 @@ preg_filter:
Notes
-----

Although `replacement` accepts an `array`, it is cast to string before calling `preg_filter()`, which results in the
literal `Array` (and a PHP warning).
An array `replacement` requires an array `pattern` (as in `preg_filter()`): otherwise an `InvalidOptionsException` is
thrown when resolving the options. If `replacement` has fewer elements than `pattern`, the missing replacements are
empty strings.
14 changes: 13 additions & 1 deletion src/Transformer/PregFilterTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace CleverAge\ProcessBundle\Transformer;

use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

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

return preg_filter($pattern, (string) $replacement, (string) $value);
return preg_filter($pattern, $replacement, (string) $value);
}

/**
Expand All @@ -38,5 +40,15 @@ public function configureOptions(OptionsResolver $resolver): void
$resolver->setRequired(['pattern', 'replacement']);
$resolver->setAllowedTypes('pattern', ['string', 'array']);
$resolver->setAllowedTypes('replacement', ['string', 'array']);
$resolver->setNormalizer(
'replacement',
static function (Options $options, string|array $value): string|array {
if (\is_array($value) && !\is_array($options['pattern'])) {
throw new InvalidOptionsException('The "replacement" option can only be an array when the "pattern" option is an array');
}

return $value;
}
);
}
}
89 changes: 89 additions & 0 deletions tests/Transformer/PregFilterTransformerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

declare(strict_types=1);

/*
* This file is part of the CleverAge/ProcessBundle package.
*
* Copyright (c) Clever-Age
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CleverAge\ProcessBundle\Tests\Transformer;

use CleverAge\ProcessBundle\Transformer\PregFilterTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
use Symfony\Component\OptionsResolver\OptionsResolver;

#[\PHPUnit\Framework\Attributes\CoversClass(PregFilterTransformer::class)]
#[\PHPUnit\Framework\Attributes\CoversMethod(PregFilterTransformer::class, 'transform')]
#[\PHPUnit\Framework\Attributes\CoversMethod(PregFilterTransformer::class, 'configureOptions')]
#[\PHPUnit\Framework\Attributes\CoversMethod(PregFilterTransformer::class, 'getCode')]
class PregFilterTransformerTest extends TestCase
{
public function testTransformWithStringReplacement(): void
{
$transformer = new PregFilterTransformer();
$options = $this->resolveOptions($transformer, [
'pattern' => '/^(\d{2})\/(\d{2})\/(\d{4})$/',
'replacement' => '$3-$2-$1',
]);

$this->assertSame('2019-12-02', $transformer->transform('02/12/2019', $options));
}

public function testTransformReturnsNullWhenPatternDoesNotMatch(): void
{
$transformer = new PregFilterTransformer();
$options = $this->resolveOptions($transformer, [
'pattern' => '/^\d+$/',
'replacement' => 'number',
]);

$this->assertNull($transformer->transform('abc', $options));
}

public function testTransformWithArrayReplacement(): void
{
$transformer = new PregFilterTransformer();
$options = $this->resolveOptions($transformer, [
'pattern' => ['/a/', '/b/'],
'replacement' => ['1', '2'],
]);

$this->assertSame('12c', $transformer->transform('abc', $options));
}

public function testArrayReplacementRequiresArrayPattern(): void
{
$transformer = new PregFilterTransformer();

$this->expectException(InvalidOptionsException::class);

$this->resolveOptions($transformer, [
'pattern' => '/a/',
'replacement' => ['1', '2'],
]);
}

public function testGetCode(): void
{
$this->assertSame('preg_filter', (new PregFilterTransformer())->getCode());
}

/**
* @param array<string, mixed> $options
*
* @return array<string, mixed>
*/
private function resolveOptions(PregFilterTransformer $transformer, array $options): array
{
$resolver = new OptionsResolver();
$transformer->configureOptions($resolver);

return $resolver->resolve($options);
}
}
Loading