feat: upgrade to symfony 7.4
This commit is contained in:
@@ -26,7 +26,8 @@ APP_SECRET=b3cb0285aea14bbffb57df0cc3aa84f4
|
||||
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
|
||||
# DATABASE_URL="mysql://app:[email protected]:3306/app?serverVersion=8.0.32&charset=utf8mb4"
|
||||
# DATABASE_URL="mysql://app:[email protected]:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
|
||||
DATABASE_URL="postgresql://app:[email protected]:5432/app?serverVersion=15&charset=utf8"
|
||||
# DATABASE_URL="postgresql://app:[email protected]:5432/app?serverVersion=15&charset=utf8"
|
||||
DATABASE_URL="mysql://db:db@db:3306/db?serverVersion=8.4.5&charset=utf8mb4"
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
###> symfony/messenger ###
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
/.env.local.php
|
||||
/.env.*.local
|
||||
/config/secrets/prod/prod.decrypt.private.php
|
||||
/config/reference.php
|
||||
/public/bundles/
|
||||
/var/
|
||||
/vendor/
|
||||
|
||||
+37
-36
@@ -10,7 +10,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"php": ">=8.2",
|
||||
"ext-ctype": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-simplexml": "*",
|
||||
@@ -29,7 +29,7 @@
|
||||
"liip/imagine-bundle": "^2.11",
|
||||
"maennchen/zipstream-php": "^3.1",
|
||||
"nelmio/security-bundle": "^3.0",
|
||||
"nesbot/carbon": "^2.70",
|
||||
"nesbot/carbon": "^3.8",
|
||||
"oneup/uploader-bundle": "^5.1",
|
||||
"phpdocumentor/reflection-docblock": "^5.3",
|
||||
"phpoffice/phpspreadsheet": "^5.9",
|
||||
@@ -41,38 +41,38 @@
|
||||
"spatie/blink": "^1.4",
|
||||
"spatie/icalendar-generator": "^2.5",
|
||||
"symfony/apache-pack": "^1.0",
|
||||
"symfony/asset": "6.4.*",
|
||||
"symfony/console": "6.4.*",
|
||||
"symfony/doctrine-messenger": "6.4.*",
|
||||
"symfony/dotenv": "6.4.*",
|
||||
"symfony/expression-language": "6.4.*",
|
||||
"symfony/asset": "7.4.*",
|
||||
"symfony/console": "7.4.*",
|
||||
"symfony/doctrine-messenger": "7.4.*",
|
||||
"symfony/dotenv": "7.4.*",
|
||||
"symfony/expression-language": "7.4.*",
|
||||
"symfony/flex": "^2",
|
||||
"symfony/form": "6.4.*",
|
||||
"symfony/framework-bundle": "6.4.*",
|
||||
"symfony/http-client": "6.4.*",
|
||||
"symfony/intl": "6.4.*",
|
||||
"symfony/mailer": "6.4.*",
|
||||
"symfony/mailjet-mailer": "6.4.*",
|
||||
"symfony/mime": "6.4.*",
|
||||
"symfony/form": "7.4.*",
|
||||
"symfony/framework-bundle": "7.4.*",
|
||||
"symfony/http-client": "7.4.*",
|
||||
"symfony/intl": "7.4.*",
|
||||
"symfony/mailer": "7.4.*",
|
||||
"symfony/mailjet-mailer": "7.4.*",
|
||||
"symfony/mime": "7.4.*",
|
||||
"symfony/monolog-bundle": "^3.0",
|
||||
"symfony/notifier": "6.4.*",
|
||||
"symfony/process": "6.4.*",
|
||||
"symfony/property-access": "6.4.*",
|
||||
"symfony/property-info": "6.4.*",
|
||||
"symfony/runtime": "6.4.*",
|
||||
"symfony/security-bundle": "6.4.*",
|
||||
"symfony/serializer": "6.4.*",
|
||||
"symfony/notifier": "7.4.*",
|
||||
"symfony/process": "7.4.*",
|
||||
"symfony/property-access": "7.4.*",
|
||||
"symfony/property-info": "7.4.*",
|
||||
"symfony/runtime": "7.4.*",
|
||||
"symfony/security-bundle": "7.4.*",
|
||||
"symfony/serializer": "7.4.*",
|
||||
"symfony/stimulus-bundle": "^2.11",
|
||||
"symfony/string": "6.4.*",
|
||||
"symfony/translation": "6.4.*",
|
||||
"symfony/twig-bundle": "6.4.*",
|
||||
"symfony/uid": "6.4.*",
|
||||
"symfony/string": "7.4.*",
|
||||
"symfony/translation": "7.4.*",
|
||||
"symfony/twig-bundle": "7.4.*",
|
||||
"symfony/uid": "7.4.*",
|
||||
"symfony/ux-twig-component": "^2.16",
|
||||
"symfony/validator": "6.4.*",
|
||||
"symfony/web-link": "6.4.*",
|
||||
"symfony/validator": "7.4.*",
|
||||
"symfony/web-link": "7.4.*",
|
||||
"symfony/webpack-encore-bundle": "^2.0",
|
||||
"symfony/workflow": "6.4.*",
|
||||
"symfony/yaml": "6.4.*",
|
||||
"symfony/workflow": "7.4.*",
|
||||
"symfony/yaml": "7.4.*",
|
||||
"twig/extra-bundle": "^2.12|^3.0",
|
||||
"twig/html-extra": "^3.7",
|
||||
"twig/intl-extra": "^3.7",
|
||||
@@ -126,7 +126,7 @@
|
||||
"extra": {
|
||||
"symfony": {
|
||||
"allow-contrib": true,
|
||||
"require": "6.4.*"
|
||||
"require": "7.4.*"
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
@@ -135,13 +135,14 @@
|
||||
"friendsofphp/php-cs-fixer": "^3.84",
|
||||
"marcocesarato/php-conventional-changelog": "^1.17",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"symfony/browser-kit": "6.4.*",
|
||||
"symfony/css-selector": "6.4.*",
|
||||
"symfony/debug-bundle": "6.4.*",
|
||||
"rector/rector": "^2.6",
|
||||
"symfony/browser-kit": "7.4.*",
|
||||
"symfony/css-selector": "7.4.*",
|
||||
"symfony/debug-bundle": "7.4.*",
|
||||
"symfony/maker-bundle": "^1.0",
|
||||
"symfony/phpunit-bridge": "^6.3",
|
||||
"symfony/stopwatch": "6.4.*",
|
||||
"symfony/web-profiler-bundle": "6.4.*"
|
||||
"symfony/phpunit-bridge": "^7.4",
|
||||
"symfony/stopwatch": "7.4.*",
|
||||
"symfony/web-profiler-bundle": "7.4.*"
|
||||
},
|
||||
"version": "0.2.5"
|
||||
}
|
||||
|
||||
Generated
+1347
-1029
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,13 @@ doctrine:
|
||||
#server_version: '15'
|
||||
orm:
|
||||
auto_generate_proxy_classes: true
|
||||
# Keep implicit controller-argument entity resolution on (many actions type-hint
|
||||
# an entity against a matching {id}/{uuid} route param without #[MapEntity]).
|
||||
# Setting this explicitly silences the "default will flip to false" deprecation;
|
||||
# the separate "automapping is deprecated" notice stays until those actions are
|
||||
# migrated to #[MapEntity], which is its own task.
|
||||
controller_resolver:
|
||||
auto_mapping: true
|
||||
enable_lazy_ghost_objects: true
|
||||
report_fields_where_declared: true
|
||||
validate_xml_mapping: true
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
framework:
|
||||
property_info:
|
||||
# Keep the current (7.x) default; enabling the constructor extractor is a
|
||||
# behaviour change to evaluate on its own, not part of the 6.4 -> 7.4 bump.
|
||||
with_constructor_extractor: false
|
||||
@@ -1,4 +1,4 @@
|
||||
when@dev:
|
||||
_errors:
|
||||
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
|
||||
resource: '@FrameworkBundle/Resources/config/routing/errors.php'
|
||||
prefix: /_error
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
when@dev:
|
||||
web_profiler_wdt:
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/wdt.php'
|
||||
prefix: /_wdt
|
||||
|
||||
web_profiler_profiler:
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/profiler.php'
|
||||
prefix: /_profiler
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Config\RectorConfig;
|
||||
use Rector\Symfony\Set\SymfonySetList;
|
||||
|
||||
return RectorConfig::configure()
|
||||
->withPaths([
|
||||
__DIR__ . '/src',
|
||||
__DIR__ . '/tests',
|
||||
])
|
||||
->withSymfonyContainerXml(__DIR__ . '/var/cache/dev/App_KernelDevDebugContainer.xml')
|
||||
// Upgrade rules bound to the Symfony / Twig / Doctrine versions currently
|
||||
// installed (resolved from composer.lock). Bump the constraints and run
|
||||
// `composer update` before executing Rector so it targets 7.x.
|
||||
->withComposerBased(twig: true, doctrine: true, symfony: true)
|
||||
->withSets([
|
||||
SymfonySetList::CONFIGS,
|
||||
])
|
||||
->withSkip([
|
||||
// Generated migrations are frozen once shipped.
|
||||
__DIR__ . '/migrations',
|
||||
__DIR__ . '/src/**/DoctrineMigrations',
|
||||
])
|
||||
->withParallel();
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -322,6 +322,7 @@ class User implements UserInterface, TimestampableEntityInterface, SoftDeletable
|
||||
return 'app_teamer_index';
|
||||
}
|
||||
|
||||
#[\Deprecated]
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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',
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -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'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -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, [
|
||||
|
||||
@@ -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, [
|
||||
|
||||
@@ -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'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -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'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -116,6 +116,18 @@
|
||||
"config/routes/oneup_uploader.yaml"
|
||||
]
|
||||
},
|
||||
"phpstan/phpstan": {
|
||||
"version": "2.2",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes-contrib",
|
||||
"branch": "main",
|
||||
"version": "1.0",
|
||||
"ref": "5e490cc197fb6bb1ae22e5abbc531ddc633b6767"
|
||||
},
|
||||
"files": [
|
||||
"phpstan.dist.neon"
|
||||
]
|
||||
},
|
||||
"phpunit/phpunit": {
|
||||
"version": "9.6",
|
||||
"recipe": {
|
||||
@@ -178,6 +190,18 @@
|
||||
".env"
|
||||
]
|
||||
},
|
||||
"symfony/form": {
|
||||
"version": "7.4",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "7.2",
|
||||
"ref": "7d86a6723f4a623f59e2bf966b6aad2fc461d36b"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/csrf.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/framework-bundle": {
|
||||
"version": "6.3",
|
||||
"recipe": {
|
||||
@@ -278,6 +302,18 @@
|
||||
"tests/bootstrap.php"
|
||||
]
|
||||
},
|
||||
"symfony/property-info": {
|
||||
"version": "7.4",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "7.3",
|
||||
"ref": "dae70df71978ae9226ae915ffd5fad817f5ca1f7"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/property_info.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/routing": {
|
||||
"version": "6.3",
|
||||
"recipe": {
|
||||
|
||||
@@ -71,14 +71,12 @@
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block label %}
|
||||
{% apply spaceless %}
|
||||
{% if item.extras.icon is defined %}
|
||||
{{ icon(item.extras.icon, 'h-5 w-5 shrink-0 text-gray-400') }}
|
||||
<span class="flex-1">{{ item.label|raw }}</span>
|
||||
{% else %}
|
||||
{{ item.label|raw }}
|
||||
{% endif %}
|
||||
{% endapply %}
|
||||
{% endblock %}
|
||||
{% block label -%}
|
||||
{% if item.extras.icon is defined -%}
|
||||
{{ icon(item.extras.icon, 'h-5 w-5 shrink-0 text-gray-400') -}}
|
||||
<span class="flex-1">{{ item.label|raw }}</span>
|
||||
{%- else -%}
|
||||
{{ item.label|raw }}
|
||||
{%- endif %}
|
||||
{%- endblock %}
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
{% apply spaceless %}
|
||||
{% for message in messages %}
|
||||
{% if message is iterable %}
|
||||
{% set message = message.id | trans(message.parameters | default({}), message.domain | default(null), message.locale | default(null)) | raw %}
|
||||
{% else %}
|
||||
{% set message = message | trans | raw %}
|
||||
{% endif %}
|
||||
<div {{ stimulus_controller('toast', { 'text': message, 'class': 'toastify--' ~ level}) }}{{ qa_attribute('toast', level)}}></div>
|
||||
{% endfor %}
|
||||
{% endapply %}
|
||||
{% for message in messages -%}
|
||||
{% if message is iterable %}
|
||||
{%- set message = message.id | trans(message.parameters | default({}), message.domain | default(null), message.locale | default(null)) | raw %}
|
||||
{%- else %}
|
||||
{%- set message = message | trans | raw %}
|
||||
{%- endif -%}
|
||||
<div {{ stimulus_controller('toast', { 'text': message, 'class': 'toastify--' ~ level}) }}{{ qa_attribute('toast', level)}}></div>
|
||||
{%- endfor %}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Migrations;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* Version20260820000000 rewrites the wording of mails that go out to every teamer, and it
|
||||
* runs exactly once with nobody watching, so the patterns it does that with are pinned
|
||||
* here. The migration is not autoloaded (only src/ and tests/ are), hence the require.
|
||||
*/
|
||||
class EmphasisRewriteTest extends TestCase
|
||||
{
|
||||
private string $single;
|
||||
private string $double;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
require_once __DIR__.'/../../migrations/Version20260820000000.php';
|
||||
|
||||
$reflection = new \ReflectionClass(\DoctrineMigrations\Version20260820000000::class);
|
||||
|
||||
$this->single = $reflection->getConstant('SINGLE_EMPHASIS');
|
||||
$this->double = $reflection->getConstant('DOUBLE_EMPHASIS');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider upCases
|
||||
*/
|
||||
public function testTheUpwardRewrite(string $before, string $after): void
|
||||
{
|
||||
$this->assertSame($after, preg_replace($this->single, '**$1**', $before));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<string, array{string, string}>
|
||||
*/
|
||||
public static function upCases(): iterable
|
||||
{
|
||||
yield 'one word' => ['Das ist *wichtig*', 'Das ist **wichtig**'];
|
||||
yield 'several words' => ['*Dein Einsatz wurde angenommen!*', '**Dein Einsatz wurde angenommen!**'];
|
||||
yield 'around a placeholder' => ['*{destination}*', '**{destination}**'];
|
||||
yield 'already bold' => ['Das ist **wichtig**', 'Das ist **wichtig**'];
|
||||
yield 'escaped asterisk' => ['Ein Sternchen: \*', 'Ein Sternchen: \*'];
|
||||
// Whitespace next to a marker means it is not emphasis - CommonMark's own rule, and
|
||||
// the reason arithmetic and stray asterisks come through untouched.
|
||||
yield 'multiplication' => ['5 * 3 = 15', '5 * 3 = 15'];
|
||||
yield 'spaced asterisks' => ['a * b * c', 'a * b * c'];
|
||||
yield 'bullet at line start' => ["* Ausweis\n* Bankverbindung", "* Ausweis\n* Bankverbindung"];
|
||||
yield 'not across lines' => ["*offen\ngeblieben*", "*offen\ngeblieben*"];
|
||||
}
|
||||
|
||||
public function testTheRewriteIsReversible(): void
|
||||
{
|
||||
$before = 'Das ist *wichtig* und *{destination}* auch';
|
||||
|
||||
$up = preg_replace($this->single, '**$1**', $before);
|
||||
|
||||
$this->assertSame($before, preg_replace($this->double, '*$1*', $up));
|
||||
}
|
||||
|
||||
/**
|
||||
* The delivered defaults were rewritten by hand in the same commit, so nothing should
|
||||
* be left in them for the migration to find. Read through the parser rather than off
|
||||
* the raw file: the header comment documents *kursiv* on purpose.
|
||||
*/
|
||||
public function testTheDeliveredDefaultsAreAlreadyMigrated(): void
|
||||
{
|
||||
$texts = Yaml::parseFile(__DIR__.'/../../config/email_texts.yaml')['texts'];
|
||||
|
||||
foreach ($texts as $key => $text) {
|
||||
$body = (string) ($text['body'] ?? '');
|
||||
|
||||
$this->assertSame(
|
||||
$body,
|
||||
preg_replace($this->single, '**$1**', $body),
|
||||
sprintf('Default wording of "%s" still carries single-asterisk emphasis', $key)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,7 @@ class TeamerMailingDraftHandlerTest extends TestCase
|
||||
$request = new Request();
|
||||
$request->setSession(new Session(new MockArraySessionStorage()));
|
||||
|
||||
$requestStack = new RequestStack();
|
||||
$requestStack->push($request);
|
||||
$requestStack = new RequestStack([$request]);
|
||||
|
||||
$this->handler = new TeamerMailingDraftHandler($requestStack);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user