From 15c538bce7ce18019e7aca27cebc13407cd38684 Mon Sep 17 00:00:00 2001 From: Xavier Marchegay Date: Tue, 9 Dec 2025 15:48:00 +0100 Subject: [PATCH 01/15] =?UTF-8?q?#40=20-=20Mise=20=C3=A0=20jour=20de=20la?= =?UTF-8?q?=20configuration=20pour=20PHP=208.5=20et=20ajustements=20divers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .docker/php/Dockerfile | 5 +- .php-cs-fixer.dist.php | 5 +- composer.json | 46 +++++++++---------- phpunit.xml.dist | 21 ++++----- rector.php | 6 +-- src/Controller/Admin/Process/LaunchAction.php | 4 +- .../Admin/Process/UploadAndExecuteAction.php | 2 +- src/Entity/ProcessSchedule.php | 7 +-- .../ProcessEventSubscriber.php | 11 ++--- src/Http/Model/HttpProcessExecution.php | 13 ++---- .../HttpProcessExecuteValueResolver.php | 7 +-- .../ProcessConfigurationValueResolver.php | 9 ++-- src/Manager/ProcessConfigurationsManager.php | 7 +-- src/Message/CronProcessMessage.php | 7 +-- src/Message/CronProcessMessageHandler.php | 7 +-- src/Message/ProcessExecuteHandler.php | 7 +-- src/Message/ProcessExecuteMessage.php | 7 +-- src/Scheduler/CronScheduler.php | 11 ++--- .../HttpProcessExecutionAuthenticator.php | 2 +- .../ProcessExecutionExtensionRuntime.php | 9 ++-- 20 files changed, 74 insertions(+), 119 deletions(-) diff --git a/.docker/php/Dockerfile b/.docker/php/Dockerfile index 33dd796..82be215 100644 --- a/.docker/php/Dockerfile +++ b/.docker/php/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.4-fpm-alpine +FROM php:8.5-fpm-alpine ARG UID ARG GID @@ -13,8 +13,7 @@ RUN apk update && apk add \ bash \ icu-dev \ && docker-php-ext-configure intl \ - && docker-php-ext-install intl opcache \ - && docker-php-ext-enable opcache + && docker-php-ext-install intl RUN ln -s /usr/share/zoneinfo/Europe/Paris /etc/localtime \ && sed -i "s/^;date.timezone =.*/date.timezone = Europe\/Paris/" $PHP_INI_DIR/php.ini diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index ed5c8c5..d097551 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -24,9 +24,8 @@ return (new PhpCsFixer\Config()) ->setRules([ - '@PHP71Migration' => true, - '@PHP82Migration' => true, - '@PHPUnit75Migration:risky' => true, + '@PHP8x2Migration' => true, + '@PHPUnit7x5Migration:risky' => true, '@Symfony' => true, '@Symfony:risky' => true, '@DoctrineAnnotation' => true, diff --git a/composer.json b/composer.json index cb0eff3..6204644 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ { "name": "Xavier Marchegay", "email": "xmarchegay@clever-age.com", - "role": "Developer" + "role": "Lead Developer" } ], "autoload": { @@ -36,24 +36,24 @@ } }, "require": { - "php": ">=8.1", + "php": ">=8.2", "ext-ctype": "*", "ext-iconv": "*", - "cleverage/process-bundle": "^4.0", - "doctrine/common": "^3.0", - "doctrine/dbal": "^2.9 || ^3.0", - "doctrine/doctrine-bundle": "^2.5", - "doctrine/doctrine-migrations-bundle": "^3.2", - "doctrine/orm": "^2.9 || ^3.0", - "dragonmantank/cron-expression": "^3.4", - "easycorp/easyadmin-bundle": "^4.8", - "symfony/doctrine-messenger": "^6.4|^7.3", - "symfony/dotenv": "^6.4|^7.3", - "symfony/messenger": "^6.4|^7.3", - "symfony/runtime": "^6.4|^7.3", - "symfony/scheduler": "^6.4|^7.3", - "symfony/string": "^6.4|^7.3", - "symfony/uid": "^6.4|^7.3" + "cleverage/process-bundle": "^5.0", + "doctrine/common": "^3.5", + "doctrine/dbal": "^3.10 || ^4.4", + "doctrine/doctrine-bundle": "^2.18 || ^3.1", + "doctrine/doctrine-migrations-bundle": "^3.7 || ^4", + "doctrine/orm": "^2.20 || ^3.5", + "dragonmantank/cron-expression": "^3.6", + "easycorp/easyadmin-bundle": "^4.27", + "symfony/doctrine-messenger": "^6.4 || ^7.4 || ^8", + "symfony/dotenv": "^6.4 || ^7.4 || ^8", + "symfony/messenger":"^6.4 || ^7.4 || ^8", + "symfony/runtime": "^6.4 || ^7.4 || ^8", + "symfony/scheduler": "^6.4 || ^7.4 || ^8", + "symfony/string":"^6.4 || ^7.4 || ^8", + "symfony/uid": "^6.4 || ^7.4 || ^8" }, "require-dev": { "doctrine/doctrine-fixtures-bundle": "^3.4", @@ -62,15 +62,15 @@ "phpstan/phpstan": "*", "phpstan/phpstan-doctrine": "*", "phpstan/phpstan-symfony": "*", - "phpunit/phpunit": "<10.0", + "phpunit/phpunit": "*", "rector/rector": "*", "roave/security-advisories": "dev-latest", - "symfony/browser-kit": "^6.4|^7.3", - "symfony/css-selector": "^6.4|^7.3", - "symfony/debug-bundle": "^6.4|^7.3", + "symfony/browser-kit": "^6.4 || ^7.4 || ^8", + "symfony/css-selector": "^6.4 || ^7.4 || ^8", + "symfony/debug-bundle": "^6.4 || ^7.4 || ^8", "symfony/maker-bundle": "^1.31", - "symfony/web-profiler-bundle": "^6.4|^7.3", - "vincentlanglet/twig-cs-fixer": "^3.3" + "symfony/web-profiler-bundle": "^6.4 || ^7.4 || ^8", + "vincentlanglet/twig-cs-fixer": "^3.11" }, "conflict": { "symfony/twig-bridge": "7.2.0", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 766495c..c3e7947 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,27 +1,22 @@ + failOnWarning="true"> tests - - + src - - + + \ No newline at end of file diff --git a/rector.php b/rector.php index 9f9d327..ed9c222 100644 --- a/rector.php +++ b/rector.php @@ -8,18 +8,18 @@ use Rector\ValueObject\PhpVersion; return RectorConfig::configure() - ->withPhpVersion(PhpVersion::PHP_84) + ->withPhpVersion(PhpVersion::PHP_85) ->withPaths([ __DIR__.'/src', __DIR__.'/tests', ]) - ->withPhpSets(php81: true) + ->withPhpSets(php82: true) // here we can define, what prepared sets of rules will be applied ->withComposerBased(doctrine: true) ->withPreparedSets(deadCode: true, codeQuality: true, doctrineCodeQuality: true, symfonyCodeQuality: true) ->withAttributesSets(symfony: true, doctrine: true) ->withSets([ - LevelSetList::UP_TO_PHP_81, + LevelSetList::UP_TO_PHP_85, SymfonySetList::SYMFONY_64, SymfonySetList::SYMFONY_CODE_QUALITY, SymfonySetList::SYMFONY_CONSTRUCTOR_INJECTION, diff --git a/src/Controller/Admin/Process/LaunchAction.php b/src/Controller/Admin/Process/LaunchAction.php index 8f6bed5..78adcf2 100644 --- a/src/Controller/Admin/Process/LaunchAction.php +++ b/src/Controller/Admin/Process/LaunchAction.php @@ -50,8 +50,8 @@ public function __invoke( ProcessConfigurationsManager $processConfigurationsManager, AdminContext $context, ): Response { - $processCode = $requestStack->getMainRequest()?->get('process'); - if (null === $processCode) { + $processCode = (string) $requestStack->getMainRequest()?->request->get('process'); + if ('' === $processCode) { throw new MissingProcessException(); } $uiOptions = $processConfigurationsManager->getUiOptions($processCode); diff --git a/src/Controller/Admin/Process/UploadAndExecuteAction.php b/src/Controller/Admin/Process/UploadAndExecuteAction.php index 8392263..2255892 100644 --- a/src/Controller/Admin/Process/UploadAndExecuteAction.php +++ b/src/Controller/Admin/Process/UploadAndExecuteAction.php @@ -49,7 +49,7 @@ public function __invoke( $form = $this->createForm( ProcessUploadFileType::class, null, - ['process_code' => $requestStack->getMainRequest()?->get('process')] + ['process_code' => $requestStack->getMainRequest()?->request->get('process')] ); $form->handleRequest($requestStack->getMainRequest()); if ($form->isSubmitted() && $form->isValid()) { diff --git a/src/Entity/ProcessSchedule.php b/src/Entity/ProcessSchedule.php index 2132202..8eea928 100644 --- a/src/Entity/ProcessSchedule.php +++ b/src/Entity/ProcessSchedule.php @@ -87,12 +87,7 @@ public function setContext(array $context): void $this->context = $context; } - /** - * PHP 8.1 Fatal error: Null can not be used as a standalone type. - * - * @phpstan-ignore missingType.return - */ - public function getNextExecution() + public function getNextExecution(): null { return null; } diff --git a/src/EventSubscriber/ProcessEventSubscriber.php b/src/EventSubscriber/ProcessEventSubscriber.php index 66e3f4f..2631b0f 100644 --- a/src/EventSubscriber/ProcessEventSubscriber.php +++ b/src/EventSubscriber/ProcessEventSubscriber.php @@ -22,15 +22,12 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Uid\Uuid; -/** - * PHP 8.2 : Replace by readonly class. - */ -final class ProcessEventSubscriber implements EventSubscriberInterface +readonly final class ProcessEventSubscriber implements EventSubscriberInterface { public function __construct( - private readonly ProcessHandler $processHandler, - private readonly DoctrineProcessHandler $doctrineProcessHandler, - private readonly ProcessExecutionManager $processExecutionManager, + private ProcessHandler $processHandler, + private DoctrineProcessHandler $doctrineProcessHandler, + private ProcessExecutionManager $processExecutionManager, ) { } diff --git a/src/Http/Model/HttpProcessExecution.php b/src/Http/Model/HttpProcessExecution.php index 7ae3e92..3c78a4a 100644 --- a/src/Http/Model/HttpProcessExecution.php +++ b/src/Http/Model/HttpProcessExecution.php @@ -20,21 +20,18 @@ use Symfony\Component\Validator\Constraints\Sequentially; use Symfony\Component\Validator\Constraints\Type; -/** - * PHP 8.2 : Replace by readonly class. - */ -final class HttpProcessExecution +final readonly class HttpProcessExecution { /** * @param string|array $context */ public function __construct( #[Sequentially(constraints: [new NotNull(message: 'Process code is required.'), new IsValidProcessCode()])] - public readonly ?string $code = null, - public readonly ?string $input = null, + public ?string $code = null, + public ?string $input = null, #[AtLeastOneOf(constraints: [new Json(), new Type('array')])] - public readonly string|array $context = [], - public readonly bool $queue = true, + public string|array $context = [], + public bool $queue = true, ) { } } diff --git a/src/Http/ValueResolver/HttpProcessExecuteValueResolver.php b/src/Http/ValueResolver/HttpProcessExecuteValueResolver.php index d1689b2..31ee50a 100644 --- a/src/Http/ValueResolver/HttpProcessExecuteValueResolver.php +++ b/src/Http/ValueResolver/HttpProcessExecuteValueResolver.php @@ -22,13 +22,10 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; use Symfony\Component\Serializer\SerializerInterface; -/** - * PHP 8.2 : Replace by readonly class. - */ #[AsTargetedValueResolver('http_process_execution')] -class HttpProcessExecuteValueResolver implements ValueResolverInterface +readonly class HttpProcessExecuteValueResolver implements ValueResolverInterface { - public function __construct(private readonly string $storageDir, private readonly SerializerInterface $serializer) + public function __construct(private string $storageDir, private SerializerInterface $serializer) { } diff --git a/src/Http/ValueResolver/ProcessConfigurationValueResolver.php b/src/Http/ValueResolver/ProcessConfigurationValueResolver.php index ef06496..39325da 100644 --- a/src/Http/ValueResolver/ProcessConfigurationValueResolver.php +++ b/src/Http/ValueResolver/ProcessConfigurationValueResolver.php @@ -20,13 +20,10 @@ use Symfony\Component\HttpKernel\Controller\ValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; -/** - * PHP 8.2 : Replace by readonly class. - */ #[AsTargetedValueResolver('process')] -class ProcessConfigurationValueResolver implements ValueResolverInterface +readonly class ProcessConfigurationValueResolver implements ValueResolverInterface { - public function __construct(private readonly ProcessConfigurationRegistry $registry) + public function __construct(private ProcessConfigurationRegistry $registry) { } @@ -35,6 +32,6 @@ public function __construct(private readonly ProcessConfigurationRegistry $regis */ public function resolve(Request $request, ArgumentMetadata $argument): iterable { - return [$this->registry->getProcessConfiguration($request->get('process'))]; + return [$this->registry->getProcessConfiguration((string)$request->request->get('process'))]; } } diff --git a/src/Manager/ProcessConfigurationsManager.php b/src/Manager/ProcessConfigurationsManager.php index 00ad111..dd962af 100644 --- a/src/Manager/ProcessConfigurationsManager.php +++ b/src/Manager/ProcessConfigurationsManager.php @@ -20,9 +20,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Validator\Constraint; -/** - * PHP 8.2 : Replace by readonly class. - */ /** * @phpstan-type UiOptions array{ * 'source': ?string, @@ -35,9 +32,9 @@ * 'default': array{'input': mixed, 'context': array{array{'key': 'int|text', 'value':'int|text'}}} * } */ -final class ProcessConfigurationsManager +readonly final class ProcessConfigurationsManager { - public function __construct(private readonly ProcessConfigurationRegistry $registry) + public function __construct(private ProcessConfigurationRegistry $registry) { } diff --git a/src/Message/CronProcessMessage.php b/src/Message/CronProcessMessage.php index a8449d7..2c1b97d 100644 --- a/src/Message/CronProcessMessage.php +++ b/src/Message/CronProcessMessage.php @@ -15,12 +15,9 @@ use CleverAge\UiProcessBundle\Entity\ProcessSchedule; -/** - * PHP 8.2 : Replace by readonly class. - */ -final class CronProcessMessage +readonly final class CronProcessMessage { - public function __construct(public readonly ProcessSchedule $processSchedule) + public function __construct(public ProcessSchedule $processSchedule) { } } diff --git a/src/Message/CronProcessMessageHandler.php b/src/Message/CronProcessMessageHandler.php index 285742a..6e370d2 100644 --- a/src/Message/CronProcessMessageHandler.php +++ b/src/Message/CronProcessMessageHandler.php @@ -16,13 +16,10 @@ use Symfony\Component\Messenger\Attribute\AsMessageHandler; use Symfony\Component\Messenger\MessageBusInterface; -/** - * PHP 8.2 : Replace by readonly class. - */ #[AsMessageHandler] -final class CronProcessMessageHandler +readonly final class CronProcessMessageHandler { - public function __construct(private readonly MessageBusInterface $bus) + public function __construct(private MessageBusInterface $bus) { } diff --git a/src/Message/ProcessExecuteHandler.php b/src/Message/ProcessExecuteHandler.php index 3443541..a76c0e1 100644 --- a/src/Message/ProcessExecuteHandler.php +++ b/src/Message/ProcessExecuteHandler.php @@ -17,13 +17,10 @@ use CleverAge\UiProcessBundle\Monolog\Handler\ProcessHandler; use Symfony\Component\Messenger\Attribute\AsMessageHandler; -/** - * PHP 8.2 : Replace by readonly class. - */ #[AsMessageHandler] -class ProcessExecuteHandler +readonly class ProcessExecuteHandler { - public function __construct(private readonly ProcessManager $manager, private readonly ProcessHandler $processHandler) + public function __construct(private ProcessManager $manager, private ProcessHandler $processHandler) { } diff --git a/src/Message/ProcessExecuteMessage.php b/src/Message/ProcessExecuteMessage.php index 39c45bb..84fddb0 100644 --- a/src/Message/ProcessExecuteMessage.php +++ b/src/Message/ProcessExecuteMessage.php @@ -13,15 +13,12 @@ namespace CleverAge\UiProcessBundle\Message; -/** - * PHP 8.2 : Replace by readonly class. - */ -class ProcessExecuteMessage +readonly class ProcessExecuteMessage { /** * @param mixed[] $context */ - public function __construct(public readonly string $code, public readonly mixed $input, public readonly array $context = []) + public function __construct(public string $code, public mixed $input, public array $context = []) { } } diff --git a/src/Scheduler/CronScheduler.php b/src/Scheduler/CronScheduler.php index 48bc202..b12fd20 100644 --- a/src/Scheduler/CronScheduler.php +++ b/src/Scheduler/CronScheduler.php @@ -22,15 +22,12 @@ use Symfony\Component\Scheduler\ScheduleProviderInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; -/** - * PHP 8.2 : Replace by readonly class. - */ -class CronScheduler implements ScheduleProviderInterface +readonly class CronScheduler implements ScheduleProviderInterface { public function __construct( - private readonly ProcessScheduleRepository $repository, - private readonly ValidatorInterface $validator, - private readonly LoggerInterface $logger, + private ProcessScheduleRepository $repository, + private ValidatorInterface $validator, + private LoggerInterface $logger, ) { } diff --git a/src/Security/HttpProcessExecutionAuthenticator.php b/src/Security/HttpProcessExecutionAuthenticator.php index 85734f9..cfb91c9 100644 --- a/src/Security/HttpProcessExecutionAuthenticator.php +++ b/src/Security/HttpProcessExecutionAuthenticator.php @@ -34,7 +34,7 @@ public function __construct(private readonly EntityManagerInterface $entityManag public function supports(Request $request): ?bool { - return 'http_process_execute' === $request->get('_route') && $request->isMethod(Request::METHOD_POST); + return 'http_process_execute' === $request->request->get('_route') && $request->isMethod(Request::METHOD_POST); } public function authenticate(Request $request): Passport diff --git a/src/Twig/Runtime/ProcessExecutionExtensionRuntime.php b/src/Twig/Runtime/ProcessExecutionExtensionRuntime.php index 90e4967..592f1e4 100644 --- a/src/Twig/Runtime/ProcessExecutionExtensionRuntime.php +++ b/src/Twig/Runtime/ProcessExecutionExtensionRuntime.php @@ -18,14 +18,11 @@ use CleverAge\UiProcessBundle\Repository\ProcessExecutionRepository; use Twig\Extension\RuntimeExtensionInterface; -/** - * PHP 8.2 : Replace by readonly class. - */ -class ProcessExecutionExtensionRuntime implements RuntimeExtensionInterface +readonly class ProcessExecutionExtensionRuntime implements RuntimeExtensionInterface { public function __construct( - private readonly ProcessExecutionRepository $processExecutionRepository, - private readonly ProcessConfigurationsManager $processConfigurationsManager, + private ProcessExecutionRepository $processExecutionRepository, + private ProcessConfigurationsManager $processConfigurationsManager, ) { } From aaa3ed4fd2be67cc2f2c45cac38ea20c588c2083 Mon Sep 17 00:00:00 2001 From: xmarchegay Date: Tue, 9 Dec 2025 20:02:29 +0100 Subject: [PATCH 02/15] #40 - update template syntax for compatibility with EasyAdmin 4 --- templates/admin/process/launch.html.twig | 4 ++-- templates/admin/process/list.html.twig | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/admin/process/launch.html.twig b/templates/admin/process/launch.html.twig index 88d0f7b..7e4e560 100644 --- a/templates/admin/process/launch.html.twig +++ b/templates/admin/process/launch.html.twig @@ -1,5 +1,5 @@ -{% extends ea.templatePath('layout') %} -{% trans_default_domain ea.i18n.translationDomain %} +{% extends ea().templatePath('layout') %} +{% trans_default_domain ea().i18n.translationDomain %} {% block main %} {% form_theme form '@EasyAdmin/crud/form_theme.html.twig' %} diff --git a/templates/admin/process/list.html.twig b/templates/admin/process/list.html.twig index 2a34372..6a1432c 100644 --- a/templates/admin/process/list.html.twig +++ b/templates/admin/process/list.html.twig @@ -1,6 +1,6 @@ {# @var urlGenerator \EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator #} -{% extends ea.templatePath('layout') %} -{% trans_default_domain ea.i18n.translationDomain %} +{% extends ea().templatePath('layout') %} +{% trans_default_domain ea().i18n.translationDomain %} {% block content_title %}{{ 'Processes'|trans }}{% endblock %} From 2d7a4cf69ccf071b3c7184b1cf8445ce818d1000 Mon Sep 17 00:00:00 2001 From: xmarchegay Date: Tue, 9 Dec 2025 20:13:14 +0100 Subject: [PATCH 03/15] #40 - add EasyAdmin routes configuration file --- config/routes/easyadmin.yaml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 config/routes/easyadmin.yaml diff --git a/config/routes/easyadmin.yaml b/config/routes/easyadmin.yaml new file mode 100644 index 0000000..a88552e --- /dev/null +++ b/config/routes/easyadmin.yaml @@ -0,0 +1,3 @@ +easyadmin: + resource: . + type: easyadmin.routes \ No newline at end of file From 7de4e8f0ed3afbcc59c4b74a5bbd3e952509c375 Mon Sep 17 00:00:00 2001 From: Xavier Marchegay Date: Mon, 12 Jan 2026 14:38:22 +0100 Subject: [PATCH 04/15] =?UTF-8?q?#40=20-=20Mise=20=C3=A0=20jour=20du=20cod?= =?UTF-8?q?e=20pour=20prendre=20en=20compte=20symfony=206,=207=20et=208?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rector.php | 2 +- src/Controller/Admin/Process/LaunchAction.php | 13 +++--- src/Controller/Admin/Process/ListAction.php | 6 +-- .../Admin/Process/UploadAndExecuteAction.php | 12 +++--- .../Admin/ProcessExecutionCrudController.php | 10 ++--- .../Admin/Security/LogoutController.php | 8 +++- src/Controller/Admin/UserCrudController.php | 10 ++--- src/Controller/ProcessExecuteController.php | 13 +++--- src/Entity/LogRecord.php | 2 +- .../ProcessEventSubscriber.php | 2 +- .../HttpProcessExecuteValueResolver.php | 40 ++++++++++++++----- .../ProcessConfigurationValueResolver.php | 2 +- src/Manager/ProcessConfigurationsManager.php | 2 +- src/Message/CronProcessMessage.php | 2 +- src/Message/CronProcessMessageHandler.php | 2 +- 15 files changed, 76 insertions(+), 50 deletions(-) diff --git a/rector.php b/rector.php index ed9c222..46168ac 100644 --- a/rector.php +++ b/rector.php @@ -19,7 +19,7 @@ ->withPreparedSets(deadCode: true, codeQuality: true, doctrineCodeQuality: true, symfonyCodeQuality: true) ->withAttributesSets(symfony: true, doctrine: true) ->withSets([ - LevelSetList::UP_TO_PHP_85, + LevelSetList::UP_TO_PHP_82, SymfonySetList::SYMFONY_64, SymfonySetList::SYMFONY_CODE_QUALITY, SymfonySetList::SYMFONY_CONSTRUCTOR_INJECTION, diff --git a/src/Controller/Admin/Process/LaunchAction.php b/src/Controller/Admin/Process/LaunchAction.php index 78adcf2..fffc32c 100644 --- a/src/Controller/Admin/Process/LaunchAction.php +++ b/src/Controller/Admin/Process/LaunchAction.php @@ -40,21 +40,18 @@ #[IsGranted('ROLE_USER')] class LaunchAction extends AbstractController { - public function __construct(private readonly MessageBusInterface $messageBus) + public function __construct(private readonly MessageBusInterface $messageBus, private readonly RequestStack $requestStack, private readonly ProcessConfigurationsManager $processConfigurationsManager, private readonly AdminContext $context) { } public function __invoke( - RequestStack $requestStack, string $uploadDirectory, - ProcessConfigurationsManager $processConfigurationsManager, - AdminContext $context, ): Response { - $processCode = (string) $requestStack->getMainRequest()?->request->get('process'); + $processCode = (string) $this->requestStack->getMainRequest()?->request->get('process'); if ('' === $processCode) { throw new MissingProcessException(); } - $uiOptions = $processConfigurationsManager->getUiOptions($processCode); + $uiOptions = $this->processConfigurationsManager->getUiOptions($processCode); if (null === $uiOptions) { throw new \InvalidArgumentException('Missing UI Options'); } @@ -84,7 +81,7 @@ public function __invoke( } $form->setData($default); } - $form->handleRequest($requestStack->getMainRequest()); + $form->handleRequest($this->requestStack->getMainRequest()); if ($form->isSubmitted() && $form->isValid()) { $input = $form->get('input')->getData(); if ($input instanceof UploadedFile) { @@ -104,7 +101,7 @@ public function __invoke( return $this->redirectToRoute('process', ['routeName' => 'process_list']); } - $context->getAssets()->addJsAsset(Asset::fromEasyAdminAssetPackage('field-collection.js')->getAsDto()); + $this->context->getAssets()->addJsAsset(Asset::fromEasyAdminAssetPackage('field-collection.js')->getAsDto()); return $this->render( '@CleverAgeUiProcess/admin/process/launch.html.twig', diff --git a/src/Controller/Admin/Process/ListAction.php b/src/Controller/Admin/Process/ListAction.php index 4857c75..7caa193 100644 --- a/src/Controller/Admin/Process/ListAction.php +++ b/src/Controller/Admin/Process/ListAction.php @@ -24,16 +24,16 @@ #[IsGranted('ROLE_USER')] class ListAction extends AbstractController { - public function __construct(private readonly IntlFormatterInterface $intlFormatter) + public function __construct(private readonly IntlFormatterInterface $intlFormatter, private readonly ProcessConfigurationsManager $processConfigurationsManager) { } - public function __invoke(ProcessConfigurationsManager $processConfigurationsManager): Response + public function __invoke(): Response { return $this->render( '@CleverAgeUiProcess/admin/process/list.html.twig', [ - 'processes' => $processConfigurationsManager->getPublicProcesses(), + 'processes' => $this->processConfigurationsManager->getPublicProcesses(), 'IntlFormatterService' => $this->intlFormatter, ] ); diff --git a/src/Controller/Admin/Process/UploadAndExecuteAction.php b/src/Controller/Admin/Process/UploadAndExecuteAction.php index 2255892..8f0691f 100644 --- a/src/Controller/Admin/Process/UploadAndExecuteAction.php +++ b/src/Controller/Admin/Process/UploadAndExecuteAction.php @@ -37,9 +37,11 @@ #[IsGranted('ROLE_USER')] class UploadAndExecuteAction extends AbstractController { + public function __construct(private readonly RequestStack $requestStack, private readonly MessageBusInterface $messageBus) + { + } + public function __invoke( - RequestStack $requestStack, - MessageBusInterface $messageBus, string $uploadDirectory, #[ValueResolver('process')] ProcessConfiguration $processConfiguration, ): Response { @@ -49,15 +51,15 @@ public function __invoke( $form = $this->createForm( ProcessUploadFileType::class, null, - ['process_code' => $requestStack->getMainRequest()?->request->get('process')] + ['process_code' => $this->requestStack->getMainRequest()?->request->get('process')] ); - $form->handleRequest($requestStack->getMainRequest()); + $form->handleRequest($this->requestStack->getMainRequest()); if ($form->isSubmitted() && $form->isValid()) { /** @var UploadedFile $file */ $file = $form->getData(); $savedFilepath = \sprintf('%s/%s.%s', $uploadDirectory, Uuid::v4(), $file->getClientOriginalExtension()); (new Filesystem())->dumpFile($savedFilepath, $file->getContent()); - $messageBus->dispatch( + $this->messageBus->dispatch( new ProcessExecuteMessage( $form->getConfig()->getOption('process_code'), $savedFilepath diff --git a/src/Controller/Admin/ProcessExecutionCrudController.php b/src/Controller/Admin/ProcessExecutionCrudController.php index 1fa21b2..22e482d 100644 --- a/src/Controller/Admin/ProcessExecutionCrudController.php +++ b/src/Controller/Admin/ProcessExecutionCrudController.php @@ -46,6 +46,7 @@ public function __construct( private readonly ProcessExecutionRepository $processExecutionRepository, private readonly string $logDirectory, private readonly TranslatorInterface $translator, + private readonly AdminContext $context, ) { } @@ -109,7 +110,7 @@ public function configureActions(Actions $actions): Actions ); } - public function showLogs(AdminContext $adminContext): RedirectResponse + public function showLogs(): RedirectResponse { /** @var AdminUrlGenerator $adminUrlGenerator */ $adminUrlGenerator = $this->container->get(AdminUrlGenerator::class); @@ -133,11 +134,10 @@ public function showLogs(AdminContext $adminContext): RedirectResponse return $this->redirect($url); } - public function downloadLogFile( - AdminContext $context, - ): Response { + public function downloadLogFile(): Response + { /** @var ProcessExecution $processExecution */ - $processExecution = $context->getEntity()->getInstance(); + $processExecution = $this->context->getEntity()->getInstance(); $filepath = $this->getLogFilePath($processExecution); $basename = basename($filepath); $content = file_get_contents($filepath); diff --git a/src/Controller/Admin/Security/LogoutController.php b/src/Controller/Admin/Security/LogoutController.php index 9ddd963..ecfd5ce 100644 --- a/src/Controller/Admin/Security/LogoutController.php +++ b/src/Controller/Admin/Security/LogoutController.php @@ -20,10 +20,14 @@ class LogoutController extends AbstractController { + public function __construct(private readonly Security $security) + { + } + #[Route('/process/logout', name: 'process_logout')] - public function __invoke(Security $security): Response + public function __invoke(): Response { - $security->logout(); + $this->security->logout(); return $this->redirectToRoute('process_login'); } diff --git a/src/Controller/Admin/UserCrudController.php b/src/Controller/Admin/UserCrudController.php index 02ccdd3..50b2504 100644 --- a/src/Controller/Admin/UserCrudController.php +++ b/src/Controller/Admin/UserCrudController.php @@ -41,7 +41,7 @@ class UserCrudController extends AbstractCrudController { /** @param array $roles */ - public function __construct(private readonly array $roles) + public function __construct(private readonly array $roles, private readonly AdminContext $adminContext, private readonly AdminUrlGenerator $adminUrlGenerator) { } @@ -103,20 +103,20 @@ public function configureActions(Actions $actions): Actions ->addCssClass(''))->add(Crud::PAGE_EDIT, Action::new('generateToken')->linkToCrudAction('generateToken')); } - public function generateToken(AdminContext $adminContext, AdminUrlGenerator $adminUrlGenerator): Response + public function generateToken(): Response { /** @var User $user */ - $user = $adminContext->getEntity()->getInstance(); + $user = $this->adminContext->getEntity()->getInstance(); $token = md5(uniqid(date('YmdHis'))); $user->setToken((new Pbkdf2PasswordHasher())->hash($token)); $this->persistEntity( - $this->container->get('doctrine')->getManagerForClass($adminContext->getEntity()->getFqcn()), + $this->container->get('doctrine')->getManagerForClass($this->adminContext->getEntity()->getFqcn()), $user ); $this->addFlash('success', 'New token generated '.$token.' (keep it in secured area. This token will never be displayed anymore)'); return $this->redirect( - $adminUrlGenerator + $this->adminUrlGenerator ->setController(self::class) ->setAction(Action::EDIT) ->setEntityId($user->getId()) diff --git a/src/Controller/ProcessExecuteController.php b/src/Controller/ProcessExecuteController.php index dc36f94..b20de45 100644 --- a/src/Controller/ProcessExecuteController.php +++ b/src/Controller/ProcessExecuteController.php @@ -28,13 +28,14 @@ #[Route(path: '/http/process/execute', name: 'http_process_execute', methods: ['POST'])] class ProcessExecuteController extends AbstractController { + public function __construct(private readonly ValidatorInterface $validator, private readonly MessageBusInterface $bus, private readonly ProcessManager $processManager) + { + } + public function __invoke( #[ValueResolver('http_process_execution')] HttpProcessExecution $httpProcessExecution, - ValidatorInterface $validator, - MessageBusInterface $bus, - ProcessManager $processManager, ): JsonResponse { - $violations = $validator->validate($httpProcessExecution); + $violations = $this->validator->validate($httpProcessExecution); if ($violations->count() > 0) { $violationsMessages = []; foreach ($violations as $violation) { @@ -43,7 +44,7 @@ public function __invoke( throw new UnprocessableEntityHttpException(implode('. ', $violationsMessages)); } if ($httpProcessExecution->queue) { - $bus->dispatch( + $this->bus->dispatch( new ProcessExecuteMessage( $httpProcessExecution->code ?? '', $httpProcessExecution->input, @@ -56,7 +57,7 @@ public function __invoke( return new JsonResponse('Process has been added to queue. It will start as soon as possible.'); } else { try { - $processManager->execute( + $this->processManager->execute( $httpProcessExecution->code ?? '', $httpProcessExecution->input, \is_string($httpProcessExecution->context) diff --git a/src/Entity/LogRecord.php b/src/Entity/LogRecord.php index 2a9c25f..808ce1f 100644 --- a/src/Entity/LogRecord.php +++ b/src/Entity/LogRecord.php @@ -51,7 +51,7 @@ public function getId(): ?int public function __construct( \Monolog\LogRecord $record, #[ORM\ManyToOne(targetEntity: ProcessExecution::class, cascade: ['all'])] - #[ORM\JoinColumn(name: 'process_execution_id', referencedColumnName: 'id', onDelete: 'CASCADE', nullable: false)] + #[ORM\JoinColumn(name: 'process_execution_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] private readonly ProcessExecution $processExecution, ) { $this->channel = (string) (new UnicodeString($record->channel))->truncate(64); diff --git a/src/EventSubscriber/ProcessEventSubscriber.php b/src/EventSubscriber/ProcessEventSubscriber.php index 2631b0f..ed90faa 100644 --- a/src/EventSubscriber/ProcessEventSubscriber.php +++ b/src/EventSubscriber/ProcessEventSubscriber.php @@ -22,7 +22,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Uid\Uuid; -readonly final class ProcessEventSubscriber implements EventSubscriberInterface +final readonly class ProcessEventSubscriber implements EventSubscriberInterface { public function __construct( private ProcessHandler $processHandler, diff --git a/src/Http/ValueResolver/HttpProcessExecuteValueResolver.php b/src/Http/ValueResolver/HttpProcessExecuteValueResolver.php index 31ee50a..fd31642 100644 --- a/src/Http/ValueResolver/HttpProcessExecuteValueResolver.php +++ b/src/Http/ValueResolver/HttpProcessExecuteValueResolver.php @@ -25,8 +25,10 @@ #[AsTargetedValueResolver('http_process_execution')] readonly class HttpProcessExecuteValueResolver implements ValueResolverInterface { - public function __construct(private string $storageDir, private SerializerInterface $serializer) - { + public function __construct( + private string $storageDir, + private SerializerInterface $serializer, + ) { } /** @@ -34,26 +36,46 @@ public function __construct(private string $storageDir, private SerializerInterf */ public function resolve(Request $request, ArgumentMetadata $argument): iterable { - $all = $request->request->all(); try { - if ([] === $all) { + $hasRequestData = $request->request->count() > 0 || $request->files->count() > 0; + + if (!$hasRequestData) { + $content = $request->getContent(); + if (empty($content)) { + return [new HttpProcessExecution()]; + } + $httpProcessExecution = $this->serializer->deserialize( - $request->getContent(), + $content, HttpProcessExecution::class, 'json' ); } else { - $input = $request->get('input', $request->files->get('input')); + $input = $request->request->get('input') ?? $request->query->get('input'); + + if (null === $input) { + $input = $request->files->get('input'); + } + if ($input instanceof UploadedFile) { $uploadFileName = $this->storageDir.\DIRECTORY_SEPARATOR.date('YmdHis').'_'.uniqid().'_'.$input->getClientOriginalName(); (new Filesystem())->dumpFile($uploadFileName, $input->getContent()); $input = $uploadFileName; } + + $code = $request->request->get('code') ?? $request->query->get('code'); + $context = $request->request->all('context'); + if ([] === $context) { + $context = $request->query->all('context'); + } + + $queue = $request->request->getBoolean('queue', true); + $httpProcessExecution = new HttpProcessExecution( - $request->get('code'), + (string) $code, $input, - $request->get('context', []), - $request->request->getBoolean('queue', true), + $context, + $queue ); } diff --git a/src/Http/ValueResolver/ProcessConfigurationValueResolver.php b/src/Http/ValueResolver/ProcessConfigurationValueResolver.php index 39325da..9412d3f 100644 --- a/src/Http/ValueResolver/ProcessConfigurationValueResolver.php +++ b/src/Http/ValueResolver/ProcessConfigurationValueResolver.php @@ -32,6 +32,6 @@ public function __construct(private ProcessConfigurationRegistry $registry) */ public function resolve(Request $request, ArgumentMetadata $argument): iterable { - return [$this->registry->getProcessConfiguration((string)$request->request->get('process'))]; + return [$this->registry->getProcessConfiguration((string) $request->request->get('process'))]; } } diff --git a/src/Manager/ProcessConfigurationsManager.php b/src/Manager/ProcessConfigurationsManager.php index dd962af..ff8b8de 100644 --- a/src/Manager/ProcessConfigurationsManager.php +++ b/src/Manager/ProcessConfigurationsManager.php @@ -32,7 +32,7 @@ * 'default': array{'input': mixed, 'context': array{array{'key': 'int|text', 'value':'int|text'}}} * } */ -readonly final class ProcessConfigurationsManager +final readonly class ProcessConfigurationsManager { public function __construct(private ProcessConfigurationRegistry $registry) { diff --git a/src/Message/CronProcessMessage.php b/src/Message/CronProcessMessage.php index 2c1b97d..8e94c09 100644 --- a/src/Message/CronProcessMessage.php +++ b/src/Message/CronProcessMessage.php @@ -15,7 +15,7 @@ use CleverAge\UiProcessBundle\Entity\ProcessSchedule; -readonly final class CronProcessMessage +final readonly class CronProcessMessage { public function __construct(public ProcessSchedule $processSchedule) { diff --git a/src/Message/CronProcessMessageHandler.php b/src/Message/CronProcessMessageHandler.php index 6e370d2..a517ece 100644 --- a/src/Message/CronProcessMessageHandler.php +++ b/src/Message/CronProcessMessageHandler.php @@ -17,7 +17,7 @@ use Symfony\Component\Messenger\MessageBusInterface; #[AsMessageHandler] -readonly final class CronProcessMessageHandler +final readonly class CronProcessMessageHandler { public function __construct(private MessageBusInterface $bus) { From a27635f5e324727113a566e1550267af8a2682db Mon Sep 17 00:00:00 2001 From: Xavier Marchegay Date: Mon, 12 Jan 2026 14:47:57 +0100 Subject: [PATCH 05/15] =?UTF-8?q?#40=20-=20Mise=20=C3=A0=20jour=20de=20la?= =?UTF-8?q?=20configuration=20des=20workflows=20pour=20PHP=208.5=20et=20Sy?= =?UTF-8?q?mfony=207.4/8=20avec=20ajustements=20des=20d=C3=A9pendances?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 44 +++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0e07db0..f2b0431 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,13 +23,14 @@ jobs: - '8.2' - '8.3' - '8.4' - dependencies: [highest] + - '8.5' + dependencies: [highest, lowest] allowed-to-fail: [false] symfony-require: [''] variant: [normal] include: - - php-version: '8.1' - dependencies: highest + - php-version: '8.2' + dependencies: lowest allowed-to-fail: false symfony-require: 6.4.* variant: symfony/symfony:"6.4.*" @@ -41,8 +42,8 @@ jobs: - php-version: '8.2' dependencies: highest allowed-to-fail: false - symfony-require: 7.3.* - variant: symfony/symfony:"7.3.*" + symfony-require: 7.4.* + variant: symfony/symfony:"7.4.*" - php-version: '8.3' dependencies: highest allowed-to-fail: false @@ -51,8 +52,8 @@ jobs: - php-version: '8.3' dependencies: highest allowed-to-fail: false - symfony-require: 7.3.* - variant: symfony/symfony:"7.3.*" + symfony-require: 7.4.* + variant: symfony/symfony:"7.4.*" - php-version: '8.4' dependencies: highest allowed-to-fail: false @@ -61,12 +62,31 @@ jobs: - php-version: '8.4' dependencies: highest allowed-to-fail: false - symfony-require: 7.3.* - variant: symfony/symfony:"7.3.*" - + symfony-require: 7.4.* + variant: symfony/symfony:"7.4.*" + - php-version: '8.4' + dependencies: highest + allowed-to-fail: false + symfony-require: 8.* + variant: symfony/symfony:"8.*" + - php-version: '8.5' + dependencies: highest + allowed-to-fail: false + symfony-require: 6.4.* + variant: symfony/symfony:"6.4.*" + - php-version: '8.5' + dependencies: highest + allowed-to-fail: false + symfony-require: 7.4.* + variant: symfony/symfony:"7.4.*" + - php-version: '8.5' + dependencies: highest + allowed-to-fail: false + symfony-require: 8.* + variant: symfony/symfony:"8.*" steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Install PHP with extensions uses: shivammathur/setup-php@v2 with: @@ -87,4 +107,4 @@ jobs: #- name: Send coverage to Codecov # uses: codecov/codecov-action@v4 # with: - # files: build/logs/clover.xml + # files: build/logs/clover.xml \ No newline at end of file From 39415422b287fe546d2a5543f8632419047d241a Mon Sep 17 00:00:00 2001 From: Xavier Marchegay Date: Mon, 12 Jan 2026 14:53:31 +0100 Subject: [PATCH 06/15] =?UTF-8?q?#40=20-=20Mise=20=C3=A0=20jour=20de=20la?= =?UTF-8?q?=20version=20de=20doctrine-fixtures-bundle=20pour=20inclure=20l?= =?UTF-8?q?a=20compatibilit=C3=A9=20avec=20la=20version=204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6204644..630fa34 100644 --- a/composer.json +++ b/composer.json @@ -56,7 +56,7 @@ "symfony/uid": "^6.4 || ^7.4 || ^8" }, "require-dev": { - "doctrine/doctrine-fixtures-bundle": "^3.4", + "doctrine/doctrine-fixtures-bundle": "^3 || ^4", "friendsofphp/php-cs-fixer": "*", "phpstan/extension-installer": "*", "phpstan/phpstan": "*", From c225063234534384bfd6e98d01a502f8cb366b1a Mon Sep 17 00:00:00 2001 From: xaviermarchegay Date: Mon, 9 Feb 2026 14:17:55 +0100 Subject: [PATCH 07/15] #40 - fix autowiring easyadmin --- src/Controller/Admin/UserCrudController.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Controller/Admin/UserCrudController.php b/src/Controller/Admin/UserCrudController.php index 50b2504..36f2172 100644 --- a/src/Controller/Admin/UserCrudController.php +++ b/src/Controller/Admin/UserCrudController.php @@ -41,7 +41,7 @@ class UserCrudController extends AbstractCrudController { /** @param array $roles */ - public function __construct(private readonly array $roles, private readonly AdminContext $adminContext, private readonly AdminUrlGenerator $adminUrlGenerator) + public function __construct(private readonly array $roles, private readonly AdminUrlGenerator $adminUrlGenerator) { } @@ -103,14 +103,14 @@ public function configureActions(Actions $actions): Actions ->addCssClass(''))->add(Crud::PAGE_EDIT, Action::new('generateToken')->linkToCrudAction('generateToken')); } - public function generateToken(): Response + public function generateToken(AdminContext $adminContext): Response { /** @var User $user */ - $user = $this->adminContext->getEntity()->getInstance(); + $user = $adminContext->getEntity()->getInstance(); $token = md5(uniqid(date('YmdHis'))); $user->setToken((new Pbkdf2PasswordHasher())->hash($token)); $this->persistEntity( - $this->container->get('doctrine')->getManagerForClass($this->adminContext->getEntity()->getFqcn()), + $this->container->get('doctrine')->getManagerForClass($adminContext->getEntity()->getFqcn()), $user ); $this->addFlash('success', 'New token generated '.$token.' (keep it in secured area. This token will never be displayed anymore)'); From 6620f2b01705537cd3225f2a8f1d5e220231744e Mon Sep 17 00:00:00 2001 From: xaviermarchegay Date: Mon, 9 Feb 2026 14:25:51 +0100 Subject: [PATCH 08/15] #40 - fix autowiring easyadmin --- src/Controller/Admin/ProcessExecutionCrudController.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Controller/Admin/ProcessExecutionCrudController.php b/src/Controller/Admin/ProcessExecutionCrudController.php index 22e482d..f410af9 100644 --- a/src/Controller/Admin/ProcessExecutionCrudController.php +++ b/src/Controller/Admin/ProcessExecutionCrudController.php @@ -46,7 +46,6 @@ public function __construct( private readonly ProcessExecutionRepository $processExecutionRepository, private readonly string $logDirectory, private readonly TranslatorInterface $translator, - private readonly AdminContext $context, ) { } @@ -134,10 +133,10 @@ public function showLogs(): RedirectResponse return $this->redirect($url); } - public function downloadLogFile(): Response + public function downloadLogFile(AdminContext $context): Response { /** @var ProcessExecution $processExecution */ - $processExecution = $this->context->getEntity()->getInstance(); + $processExecution = $context->getEntity()->getInstance(); $filepath = $this->getLogFilePath($processExecution); $basename = basename($filepath); $content = file_get_contents($filepath); From b8ffaa43fdb0c8089849d032d8a17af89abb7fbd Mon Sep 17 00:00:00 2001 From: xaviermarchegay Date: Mon, 9 Feb 2026 14:48:34 +0100 Subject: [PATCH 09/15] #40 - fix default options --- src/Manager/ProcessConfigurationsManager.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Manager/ProcessConfigurationsManager.php b/src/Manager/ProcessConfigurationsManager.php index ff8b8de..3de2102 100644 --- a/src/Manager/ProcessConfigurationsManager.php +++ b/src/Manager/ProcessConfigurationsManager.php @@ -25,7 +25,6 @@ * 'source': ?string, * 'target': ?string, * 'ui_launch_mode': ?string, - * 'run_confirmation_modal': bool, * 'entrypoint_type': string, * 'constraints': Constraint[], * 'run': 'null|bool', @@ -72,7 +71,10 @@ public function getUiOptions(string $processCode): ?array private function resolveUiOptions(array $options): array { $resolver = new OptionsResolver(); - $resolver->setDefault('ui', function (OptionsResolver $uiResolver): void { + $resolver->setDefault('ui', []); + $resolver->setAllowedTypes('ui', 'array'); + $resolver->setNormalizer('ui', function (Options $options, array $ui): array { + $uiResolver = new OptionsResolver(); $uiResolver->setDefaults( [ 'source' => null, @@ -90,15 +92,11 @@ private function resolveUiOptions(array $options): array }, ] ); - $uiResolver->setDeprecated( - 'run', - 'cleverage/ui-process-bundle', - '2', - 'run ui option is deprecated. Use public option instead to hide a process from UI' - ); $uiResolver->setAllowedValues('entrypoint_type', ['text', 'file']); $uiResolver->setNormalizer('constraints', fn (Options $options, array $values): array => (new ConstraintLoader())->buildConstraints($values)); $uiResolver->setAllowedValues('ui_launch_mode', ['modal', null, 'form']); + + return $uiResolver->resolve($ui); }); /** * @var array{'ui': UiOptions} $options From bc008b294a34d1e3dea13774cfab7dfd48353fe6 Mon Sep 17 00:00:00 2001 From: Xavier Marchegay Date: Tue, 10 Feb 2026 20:01:44 +0100 Subject: [PATCH 10/15] Refactor LaunchAction to inject AdminContext as a method parameter --- src/Controller/Admin/Process/LaunchAction.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Controller/Admin/Process/LaunchAction.php b/src/Controller/Admin/Process/LaunchAction.php index fffc32c..d576db1 100644 --- a/src/Controller/Admin/Process/LaunchAction.php +++ b/src/Controller/Admin/Process/LaunchAction.php @@ -40,11 +40,12 @@ #[IsGranted('ROLE_USER')] class LaunchAction extends AbstractController { - public function __construct(private readonly MessageBusInterface $messageBus, private readonly RequestStack $requestStack, private readonly ProcessConfigurationsManager $processConfigurationsManager, private readonly AdminContext $context) + public function __construct(private readonly MessageBusInterface $messageBus, private readonly RequestStack $requestStack, private readonly ProcessConfigurationsManager $processConfigurationsManager) { } public function __invoke( + AdminContext $context, string $uploadDirectory, ): Response { $processCode = (string) $this->requestStack->getMainRequest()?->request->get('process'); @@ -101,7 +102,7 @@ public function __invoke( return $this->redirectToRoute('process', ['routeName' => 'process_list']); } - $this->context->getAssets()->addJsAsset(Asset::fromEasyAdminAssetPackage('field-collection.js')->getAsDto()); + $context->getAssets()->addJsAsset(Asset::fromEasyAdminAssetPackage('field-collection.js')->getAsDto()); return $this->render( '@CleverAgeUiProcess/admin/process/launch.html.twig', From 1ad75c1fce78d22b29b8d22d7b4e71e4585a4ec9 Mon Sep 17 00:00:00 2001 From: Xavier Marchegay Date: Tue, 10 Feb 2026 20:09:06 +0100 Subject: [PATCH 11/15] fix: update process code retrieval from request query --- src/Controller/Admin/Process/LaunchAction.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/Admin/Process/LaunchAction.php b/src/Controller/Admin/Process/LaunchAction.php index d576db1..ef15889 100644 --- a/src/Controller/Admin/Process/LaunchAction.php +++ b/src/Controller/Admin/Process/LaunchAction.php @@ -48,7 +48,7 @@ public function __invoke( AdminContext $context, string $uploadDirectory, ): Response { - $processCode = (string) $this->requestStack->getMainRequest()?->request->get('process'); + $processCode = (string) $this->requestStack->getMainRequest()?->query->get('process'); if ('' === $processCode) { throw new MissingProcessException(); } From 0c03d26578b71c72059bb430d637dbe63afdea70 Mon Sep 17 00:00:00 2001 From: xaviermarchegay Date: Tue, 17 Feb 2026 10:36:34 +0100 Subject: [PATCH 12/15] #40 - add getter to fetch the process execution --- src/Entity/LogRecord.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Entity/LogRecord.php b/src/Entity/LogRecord.php index 808ce1f..d20b261 100644 --- a/src/Entity/LogRecord.php +++ b/src/Entity/LogRecord.php @@ -65,4 +65,9 @@ public function contextIsEmpty(): bool { return [] !== $this->context; } + + public function getProcessExecution(): ProcessExecution + { + return $this->processExecution; + } } From 705334228a2b3cf3f6ae48c6928b64bc8bd32943 Mon Sep 17 00:00:00 2001 From: xaviermarchegay Date: Tue, 17 Feb 2026 10:49:32 +0100 Subject: [PATCH 13/15] #40 - linter --- .../Admin/LogRecordCrudController.php | 4 +-- src/Controller/Admin/Process/LaunchAction.php | 8 +++--- .../Admin/ProcessExecutionCrudController.php | 8 ++++-- .../Admin/ProcessScheduleCrudController.php | 12 ++++----- src/Controller/Admin/UserCrudController.php | 21 ++++++++------- src/Controller/ProcessExecuteController.php | 27 +++++++++---------- src/Form/Type/LaunchType.php | 4 +-- src/Manager/ProcessConfigurationsManager.php | 12 ++++----- src/Message/CronProcessMessageHandler.php | 2 +- 9 files changed, 53 insertions(+), 45 deletions(-) diff --git a/src/Controller/Admin/LogRecordCrudController.php b/src/Controller/Admin/LogRecordCrudController.php index 40ea6cb..8659dc4 100644 --- a/src/Controller/Admin/LogRecordCrudController.php +++ b/src/Controller/Admin/LogRecordCrudController.php @@ -89,7 +89,7 @@ public function configureFilters(Filters $filters): Filters { $id = $this->requestStack->getMainRequest()?->query->all('filters')['process']['value'] ?? null; $processList = $this->processConfigurationsManager->getPublicProcesses(); - $processList = array_map(fn (ProcessConfiguration $cfg) => $cfg->getCode(), $processList); + $processList = array_map(static fn (ProcessConfiguration $cfg) => $cfg->getCode(), $processList); return $filters->add( LogProcessFilter::new('Process', $processList, $id) @@ -97,7 +97,7 @@ public function configureFilters(Filters $filters): Filters ChoiceFilter::new('level') ->setTranslatableChoices(array_combine( Level::VALUES, - array_map(fn ($value) => 'enum.log_level.'.strtolower((string) $value), Level::NAMES) + array_map(static fn ($value) => 'enum.log_level.'.strtolower((string) $value), Level::NAMES) )) ->setFormTypeOption('translation_domain', 'enums'), )->add('message')->add('context')->add('createdAt'); diff --git a/src/Controller/Admin/Process/LaunchAction.php b/src/Controller/Admin/Process/LaunchAction.php index ef15889..77e161c 100644 --- a/src/Controller/Admin/Process/LaunchAction.php +++ b/src/Controller/Admin/Process/LaunchAction.php @@ -40,12 +40,14 @@ #[IsGranted('ROLE_USER')] class LaunchAction extends AbstractController { - public function __construct(private readonly MessageBusInterface $messageBus, private readonly RequestStack $requestStack, private readonly ProcessConfigurationsManager $processConfigurationsManager) + /** + * @param AdminContext $context + */ + public function __construct(private readonly MessageBusInterface $messageBus, private readonly RequestStack $requestStack, private readonly ProcessConfigurationsManager $processConfigurationsManager, private readonly AdminContext $context) { } public function __invoke( - AdminContext $context, string $uploadDirectory, ): Response { $processCode = (string) $this->requestStack->getMainRequest()?->query->get('process'); @@ -102,7 +104,7 @@ public function __invoke( return $this->redirectToRoute('process', ['routeName' => 'process_list']); } - $context->getAssets()->addJsAsset(Asset::fromEasyAdminAssetPackage('field-collection.js')->getAsDto()); + $this->context->getAssets()->addJsAsset(Asset::fromEasyAdminAssetPackage('field-collection.js')->getAsDto()); return $this->render( '@CleverAgeUiProcess/admin/process/launch.html.twig', diff --git a/src/Controller/Admin/ProcessExecutionCrudController.php b/src/Controller/Admin/ProcessExecutionCrudController.php index f410af9..d815024 100644 --- a/src/Controller/Admin/ProcessExecutionCrudController.php +++ b/src/Controller/Admin/ProcessExecutionCrudController.php @@ -42,10 +42,14 @@ #[IsGranted('ROLE_USER')] class ProcessExecutionCrudController extends AbstractCrudController { + /** + * @param AdminContext $context + */ public function __construct( private readonly ProcessExecutionRepository $processExecutionRepository, private readonly string $logDirectory, private readonly TranslatorInterface $translator, + private readonly AdminContext $context, ) { } @@ -133,10 +137,10 @@ public function showLogs(): RedirectResponse return $this->redirect($url); } - public function downloadLogFile(AdminContext $context): Response + public function downloadLogFile(): Response { /** @var ProcessExecution $processExecution */ - $processExecution = $context->getEntity()->getInstance(); + $processExecution = $this->context->getEntity()->getInstance(); $filepath = $this->getLogFilePath($processExecution); $basename = basename($filepath); $content = file_get_contents($filepath); diff --git a/src/Controller/Admin/ProcessScheduleCrudController.php b/src/Controller/Admin/ProcessScheduleCrudController.php index 5501aff..3870271 100644 --- a/src/Controller/Admin/ProcessScheduleCrudController.php +++ b/src/Controller/Admin/ProcessScheduleCrudController.php @@ -57,13 +57,13 @@ public function configureCrud(Crud $crud): Crud public function configureActions(Actions $actions): Actions { return $actions - ->update(Crud::PAGE_INDEX, Action::NEW, fn (Action $action) => $action->setIcon('fa fa-plus') + ->update(Crud::PAGE_INDEX, Action::NEW, static fn (Action $action) => $action->setIcon('fa fa-plus') ->setLabel(false) - ->addCssClass(''))->update(Crud::PAGE_INDEX, Action::EDIT, fn (Action $action) => $action->setIcon('fa fa-edit') + ->addCssClass(''))->update(Crud::PAGE_INDEX, Action::EDIT, static fn (Action $action) => $action->setIcon('fa fa-edit') ->setLabel(false) - ->addCssClass('text-warning'))->update(Crud::PAGE_INDEX, Action::DELETE, fn (Action $action) => $action->setIcon('fa fa-trash-o') + ->addCssClass('text-warning'))->update(Crud::PAGE_INDEX, Action::DELETE, static fn (Action $action) => $action->setIcon('fa fa-trash-o') ->setLabel(false) - ->addCssClass(''))->update(Crud::PAGE_INDEX, Action::BATCH_DELETE, fn (Action $action) => $action->setLabel('Delete') + ->addCssClass(''))->update(Crud::PAGE_INDEX, Action::BATCH_DELETE, static fn (Action $action) => $action->setLabel('Delete') ->addCssClass('')); } @@ -74,7 +74,7 @@ public static function getEntityFqcn(): string public function configureFields(string $pageName): iterable { - $choices = array_map(fn (ProcessConfiguration $configuration) => [$configuration->getCode()], $this->processConfigurationsManager->getPublicProcesses()); + $choices = array_map(static fn (ProcessConfiguration $configuration) => [$configuration->getCode()], $this->processConfigurationsManager->getPublicProcesses()); return [ FormField::addTab('General'), @@ -90,7 +90,7 @@ public function configureFields(string $pageName): iterable ->setVirtual(true) ->hideOnForm() ->hideOnDetail() - ->formatValue(fn ($value, ProcessSchedule $entity) => ProcessScheduleType::CRON === $entity->getType() + ->formatValue(static fn ($value, ProcessSchedule $entity) => ProcessScheduleType::CRON === $entity->getType() ? CronExpressionTrigger::fromSpec($entity->getExpression() ?? '') ->getNextRunDate(new \DateTimeImmutable()) ?->format('c') diff --git a/src/Controller/Admin/UserCrudController.php b/src/Controller/Admin/UserCrudController.php index 36f2172..653aa61 100644 --- a/src/Controller/Admin/UserCrudController.php +++ b/src/Controller/Admin/UserCrudController.php @@ -40,8 +40,11 @@ #[IsGranted('ROLE_USER')] class UserCrudController extends AbstractCrudController { - /** @param array $roles */ - public function __construct(private readonly array $roles, private readonly AdminUrlGenerator $adminUrlGenerator) + /** + * @param array $roles + * @param AdminContext $adminContext + */ + public function __construct(private readonly array $roles, private readonly AdminUrlGenerator $adminUrlGenerator, private readonly AdminContext $adminContext) { } @@ -93,24 +96,24 @@ public function configureFields(string $pageName): iterable public function configureActions(Actions $actions): Actions { return $actions - ->update(Crud::PAGE_INDEX, Action::NEW, fn (Action $action) => $action->setIcon('fa fa-plus') + ->update(Crud::PAGE_INDEX, Action::NEW, static fn (Action $action) => $action->setIcon('fa fa-plus') ->setLabel(false) - ->addCssClass(''))->update(Crud::PAGE_INDEX, Action::EDIT, fn (Action $action) => $action->setIcon('fa fa-edit') + ->addCssClass(''))->update(Crud::PAGE_INDEX, Action::EDIT, static fn (Action $action) => $action->setIcon('fa fa-edit') ->setLabel(false) - ->addCssClass('text-warning'))->update(Crud::PAGE_INDEX, Action::DELETE, fn (Action $action) => $action->setIcon('fa fa-trash-o') + ->addCssClass('text-warning'))->update(Crud::PAGE_INDEX, Action::DELETE, static fn (Action $action) => $action->setIcon('fa fa-trash-o') ->setLabel(false) - ->addCssClass(''))->update(Crud::PAGE_INDEX, Action::BATCH_DELETE, fn (Action $action) => $action->setLabel('Delete') + ->addCssClass(''))->update(Crud::PAGE_INDEX, Action::BATCH_DELETE, static fn (Action $action) => $action->setLabel('Delete') ->addCssClass(''))->add(Crud::PAGE_EDIT, Action::new('generateToken')->linkToCrudAction('generateToken')); } - public function generateToken(AdminContext $adminContext): Response + public function generateToken(): Response { /** @var User $user */ - $user = $adminContext->getEntity()->getInstance(); + $user = $this->adminContext->getEntity()->getInstance(); $token = md5(uniqid(date('YmdHis'))); $user->setToken((new Pbkdf2PasswordHasher())->hash($token)); $this->persistEntity( - $this->container->get('doctrine')->getManagerForClass($adminContext->getEntity()->getFqcn()), + $this->container->get('doctrine')->getManagerForClass($this->adminContext->getEntity()->getFqcn()), $user ); $this->addFlash('success', 'New token generated '.$token.' (keep it in secured area. This token will never be displayed anymore)'); diff --git a/src/Controller/ProcessExecuteController.php b/src/Controller/ProcessExecuteController.php index b20de45..2ac555d 100644 --- a/src/Controller/ProcessExecuteController.php +++ b/src/Controller/ProcessExecuteController.php @@ -55,20 +55,19 @@ public function __invoke( ); return new JsonResponse('Process has been added to queue. It will start as soon as possible.'); - } else { - try { - $this->processManager->execute( - $httpProcessExecution->code ?? '', - $httpProcessExecution->input, - \is_string($httpProcessExecution->context) - ? json_decode($httpProcessExecution->context, true) - : $httpProcessExecution->context - ); - } catch (\Throwable $e) { - return new JsonResponse($e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); - } - - return new JsonResponse('Process has been proceed well.'); } + try { + $this->processManager->execute( + $httpProcessExecution->code ?? '', + $httpProcessExecution->input, + \is_string($httpProcessExecution->context) + ? json_decode($httpProcessExecution->context, true) + : $httpProcessExecution->context + ); + } catch (\Throwable $e) { + return new JsonResponse($e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); + } + + return new JsonResponse('Process has been proceed well.'); } } diff --git a/src/Form/Type/LaunchType.php b/src/Form/Type/LaunchType.php index 3c876bc..3881cf6 100644 --- a/src/Form/Type/LaunchType.php +++ b/src/Form/Type/LaunchType.php @@ -59,8 +59,8 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ] ); $builder->get('context')->addModelTransformer(new CallbackTransformer( - fn ($data) => $data ?? [], - fn ($data) => array_column($data ?? [], 'value', 'key'), + static fn ($data) => $data ?? [], + static fn ($data) => array_column($data ?? [], 'value', 'key'), )); } diff --git a/src/Manager/ProcessConfigurationsManager.php b/src/Manager/ProcessConfigurationsManager.php index 3de2102..eb365fc 100644 --- a/src/Manager/ProcessConfigurationsManager.php +++ b/src/Manager/ProcessConfigurationsManager.php @@ -40,13 +40,13 @@ public function __construct(private ProcessConfigurationRegistry $registry) /** @return ProcessConfiguration[] */ public function getPublicProcesses(): array { - return array_filter($this->getConfigurations(), fn (ProcessConfiguration $cfg) => $cfg->isPublic()); + return array_filter($this->getConfigurations(), static fn (ProcessConfiguration $cfg) => $cfg->isPublic()); } /** @return ProcessConfiguration[] */ public function getPrivateProcesses(): array { - return array_filter($this->getConfigurations(), fn (ProcessConfiguration $cfg) => !$cfg->isPublic()); + return array_filter($this->getConfigurations(), static fn (ProcessConfiguration $cfg) => !$cfg->isPublic()); } /** @@ -73,7 +73,7 @@ private function resolveUiOptions(array $options): array $resolver = new OptionsResolver(); $resolver->setDefault('ui', []); $resolver->setAllowedTypes('ui', 'array'); - $resolver->setNormalizer('ui', function (Options $options, array $ui): array { + $resolver->setNormalizer('ui', static function (Options $options, array $ui): array { $uiResolver = new OptionsResolver(); $uiResolver->setDefaults( [ @@ -83,9 +83,9 @@ private function resolveUiOptions(array $options): array 'ui_launch_mode' => 'modal', 'constraints' => [], 'run' => null, - 'default' => function (OptionsResolver $defaultResolver) { + 'default' => static function (OptionsResolver $defaultResolver) { $defaultResolver->setDefault('input', null); - $defaultResolver->setDefault('context', function (OptionsResolver $contextResolver) { + $defaultResolver->setDefault('context', static function (OptionsResolver $contextResolver) { $contextResolver->setPrototype(true); $contextResolver->setRequired(['key', 'value']); }); @@ -93,7 +93,7 @@ private function resolveUiOptions(array $options): array ] ); $uiResolver->setAllowedValues('entrypoint_type', ['text', 'file']); - $uiResolver->setNormalizer('constraints', fn (Options $options, array $values): array => (new ConstraintLoader())->buildConstraints($values)); + $uiResolver->setNormalizer('constraints', static fn (Options $options, array $values): array => (new ConstraintLoader())->buildConstraints($values)); $uiResolver->setAllowedValues('ui_launch_mode', ['modal', null, 'form']); return $uiResolver->resolve($ui); diff --git a/src/Message/CronProcessMessageHandler.php b/src/Message/CronProcessMessageHandler.php index a517ece..13ab26c 100644 --- a/src/Message/CronProcessMessageHandler.php +++ b/src/Message/CronProcessMessageHandler.php @@ -26,7 +26,7 @@ public function __construct(private MessageBusInterface $bus) public function __invoke(CronProcessMessage $message): void { $schedule = $message->processSchedule; - $context = array_merge(...array_map(fn ($ctx) => [$ctx['key'] => $ctx['value']], $schedule->getContext())); + $context = array_merge(...array_map(static fn ($ctx) => [$ctx['key'] => $ctx['value']], $schedule->getContext())); $this->bus->dispatch( new ProcessExecuteMessage($schedule->getProcess() ?? '', $schedule->getInput(), $context) ); From 13995fba961086ab16971be0029d060926bc347a Mon Sep 17 00:00:00 2001 From: xaviermarchegay Date: Tue, 17 Feb 2026 11:09:34 +0100 Subject: [PATCH 14/15] #40 - fix injection admincontext --- src/Controller/Admin/Process/LaunchAction.php | 9 +++------ src/Controller/Admin/ProcessExecutionCrudController.php | 7 +------ src/Controller/Admin/UserCrudController.php | 9 ++++----- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/Controller/Admin/Process/LaunchAction.php b/src/Controller/Admin/Process/LaunchAction.php index 77e161c..709b5f2 100644 --- a/src/Controller/Admin/Process/LaunchAction.php +++ b/src/Controller/Admin/Process/LaunchAction.php @@ -19,7 +19,7 @@ use CleverAge\UiProcessBundle\Manager\ProcessConfigurationsManager; use CleverAge\UiProcessBundle\Message\ProcessExecuteMessage; use EasyCorp\Bundle\EasyAdminBundle\Config\Asset; -use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; +use EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Form\Extension\Core\Type\TextType; @@ -40,10 +40,7 @@ #[IsGranted('ROLE_USER')] class LaunchAction extends AbstractController { - /** - * @param AdminContext $context - */ - public function __construct(private readonly MessageBusInterface $messageBus, private readonly RequestStack $requestStack, private readonly ProcessConfigurationsManager $processConfigurationsManager, private readonly AdminContext $context) + public function __construct(private readonly MessageBusInterface $messageBus, private readonly RequestStack $requestStack, private readonly ProcessConfigurationsManager $processConfigurationsManager, private readonly AdminContextProvider $adminContextProvider) { } @@ -104,7 +101,7 @@ public function __invoke( return $this->redirectToRoute('process', ['routeName' => 'process_list']); } - $this->context->getAssets()->addJsAsset(Asset::fromEasyAdminAssetPackage('field-collection.js')->getAsDto()); + $this->adminContextProvider->getContext()?->getAssets()->addJsAsset(Asset::fromEasyAdminAssetPackage('field-collection.js')->getAsDto()); return $this->render( '@CleverAgeUiProcess/admin/process/launch.html.twig', diff --git a/src/Controller/Admin/ProcessExecutionCrudController.php b/src/Controller/Admin/ProcessExecutionCrudController.php index d815024..ebb7862 100644 --- a/src/Controller/Admin/ProcessExecutionCrudController.php +++ b/src/Controller/Admin/ProcessExecutionCrudController.php @@ -22,7 +22,6 @@ use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Config\Filters; -use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Field\ArrayField; use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField; @@ -42,14 +41,10 @@ #[IsGranted('ROLE_USER')] class ProcessExecutionCrudController extends AbstractCrudController { - /** - * @param AdminContext $context - */ public function __construct( private readonly ProcessExecutionRepository $processExecutionRepository, private readonly string $logDirectory, private readonly TranslatorInterface $translator, - private readonly AdminContext $context, ) { } @@ -140,7 +135,7 @@ public function showLogs(): RedirectResponse public function downloadLogFile(): Response { /** @var ProcessExecution $processExecution */ - $processExecution = $this->context->getEntity()->getInstance(); + $processExecution = $this->getContext()->getEntity()->getInstance(); $filepath = $this->getLogFilePath($processExecution); $basename = basename($filepath); $content = file_get_contents($filepath); diff --git a/src/Controller/Admin/UserCrudController.php b/src/Controller/Admin/UserCrudController.php index 653aa61..8ade166 100644 --- a/src/Controller/Admin/UserCrudController.php +++ b/src/Controller/Admin/UserCrudController.php @@ -17,7 +17,6 @@ use EasyCorp\Bundle\EasyAdminBundle\Config\Action; use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; -use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField; @@ -42,9 +41,8 @@ class UserCrudController extends AbstractCrudController { /** * @param array $roles - * @param AdminContext $adminContext */ - public function __construct(private readonly array $roles, private readonly AdminUrlGenerator $adminUrlGenerator, private readonly AdminContext $adminContext) + public function __construct(private readonly array $roles, private readonly AdminUrlGenerator $adminUrlGenerator) { } @@ -108,12 +106,13 @@ public function configureActions(Actions $actions): Actions public function generateToken(): Response { + $adminContext = $this->getContext(); /** @var User $user */ - $user = $this->adminContext->getEntity()->getInstance(); + $user = $adminContext->getEntity()->getInstance(); $token = md5(uniqid(date('YmdHis'))); $user->setToken((new Pbkdf2PasswordHasher())->hash($token)); $this->persistEntity( - $this->container->get('doctrine')->getManagerForClass($this->adminContext->getEntity()->getFqcn()), + $this->container->get('doctrine')->getManagerForClass($adminContext->getEntity()->getFqcn()), $user ); $this->addFlash('success', 'New token generated '.$token.' (keep it in secured area. This token will never be displayed anymore)'); From 52829c92ff2612fd7b6eb47387a959800d2f0ab7 Mon Sep 17 00:00:00 2001 From: xaviermarchegay Date: Tue, 17 Feb 2026 11:40:52 +0100 Subject: [PATCH 15/15] #40 - fix monolog --- src/Monolog/Handler/ProcessHandler.php | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Monolog/Handler/ProcessHandler.php b/src/Monolog/Handler/ProcessHandler.php index b1f94da..8ddcc6a 100644 --- a/src/Monolog/Handler/ProcessHandler.php +++ b/src/Monolog/Handler/ProcessHandler.php @@ -21,13 +21,15 @@ class ProcessHandler extends StreamHandler { private Level $reportIncrementLevel = Level::Error; + private bool $filenameSet = false; public function __construct( private readonly string $directory, private readonly ProcessExecutionManager $processExecutionManager, int|string|Level $level = Level::Debug, ) { - parent::__construct($this->directory, $level); + // Initialize with php://memory as placeholder - actual file will be set via setFilename() + parent::__construct('php://memory', $level); } /** @@ -40,27 +42,33 @@ public function setReportIncrementLevel(string $level): void public function hasFilename(): bool { - return $this->directory !== $this->url; + return $this->filenameSet; } public function setFilename(string $filename): void { + $this->close(); $this->url = \sprintf('%s/%s', $this->directory, $filename); + $this->filenameSet = true; } public function close(): void { - $this->url = $this->directory; parent::close(); + $this->filenameSet = false; } public function getFilename(): ?string { - return $this->url; + return $this->filenameSet ? $this->url : null; } - public function write(LogRecord $record): void + protected function write(LogRecord $record): void { + if (!$this->filenameSet) { + // Skip writing if no filename has been set yet + return; + } parent::write($record); if ($record->level->value >= $this->reportIncrementLevel->value) { $this->processExecutionManager->increment($record->level->name);