feat: upgrade project to symfony 7.4

This commit is contained in:
Björn Fromme
2026-08-31 09:03:44 +02:00
parent c1fa08fed0
commit 010cfe56b2
29 changed files with 1391 additions and 1133 deletions
+23
View File
@@ -0,0 +1,23 @@
<?php
namespace App\BusProNet;
use Symfony\Component\DomCrawler\Crawler;
/**
* Builds a Crawler over BusPro's XML payloads.
*
* The Crawler constructor parses its content as HTML5, which flattens the
* nesting BusPro's exports and API responses rely on, so XML has to be added
* through addXmlContent() instead.
*/
final class XmlCrawlerFactory
{
public static function create(string $xml): Crawler
{
$crawler = new Crawler();
$crawler->addXmlContent($xml);
return $crawler;
}
}
+2 -1
View File
@@ -4,6 +4,7 @@ namespace App\BusProNet\XmlLoader;
use App\BusProNet\Model\Hotel;
use App\BusProNet\Model\Travel;
use App\BusProNet\XmlCrawlerFactory;
use App\Exception\HotelNotFoundException;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\DomCrawler\Crawler;
@@ -73,7 +74,7 @@ class HotelLoader extends AbstractLoader
{
$xml = $this->xmlExport->read($filename);
return new Crawler($xml);
return XmlCrawlerFactory::create($xml);
}
public function parseXml(Crawler $node): Hotel
+2 -1
View File
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\BusProNet\XmlLoader;
use App\BusProNet\Model\Insurance;
use App\BusProNet\XmlCrawlerFactory;
use App\BusProNet\XmlParser\InsuranceParser;
use League\Flysystem\FilesystemOperator;
use Psr\Cache\InvalidArgumentException;
@@ -50,6 +51,6 @@ class InsuranceLoader extends AbstractLoader
{
$xml = $this->xmlExport->read($filename);
return new Crawler($xml);
return XmlCrawlerFactory::create($xml);
}
}
+2 -1
View File
@@ -4,6 +4,7 @@ namespace App\BusProNet\XmlLoader;
use App\BusProNet\Model\Pickup;
use App\BusProNet\Model\Travel;
use App\BusProNet\XmlCrawlerFactory;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Contracts\Cache\ItemInterface;
@@ -46,7 +47,7 @@ class PickupLoader extends AbstractLoader
{
$xml = $this->xmlExport->read($filename);
return new Crawler($xml);
return XmlCrawlerFactory::create($xml);
}
public function parseXml(Crawler $node): Pickup
+3 -2
View File
@@ -7,6 +7,7 @@ use App\BusProNet\Model\MutableData;
use App\BusProNet\Model\ServiceAvailabilityResponse;
use App\BusProNet\Model\Travel;
use App\BusProNet\Utility\DateCodeUtility;
use App\BusProNet\XmlCrawlerFactory;
use App\BusProNet\XmlParser\TravelParser;
use App\Exception\HotelNotInTravelException;
use App\Exception\TravelNotFoundException;
@@ -71,7 +72,7 @@ class TravelLoader extends AbstractLoader
foreach ($xmlFiles as $file) {
$xml = $this->xmlExport->read($file->path());
$crawler = new Crawler($xml);
$crawler = XmlCrawlerFactory::create($xml);
$travelDataNodes = $crawler->filterXPath('//reisen/reise/termin');
$travelDataNodes->each(function (Crawler $node) use (&$mapping, $hotels, $file) {
@@ -218,7 +219,7 @@ class TravelLoader extends AbstractLoader
{
try {
$xml = $this->xmlExport->read($filename);
$crawler = new Crawler($xml);
$crawler = XmlCrawlerFactory::create($xml);
$travelNode = $crawler->filterXPath(sprintf('//reise/termin[@idbuspro="%d"]', $dateId));
@@ -4,7 +4,7 @@ namespace App\BusProNet\XmlParser;
use App\BusProNet\ApiClient;
use App\BusProNet\Exception\ResponseParserException;
use Symfony\Component\DomCrawler\Crawler;
use App\BusProNet\XmlCrawlerFactory;
class ApiResponseParser extends AbstractParser
{
@@ -14,7 +14,7 @@ class ApiResponseParser extends AbstractParser
/** @param array<string, mixed> $additionalArgs */
public function parseXmlString(string $type, string $xml, array $additionalArgs = []): mixed
{
$crawler = new Crawler($xml);
$crawler = XmlCrawlerFactory::create($xml);
if (0 === $crawler->count()) {
throw new ResponseParserException('Empty response received from server');
@@ -5,7 +5,8 @@ declare(strict_types=1);
namespace App\Security\Voter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
/**
@@ -16,7 +17,7 @@ class AdministrativeAccessVoter extends Voter
public const ADMINISTRATIVE_ACCESS = 'ADMINISTRATIVE_ACCESS';
public function __construct(
private readonly AuthorizationCheckerInterface $authorizationChecker,
private readonly AccessDecisionManagerInterface $accessDecisionManager,
) {
}
@@ -25,9 +26,9 @@ class AdministrativeAccessVoter extends Voter
return self::ADMINISTRATIVE_ACCESS === $attribute;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool
{
return $this->authorizationChecker->isGranted('ROLE_ADMIN')
|| $this->authorizationChecker->isGranted('ROLE_GROUPS_MANAGER');
return $this->accessDecisionManager->decide($token, ['ROLE_ADMIN'])
|| $this->accessDecisionManager->decide($token, ['ROLE_GROUPS_MANAGER']);
}
}
+2 -1
View File
@@ -7,6 +7,7 @@ namespace App\Security\Voter;
use App\BusProNet\Model\Booking;
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;
/**
@@ -32,7 +33,7 @@ class BookingVoter extends Voter
return $subject instanceof Booking;
}
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|null $user */
$user = $token->getUser();