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 @@ -2,6 +2,7 @@ Latest
------

## Changes
* [#309](https://github.com/cleverage/process-bundle/issues/309) Composer: `ext-intl` is no longer required, it is suggested: it is only needed by the `slugify` transformer (`SlugifyTransformer`), which is replaced by a service failing with an explicit message when the extension is missing (`UnavailableServicesCompilerPass`). Update documentation, add tests.
* [#305](https://github.com/cleverage/process-bundle/issues/305) Bundle best practices, residues: the generic transformers are no longer autowired (explicit arguments). `ProcessHelpCommand` receives the `TaskRegistry` instead of the service container (passing a container is deprecated). Fetching from the service container a task of the application made public by the `TaskInterface` autoconfiguration is deprecated (`container.private` tag, new internal `PublicTaskDeprecationCompilerPass`); the tasks made public by the application itself are not concerned. Trigger the missing deprecation notices: `CheckSerializerCompilerPass`, `errors` task configuration key (use `error_outputs`). `TaskConfiguration::getErrors()` triggers a single notice on PHP 8.4+. `CleverAgeProcessBundle` is marked `@final since 5.4`. Update documentation, add tests.
* [#299](https://github.com/cleverage/process-bundle/issues/299) Require `symfony/polyfill-php83`, `symfony/polyfill-php84` and `symfony/polyfill-php85`: the functions of PHP 8.3 to 8.5 can be used while supporting PHP 8.2. Rector targets PHP 8.2 (`withPhpVersion()`, `withPhpSets()` read from `composer.json`) and applies the rules using a newer function when its polyfill is required: `ProcessConfiguration` uses `array_any()` again; `array_first()` replaces `reset()` / `current()` in `ProcessConfiguration::getMainTask()`, `ConstraintLoader` and `ProcessHelpCommand` (no internal array pointer, same results).
* [#279](https://github.com/cleverage/process-bundle/issues/279) Define the public API (Symfony BC promise): the classes not meant to be extended are marked `@final since 5.4` (the engine: `ProcessManager`, `ProcessConfigurationRegistry`, `TransformerRegistry`, `ContextualOptionResolver`; the models: `ProcessState`, `ProcessHistory`, `SubprocessInstance`, the configurations, the events, the `Filesystem` files; the concrete tasks and transformers), they will be `final` in v6.0: extending them triggers a deprecation with the Symfony `DebugClassLoader`. The abstract classes, interfaces, traits, exceptions and the file tasks extended by other tasks (`FileReaderTask`, `LineReaderTask`, `FolderBrowserTask`, `CsvReaderTask`, `InputCsvReaderTask`, `Filesystem\CsvResource`) stay open. `TaskRegistry`, new in this version, is `final`. The infrastructure classes are marked `@internal`: `CleverAgeProcessExtension`, `Configuration`, the commands, `DataQueueEventListener`, `PhpFunctionProvider`, the Monolog processors, `ProcessLogger` and `TaskLogger`. Update documentation.
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
"require": {
"php": ">=8.2",
"ext-dom": "*",
"ext-intl": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
Expand Down Expand Up @@ -105,6 +104,7 @@
"cleverage/ui-process-bundle": "<3.3"
},
"suggest": {
"ext-intl": "Required by the slugify transformer",
"symfony/monolog-bundle": "To log in the dedicated cleverage_process, cleverage_process_task and cleverage_process_transformer channels, with the process and task data in the extra of the records",
"symfony/process": "Required by the CommandRunnerTask and the ProcessLauncherTask",
"symfony/stopwatch": "Required by the StopwatchTask",
Expand Down
5 changes: 3 additions & 2 deletions docs/01-quick_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,14 @@ Some features rely on optional packages, suggested by the bundle:

| Package | Needed by |
| ------- | --------- |
| `ext-intl` (PHP extension) | the [SlugifyTransformer](reference/transformers/slugify_transformer.md) |
| `symfony/process` | the [CommandRunnerTask](reference/tasks/command_runner_task.md) and the [ProcessLauncherTask](reference/tasks/process_launcher_task.md) |
| `symfony/stopwatch` | the [StopwatchTask](reference/tasks/stopwatch_task.md) |
| `symfony/var-dumper` | the dumps of the [DebugTask](reference/tasks/debug_task.md), of the `debug` transformer and of `cleverage:process:execute --output-format=dump` (nothing is dumped without it) |
| `symfony/monolog-bundle` | the `cleverage_process`, `cleverage_process_task` and `cleverage_process_transformer` log channels, with the process and task data in the `extra` of the records (see [logging](03-custom_tasks.md#logging)); without it, the default Symfony logger is used |

Without `symfony/process` or `symfony/stopwatch`, the container still compiles, and a process using one of these tasks
fails with an explicit message giving the package to install.
Without `symfony/process`, `symfony/stopwatch` or `ext-intl`, the container still compiles, and a process using one of
these tasks or transformers fails with an explicit message giving the package or extension to install.

## Global configuration

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/transformers/slugify_transformer.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Convert a string into a slug. The value is transliterated with a
tags are stripped, the result is trimmed and lowercased, every sequence of characters matching `replace` is replaced by
`separator`, and leading and trailing separators are removed.

Requires the `intl` PHP extension.
Requires the `intl` PHP extension (suggested by the bundle): without it, the transformer fails with an explicit message.

Transformer reference
---------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use CleverAge\ProcessBundle\Task\Validation\ValidatorTask;
use CleverAge\ProcessBundle\Transformer\Serialization\DenormalizeTransformer;
use CleverAge\ProcessBundle\Transformer\Serialization\NormalizeTransformer;
use CleverAge\ProcessBundle\Transformer\String\SlugifyTransformer;
use CleverAge\ProcessBundle\Transformer\TransformerInterface;
use CleverAge\ProcessBundle\Transformer\UnavailableTransformer;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
Expand All @@ -49,6 +50,8 @@

public const PROCESS_MESSAGE = 'The "%s" service requires the Symfony Process component, which does not seem installed: try "composer require symfony/process".';

public const INTL_MESSAGE = 'The "%s" service requires the PHP intl extension, which does not seem installed (see https://www.php.net/manual/en/book.intl.php).';

/**
* @param (\Closure(class-string): bool)|null $classExists defaults to class_exists() (the tests check the missing packages)
*/
Expand Down Expand Up @@ -82,6 +85,10 @@ public function process(ContainerBuilder $container): void
if (!($this->classExists ?? class_exists(...))(Process::class)) {
$this->replace($container, self::PROCESS_MESSAGE, [CommandRunnerTask::class, ProcessLauncherTask::class]);
}

if (!($this->classExists ?? class_exists(...))(\Transliterator::class)) {
$this->replace($container, self::INTL_MESSAGE, [SlugifyTransformer::class]);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use CleverAge\ProcessBundle\Task\Validation\ValidatorTask;
use CleverAge\ProcessBundle\Transformer\Serialization\DenormalizeTransformer;
use CleverAge\ProcessBundle\Transformer\Serialization\NormalizeTransformer;
use CleverAge\ProcessBundle\Transformer\String\SlugifyTransformer;
use CleverAge\ProcessBundle\Transformer\UnavailableTransformer;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;
Expand All @@ -49,7 +50,7 @@ public function testServicesAreKeptWhenTheirDependenciesAreAvailable(): void
{
$container = $this->createContainer(serializer: true, validator: true);

foreach ([...self::SERIALIZER_TASKS, NormalizeTransformer::class, DenormalizeTransformer::class, ValidatorTask::class, StopwatchTask::class, CommandRunnerTask::class, ProcessLauncherTask::class] as $id) {
foreach ([...self::SERIALIZER_TASKS, NormalizeTransformer::class, DenormalizeTransformer::class, ValidatorTask::class, StopwatchTask::class, CommandRunnerTask::class, ProcessLauncherTask::class, SlugifyTransformer::class] as $id) {
self::assertSame($id, $container->findDefinition($id)->getClass());
}
}
Expand Down Expand Up @@ -128,7 +129,18 @@ public function testProcessTasksAreReplacedWithoutProcessComponent(): void
self::assertSame(StopwatchTask::class, $container->findDefinition(StopwatchTask::class)->getClass());
}

private function createContainer(bool $serializer, bool $validator, bool $stopwatch = true, bool $process = true): ContainerBuilder
public function testSlugifyTransformerIsReplacedWithoutIntl(): void
{
$container = $this->createContainer(serializer: true, validator: true, intl: false);

$definition = $container->findDefinition(SlugifyTransformer::class);
self::assertSame(UnavailableTransformer::class, $definition->getClass());
self::assertSame(['slugify', \sprintf(UnavailableServicesCompilerPass::INTL_MESSAGE, SlugifyTransformer::class)], $definition->getArguments());
self::assertSame([['code' => 'slugify']], $definition->getTag('cleverage.transformer'));
self::assertSame(StopwatchTask::class, $container->findDefinition(StopwatchTask::class)->getClass());
}

private function createContainer(bool $serializer, bool $validator, bool $stopwatch = true, bool $process = true, bool $intl = true): ContainerBuilder
{
$container = new ContainerBuilder();
(new CleverAgeProcessExtension())->load([], $container);
Expand All @@ -143,7 +155,9 @@ private function createContainer(bool $serializer, bool $validator, bool $stopwa
if ($stopwatch) {
$container->setDefinition('debug.stopwatch', new Definition(\stdClass::class));
}
$classExists = static fn (string $class): bool => (Process::class !== $class || $process) && class_exists($class);
$classExists = static fn (string $class): bool => (Process::class !== $class || $process)
&& (\Transliterator::class !== $class || $intl)
&& class_exists($class);
(new UnavailableServicesCompilerPass($classExists))->process($container);

return $container;
Expand Down
Loading