From 639fdd1e31548a4afeb8f6386877c3d5ae303d59 Mon Sep 17 00:00:00 2001 From: Martin Lagler Date: Wed, 10 Apr 2024 09:01:32 +0200 Subject: [PATCH] Add swiftmailer bc-layer and update pipeline --- .github/workflows/test-application.yaml | 11 ++++ Controller/AbstractController.php | 14 ++-- Controller/BlacklistItemController.php | 1 + Controller/ConfirmationController.php | 2 +- .../CommunityManagerCompilerPass.php | 1 - .../SuluCommunityExtension.php | 2 +- Entity/BlacklistItem.php | 4 -- EventListener/LastLoginListener.php | 2 +- Mail/Mail.php | 2 - Mail/MailFactory.php | 41 +++++++----- Manager/CommunityManagerInterface.php | 3 - Tests/Application/config/config.php | 2 +- .../Controller/RegistrationTest.php | 2 +- composer.json | 48 +++++++------- phpstan-baseline.neon | 66 ++++++++++++++++++- 15 files changed, 137 insertions(+), 64 deletions(-) diff --git a/.github/workflows/test-application.yaml b/.github/workflows/test-application.yaml index d4cb96d5..18820de3 100644 --- a/.github/workflows/test-application.yaml +++ b/.github/workflows/test-application.yaml @@ -47,6 +47,12 @@ jobs: env: SYMFONY_DEPRECATIONS_HELPER: weak + - php-version: '8.2' + lint: true + dependency-versions: 'highest' + tools: 'composer:v2' + env: + SYMFONY_DEPRECATIONS_HELPER: weak services: mysql: image: mysql:5.7 @@ -71,6 +77,11 @@ jobs: if: ${{ matrix.php-version == '7.2' }} run: composer remove php-cs-fixer/shim --dev --no-interaction + - name: Install additional lowest dependencies + if: ${{ matrix.dependency-versions == 'lowest' }} + run: | + composer require symfony/swiftmailer-bundle --no-interaction --no-update + - name: Install composer dependencies uses: ramsey/composer-install@v1 with: diff --git a/Controller/AbstractController.php b/Controller/AbstractController.php index dc4a08c9..148a1b16 100644 --- a/Controller/AbstractController.php +++ b/Controller/AbstractController.php @@ -88,12 +88,11 @@ protected function encodePassword(User $user, string $plainPassword): string $hasher = $this->container->get('?security.password_hasher'); return $hasher->hashPassword($user, $plainPassword); - } else { - /** @var \Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface $encoder */ - $encoder = $this->container->get('?security.password_encoder'); - - return $encoder->encodePassword($user, $plainPassword); } + /** @var \Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface $encoder */ + $encoder = $this->container->get('?security.password_encoder'); + + return $encoder->encodePassword($user, $plainPassword); } /** @@ -147,9 +146,6 @@ private function getTemplateAttributes(array $custom = []): array return $this->getTemplateAttributeResolver()->resolve($custom); } - /** - * @return User - */ public function getUser(): ?User { $user = parent::getUser(); @@ -190,7 +186,7 @@ private function addAddress(User $user): void /** * @param mixed[] $parameters */ - public function render(string $view, array $parameters = [], Response $response = null): Response + public function render(string $view, array $parameters = [], ?Response $response = null): Response { return parent::render( $view, diff --git a/Controller/BlacklistItemController.php b/Controller/BlacklistItemController.php index 1d46d1ce..a0a85cfe 100644 --- a/Controller/BlacklistItemController.php +++ b/Controller/BlacklistItemController.php @@ -34,6 +34,7 @@ * Provides admin-api for blacklist-items. * * @NamePrefix("sulu_community.") + * * @RouteResource("blacklist-item") */ class BlacklistItemController extends AbstractRestController implements ClassResourceInterface diff --git a/Controller/ConfirmationController.php b/Controller/ConfirmationController.php index 8316ae69..305dddc1 100644 --- a/Controller/ConfirmationController.php +++ b/Controller/ConfirmationController.php @@ -49,7 +49,7 @@ public function indexAction(Request $request, string $token): Response $redirectTo = $communityManager->getConfigTypeProperty(self::TYPE, Configuration::REDIRECT_TO); if ($redirectTo) { - if (0 === \strpos($redirectTo, '/')) { + if (\str_starts_with($redirectTo, '/')) { $url = \str_replace('{localization}', $request->getLocale(), $redirectTo); } else { $url = $this->getRouter()->generate($redirectTo); diff --git a/DependencyInjection/CompilerPass/CommunityManagerCompilerPass.php b/DependencyInjection/CompilerPass/CommunityManagerCompilerPass.php index bde28d33..5be3d11a 100644 --- a/DependencyInjection/CompilerPass/CommunityManagerCompilerPass.php +++ b/DependencyInjection/CompilerPass/CommunityManagerCompilerPass.php @@ -38,7 +38,6 @@ * }, * delete_user: bool, * } - * * @phpstan-type Config array{ * from: string|string[], * to: string|string[], diff --git a/DependencyInjection/SuluCommunityExtension.php b/DependencyInjection/SuluCommunityExtension.php index d456bdac..a219ffe1 100644 --- a/DependencyInjection/SuluCommunityExtension.php +++ b/DependencyInjection/SuluCommunityExtension.php @@ -153,7 +153,7 @@ public function prepend(ContainerBuilder $container): void 'orm' => [ 'dql' => [ 'string_functions' => [ - 'regexp' => RegExp::class, + 'regexp' => Regexp::class, ], ], ], diff --git a/Entity/BlacklistItem.php b/Entity/BlacklistItem.php index e7bfd6ee..d8d85ccf 100644 --- a/Entity/BlacklistItem.php +++ b/Entity/BlacklistItem.php @@ -44,10 +44,6 @@ class BlacklistItem */ private $type; - /** - * @param string $pattern - * @param string $type - */ public function __construct(?string $pattern = null, ?string $type = null) { $this->type = $type; diff --git a/EventListener/LastLoginListener.php b/EventListener/LastLoginListener.php index 97d60bd1..73f84587 100644 --- a/EventListener/LastLoginListener.php +++ b/EventListener/LastLoginListener.php @@ -66,7 +66,7 @@ public static function getSubscribedEvents() */ public function onRequest(RequestEvent $event): void { - if (!$event->isMasterRequest()) { + if (!$event->isMainRequest()) { return; } diff --git a/Mail/Mail.php b/Mail/Mail.php index 76f0d352..a4b7f52e 100644 --- a/Mail/Mail.php +++ b/Mail/Mail.php @@ -28,8 +28,6 @@ class Mail * user_template: string|null, * admin_template: string|null, * } $config - * - * @return Mail */ public static function create($from, $to, array $config): self { diff --git a/Mail/MailFactory.php b/Mail/MailFactory.php index 9fe6e98a..55c91f34 100644 --- a/Mail/MailFactory.php +++ b/Mail/MailFactory.php @@ -12,6 +12,7 @@ namespace Sulu\Bundle\CommunityBundle\Mail; use Sulu\Bundle\SecurityBundle\Entity\User; +use Symfony\Component\Mailer\Mailer; use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Email; @@ -25,7 +26,7 @@ class MailFactory implements MailFactoryInterface { /** - * @var MailerInterface + * @var MailerInterface|\Swift_Mailer */ protected $mailer; @@ -39,7 +40,7 @@ class MailFactory implements MailFactoryInterface */ protected $translator; - public function __construct(MailerInterface $mailer, Environment $twig, TranslatorInterface $translator) + public function __construct($mailer, Environment $twig, TranslatorInterface $translator) { $this->mailer = $mailer; $this->twig = $twig; @@ -72,7 +73,6 @@ public function sendEmails(Mail $mail, User $user, array $parameters = []): void } } - /** * Create and send email. * @@ -84,30 +84,41 @@ protected function sendEmail($from, $to, string $subject, string $template, arra { $body = $this->twig->render($template, $data); - $email = (new Email()) - ->subject($this->translator->trans($subject)) - ->from($this->getAddress($from)) - ->to($this->getAddress($to)) - ->html($body); + if ($this->mailer instanceof \Swift_Mailer) { + $email = $this->mailer->createMessage() + ->setSubject($this->translator->trans($subject)) + ->setFrom($from) + ->setTo($to) + ->setBody($body, 'text/html'); + } else { + if (!$this->getAddress($from) || !$this->getAddress($to)) { + return; + } + + $email = (new Email()) + ->subject($this->translator->trans($subject)) + ->from($this->getAddress($from)) + ->to($this->getAddress($to)) + ->html($body); + } $this->mailer->send($email); } /** - * Convert string/array email address to an Address object + * Convert string/array email address to an Address object. * - * @param $address - * @return Address + * @param mixed $address */ protected function getAddress($address): ?Address { $name = ''; - if (is_array($address)) { - if(empty($address)) { + if (\is_array($address)) { + if (empty($address)) { return null; - } else if (!isset($address['email'])) { - $email = $address[array_keys($address)[0]]; + } elseif (!isset($address['email'])) { + $email = $address[\array_keys($address)[0]]; } else { $email = $address['email']; $name = $address['name'] ?? ''; diff --git a/Manager/CommunityManagerInterface.php b/Manager/CommunityManagerInterface.php index f26e8a16..2fb27308 100644 --- a/Manager/CommunityManagerInterface.php +++ b/Manager/CommunityManagerInterface.php @@ -34,7 +34,6 @@ * }, * delete_user: bool, * } - * * @phpstan-type Config array{ * from: string|string[], * to: string|string[], @@ -137,8 +136,6 @@ public function sendEmails(string $type, User $user): void; /** * Save profile for given user. - * - * @return User */ public function saveProfile(User $user): ?User; } diff --git a/Tests/Application/config/config.php b/Tests/Application/config/config.php index 4fd9d10b..06445f03 100644 --- a/Tests/Application/config/config.php +++ b/Tests/Application/config/config.php @@ -13,7 +13,7 @@ use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\HttpKernel\Kernel; -return static function(PhpFileLoader $loader, ContainerBuilder $container) { +return static function (PhpFileLoader $loader, ContainerBuilder $container) { $context = $container->getParameter('sulu.context'); $loader->import('context_' . $context . '.yml'); diff --git a/Tests/Functional/Controller/RegistrationTest.php b/Tests/Functional/Controller/RegistrationTest.php index b806da89..f59ef473 100644 --- a/Tests/Functional/Controller/RegistrationTest.php +++ b/Tests/Functional/Controller/RegistrationTest.php @@ -181,7 +181,7 @@ public function testRegistrationBlacklistedBlocked(): void $this->assertNull($this->findUser()); } - public function testRegistrationBlacklistedRequested(): RawMessage + public function testRegistrationBlacklistedRequested(): ?RawMessage { $this->createBlacklistItem($this->getEntityManager(), '*@sulu.io', BlacklistItem::TYPE_REQUEST); diff --git a/composer.json b/composer.json index 032ba4c1..267f9c27 100644 --- a/composer.json +++ b/composer.json @@ -4,26 +4,27 @@ "type": "sulu-bundle", "license": "MIT", "require": { - "php": "^8.0 || ^8.1", + "php": "^7.2 || ^8.0", "beberlei/doctrineextensions": "^1.0", "doctrine/doctrine-bundle": "^1.10 || ^2.0", "doctrine/orm": "^2.5.3", - "doctrine/persistence": "^1.3 || ^2.0", + "doctrine/persistence": "^1.3 || ^2.0 || ^3.0", + "doctrine/phpcr-bundle": "^2 || ^3.0", "jms/serializer-bundle": "^3.3 || ^4.0", "massive/build-bundle": "^0.3 || ^0.4 || ^0.5", - "sulu/sulu": "^2.5.0 || ^2.6@dev", - "symfony/config": "^5.4 || ^6.0", - "symfony/console": "^5.4 || ^6.0", - "symfony/dependency-injection": "^5.4 || ^6.0", - "symfony/event-dispatcher": "^5.4 || ^6.0", - "symfony/form": "^5.4 || ^6.0", - "symfony/mailer": "^5.4 || ^6.0", - "symfony/framework-bundle": "^5.4 || ^6.0", - "symfony/http-foundation": "^5.4 || ^6.0", - "symfony/http-kernel": "^5.4 || ^6.0", - "symfony/intl": "^5.4 || ^6.0", - "symfony/routing": "^5.4 || ^6.0", - "symfony/security-bundle": "^5.4 || ^6.0" + "sulu/sulu": "^2.4.0 || ^2.6@dev", + "symfony/config": "^5.4 || ^6.2", + "symfony/console": "^5.4 || ^6.2", + "symfony/dependency-injection": "^5.4 || ^6.2", + "symfony/event-dispatcher": "^5.4 || ^6.2", + "symfony/form": "^5.4 || ^6.2", + "symfony/framework-bundle": "^5.4 || ^6.2", + "symfony/http-foundation": "^5.4 || ^6.2", + "symfony/http-kernel": "^5.4 || ^6.2", + "symfony/intl": "^5.4 || ^6.2", + "symfony/mailer": "^5.4 || ^6.2", + "symfony/routing": "^5.4 || ^6.2", + "symfony/security-bundle": "^5.4 || ^6.2" }, "require-dev": { "doctrine/data-fixtures": "^1.3.3", @@ -38,13 +39,13 @@ "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-symfony": "^1.0", "phpunit/phpunit": "^8.2", - "symfony/browser-kit": "^5.4 || ^6.0", - "symfony/css-selector": "^5.4 || ^6.0", - "symfony/dotenv": "^5.4 || ^6.0", + "symfony/browser-kit": "^5.4 || ^6.2", + "symfony/css-selector": "^5.4 || ^6.2", + "symfony/dotenv": "^5.4 || ^6.2", "symfony/monolog-bundle": "^3.1", - "symfony/phpunit-bridge": "^5.4 || ^6.0", - "symfony/stopwatch": "^5.4 || ^6.0", - "symfony/var-dumper": "^5.4 || ^6.0", + "symfony/phpunit-bridge": "^5.4 || ^6.2", + "symfony/stopwatch": "^5.4 || ^6.2", + "symfony/var-dumper": "^5.4 || ^6.2", "thecodingmachine/phpstan-strict-rules": "^1.0" }, "keywords": [ @@ -112,6 +113,9 @@ ] }, "config": { - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "php-http/discovery": true + } } } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 3c960b48..b730990f 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,5 +1,25 @@ parameters: ignoreErrors: + - + message: "#^Else branch is unreachable because previous condition is always true\\.$#" + count: 1 + path: Command/InitCommand.php + + - + message: "#^Call to method encodePassword\\(\\) on an unknown class Symfony\\\\Component\\\\Security\\\\Core\\\\Encoder\\\\UserPasswordEncoderInterface\\.$#" + count: 1 + path: Controller/AbstractController.php + + - + message: "#^Method Sulu\\\\Bundle\\\\CommunityBundle\\\\Controller\\\\AbstractController\\:\\:getSubscribedServices\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: Controller/AbstractController.php + + - + message: "#^PHPDoc tag @var for variable \\$encoder contains unknown class Symfony\\\\Component\\\\Security\\\\Core\\\\Encoder\\\\UserPasswordEncoderInterface\\.$#" + count: 1 + path: Controller/AbstractController.php + - message: "#^Strict comparison using \\=\\=\\= between true and array\\{from\\: array\\\\|string, to\\: array\\\\|string, webspace_key\\: string, role\\: string, firewall\\: string, maintenance\\: array\\{enabled\\: bool, template\\: string\\}, login\\: array\\{enabled\\: bool, template\\: string, service\\: string\\|null, embed_template\\: string, type\\: string, options\\: array, activate_user\\: bool, auto_login\\: bool, \\.\\.\\.\\}, registration\\: array\\{enabled\\: bool, template\\: string, service\\: string\\|null, embed_template\\: string, type\\: string, options\\: array, activate_user\\: bool, auto_login\\: bool, \\.\\.\\.\\}, \\.\\.\\.\\} will always evaluate to false\\.$#" count: 1 @@ -41,7 +61,7 @@ parameters: path: Controller/ConfirmationController.php - - message: "#^Parameter \\#1 \\$haystack of function strpos expects string, array\\\\|string\\> given\\.$#" + message: "#^Parameter \\#1 \\$haystack of function str_starts_with expects string, array\\\\|string\\> given\\.$#" count: 1 path: Controller/ConfirmationController.php @@ -250,6 +270,31 @@ parameters: count: 1 path: EventListener/MailListener.php + - + message: "#^Call to method createMessage\\(\\) on an unknown class Swift_Mailer\\.$#" + count: 1 + path: Mail/MailFactory.php + + - + message: "#^Call to method send\\(\\) on an unknown class Swift_Mailer\\.$#" + count: 1 + path: Mail/MailFactory.php + + - + message: "#^Class Swift_Mailer not found\\.$#" + count: 1 + path: Mail/MailFactory.php + + - + message: "#^Method Sulu\\\\Bundle\\\\CommunityBundle\\\\Mail\\\\MailFactory\\:\\:__construct\\(\\) has parameter \\$mailer with no type specified\\.$#" + count: 1 + path: Mail/MailFactory.php + + - + message: "#^Property Sulu\\\\Bundle\\\\CommunityBundle\\\\Mail\\\\MailFactory\\:\\:\\$mailer has unknown class Swift_Mailer as its type\\.$#" + count: 1 + path: Mail/MailFactory.php + - message: "#^Method Sulu\\\\Bundle\\\\CommunityBundle\\\\Manager\\\\CommunityManager\\:\\:getConfigProperty\\(\\) should return array\\{from\\: array\\\\|string, to\\: array\\\\|string, webspace_key\\: string, role\\: string, firewall\\: string, maintenance\\: array\\{enabled\\: bool, template\\: string\\}, login\\: array\\{enabled\\: bool, template\\: string, service\\: string\\|null, embed_template\\: string, type\\: string, options\\: array, activate_user\\: bool, auto_login\\: bool, \\.\\.\\.\\}, registration\\: array\\{enabled\\: bool, template\\: string, service\\: string\\|null, embed_template\\: string, type\\: string, options\\: array, activate_user\\: bool, auto_login\\: bool, \\.\\.\\.\\}, \\.\\.\\.\\} but returns array\\\\|string\\.$#" count: 1 @@ -275,6 +320,11 @@ parameters: count: 1 path: Manager/CommunityManager.php + - + message: "#^Parameter \\#2 \\$firewallName of class Symfony\\\\Component\\\\Security\\\\Core\\\\Authentication\\\\Token\\\\UsernamePasswordToken constructor expects string, array\\\\|string\\> given\\.$#" + count: 1 + path: Manager/CommunityManager.php + - message: "#^Parameter \\#2 \\$to of static method Sulu\\\\Bundle\\\\CommunityBundle\\\\Mail\\\\Mail\\:\\:create\\(\\) expects array\\\\|string, array\\\\|string\\> given\\.$#" count: 1 @@ -291,7 +341,17 @@ parameters: path: Manager/CommunityManager.php - - message: "#^Parameter \\#3 \\$roles of class Symfony\\\\Component\\\\Security\\\\Core\\\\Authentication\\\\Token\\\\UsernamePasswordToken constructor expects array\\, array\\\\|string\\> given\\.$#" + message: "#^If condition is always true\\.$#" count: 1 - path: Manager/CommunityManager.php + path: Tests/Application/config/config.php + + - + message: "#^Cannot call method getHtmlBody\\(\\) on Symfony\\\\Component\\\\Mime\\\\RawMessage\\|null\\.$#" + count: 3 + path: Tests/Functional/Controller/RegistrationTest.php + + - + message: "#^Cannot call method getTo\\(\\) on Symfony\\\\Component\\\\Mime\\\\RawMessage\\|null\\.$#" + count: 3 + path: Tests/Functional/Controller/RegistrationTest.php