From 1621e11c0472b46a5ec6c7dabeabc124a71ae4c5 Mon Sep 17 00:00:00 2001 From: Daniel Metzner Date: Sun, 15 Sep 2024 11:09:18 +0200 Subject: [PATCH] Reduce services.php by using attributes, and better structured config Signed-off-by: Daniel Metzner --- config/features.php | 10 -- config/packages/bugsnag.php | 11 ++ config/packages/bugsnag.yaml | 2 - config/packages/feature_flags.php | 20 +++ config/packages/fos_elastica.php | 4 +- config/services.php | 142 +++--------------- config/services_test.php | 2 - .../System/FeatureFlag/FeatureFlagManager.php | 7 +- .../Maintenance/MaintenanceController.php | 4 + src/Admin/Users/SecurityRolesBuilder.php | 4 + .../Authentication/JWTTokenRefreshService.php | 7 +- src/Api/Services/AuthenticationManager.php | 13 +- src/DB/Entity/Project/Program.php | 2 + src/DB/Entity/User/User.php | 3 + .../Project/ProgramRepository.php | 10 +- src/Project/Apk/JenkinsDispatcher.php | 8 +- .../CatrobatFile/CatrobatFileExtractor.php | 3 + src/Project/ProjectManager.php | 2 + src/Project/Scratch/AsyncHttpClient.php | 9 +- src/Security/Authentication/CookieService.php | 8 +- .../JwtRefresh/RefreshTokenService.php | 2 + .../OAuth/HwiOauthAccountConnector.php | 5 +- src/Security/OAuth/HwiOauthUserProvider.php | 12 +- src/System/Log/LoggerProcessor.php | 2 + src/System/Mail/MailerAdapter.php | 10 +- src/Translation/ItranslateApi.php | 15 +- src/User/UserManager.php | 13 +- .../OAuth/HwiOauthUserProviderTest.php | 5 +- .../PhpUnit/Translation/ItranslateApiTest.php | 2 +- 29 files changed, 168 insertions(+), 169 deletions(-) delete mode 100644 config/features.php create mode 100644 config/packages/bugsnag.php delete mode 100644 config/packages/bugsnag.yaml create mode 100644 config/packages/feature_flags.php diff --git a/config/features.php b/config/features.php deleted file mode 100644 index c6e39978a6..0000000000 --- a/config/features.php +++ /dev/null @@ -1,10 +0,0 @@ - false, - 'Sidebar-Studio-Link-Feature' => false, - 'GET_projects_elastica' => false, - 'remix-graph' => false, // performance issues - 'sign-apk' => false, // not allowed by Google - 'force-account-verification' => false, -]; diff --git a/config/packages/bugsnag.php b/config/packages/bugsnag.php new file mode 100644 index 0000000000..8be6279d7f --- /dev/null +++ b/config/packages/bugsnag.php @@ -0,0 +1,11 @@ +extension('bugsnag', [ + 'api_key' => '%env(BUGSNAG_API_KEY)%', + ]); +}; diff --git a/config/packages/bugsnag.yaml b/config/packages/bugsnag.yaml deleted file mode 100644 index 17d91d9934..0000000000 --- a/config/packages/bugsnag.yaml +++ /dev/null @@ -1,2 +0,0 @@ -bugsnag: - api_key: '%env(BUGSNAG_API_KEY)%' diff --git a/config/packages/feature_flags.php b/config/packages/feature_flags.php new file mode 100644 index 0000000000..426a9ac317 --- /dev/null +++ b/config/packages/feature_flags.php @@ -0,0 +1,20 @@ +parameters(); + $parameters->set( + 'feature_flags', + [ + 'Test-Flag' => false, + 'Sidebar-Studio-Link-Feature' => false, + 'GET_projects_elastica' => false, + 'remix-graph' => false, // performance issues + 'sign-apk' => false, // not allowed by Google + 'force-account-verification' => false, + ] + ); +}; diff --git a/config/packages/fos_elastica.php b/config/packages/fos_elastica.php index 5dd074a84c..6713d63483 100644 --- a/config/packages/fos_elastica.php +++ b/config/packages/fos_elastica.php @@ -17,10 +17,10 @@ 'url' => '%env(ELASTICSEARCH_URL)%', ], [ - 'host' => '%es_host%', + 'host' => '%env(ES_HOST)%', ], [ - 'port' => '%es_port%', + 'port' => '%env(ES_PORT)%', ], ], ], diff --git a/config/services.php b/config/services.php index 2783f3e1b3..9a4206cd44 100644 --- a/config/services.php +++ b/config/services.php @@ -51,7 +51,6 @@ use App\Admin\UserCommunication\Survey\AllSurveysAdmin; use App\Admin\Users\ReportedUsers\ReportedUsersAdmin; use App\Admin\Users\ReportedUsers\ReportedUsersController; -use App\Admin\Users\SecurityRolesBuilder; use App\Admin\Users\UserAdmin; use App\Admin\Users\UserDataReport\UserDataReportAdmin; use App\Admin\Users\UserDataReport\UserDataReportController; @@ -60,7 +59,6 @@ use App\Api\NotificationsApi; use App\Api\ProjectsApi; use App\Api\SearchApi; -use App\Api\Services\Authentication\JWTTokenRefreshService; use App\Api\Services\OverwriteController; use App\Api\StudioApi; use App\Api\UserApi; @@ -86,35 +84,14 @@ use App\DB\Entity\User\Comment\UserComment; use App\DB\Entity\User\Notifications\BroadcastNotification; use App\DB\Entity\User\User; -use App\Project\Apk\JenkinsDispatcher; -use App\Project\CatrobatFile\CatrobatFileExtractor; -use App\Project\EventListener\ExampleProjectImageListener; -use App\Project\EventListener\FeaturedProjectImageListener; -use App\Project\EventListener\ProjectPostUpdateNotifier; -use App\Project\Scratch\AsyncHttpClient; -use App\Security\Authentication\CookieService; -use App\Security\Authentication\JwtRefresh\RefreshTokenService; -use App\Security\OAuth\HwiOauthAccountConnector; -use App\Security\OAuth\HwiOauthUserProvider; -use App\System\Log\LoggerProcessor; -use App\Translation\GoogleTranslateApi; -use App\Translation\ItranslateApi; -use App\Translation\TranslationDelegate; -use App\User\EventListener\UserPostPersistNotifier; -use App\User\EventListener\UserPostUpdateNotifier; -use App\User\UserManager; use App\User\UserProvider; -use Google\Cloud\Translate\V2\TranslateClient; use Monolog\Formatter\LineFormatter; use OpenAPI\Server\Service\SerializerInterface; use Ramsey\Uuid\Doctrine\UuidGenerator; use Sonata\AdminBundle\Security\Acl\Permission\AdminPermissionMap; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; -use Symfony\Component\Dotenv\Command\DotenvDumpCommand; use Symfony\Component\Security\Core\User\UserProviderInterface; -use function Symfony\Component\DependencyInjection\Loader\Configurator\service; - return static function (ContainerConfigurator $containerConfigurator): void { $parameters = $containerConfigurator->parameters(); @@ -154,66 +131,34 @@ $parameters->set('catrobat.translations.project_cache_threshold', 15); $parameters->set('catrobat.upload.temp.dir', '%catrobat.pubdir%resources/tmp/uploads/'); $parameters->set('catrobat.upload.temp.path', 'resources/tmp/uploads/'); - $parameters->set('es_host', '%env(ES_HOST)%'); - $parameters->set('es_port', '%env(ES_PORT)%'); $parameters->set('dkim.private.key', '%kernel.project_dir%/.dkim/private.key'); $parameters->set('.container.dumper.inline_class_loader', true); - $parameters->set('features', '%kernel.project_dir%/config/features.php'); $parameters->set('reset_password.throttle_limit', 86400); $services = $containerConfigurator->services(); - - $services->set('security.acl.permission.map', AdminPermissionMap::class); - $services->defaults() - ->autowire() - ->autoconfigure() - ->bind('$program_finder', service('fos_elastica.finder.app_program')) - ->bind('$user_finder', service('fos_elastica.finder.app_user')) - ->bind('$refresh_token_ttl', '%lexik_jwt_authentication.token_ttl%') - ->bind('$dkim_private_key_path', '%dkim.private.key%') + ->autowire() // Automatically inject dependencies + ->autoconfigure() // Automatically configure services with tags (e.g., listeners) + + // Load all classes in the App namespace as services, making them available for DI ->load('App\\', __DIR__.'/../src/*') -// ->exclude([]) entity, system testing, ..? + + // Exclude files and directories not meant for DI to improve performance and avoid misconfigurations + ->exclude([ + __DIR__.'/../src/Kernel.php', // Exclude Kernel, as it's not a service + __DIR__.'/../src/System/Testing', // Exclude testing classes + __DIR__.'/../src/DB/Entity', // Exclude Doctrine entities from DI container + ]) ; + // Register additional vendor classes as services $services->set(UuidGenerator::class); $services->alias(Sonata\AdminBundle\SonataConfiguration::class, 'sonata.admin.configuration'); $services->alias(UserProviderInterface::class, UserProvider::class); + $services->set('security.acl.permission.map', AdminPermissionMap::class); - $services->set(SecurityRolesBuilder::class) - ->args([service('security.authorization_checker'), service('sonata.admin.configuration'), service('translator')]) - ; - - $services->set(MaintenanceController::class) - ->arg('$file_storage_dir', '%catrobat.file.storage.dir%') - ->arg('$apk_dir', '%catrobat.apk.dir%') - ->arg('$log_dir', '%catrobat.logs.dir%') - ; - - $services->set(JWTTokenRefreshService::class) - ->args([service('gesdinet.jwtrefreshtoken')]) - ; - - $services->set(JenkinsDispatcher::class)->args(['%jenkins%']); - $services->set(CookieService::class)->args(['%env(JWT_TTL)%', '%env(REFRESH_TOKEN_TTL)%']); - $services->set(RefreshTokenService::class)->args(['%env(REFRESH_TOKEN_TTL)%']); - $services->set(AsyncHttpClient::class)->args([['timeout' => 8.0], ['max_number_of_total_requests' => 12], ['max_number_of_concurrent_requests' => 4]]); - $services->set(CatrobatFileExtractor::class)->args(['%catrobat.file.extract.dir%', '%catrobat.file.extract.path%']); - $services->set(ProjectPostUpdateNotifier::class) - ->tag('doctrine.orm.entity_listener', ['event' => 'postUpdate', 'entity' => Program::class]) - ->tag('doctrine.orm.entity_listener', ['event' => 'postPersist', 'entity' => Program::class]) - ; - - $services->set(UserPostPersistNotifier::class) - ->tag('doctrine.orm.entity_listener', ['event' => 'postPersist', 'entity' => User::class]) - ; - - $services->set(UserPostUpdateNotifier::class) - ->tag('doctrine.orm.entity_listener', ['event' => 'postUpdate', 'entity' => User::class]) - ; - + // Custom formatting for our logs $logFormat = "[%%datetime%%] %%channel%%.%%level_name%%: %%message%% %%context%% %%extra%%\n[Client IP: %%extra.client_ip%%, User Agent: %%extra.user_agent%%, Session User: %%extra.session_user%%]"; - $services->set('monolog.formatter.catrobat_custom_formatter', LineFormatter::class) ->args([$logFormat, null, true, false]) ->call('includeStacktraces', [true]) @@ -222,19 +167,10 @@ ->call('setMaxLevelNameLength', [5]) ; - $services->set(LoggerProcessor::class) - ->tag('monolog.processor') - ; - - $services->set(FeaturedProjectImageListener::class) - ->tag('doctrine.orm.entity_listener') - ; - - $services->set(ExampleProjectImageListener::class) - ->tag('doctrine.orm.entity_listener') - ; - - // CAPI: Api service tagging - Custom Tags not yet supported by attributes + // ------------------------------------------------------------------------------------------------------------------- + // CAPI: Api service tagging + // - custom tags not yet supported by attributes + // $services->set(MediaLibraryApi::class)->tag('open_api_server.api', ['api' => 'mediaLibrary']); $services->set(ProjectsApi::class)->tag('open_api_server.api', ['api' => 'projects']); $services->set(UserApi::class)->tag('open_api_server.api', ['api' => 'user']); @@ -245,46 +181,8 @@ $services->set(StudioApi::class)->tag('open_api_server.api', ['api' => 'studio']); $services->set(OverwriteController::class); $services->alias(SerializerInterface::class, 'open_api_server.service.serializer'); - // end CAPI - - $services->set(HwiOauthUserProvider::class) - ->args([service(UserManager::class), ['google' => 'google_id', 'facebook' => 'facebook_id', 'apple' => 'apple_id']]) - ; - - $services->set(HwiOauthAccountConnector::class) - ->args([service(UserManager::class), ['google' => 'google_id', 'facebook' => 'facebook_id', 'apple' => 'apple_id']]) - ; - - $services->set(ItranslateApi::class) - ->lazy() - ->args([service('eight_points_guzzle.client.itranslate')]) - ; - - $services->set(GoogleTranslateApi::class) - ->lazy() - ->arg('$client', service(TranslateClient::class)) - ->arg('$short_text_length', 20) - ; - - $services->set(TranslateClient::class) - ->lazy() - ; - - $services->set(TranslationDelegate::class) - ->lazy() - ->arg('$apis', [ - service(ItranslateApi::class), - service(GoogleTranslateApi::class), - ]) - ; - - $services->set(DotenvDumpCommand::class) - ->tag('console.command') - ->arg('$projectDir', '%kernel.project_dir%/.env') - ->arg('$defaultEnv', '%kernel.environment%') - ; - // -------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- // Sonata admin service definitions: // - used by config/packages/sonata_admin.php to build the navigation tree // - each services defines a page in the admin interface - go to /admin @@ -614,7 +512,7 @@ ]) ; - // -------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- // Load additional services, or overwrite them for the test environment by defining them in services_test.php // if ('test' === $_SERVER['APP_ENV']) { diff --git a/config/services_test.php b/config/services_test.php index aa535a0bb7..ac93465fa0 100644 --- a/config/services_test.php +++ b/config/services_test.php @@ -3,7 +3,6 @@ declare(strict_types=1); use App\Project\Apk\JenkinsDispatcher; -use App\Project\CatrobatFile\CatrobatFileExtractor; use App\Security\TokenGenerator; use App\System\Testing\DataFixtures\ProjectDataFixtures; use App\System\Testing\DataFixtures\UserDataFixtures; @@ -47,7 +46,6 @@ $services->set('token_generator.inner', TokenGenerator::class); $services->set(TokenGenerator::class, ProxyTokenGenerator::class)->autowire(false)->args([service('token_generator.inner')]); $services->set(JenkinsDispatcher::class, FakeJenkinsDispatcher::class)->args(['%jenkins%']); - $services->set(CatrobatFileExtractor::class)->args(['%catrobat.file.extract.dir%', '%catrobat.file.extract.path%']); $services->set(TranslationDelegate::class, FakeTranslationDelegate::class); // Load additional test-only services: diff --git a/src/Admin/System/FeatureFlag/FeatureFlagManager.php b/src/Admin/System/FeatureFlag/FeatureFlagManager.php index 6bb0a26211..f7c767def5 100644 --- a/src/Admin/System/FeatureFlag/FeatureFlagManager.php +++ b/src/Admin/System/FeatureFlag/FeatureFlagManager.php @@ -6,7 +6,7 @@ use App\DB\Entity\FeatureFlag; use Doctrine\ORM\EntityManagerInterface; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\RequestStack; class FeatureFlagManager @@ -16,10 +16,11 @@ class FeatureFlagManager public function __construct( protected RequestStack $requestStack, protected EntityManagerInterface $entityManager, - protected ParameterBagInterface $parameter_bag, + #[Autowire('%feature_flags%')] + protected array $feature_flags, ) { if ($this->entityManager->getConnection()->isConnected()) { - $this->defaultFlags = include $parameter_bag->get('features'); + $this->defaultFlags = $this->feature_flags; $flagMap = []; foreach ($this->defaultFlags as $name => $value) { diff --git a/src/Admin/System/Maintenance/MaintenanceController.php b/src/Admin/System/Maintenance/MaintenanceController.php index 5b3aca12da..df4f912632 100644 --- a/src/Admin/System/Maintenance/MaintenanceController.php +++ b/src/Admin/System/Maintenance/MaintenanceController.php @@ -9,6 +9,7 @@ use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\NullOutput; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -22,8 +23,11 @@ class MaintenanceController extends CRUDController { public function __construct( protected KernelInterface $kernel, + #[Autowire('%catrobat.file.storage.dir%')] private readonly string $file_storage_dir, + #[Autowire('%catrobat.apk.dir%')] private readonly string $apk_dir, + #[Autowire('%catrobat.logs.dir%')] private readonly string $log_dir, ) { } diff --git a/src/Admin/Users/SecurityRolesBuilder.php b/src/Admin/Users/SecurityRolesBuilder.php index 9b5e9f965b..a6f3a3b704 100644 --- a/src/Admin/Users/SecurityRolesBuilder.php +++ b/src/Admin/Users/SecurityRolesBuilder.php @@ -5,6 +5,7 @@ namespace App\Admin\Users; use Sonata\AdminBundle\SonataConfiguration; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Contracts\Translation\TranslatorInterface; @@ -26,8 +27,11 @@ * @param array> $rolesHierarchy */ public function __construct( + #[Autowire(service: 'security.authorization_checker')] private AuthorizationCheckerInterface $authorizationChecker, + #[Autowire(service: 'sonata.admin.configuration')] private SonataConfiguration $configuration, + #[Autowire(service: 'translator')] private TranslatorInterface $translator, private array $rolesHierarchy = [], ) { diff --git a/src/Api/Services/Authentication/JWTTokenRefreshService.php b/src/Api/Services/Authentication/JWTTokenRefreshService.php index c2292f8dc2..4d8b2a0319 100644 --- a/src/Api/Services/Authentication/JWTTokenRefreshService.php +++ b/src/Api/Services/Authentication/JWTTokenRefreshService.php @@ -5,13 +5,16 @@ namespace App\Api\Services\Authentication; use Gesdinet\JWTRefreshTokenBundle\Service\RefreshToken; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; readonly class JWTTokenRefreshService { - public function __construct(private RefreshToken $refreshToken) - { + public function __construct( + #[Autowire(service: 'gesdinet.jwtrefreshtoken')] + private RefreshToken $refreshToken, + ) { } public function refresh(Request $request): Response diff --git a/src/Api/Services/AuthenticationManager.php b/src/Api/Services/AuthenticationManager.php index 2e0db3c85a..f375ddcded 100644 --- a/src/Api/Services/AuthenticationManager.php +++ b/src/Api/Services/AuthenticationManager.php @@ -10,13 +10,22 @@ use Gesdinet\JWTRefreshTokenBundle\Generator\RefreshTokenGeneratorInterface; use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenManagerInterface; use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; class AuthenticationManager { - public function __construct(private readonly TokenStorageInterface $token_storage, private readonly JWTTokenManagerInterface $jwt_manager, private readonly UserManager $user_manager, private readonly RefreshTokenGeneratorInterface $refresh_token_generator, private readonly RefreshTokenManagerInterface $refresh_manager, protected RequestHelper $request_helper, protected int $refresh_token_ttl) - { + public function __construct( + private readonly TokenStorageInterface $token_storage, + private readonly JWTTokenManagerInterface $jwt_manager, + private readonly UserManager $user_manager, + private readonly RefreshTokenGeneratorInterface $refresh_token_generator, + private readonly RefreshTokenManagerInterface $refresh_manager, + protected RequestHelper $request_helper, + #[Autowire('%lexik_jwt_authentication.token_ttl%')] + protected int $refresh_token_ttl, + ) { } /** diff --git a/src/DB/Entity/Project/Program.php b/src/DB/Entity/Project/Program.php index 001245478e..062c9b36da 100644 --- a/src/DB/Entity/Project/Program.php +++ b/src/DB/Entity/Project/Program.php @@ -16,6 +16,7 @@ use App\DB\Entity\User\User; use App\DB\EntityRepository\Project\ProgramRepository; use App\DB\Generator\MyUuidGenerator; +use App\Project\EventListener\ProjectPostUpdateNotifier; use App\Utils\TimeUtils; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -35,6 +36,7 @@ #[ORM\Index(name: 'debug_build_idx', columns: ['debug_build'])] #[ORM\Index(name: 'flavor_idx', columns: ['flavor'])] #[ORM\HasLifecycleCallbacks] +#[ORM\EntityListeners([ProjectPostUpdateNotifier::class])] #[ORM\Entity(repositoryClass: ProgramRepository::class)] class Program implements \Stringable { diff --git a/src/DB/Entity/User/User.php b/src/DB/Entity/User/User.php index 6ea131c51e..e877366c1e 100644 --- a/src/DB/Entity/User/User.php +++ b/src/DB/Entity/User/User.php @@ -15,6 +15,8 @@ use App\DB\Entity\User\RecommenderSystem\UserRemixSimilarityRelation; use App\DB\EntityRepository\User\UserRepository; use App\DB\Generator\MyUuidGenerator; +use App\User\EventListener\UserPostPersistNotifier; +use App\User\EventListener\UserPostUpdateNotifier; use App\Utils\CanonicalFieldsUpdater; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -34,6 +36,7 @@ #[ORM\Index(name: 'facebook_id_idx', columns: ['google_id'])] #[ORM\Index(name: 'apple_id_idx', columns: ['google_id'])] #[ORM\Entity(repositoryClass: UserRepository::class)] +#[ORM\EntityListeners([UserPostPersistNotifier::class, UserPostUpdateNotifier::class])] #[ORM\HasLifecycleCallbacks] class User implements UserInterface, PasswordAuthenticatedUserInterface { diff --git a/src/DB/EntityRepository/Project/ProgramRepository.php b/src/DB/EntityRepository/Project/ProgramRepository.php index efb0d9c40c..fe7557fef6 100644 --- a/src/DB/EntityRepository/Project/ProgramRepository.php +++ b/src/DB/EntityRepository/Project/ProgramRepository.php @@ -19,11 +19,17 @@ use Elastica\Query\BoolQuery; use Elastica\Query\MatchQuery; use FOS\ElasticaBundle\Finder\TransformedFinder; +use Symfony\Component\DependencyInjection\Attribute\Autowire; class ProgramRepository extends ServiceEntityRepository { - public function __construct(ManagerRegistry $managerRegistry, protected RequestHelper $app_request, protected FeatureFlagManager $feature_flag_manager, private readonly TransformedFinder $program_finder) - { + public function __construct( + ManagerRegistry $managerRegistry, + protected RequestHelper $app_request, + protected FeatureFlagManager $feature_flag_manager, + #[Autowire(service: 'fos_elastica.finder.app_program')] + private readonly TransformedFinder $program_finder, + ) { parent::__construct($managerRegistry, Program::class); } diff --git a/src/Project/Apk/JenkinsDispatcher.php b/src/Project/Apk/JenkinsDispatcher.php index 2d191c6937..081e91989a 100644 --- a/src/Project/Apk/JenkinsDispatcher.php +++ b/src/Project/Apk/JenkinsDispatcher.php @@ -4,6 +4,7 @@ namespace App\Project\Apk; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\Routing\RouterInterface; class JenkinsDispatcher @@ -15,8 +16,11 @@ class JenkinsDispatcher * * @throws \Exception */ - public function __construct(array $config, protected RouterInterface $router) - { + public function __construct( + #[Autowire('%jenkins%')] + array $config, + protected RouterInterface $router, + ) { if (!isset($config['url'])) { throw new \Exception(); } diff --git a/src/Project/CatrobatFile/CatrobatFileExtractor.php b/src/Project/CatrobatFile/CatrobatFileExtractor.php index dc5a27b66d..bbf1f19ea7 100644 --- a/src/Project/CatrobatFile/CatrobatFileExtractor.php +++ b/src/Project/CatrobatFile/CatrobatFileExtractor.php @@ -6,6 +6,7 @@ use App\Storage\FileHelper; use App\Utils\TimeUtils; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\File\File; class CatrobatFileExtractor @@ -16,7 +17,9 @@ class CatrobatFileExtractor * @throws \Exception */ public function __construct( + #[Autowire('%catrobat.file.extract.dir%')] string $extract_dir, + #[Autowire('%catrobat.file.extract.path%')] private readonly string $extract_path, ) { FileHelper::verifyDirectoryExists($extract_dir); diff --git a/src/Project/ProjectManager.php b/src/Project/ProjectManager.php index 19c4ab0f99..26fd23c3ce 100644 --- a/src/Project/ProjectManager.php +++ b/src/Project/ProjectManager.php @@ -40,6 +40,7 @@ use FOS\ElasticaBundle\Finder\TransformedFinder; use Psr\Log\LoggerInterface; use Symfony\Bundle\SecurityBundle\Security; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; @@ -64,6 +65,7 @@ public function __construct( protected ExtensionRepository $extension_repository, protected CatrobatFileSanitizer $file_sanitizer, protected NotificationManager $notification_service, + #[Autowire(service: 'fos_elastica.finder.app_program')] private readonly TransformedFinder $program_finder, private readonly ?UrlHelper $urlHelper, protected Security $security, diff --git a/src/Project/Scratch/AsyncHttpClient.php b/src/Project/Scratch/AsyncHttpClient.php index 88e1af17a8..78f7dea096 100644 --- a/src/Project/Scratch/AsyncHttpClient.php +++ b/src/Project/Scratch/AsyncHttpClient.php @@ -14,8 +14,15 @@ class AsyncHttpClient private ?array $scratch_info_data = null; - public function __construct(private readonly array $config = []) + public function __construct(private array $config = []) { + if (empty($this->config)) { + $this->config = [ + 'timeout' => 8.0, + 'max_number_of_total_requests' => 12, + 'max_number_of_concurrent_requests' => 4, + ]; + } $this->async_http_client = new Client($config); } diff --git a/src/Security/Authentication/CookieService.php b/src/Security/Authentication/CookieService.php index 9f7b54f424..3e29153977 100644 --- a/src/Security/Authentication/CookieService.php +++ b/src/Security/Authentication/CookieService.php @@ -4,12 +4,18 @@ namespace App\Security\Authentication; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\Routing\RouterInterface; readonly class CookieService { - public function __construct(private int $jwtTokenLifetime, private int $refreshTokenLifetime, private RouterInterface $router) + public function __construct( + #[Autowire('%env(JWT_TTL)%')] + private int $jwtTokenLifetime, + #[Autowire('%env(REFRESH_TOKEN_TTL)%')] + private int $refreshTokenLifetime, + private RouterInterface $router) { } diff --git a/src/Security/Authentication/JwtRefresh/RefreshTokenService.php b/src/Security/Authentication/JwtRefresh/RefreshTokenService.php index ee45b56f5b..ac8d55d44c 100644 --- a/src/Security/Authentication/JwtRefresh/RefreshTokenService.php +++ b/src/Security/Authentication/JwtRefresh/RefreshTokenService.php @@ -10,12 +10,14 @@ use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenInterface; use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenManagerInterface; use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpKernel\Event\KernelEvent; use Symfony\Component\HttpKernel\Event\ResponseEvent; class RefreshTokenService { public function __construct( + #[Autowire('%env(REFRESH_TOKEN_TTL)%')] protected int $refreshTokenLifetime, protected RefreshTokenManagerInterface $refresh_manager, protected UserManager $user_manager, diff --git a/src/Security/OAuth/HwiOauthAccountConnector.php b/src/Security/OAuth/HwiOauthAccountConnector.php index 26ed70afb4..6d9db166a9 100644 --- a/src/Security/OAuth/HwiOauthAccountConnector.php +++ b/src/Security/OAuth/HwiOauthAccountConnector.php @@ -13,11 +13,10 @@ class HwiOauthAccountConnector implements AccountConnectorInterface { - protected array $properties = ['identifier' => 'id']; + protected array $properties = ['identifier' => 'id', 'google' => 'google_id', 'facebook' => 'facebook_id', 'apple' => 'apple_id']; - public function __construct(protected UserManager $user_manager, array $properties) + public function __construct(protected UserManager $user_manager) { - $this->properties = array_merge($this->properties, $properties); } /** diff --git a/src/Security/OAuth/HwiOauthUserProvider.php b/src/Security/OAuth/HwiOauthUserProvider.php index 035f0f7bc4..af2b6af7e7 100644 --- a/src/Security/OAuth/HwiOauthUserProvider.php +++ b/src/Security/OAuth/HwiOauthUserProvider.php @@ -13,11 +13,17 @@ class HwiOauthUserProvider implements OAuthAwareUserProviderInterface { - protected array $properties = ['identifier' => 'id']; + protected array $properties = ['identifier' => 'id', 'google' => 'google_id', 'facebook' => 'facebook_id', 'apple' => 'apple_id']; - public function __construct(protected UserManager $user_manager, array $properties) + public function __construct(protected UserManager $user_manager) { - $this->properties = array_merge($this->properties, $properties); + } + + public function setProperties(array $properties): self + { + $this->properties = $properties; + + return $this; } /** diff --git a/src/System/Log/LoggerProcessor.php b/src/System/Log/LoggerProcessor.php index 2f769f2421..cd9374de39 100644 --- a/src/System/Log/LoggerProcessor.php +++ b/src/System/Log/LoggerProcessor.php @@ -6,11 +6,13 @@ use App\DB\Entity\User\User; use Monolog\LogRecord; +use Symfony\Component\DependencyInjection\Attribute\Autoconfigure; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +#[Autoconfigure(tags: ['monolog.processor'])] class LoggerProcessor { private const string ANON_USER = 'anonymous'; diff --git a/src/System/Mail/MailerAdapter.php b/src/System/Mail/MailerAdapter.php index 987a13c334..4a1de8c10a 100644 --- a/src/System/Mail/MailerAdapter.php +++ b/src/System/Mail/MailerAdapter.php @@ -6,6 +6,7 @@ use Psr\Log\LoggerInterface; use Symfony\Bridge\Twig\Mime\TemplatedEmail; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Mime\Address; @@ -16,8 +17,13 @@ class MailerAdapter { - public function __construct(protected MailerInterface $mailer, protected LoggerInterface $logger, protected Environment $templateWrapper, protected string $dkim_private_key_path) - { + public function __construct( + protected MailerInterface $mailer, + protected LoggerInterface $logger, + protected Environment $templateWrapper, + #[Autowire('%dkim.private.key%')] + protected string $dkim_private_key_path, + ) { } public function send(string $to, string $subject, string $template, array $context = []): void diff --git a/src/Translation/ItranslateApi.php b/src/Translation/ItranslateApi.php index d39e0136b8..75c6cdac68 100644 --- a/src/Translation/ItranslateApi.php +++ b/src/Translation/ItranslateApi.php @@ -7,7 +7,10 @@ use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; use Psr\Log\LoggerInterface; +use Symfony\Component\DependencyInjection\Attribute\Autoconfigure; +use Symfony\Component\DependencyInjection\Attribute\Autowire; +#[Autoconfigure(lazy: true)] class ItranslateApi implements TranslationApiInterface { private const array LONG_LANGUAGE_CODE = [ @@ -76,13 +79,15 @@ class ItranslateApi implements TranslationApiInterface 'zh-TW', ]; - private readonly string $api_key; - private readonly TranslationApiHelper $helper; - public function __construct(private readonly Client $client, private readonly LoggerInterface $logger) - { - $this->api_key = $_ENV['ITRANSLATE_API_KEY']; + public function __construct( + #[Autowire(service: 'eight_points_guzzle.client.itranslate')] + private readonly Client $client, + #[Autowire(env: 'ITRANSLATE_API_KEY')] + private readonly string $api_key, + private readonly LoggerInterface $logger, + ) { $this->helper = new TranslationApiHelper(self::LONG_LANGUAGE_CODE); } diff --git a/src/User/UserManager.php b/src/User/UserManager.php index 6c9dd5310d..bdd985a518 100644 --- a/src/User/UserManager.php +++ b/src/User/UserManager.php @@ -19,13 +19,22 @@ use Elastica\Query\QueryString; use Elastica\Util; use FOS\ElasticaBundle\Finder\TransformedFinder; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\UrlHelper; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; class UserManager { - public function __construct(protected CanonicalFieldsUpdater $canonicalFieldsUpdater, protected UserPasswordHasherInterface $userPasswordHasher, protected EntityManagerInterface $entity_manager, protected TransformedFinder $user_finder, protected ProjectManager $project_manager, protected UrlHelper $url_helper, protected UserRepository $user_repository) - { + public function __construct( + protected CanonicalFieldsUpdater $canonicalFieldsUpdater, + protected UserPasswordHasherInterface $userPasswordHasher, + protected EntityManagerInterface $entity_manager, + #[Autowire(service: 'fos_elastica.finder.app_user')] + protected TransformedFinder $user_finder, + protected ProjectManager $project_manager, + protected UrlHelper $url_helper, + protected UserRepository $user_repository, + ) { } public function decodeToken(string $token): array diff --git a/tests/PhpUnit/Security/OAuth/HwiOauthUserProviderTest.php b/tests/PhpUnit/Security/OAuth/HwiOauthUserProviderTest.php index 7322642043..ea34320134 100644 --- a/tests/PhpUnit/Security/OAuth/HwiOauthUserProviderTest.php +++ b/tests/PhpUnit/Security/OAuth/HwiOauthUserProviderTest.php @@ -68,11 +68,12 @@ class HwiOauthUserProviderTest extends WebTestCase protected function setUp(): void { static::createClient(); - $kernel = self::bootKernel(); + self::bootKernel(); $container = static::getContainer(); /** @var UserManager $user_manager */ $user_manager = $container->get(UserManager::class); - $this->object = new HwiOauthUserProvider($user_manager, $this->properties); + $this->object = new HwiOauthUserProvider($user_manager); + $this->object->setProperties($this->properties); } public function testInitialization(): void diff --git a/tests/PhpUnit/Translation/ItranslateApiTest.php b/tests/PhpUnit/Translation/ItranslateApiTest.php index 4474c347a1..743c04e781 100644 --- a/tests/PhpUnit/Translation/ItranslateApiTest.php +++ b/tests/PhpUnit/Translation/ItranslateApiTest.php @@ -33,7 +33,7 @@ protected function setUp(): void { $this->httpClient = $this->getMockBuilder(Client::class)->getMock(); - $this->api = new ItranslateApi($this->httpClient, $this->createMock(LoggerInterface::class)); + $this->api = new ItranslateApi($this->httpClient, 'fake', $this->createMock(LoggerInterface::class)); } /**