feat: replace *Service suffix with role-based class names

This commit is contained in:
Björn Fromme
2026-04-16 13:34:54 +02:00
parent 0d2cc5b998
commit d1c92f2957
88 changed files with 435 additions and 435 deletions
@@ -14,7 +14,7 @@ use App\Form\Model\ParticipantDto;
* Used by EditController to determine if user modifications need to be saved.
* Also provides data extraction for draft persistence.
*/
class BookingFingerprintService
class BookingChangeTracker
{
/**
* Generates a fingerprint (hash) of all mutable booking data.
@@ -19,12 +19,12 @@ use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class BookingService
class BookingConfigurator
{
public function __construct(
private readonly BookingSessionService $bookingSessionService,
private readonly TravelDataService $travelDataService,
private readonly ParticipantEligibilityService $participantEligibilityService,
private readonly BookingSessionStore $bookingSessionService,
private readonly TravelDataProvider $travelDataService,
private readonly ParticipantEligibilityChecker $participantEligibilityService,
private readonly BookingStatusRuleRegistry $bookingStatusRuleRegistry,
private readonly AgencyLoader $agencyLoader,
#[Autowire('%default_booking_status%')]
+3 -3
View File
@@ -16,9 +16,9 @@ use App\Form\Model\BookingMutabilityDto;
class BookingEditContextFactory
{
public function __construct(
private readonly ParticipantCardDataService $participantCardDataService,
private readonly BookingSummaryDataService $summaryDataService,
private readonly TravelDataService $travelDataService,
private readonly ParticipantCardAssembler $participantCardDataService,
private readonly BookingSummaryAssembler $summaryDataService,
private readonly TravelDataProvider $travelDataService,
) {
}
@@ -23,7 +23,7 @@ use Symfony\Contracts\Cache\TagAwareCacheInterface;
* Encapsulates the logic for loading booking data from session or API,
* refreshing availability data, and restoring drafts when available.
*/
class BookingEditDataLoaderService
class BookingEditDataLoader
{
public const string CACHE_TAG_USER_PREFIX = 'user_bookings_';
@@ -32,10 +32,10 @@ class BookingEditDataLoaderService
public function __construct(
private readonly ApiClient $apiClient,
private readonly BookingDataProcessor $bookingDataProcessor,
private readonly BookingSessionService $bookingSessionService,
private readonly BookingFingerprintService $fingerprintService,
private readonly TravelDataService $travelDataService,
private readonly BookingEditDraftService $draftService,
private readonly BookingSessionStore $bookingSessionService,
private readonly BookingChangeTracker $fingerprintService,
private readonly TravelDataProvider $travelDataService,
private readonly BookingEditDraftManager $draftService,
private readonly AgencyLoader $agencyLoader,
private readonly Crypt $crypt,
private readonly TagAwareCacheInterface $bpnCache,
@@ -20,7 +20,7 @@ use App\Form\Service\Condition\TravelStartCutoffReachedCondition;
* immutable categories are reverted to the current booking state so update
* payloads cannot include blocked changes.
*/
class BookingEditSubmitGuardService
class BookingEditSubmitGuard
{
public function __construct(
private readonly BookingDataProcessor $bookingDataProcessor,
@@ -18,15 +18,15 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* Handles the final booking edit submission workflow.
*/
class BookingEditSubmitService
class BookingEditSubmitter
{
public function __construct(
private readonly ApiClient $apiClient,
private readonly BookingEditDataLoaderService $dataLoader,
private readonly BookingEditDraftService $draftService,
private readonly TravelDataService $travelDataService,
private readonly BookingEditSubmitGuardService $submitGuard,
private readonly BookingSessionService $bookingSessionService,
private readonly BookingEditDataLoader $dataLoader,
private readonly BookingEditDraftManager $draftService,
private readonly TravelDataProvider $travelDataService,
private readonly BookingEditSubmitGuard $submitGuard,
private readonly BookingSessionStore $bookingSessionService,
private readonly UrlGeneratorInterface $urlGenerator,
private readonly LoggerInterface $logger,
) {
@@ -16,7 +16,7 @@ use Symfony\Component\HttpFoundation\StreamedResponse;
* converting all service, room, and pickup IDs to human-readable labels using
* travel data loaded from XML files.
*/
class BookingExportService
class BookingExporter
{
private const COLUMN_HEADERS = [
'Vorname',
@@ -54,7 +54,7 @@ class BookingExportService
];
public function __construct(
private readonly TravelDataService $travelDataService,
private readonly TravelDataProvider $travelDataService,
) {
}
@@ -17,12 +17,12 @@ use App\Form\Model\ParticipantDto;
* coordinating room and participant calculations and handling service aggregation directly.
* Returns structured pricing data for display in forms and summaries.
*/
class BookingPriceCalculatorService
class BookingPriceCalculator
{
public function __construct(
private readonly RoomPricingCalculator $roomPricingCalculator,
private readonly ParticipantEligibilityService $participantEligibilityService,
private readonly InsuranceService $insuranceService,
private readonly ParticipantEligibilityChecker $participantEligibilityService,
private readonly InsuranceManager $insuranceService,
private readonly ParticipantPricingCalculator $participantPricingCalculator,
) {
}
@@ -12,10 +12,10 @@ use App\Form\Model\BookingDto;
/**
* Builds diagnostic payloads for booking price mismatches.
*/
class BookingPriceMismatchDiagnosticsService
class BookingPriceMismatchAnalyzer
{
public function __construct(
private readonly BookingPriceCalculatorService $priceCalculator,
private readonly BookingPricingAssembler $pricingAssembler,
) {
}
@@ -24,7 +24,7 @@ class BookingPriceMismatchDiagnosticsService
*/
public function buildDiagnostics(BookingDto $bookingCreateDto, BookingResponse $response): array
{
$pricingBreakdown = $this->priceCalculator->getPricingBreakdown($bookingCreateDto);
$pricingBreakdown = $this->pricingAssembler->getPricingBreakdown($bookingCreateDto);
$roomLines = $pricingBreakdown['rooms'] ?? [];
$serviceGroups = $pricingBreakdown['services'] ?? [];
@@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\Request;
* orchestration and pricing logic. It handles DTO persistence, baseline
* room snapshots, and return URL storage for the booking create/edit flows.
*/
class BookingSessionService
class BookingSessionStore
{
public const BOOKING_CREATE_KEY = 'booking_create';
public const BOOKING_CREATE_BASELINE_KEY = 'booking_create_baseline_snapshot';
@@ -24,7 +24,7 @@ class BookingSessionService
public const DEFAULT_RETURN_URL = 'https://www.ep-reisen.de';
public function __construct(
private readonly TravelDataService $travelDataService,
private readonly TravelDataProvider $travelDataService,
) {
}
@@ -5,7 +5,7 @@ namespace App\Service;
use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class CmsDataService
class CmsDataProvider
{
public function __construct(private readonly HttpClientInterface $httpClient, private readonly string $apiKey)
{
@@ -13,7 +13,7 @@ use Symfony\Component\HttpFoundation\RequestStack;
* to report error codes to support staff who can then search logs by the code.
* The code format is E-XXXXXXXX (8 uppercase alphanumeric characters in base36).
*/
class ErrorCodeService
class ErrorCodeGenerator
{
private ?string $errorCode = null;
private bool $hasError = false;
@@ -18,7 +18,7 @@ use Carbon\Carbon;
* Uses request-scoped instance-level caching to optimize performance for bookings with many participants.
* This service is stateless and has no dependencies to avoid circular dependency issues.
*/
class InsuranceService
class InsuranceManager
{
use SortByPriceTrait;
@@ -8,7 +8,7 @@ use App\Exception\NewsletterProviderException;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class MailjetNewsletterService
class MailjetApiClient
{
private const DEFAULT_BASE_URL = 'https://api.mailjet.com/v3/REST';
@@ -12,12 +12,12 @@ use App\Repository\NewsletterOptInConfirmationRepository;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
class NewsletterDoubleOptInService
class NewsletterManager
{
public function __construct(
private readonly NewsletterOptInConfirmationRepository $confirmationRepository,
private readonly EntityManagerInterface $entityManager,
private readonly MailjetNewsletterService $newsletterService,
private readonly MailjetApiClient $newsletterService,
private readonly Mailer $mailer,
private readonly LoggerInterface $logger,
private readonly int $newsletterConfirmationTtlHours,
@@ -16,10 +16,10 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
* Provides participant name, room assignment, and individual pricing for
* display in the card overview UI.
*/
class ParticipantCardDataService
class ParticipantCardAssembler
{
public function __construct(
private readonly BookingPriceCalculatorService $priceCalculator,
private readonly BookingPriceCalculator $priceCalculator,
private readonly ValidatorInterface $validator,
) {
}
@@ -21,7 +21,7 @@ use Psr\Log\LoggerInterface;
* the booking process for authenticated users. All errors are handled gracefully
* to ensure the booking flow is never interrupted.
*/
class ParticipantPrepopulationService
class ParticipantDataPrefiller
{
public const TOKEN = '#KUN#';
@@ -45,7 +45,7 @@ class ParticipantPrepopulationService
*
* @return ParticipantDto The prepopulated participant (or unchanged if API fails)
*/
public function prepopulateApplicantFromUser(User $user, ParticipantDto $applicant): ParticipantDto
public function prefillApplicantFromUser(User $user, ParticipantDto $applicant): ParticipantDto
{
try {
// Decrypt user password for API authentication
@@ -105,7 +105,7 @@ class ParticipantPrepopulationService
*
* Only prepopulates if the participant is fresh.
*/
public function shouldPrepopulateApplicant(ParticipantDto $applicant): bool
public function shouldPrefillApplicant(ParticipantDto $applicant): bool
{
return null === $applicant->firstName || '' === $applicant->firstName;
}
@@ -20,7 +20,7 @@ use Carbon\CarbonImmutable;
* Results are cached per request using instance-level arrays to avoid redundant calculations
* when checking the same participant multiple times.
*/
class ParticipantEligibilityService
class ParticipantEligibilityChecker
{
/** @var array<string, bool> Request-scoped cache for participant eligibility */
private array $eligibilityCache = [];
@@ -13,7 +13,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
/**
* Shared helpers for participant edit forms in create and edit booking flows.
*/
class ParticipantFormSupportService
class ParticipantFormSupport
{
public function __construct(
private readonly ParameterBagInterface $parameterBag,
@@ -12,7 +12,7 @@ use App\Form\Model\BookingDto;
* This service automatically assigns participants to selected rooms based on room capacity
* and quantity, eliminating the need for manual room selection in the booking flow.
*/
class RoomAssignmentService
class RoomAssigner
{
/**
* Determines if automatic room assignment should be performed.
@@ -27,10 +27,10 @@ use Symfony\Contracts\Cache\ItemInterface;
* prefer snapshots for performance and refresh those snapshots from XML during sync. It handles
* caching, error recovery, and data enrichment for both data sources.
*
* Mapping/lookup operations are delegated to TravelLookupService.
* Travel enrichment (XML details, insurances) is delegated to TravelEnrichmentService.
* Mapping/lookup operations are delegated to TravelIndex.
* Travel enrichment (XML details, insurances) is delegated to TravelEnricher.
*/
class TravelDataService
class TravelDataProvider
{
public const string SOURCE_LOCAL = 'local';
public const string SOURCE_REMOTE = 'remote';
@@ -42,9 +42,9 @@ class TravelDataService
private readonly ApiClient $apiClient,
private readonly CacheInterface $cache,
private readonly LoggerInterface $logger,
private readonly TravelSnapshotService $travelSnapshotService,
private readonly TravelLookupService $travelLookupService,
private readonly TravelEnrichmentService $travelEnrichmentService,
private readonly TravelSnapshotManager $travelSnapshotService,
private readonly TravelIndex $travelLookupService,
private readonly TravelEnricher $travelEnrichmentService,
private readonly bool $preferRemote = false,
private readonly bool $enableFallback = true,
) {
@@ -18,7 +18,7 @@ use Psr\Log\LoggerInterface;
* - Insurance patching applied to every local travel, replacing any stale snapshot data
* with freshly parsed, fully-hydrated Insurance objects from the XML loader
*/
class TravelEnrichmentService
class TravelEnricher
{
public function __construct(
private readonly PickupLoader $pickupLoader,
@@ -14,7 +14,7 @@ use Psr\Log\LoggerInterface;
* Consolidates code/ID mapping, dateId→productId resolution, and the combined XML+snapshot
* files map. All operations are read-only and never load full Travel objects.
*/
class TravelLookupService
class TravelIndex
{
/** @var array<int, array<string, mixed>>|null */
private ?array $filesMapCache = null;
@@ -22,7 +22,7 @@ class TravelLookupService
public function __construct(
private readonly TravelLoader $travelLoader,
private readonly HotelLoader $hotelLoader,
private readonly TravelSnapshotService $travelSnapshotService,
private readonly TravelSnapshotManager $travelSnapshotService,
private readonly LoggerInterface $logger,
) {
}
@@ -27,7 +27,7 @@ use Symfony\Component\Serializer\SerializerInterface;
* - Enrich snapshots with extended availability data.
* - Purge expired snapshot records.
*/
class TravelSnapshotService
class TravelSnapshotManager
{
public function __construct(
private readonly TravelSnapshotRepository $snapshotRepository,
@@ -13,7 +13,7 @@ use Psr\Log\LoggerInterface;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
class VoucherValidationService
class VoucherValidator
{
private const CACHE_TTL = 900; // 15 minutes
@@ -14,7 +14,7 @@ use League\Flysystem\FilesystemOperator;
* the request ID, sequence number, and type (request/response). This service
* allows finding and reading dumps by request ID.
*/
class XmlDumpService
class XmlDumpReader
{
public function __construct(
private readonly FilesystemOperator $xmlDump,