From e7f3233dbc83385b93f46fc22a5b7f6b5f2bd570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Thu, 27 Aug 2026 10:16:03 +0200 Subject: [PATCH] fix: type mismatches and handle nullable values --- src/BusProNet/ResponseParser.php | 16 +++++++--- .../Admin/System/EmailText/EditController.php | 20 ++++-------- .../Admin/Teamer/MailingController.php | 6 ++-- .../Traits/AuthenticatedUserTrait.php | 20 ++++++++++++ src/Entity/User.php | 4 +-- src/EventListener/DeletedUserSubscriber.php | 9 ++++-- src/Repository/AssignmentRepository.php | 2 +- .../feedback_by_destination.html.twig | 32 ++++++------------- tests/Config/EmailTextCatalogTest.php | 5 ++- 9 files changed, 67 insertions(+), 47 deletions(-) create mode 100644 src/Controller/Traits/AuthenticatedUserTrait.php diff --git a/src/BusProNet/ResponseParser.php b/src/BusProNet/ResponseParser.php index c9081cd..a9c3037 100644 --- a/src/BusProNet/ResponseParser.php +++ b/src/BusProNet/ResponseParser.php @@ -31,12 +31,15 @@ class ResponseParser public function parseXmlString(string $type, string $content): mixed { $xml = simplexml_load_string($content); + if (false === $xml) { + throw new ResponseParserException('Unable to parse XML response'); + } // Override type when present in XML to catch error responses $responseType = $type; - $responseTypeXml = $xml->xpath('satz/@typ'); + $responseTypeXml = $xml->xpath('satz/@typ') ?: []; if (0 < count($responseTypeXml)) { - $responseType = (string) $xml->xpath('satz/@typ')[0]; + $responseType = (string) $responseTypeXml[0]; } switch ($responseType) { @@ -91,7 +94,12 @@ class ResponseParser $gender = 'W' === strtoupper($gender) ? 'F' : strtoupper($gender); $dateString = (string) $addressXml->geburtsdatum; - $dateOfBirth = empty($dateString) ? null : \DateTimeImmutable::createFromFormat('d.m.Y', $dateString); + $dateOfBirth = null; + + if ('' !== $dateString) { + $parsedDate = \DateTimeImmutable::createFromFormat('d.m.Y', $dateString); + $dateOfBirth = false === $parsedDate ? null : $parsedDate; + } $response = new ProfileResponse(); $response @@ -146,7 +154,7 @@ class ResponseParser $personId = (int) $xml->idperson; $updated = false; - $updatedXml = $xml->xpath('änderung|aenderung'); + $updatedXml = $xml->xpath('änderung|aenderung') ?: []; if (0 < count($updatedXml)) { $updated = 'true' === strtolower((string) $updatedXml[0]); } diff --git a/src/Controller/Admin/System/EmailText/EditController.php b/src/Controller/Admin/System/EmailText/EditController.php index 1c61bbc..f303b5d 100644 --- a/src/Controller/Admin/System/EmailText/EditController.php +++ b/src/Controller/Admin/System/EmailText/EditController.php @@ -32,18 +32,15 @@ class EditController extends AbstractController public function index(EmailTextKey $key, Request $request): Response { $definition = $this->catalog->get($key); - $emailText = $this->emailTextRepository->findByKey($key); - $isNew = null === $emailText; + $existing = $this->emailTextRepository->findByKey($key); // Editing a mail for the first time starts from the delivered wording rather than // from an empty form, so an admin adjusts a sentence instead of rewriting the mail. - if (true === $isNew) { - $emailText = (new EmailText($key)) - ->setSubject($definition->defaultSubject) - ->setHeadline($definition->defaultHeadline) - ->setBody($definition->defaultBody) - ; - } + $emailText = $existing ?? (new EmailText($key)) + ->setSubject($definition->defaultSubject) + ->setHeadline($definition->defaultHeadline) + ->setBody($definition->defaultBody) + ; $form = $this->createForm(EmailTextType::class, $emailText, [ 'definition' => $definition, @@ -51,10 +48,7 @@ class EditController extends AbstractController $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - if (true === $isNew) { - $this->entityManager->persist($emailText); - } - + $this->entityManager->persist($emailText); $this->entityManager->flush(); $this->addFlash('success', 'Der E-Mail-Text wurde aktualisiert'); diff --git a/src/Controller/Admin/Teamer/MailingController.php b/src/Controller/Admin/Teamer/MailingController.php index 4b22413..c862ecd 100644 --- a/src/Controller/Admin/Teamer/MailingController.php +++ b/src/Controller/Admin/Teamer/MailingController.php @@ -2,6 +2,7 @@ namespace App\Controller\Admin\Teamer; +use App\Controller\Traits\AuthenticatedUserTrait; use App\Controller\Traits\ReturnUrlTrait; use App\Email\MailBodyRenderer; use App\Form\TeamerMailingType; @@ -21,6 +22,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted; class MailingController extends AbstractController { + use AuthenticatedUserTrait; use ReturnUrlTrait; public function __construct( @@ -47,7 +49,7 @@ class MailingController extends AbstractController } if ($form->isSubmitted() && $form->isValid()) { - $this->mailingService->sendPreview($form->getData(), $this->getUser()); + $this->mailingService->sendPreview($form->getData(), $this->getAuthenticatedUser()); $this->addFlash('success', sprintf( 'Die Vorschau wurde an %s gesendet', @@ -164,7 +166,7 @@ class MailingController extends AbstractController */ private function renderPreview(TeamerMailingDto $mailingDto): array { - $values = $this->mailingService->placeholderValuesForUser($this->getUser()); + $values = $this->mailingService->placeholderValuesForUser($this->getAuthenticatedUser()); return [ 'subject' => $this->mailingService->render($mailingDto->getSubject(), $values), diff --git a/src/Controller/Traits/AuthenticatedUserTrait.php b/src/Controller/Traits/AuthenticatedUserTrait.php new file mode 100644 index 0000000..9e42145 --- /dev/null +++ b/src/Controller/Traits/AuthenticatedUserTrait.php @@ -0,0 +1,20 @@ +getUser(); + + if (null === $user) { + throw new AuthenticationException(); + } + + return $user; + } +} diff --git a/src/Entity/User.php b/src/Entity/User.php index fc82afa..638a4b7 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -172,7 +172,7 @@ class User implements UserInterface, TimestampableEntityInterface, SoftDeletable public function getInitials(): string { - $token = substr($this->getFirstName(), 0, 1).substr($this->getLastName(), 0, 2); + $token = substr($this->getFirstName() ?? '', 0, 1).substr($this->getLastName() ?? '', 0, 2); return strtoupper($token); } @@ -328,7 +328,7 @@ class User implements UserInterface, TimestampableEntityInterface, SoftDeletable public function getUserIdentifier(): string { - return $this->email; + return $this->email ?? ''; } public function getTeamer(): ?Teamer diff --git a/src/EventListener/DeletedUserSubscriber.php b/src/EventListener/DeletedUserSubscriber.php index f93e6f4..099b821 100644 --- a/src/EventListener/DeletedUserSubscriber.php +++ b/src/EventListener/DeletedUserSubscriber.php @@ -41,9 +41,14 @@ class DeletedUserSubscriber implements EventSubscriberInterface return; } - $user = $this->security->getUser(); + $currentUser = $this->security->getUser(); - if (false === $user instanceof User || false === $user->isDeleted()) { + if (false === $currentUser instanceof User) { + return; + } + + /** @var User $currentUser */ + if (false === $currentUser->isDeleted()) { return; } diff --git a/src/Repository/AssignmentRepository.php b/src/Repository/AssignmentRepository.php index 4b9c925..31b3d3b 100644 --- a/src/Repository/AssignmentRepository.php +++ b/src/Repository/AssignmentRepository.php @@ -158,7 +158,7 @@ class AssignmentRepository extends ServiceEntityRepository ; } - if (0 < count($filterDto->getHotels())) { + if (0 < count((array)$filterDto->getHotels())) { $constraints = []; foreach ($filterDto->getHotels() as $index => $hotel) { $constraints[] = $qb->expr()->like('destination.hotel', ':hotel'.$index); diff --git a/templates/administrative/statistics/feedback_by_destination.html.twig b/templates/administrative/statistics/feedback_by_destination.html.twig index 22f770d..7c61343 100644 --- a/templates/administrative/statistics/feedback_by_destination.html.twig +++ b/templates/administrative/statistics/feedback_by_destination.html.twig @@ -56,17 +56,11 @@ {{ stat.providedFeedbacks }} {{ stat.missingFeedbacks }} - - {{ stat.percentageProvided|number_format(1, ',', '.') }}% - + {{ stat.percentageProvided|number_format(1, ',', '.') }}% {% endfor %} @@ -87,17 +81,11 @@ {{ totalProvided }} {{ totalMissing }} - - {{ totalPercentage|number_format(1, ',', '.') }}% - + {{ totalPercentage|number_format(1, ',', '.') }}% diff --git a/tests/Config/EmailTextCatalogTest.php b/tests/Config/EmailTextCatalogTest.php index 0390c23..0c52eb2 100644 --- a/tests/Config/EmailTextCatalogTest.php +++ b/tests/Config/EmailTextCatalogTest.php @@ -93,6 +93,9 @@ class EmailTextCatalogTest extends KernelTestCase { self::bootKernel(); - return self::getContainer()->get(EmailTextCatalog::class); + /** @var EmailTextCatalog $catalog */ + $catalog = self::getContainer()->get(EmailTextCatalog::class); + + return $catalog; } }