feat: upgrade to symfony 7.4

This commit is contained in:
2026-09-01 11:24:44 +02:00
parent 8ed20db90c
commit 2459af122f
41 changed files with 1527 additions and 1219 deletions
+1 -1
View File
@@ -45,7 +45,7 @@ class DownloadController extends AbstractController
}
}
$inline = (bool) $request->get('inline');
$inline = $request->query->getBoolean('inline');
$disposition = $inline ? ResponseHeaderBag::DISPOSITION_INLINE : ResponseHeaderBag::DISPOSITION_ATTACHMENT;
// mark file downloaded if applicable
@@ -27,13 +27,8 @@ class PasswordResetController extends AbstractController
->add('email', EmailType::class, [
'label' => 'E-Mail',
'constraints' => [
new NotBlank([
'message' => 'Bitte angeben',
]),
new Email([
'mode' => 'strict',
'message' => 'Ungültige E-Mail-Adresse',
]),
new NotBlank(message: 'Bitte angeben'),
new Email(mode: 'strict', message: 'Ungültige E-Mail-Adresse'),
],
])
->getForm()
+1 -1
View File
@@ -19,7 +19,7 @@ class DeleteController extends AbstractController
#[IsGranted('ROLE_USER')]
public function index(Request $request): JsonResponse
{
$uuid = $request->get('uuid');
$uuid = $request->query->get('uuid');
$this->uploadHandler->removeUploadFromSession($uuid);
+1 -1
View File
@@ -24,7 +24,7 @@ class Contact
#[ORM\Column(length: 255)]
#[Assert\NotBlank(message: 'Bitte gib die E-Mail-Adresse an')]
#[Assert\Email(message: 'Bitte gib eine gültige E-Mail-Adresse an', mode: 'strict')]
#[Assert\Email(message: 'Bitte gib eine gültige E-Mail-Adresse an', mode: Assert\Email::VALIDATION_MODE_STRICT)]
private ?string $email = null;
#[ORM\Column(length: 255)]
+1 -1
View File
@@ -18,7 +18,7 @@ class Communication
protected ?string $mobile = null;
#[ORM\Column(type: 'string', nullable: true)]
#[Assert\Email(mode: 'strict', message: 'Bitte gib eine gültige E-Mail-Adresse an', groups: ['profile'])]
#[Assert\Email(mode: Assert\Email::VALIDATION_MODE_STRICT, message: 'Bitte gib eine gültige E-Mail-Adresse an', groups: ['profile'])]
#[Assert\NotBlank(message: 'Bitte gib deine E-Mail-Adresse an', groups: ['profile'])]
protected ?string $email = null;
+1
View File
@@ -322,6 +322,7 @@ class User implements UserInterface, TimestampableEntityInterface, SoftDeletable
return 'app_teamer_index';
}
#[\Deprecated]
public function eraseCredentials(): void
{
}
+2 -2
View File
@@ -20,10 +20,10 @@ class UploadSessionListener
$uploadedFile = $event->getFile();
// Get upload uuid from Dropzone request
$uuid = $request->get('uuid');
$uuid = $request->request->get('uuid');
// Get original filename from Dropzone request
$originalFileName = $request->get('originalFilename');
$originalFileName = $request->request->get('originalFilename');
$upload = new UploadDto(
$uuid,
@@ -17,7 +17,7 @@ class UploadSessionValidationListener
$request = $event->getRequest();
$session = $request->getSession();
$uploadSessionId = $request->get(UploadHandler::SESSION_KEY);
$uploadSessionId = $request->request->get(UploadHandler::SESSION_KEY);
if (null === $uploadSessionId || false === $session->has(UploadHandler::SESSION_KEY)) {
throw new ValidationException('Invalid upload session');
+5
View File
@@ -24,6 +24,11 @@ class AbbreviatedDateType extends AbstractType
{
$resolver->setDefaults([
'input' => 'datetime_immutable',
// Explicit 'choice' preserves the pre-Symfony-7.4 default (7.4 flipped it to
// 'single_text'). This type needs the multi-field widget: the 'years' option at
// the call sites and FirstDayOfMonthDateTransformer both assume array submissions,
// and 'single_text' + the custom 'format' below throws under html5.
'widget' => 'choice',
'format' => 'y-MMMM-d',
]);
}
+1 -3
View File
@@ -17,9 +17,7 @@ class DeleteAccountType extends AbstractType
'label' => 'Ja, ich möchte meinen Account endgültig löschen',
'mapped' => false,
'constraints' => [
new IsTrue([
'message' => 'Bitte bestätige die Löschung',
]),
new IsTrue(message: 'Bitte bestätige die Löschung'),
],
]);
}
+1 -3
View File
@@ -21,9 +21,7 @@ class DisableUserType extends AbstractType
'data-action' => 'textarea-autosize#resize',
],
'constraints' => [
new NotBlank([
'message' => 'Bitte gib die Begründung ein',
]),
new NotBlank(message: 'Bitte gib die Begründung ein'),
],
])
->add('disabledReasonInternal', TextareaType::class, [
+1 -3
View File
@@ -30,9 +30,7 @@ class DispositionCallOffType extends AbstractType
'data-action' => 'textarea-autosize#resize',
],
'constraints' => [
new NotBlank([
'message' => 'Bitte gib die Begründung ein',
]),
new NotBlank(message: 'Bitte gib die Begründung ein'),
],
])
->add('sendNotification', CheckboxType::class, [
+1 -3
View File
@@ -58,9 +58,7 @@ class TeamerApplicationType extends AbstractType
'label' => 'Ich bestätige den abweichenden Buszustieg',
'mapped' => false,
'constraints' => [
new IsTrue([
'message' => 'Deine Bestätigung ist erforderlich',
]),
new IsTrue(message: 'Deine Bestätigung ist erforderlich'),
],
]);
}
+1 -3
View File
@@ -42,9 +42,7 @@ class TeamerDispositionType extends AbstractType
'label' => 'Ich bestätige, dass meine persönlichen Daten, Bankverbindung und Kontoinhaber korrekt sind',
'mapped' => false,
'constraints' => [
new IsTrue([
'message' => 'Deine Bestätigung ist erforderlich',
]),
new IsTrue(message: 'Deine Bestätigung ist erforderlich'),
],
]);
}
+3 -3
View File
@@ -98,8 +98,8 @@ abstract class AbstractMenuBuilder
$request = $this->requestStack->getMainRequest();
return [
$parameter => $request->get($parameter, $default),
'r' => $request->get('r'),
$parameter => $request->attributes->get($parameter, $default),
'r' => $request->query->get('r'),
];
}
@@ -123,7 +123,7 @@ abstract class AbstractMenuBuilder
$returnUrl = $options['return_url'] ?? null;
if (false === is_string($returnUrl) || '' === $returnUrl) {
$requestReturnUrl = $this->requestStack->getMainRequest()?->get('r');
$requestReturnUrl = $this->requestStack->getMainRequest()?->query->get('r');
$returnUrl = is_string($requestReturnUrl) && '' !== $requestReturnUrl
? rawurldecode($requestReturnUrl)
+2 -1
View File
@@ -3,6 +3,7 @@
namespace App\Security;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAccountStatusException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
@@ -34,7 +35,7 @@ class UserChecker implements UserCheckerInterface
}
}
public function checkPostAuth(UserInterface $user): void
public function checkPostAuth(UserInterface $user, ?TokenInterface $token = null): void
{
}
}
+2 -1
View File
@@ -6,6 +6,7 @@ use App\Entity\Application;
use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class ApplicationVoter extends Voter
@@ -29,7 +30,7 @@ class ApplicationVoter extends Voter
return in_array($attribute, [static::VIEW, static::WITHDRAW, static::DELETE, static::DISPOSE, static::STATUS]);
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool
{
/** @var User $user */
$user = $token->getUser();
+2 -1
View File
@@ -5,6 +5,7 @@ namespace App\Security\Voter;
use App\Entity\Assignment;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class AssignmentVoter extends Voter
@@ -28,7 +29,7 @@ class AssignmentVoter extends Voter
return in_array($attribute, [self::VIEW, self::EDIT, self::APPLY, self::PUBLISH, self::CALL_OFF], true);
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool
{
if (null === $token->getUser()) {
return false;
+2 -1
View File
@@ -6,6 +6,7 @@ use App\Entity\Availability;
use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class AvailabilityVoter extends Voter
@@ -26,7 +27,7 @@ class AvailabilityVoter extends Voter
return in_array($attribute, [static::ASSIGN, static::DELETE]);
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool
{
/** @var Availability $availability */
$availability = $subject;
+2 -1
View File
@@ -7,6 +7,7 @@ use App\Entity\Upload;
use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class DispositionVoter extends Voter
@@ -44,7 +45,7 @@ class DispositionVoter extends Voter
]);
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool
{
/** @var Disposition $disposition */
$disposition = $subject;
+2 -1
View File
@@ -5,6 +5,7 @@ namespace App\Security\Voter;
use App\Entity\FeedbackSet;
use App\Repository\JobProfileRepository;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class FeedbackSetVoter extends Voter
@@ -20,7 +21,7 @@ class FeedbackSetVoter extends Voter
return $subject instanceof FeedbackSet && static::DELETE === $attribute;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool
{
/** @var FeedbackSet $feedbackSet */
$feedbackSet = $subject;
+2 -1
View File
@@ -5,6 +5,7 @@ namespace App\Security\Voter;
use App\Entity\Feedback;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class FeedbackVoter extends Voter
@@ -18,7 +19,7 @@ class FeedbackVoter extends Voter
return $subject instanceof Feedback && in_array($attribute, [static::VIEW, static::PUBLISH, static::DELETE]);
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool
{
/** @var Feedback $feedback */
$feedback = $subject;
+2 -1
View File
@@ -5,6 +5,7 @@ namespace App\Security\Voter;
use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\User\UserInterface;
@@ -19,7 +20,7 @@ class ImpersonationVoter extends Voter
return 'CAN_IMPERSONATE' === $attribute && $subject instanceof UserInterface;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool
{
$currentUser = $token->getUser();
$targetUser = $subject;
+2 -1
View File
@@ -6,6 +6,7 @@ use App\Entity\License;
use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class LicenseVoter extends Voter
@@ -26,7 +27,7 @@ class LicenseVoter extends Voter
return in_array($attribute, [static::VIEW, static::DELETE]);
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool
{
if (true === $this->security->isGranted('ROLE_ADMINISTRATIVE')) {
return true;
+2 -1
View File
@@ -6,6 +6,7 @@ use App\Entity\Upload;
use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class UploadVoter extends Voter
@@ -29,7 +30,7 @@ class UploadVoter extends Voter
return in_array($attribute, [static::VIEW, static::DELETE, static::DOWNLOAD, static::CHECK, static::COMMENT]);
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool
{
/** @var Upload $upload */
$upload = $subject;
+2 -1
View File
@@ -5,6 +5,7 @@ namespace App\Security\Voter;
use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class UserVoter extends Voter
@@ -20,7 +21,7 @@ class UserVoter extends Voter
return self::EDIT === $attribute && $subject instanceof User;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool
{
$currentUser = $token->getUser();
$targetUser = $subject;
+1 -1
View File
@@ -25,7 +25,7 @@ class KnownPlaceholders extends Constraint
*/
public function __construct(array $allowed = [], ?string $message = null, ?array $groups = null, mixed $payload = null)
{
parent::__construct([], $groups, $payload);
parent::__construct(null, $groups, $payload);
$this->allowed = $allowed;
$this->message = $message ?? $this->message;