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
* [#192](https://github.com/cleverage/ui-process-bundle/issues/192) The controllers and the HTTP value resolver are defined explicitly, without autowiring nor autoconfiguration (Symfony best practices for bundles, as [cleverage/process-bundle#149](https://github.com/cleverage/process-bundle/issues/149)): same arguments, tags and calls. The `$context` binding of the controllers no longer registers the `AdminContextFactory` service for the `AdminContext $context` arguments of the EasyAdmin actions (never used: EasyAdmin resolves the context first). Add tests.
* [#187](https://github.com/cleverage/ui-process-bundle/issues/187) Composer: require PHP `^8.2` instead of `>=8.2` (PHP 9 is no longer accepted before being tested), remove the authorization of the `symfony/flex` plugin, which is not required (the CI installs it globally), as [cleverage/process-bundle#319](https://github.com/cleverage/process-bundle/issues/319).
* [#181](https://github.com/cleverage/ui-process-bundle/issues/181) Fix the deprecations revealed by the tests, which now fail on deprecations: `ProcessExecutionRepository::getLastProcessExecution()` passes the `\SortDirection` enum to `orderBy()` when doctrine/orm accepts it (3.7 or later, where a string direction is deprecated, [#152](https://github.com/cleverage/ui-process-bundle/issues/152)); `ProcessExecutionRepository::hasLogs()` counts the log records without an arbitrary join (`WITH` deprecated by doctrine/orm 3.7, same result); the date filters of the log records (`createdAt`) and of the process executions (`startDate`) use the `single_text` widget (not configuring it is deprecated by Symfony 6.4, already the default since Symfony 7.0); `User::eraseCredentials()` is marked `#[\Deprecated]`, as required by Symfony 7.3 (with Symfony 6.4 and PHP 8.4 or later, which still call it, set `security.erase_credentials: false` to avoid the deprecation).
* [#180](https://github.com/cleverage/ui-process-bundle/issues/180) Define the public API (Symfony BC promise, as [cleverage/process-bundle#279](https://github.com/cleverage/process-bundle/issues/279)): `ProcessExecutionManager`, `ProcessExecutionRepository`, `ProcessScheduleRepository`, `ProcessExecuteMessage`, `ProcessExecutionNotification` and `CleverAgeUiProcessBundle` are marked `@final since 3.3`, they will be `final` in 4.0: extending them triggers a deprecation with the Symfony `DebugClassLoader`. The entities stay open (overriding them: [#37](https://github.com/cleverage/ui-process-bundle/issues/37)). The infrastructure classes are marked `@internal`: the extension, `Configuration`, the commands, the controllers, the EasyAdmin fields and filters, the form types, the Messenger handlers, the Monolog handlers, `HttpProcessExecuteValueResolver`, `HttpProcessExecutionAuthenticator`, `ProcessExecutionStopChecker`, `CronScheduler`, `ProcessEventSubscriber` and the Twig extensions, runtimes and components.
Expand Down
132 changes: 122 additions & 10 deletions config/services/controller.yaml
Original file line number Diff line number Diff line change
@@ -1,20 +1,132 @@
services:
CleverAge\UiProcessBundle\Controller\:
resource: '../../src/Controller/'
autowire: true
autoconfigure: true
bind:
# The controllers extend AbstractController: its services are injected by setContainer(), with the service locator
# of the "container.service_subscriber" tag. The "routing.controller" tag (#[Route] attribute, Symfony 7.3 or
# later) and the "ea.admin_route_controller" tag (#[AdminRoute] attribute) are the ones of the autoconfiguration.
CleverAge\UiProcessBundle\Controller\Admin\LogRecordCrudController:
public: true
arguments:
$processConfigurationsManager: '@cleverage_ui_process.manager.process_configuration'
$localeSwitcher: '@translation.locale_switcher'
$requestStack: '@request_stack'
calls:
- [setContainer, ['@Psr\Container\ContainerInterface']]
tags:
- controller.service_arguments
- ea.crud_controller
- container.service_subscriber

CleverAge\UiProcessBundle\Controller\Admin\Process\LaunchAction:
public: true
arguments:
$messageBus: '@messenger.default_bus'
$requestStack: '@request_stack'
$processConfigurationsManager: '@cleverage_ui_process.manager.process_configuration'
$adminContextProvider: '@EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider'
bind:
# Argument of the action
$uploadDirectory: '%upload_directory%'
$context: '@EasyCorp\Bundle\EasyAdminBundle\Factory\AdminContextFactory'
$logDirectory: '%kernel.logs_dir%'
$processExecutionRepository: '@cleverage_ui_process.repository.process_execution'
calls:
- [setContainer, ['@Psr\Container\ContainerInterface']]
tags:
- controller.service_arguments
- routing.controller
- container.service_subscriber

CleverAge\UiProcessBundle\Controller\Admin\Process\ListAction:
public: true
arguments:
$intlFormatter: '@EasyCorp\Bundle\EasyAdminBundle\Intl\IntlFormatter'
$processConfigurationsManager: '@cleverage_ui_process.manager.process_configuration'
$adminContextProvider: '@EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider'
calls:
- [setContainer, ['@Psr\Container\ContainerInterface']]
tags:
- controller.service_arguments
- routing.controller
- container.service_subscriber

CleverAge\UiProcessBundle\Controller\Admin\ProcessDashboardController:
public: true
arguments:
$localeSwitcher: '@translation.locale_switcher'
$packages: '@assets.packages'
# $logoPath: set by the extension (design.logo_path)
calls:
- [setContainer, ['@Psr\Container\ContainerInterface']]
tags:
- controller.service_arguments
- ea.dashboard_controller
- container.service_subscriber

CleverAge\UiProcessBundle\Controller\Admin\ProcessExecutionCrudController:
public: true
arguments:
$processExecutionRepository: '@cleverage_ui_process.repository.process_execution'
$logDirectory: '%kernel.logs_dir%'
$translator: '@translator'
# $staleAfter: set by the extension (process_execution.stale_after)
calls:
- [setContainer, ['@Psr\Container\ContainerInterface']]
tags:
- controller.service_arguments
- ea.admin_route_controller
- ea.crud_controller
- container.service_subscriber

CleverAge\UiProcessBundle\Controller\Admin\ProcessScheduleCrudController:
public: true
arguments:
$processConfigurationsManager: '@cleverage_ui_process.manager.process_configuration'
calls:
- [setContainer, ['@Psr\Container\ContainerInterface']]
tags:
- controller.service_arguments
- ea.crud_controller
- container.service_subscriber

CleverAge\UiProcessBundle\Controller\Admin\Security\LoginController:
public: true
calls:
- [setContainer, ['@Psr\Container\ContainerInterface']]
tags:
# With the service of the argument of the action
- { name: controller.service_arguments, action: __invoke, argument: authenticationUtils, id: security.authentication_utils }
- routing.controller
- container.service_subscriber

CleverAge\UiProcessBundle\Controller\Admin\Security\LogoutController:
public: true
arguments:
$security: '@security.helper'
calls:
- [setContainer, ['@Psr\Container\ContainerInterface']]
tags:
- controller.service_arguments
- routing.controller
- container.service_subscriber

CleverAge\UiProcessBundle\Controller\Admin\UserCrudController:
public: true
arguments:
# $roles: set by the extension (security.roles)
$adminUrlGenerator: '@EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator'
calls:
- [setContainer, ['@Psr\Container\ContainerInterface']]
tags:
- controller.service_arguments
- ea.admin_route_controller
- ea.crud_controller
- container.service_subscriber

CleverAge\UiProcessBundle\Controller\ProcessExecuteController:
public: true
arguments:
$validator: '@validator'
$bus: '@messenger.default_bus'
$processManager: '@cleverage_process.manager.process'
$processExecutionManager: '@cleverage_ui_process.manager.process_execution'
calls:
- [setContainer, ['@Psr\Container\ContainerInterface']]
tags:
- { name: 'controller.service_arguments' }
- controller.service_arguments
- routing.controller
- container.service_subscriber
5 changes: 4 additions & 1 deletion config/services/http_value_resolver.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
services:
cleverage_ui_process.http_value_resolver.http_process_execute:
class: CleverAge\UiProcessBundle\Http\ValueResolver\HttpProcessExecuteValueResolver
autoconfigure: true
public: false
arguments:
- '%upload_directory%'
- '@serializer'
tags:
# Targeted value resolver: #[ValueResolver('http_process_execution')], as #[AsTargetedValueResolver]
- controller.targeted_value_resolver: { name: http_process_execution }
- controller.argument_value_resolver
42 changes: 42 additions & 0 deletions tests/DependencyInjection/CleverAgeUiProcessExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,48 @@ public function testEveryServiceDefinitionFileIsLoaded(): void
}
}

public function testServicesAreDefinedExplicitly(): void
{
$container = $this->createContainer('prod');
(new CleverAgeUiProcessExtension())->load([], $container);

// Neither autowiring nor autoconfiguration (Symfony best practices for bundles)
foreach ($container->getDefinitions() as $id => $definition) {
if (!str_starts_with((string) $definition->getClass(), 'CleverAge\\UiProcessBundle\\')) {
continue;
}
self::assertFalse($definition->isAutowired(), \sprintf('Service "%s" is autowired', $id));
self::assertFalse($definition->isAutoconfigured(), \sprintf('Service "%s" is autoconfigured', $id));
}

// The targeted value resolver of the HTTP API (#[AsTargetedValueResolver])
$resolver = $container->getDefinition('cleverage_ui_process.http_value_resolver.http_process_execute');
self::assertSame([['name' => 'http_process_execution']], $resolver->getTag('controller.targeted_value_resolver'));
self::assertTrue($resolver->hasTag('controller.argument_value_resolver'));
}

public function testEveryControllerIsRegistered(): void
{
$container = $this->createContainer('prod');
(new CleverAgeUiProcessExtension())->load([], $container);

$files = array_merge(...array_map(
static fn (string $pattern): array => glob($pattern) ?: [],
[\dirname(__DIR__, 2).'/src/Controller/*.php', \dirname(__DIR__, 2).'/src/Controller/*/*.php', \dirname(__DIR__, 2).'/src/Controller/*/*/*.php']
));
self::assertNotEmpty($files);
foreach ($files as $file) {
$class = 'CleverAge\\UiProcessBundle\\Controller\\'.str_replace('/', '\\', substr($file, \strlen(\dirname(__DIR__, 2).'/src/Controller/'), -4));
self::assertTrue($container->hasDefinition($class), \sprintf('Controller "%s" is not registered', $class));
$definition = $container->getDefinition($class);
self::assertTrue($definition->isPublic());
self::assertTrue($definition->hasTag('controller.service_arguments'));
// Services of AbstractController
self::assertTrue($definition->hasTag('container.service_subscriber'));
self::assertTrue($definition->hasMethodCall('setContainer'));
}
}

public function testLoadWithDefaultConfiguration(): void
{
$container = $this->createContainer('prod');
Expand Down
Loading