From bef18971c36699ff5f030ee2d9d1e0895583e05e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Mon, 14 Jul 2025 17:15:15 +0200 Subject: [PATCH] wip: booking process --- composer.lock | 251 ++++++------------ src/BusProNet/ApiClient.php | 8 +- src/BusProNet/Constants.php | 22 ++ .../DataProcessor/BookingDataProcessor.php | 13 +- src/BusProNet/Model/Address.php | 27 +- src/BusProNet/Model/Availability.php | 17 ++ src/BusProNet/Model/BankAccount.php | 8 + src/BusProNet/Model/BaseData.php | 20 ++ src/BusProNet/Model/Booking.php | 105 +++++++- src/BusProNet/Model/BookingUpdate.php | 8 + src/BusProNet/Model/Communication.php | 23 +- src/BusProNet/Model/Country.php | 8 + src/BusProNet/Model/CrmAction.php | 8 + src/BusProNet/Model/CrmAttributes.php | 8 + src/BusProNet/Model/CrmSelection.php | 9 + src/BusProNet/Model/CrmSelectionGroup.php | 27 +- src/BusProNet/Model/Error.php | 12 + src/BusProNet/Model/File.php | 8 + src/BusProNet/Model/Guide.php | 8 + src/BusProNet/Model/Hotel.php | 9 + src/BusProNet/Model/MutableData.php | 8 + src/BusProNet/Model/Notification.php | 17 ++ src/BusProNet/Model/PersonalData.php | 56 +++- src/BusProNet/Model/Pickup.php | 9 + src/BusProNet/Model/Room.php | 9 + src/BusProNet/Model/Service.php | 25 +- src/BusProNet/Model/Surcharge.php | 8 + src/BusProNet/Model/Travel.php | 62 +++++ src/BusProNet/XmlLoader/TravelLoader.php | 15 +- src/BusProNet/XmlParser/BookingParser.php | 7 +- src/BusProNet/XmlParser/BookingsParser.php | 2 +- src/BusProNet/XmlParser/ServicesParser.php | 3 +- src/Controller/Booking/CreateController.php | 50 ++++ src/Controller/Booking/EditController.php | 4 +- src/Controller/RegistrationController.php | 4 +- src/Form/BookingType.php | 19 +- .../{BookingData.php => BookingEditDto.php} | 16 +- ...ParticipantData.php => ParticipantDto.php} | 2 +- ...gistrationData.php => RegistrationDto.php} | 2 +- src/Form/ParticipantType.php | 19 +- src/Form/RegistrationType.php | 4 +- .../Constraints/BookingValidator.php | 4 +- .../Constraints/ParticipantValidator.php | 10 +- templates/booking/edit.html.twig | 2 +- templates/booking/index.html.twig | 2 +- 45 files changed, 688 insertions(+), 270 deletions(-) create mode 100644 src/BusProNet/Constants.php create mode 100644 src/Controller/Booking/CreateController.php rename src/Form/Model/{BookingData.php => BookingEditDto.php} (87%) rename src/Form/Model/{ParticipantData.php => ParticipantDto.php} (99%) rename src/Form/Model/{RegistrationData.php => RegistrationDto.php} (96%) diff --git a/composer.lock b/composer.lock index 648a52b..1a6b2cc 100644 --- a/composer.lock +++ b/composer.lock @@ -142,99 +142,6 @@ }, "time": "2023-06-19T06:10:36+00:00" }, - { - "name": "doctrine/cache", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", - "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", - "shasum": "" - }, - "require": { - "php": "~7.1 || ^8.0" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psr/cache": "^1.0 || ^2.0 || ^3.0", - "symfony/cache": "^4.4 || ^5.4 || ^6", - "symfony/var-exporter": "^4.4 || ^5.4 || ^6" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", - "homepage": "https://www.doctrine-project.org/projects/cache.html", - "keywords": [ - "abstraction", - "apcu", - "cache", - "caching", - "couchdb", - "memcached", - "php", - "redis", - "xcache" - ], - "support": { - "issues": "https://github.com/doctrine/cache/issues", - "source": "https://github.com/doctrine/cache/tree/2.2.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", - "type": "tidelift" - } - ], - "time": "2022-05-20T20:07:39+00:00" - }, { "name": "doctrine/collections", "version": "2.3.0", @@ -323,28 +230,31 @@ }, { "name": "doctrine/dbal", - "version": "3.9.5", + "version": "3.10.0", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "4a4e2eed3134036ee36a147ee0dac037dfa17868" + "reference": "1cf840d696373ea0d58ad0a8875c0fadcfc67214" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/4a4e2eed3134036ee36a147ee0dac037dfa17868", - "reference": "4a4e2eed3134036ee36a147ee0dac037dfa17868", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/1cf840d696373ea0d58ad0a8875c0fadcfc67214", + "reference": "1cf840d696373ea0d58ad0a8875c0fadcfc67214", "shasum": "" }, "require": { "composer-runtime-api": "^2", - "doctrine/cache": "^1.11|^2.0", "doctrine/deprecations": "^0.5.3|^1", "doctrine/event-manager": "^1|^2", "php": "^7.4 || ^8.0", "psr/cache": "^1|^2|^3", "psr/log": "^1|^2|^3" }, + "conflict": { + "doctrine/cache": "< 1.11" + }, "require-dev": { + "doctrine/cache": "^1.11|^2.0", "doctrine/coding-standard": "13.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", @@ -414,7 +324,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.9.5" + "source": "https://github.com/doctrine/dbal/tree/3.10.0" }, "funding": [ { @@ -430,7 +340,7 @@ "type": "tidelift" } ], - "time": "2025-06-15T22:40:05+00:00" + "time": "2025-07-10T21:11:04+00:00" }, { "name": "doctrine/deprecations", @@ -1121,16 +1031,16 @@ }, { "name": "doctrine/orm", - "version": "3.4.3", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "ef607f26c2965fe460c55733cc7c031fb7e1f2fa" + "reference": "6deec3655ba3e8f15280aac11e264225854d2369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/ef607f26c2965fe460c55733cc7c031fb7e1f2fa", - "reference": "ef607f26c2965fe460c55733cc7c031fb7e1f2fa", + "url": "https://api.github.com/repos/doctrine/orm/zipball/6deec3655ba3e8f15280aac11e264225854d2369", + "reference": "6deec3655ba3e8f15280aac11e264225854d2369", "shasum": "" }, "require": { @@ -1205,9 +1115,9 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/3.4.3" + "source": "https://github.com/doctrine/orm/tree/3.5.0" }, - "time": "2025-06-27T12:14:15+00:00" + "time": "2025-07-01T17:40:53+00:00" }, { "name": "doctrine/persistence", @@ -3136,16 +3046,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.45", + "version": "3.0.46", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8" + "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/bd81b90d5963c6b9d87de50357585375223f4dd8", - "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", + "reference": "56483a7de62a6c2a6635e42e93b8a9e25d4f0ec6", "shasum": "" }, "require": { @@ -3226,7 +3136,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.45" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.46" }, "funding": [ { @@ -3242,20 +3152,20 @@ "type": "tidelift" } ], - "time": "2025-06-22T22:54:43+00:00" + "time": "2025-06-26T16:29:55+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "2.1.0", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68" + "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", - "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/b9e61a61e39e02dd90944e9115241c7f7e76bfd8", + "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8", "shasum": "" }, "require": { @@ -3287,9 +3197,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.1.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.2.0" }, - "time": "2025-02-19T13:28:12+00:00" + "time": "2025-07-13T07:04:09+00:00" }, { "name": "psr/cache", @@ -5285,16 +5195,16 @@ }, { "name": "symfony/flex", - "version": "v2.7.1", + "version": "v2.8.1", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "4ae50d368415a06820739e54d38a4a29d6df9155" + "reference": "423c36e369361003dc31ef11c5f15fb589e52c01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/4ae50d368415a06820739e54d38a4a29d6df9155", - "reference": "4ae50d368415a06820739e54d38a4a29d6df9155", + "url": "https://api.github.com/repos/symfony/flex/zipball/423c36e369361003dc31ef11c5f15fb589e52c01", + "reference": "423c36e369361003dc31ef11c5f15fb589e52c01", "shasum": "" }, "require": { @@ -5333,7 +5243,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v2.7.1" + "source": "https://github.com/symfony/flex/tree/v2.8.1" }, "funding": [ { @@ -5349,7 +5259,7 @@ "type": "tidelift" } ], - "time": "2025-05-28T14:22:54+00:00" + "time": "2025-07-05T07:45:19+00:00" }, { "name": "symfony/form", @@ -10515,58 +10425,59 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.75.0", + "version": "v3.82.2", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "399a128ff2fdaf4281e4e79b755693286cdf325c" + "reference": "684ed3ab41008a2a4848de8bde17eb168c596247" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/399a128ff2fdaf4281e4e79b755693286cdf325c", - "reference": "399a128ff2fdaf4281e4e79b755693286cdf325c", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/684ed3ab41008a2a4848de8bde17eb168c596247", + "reference": "684ed3ab41008a2a4848de8bde17eb168c596247", "shasum": "" }, "require": { "clue/ndjson-react": "^1.0", "composer/semver": "^3.4", - "composer/xdebug-handler": "^3.0.3", + "composer/xdebug-handler": "^3.0.5", "ext-filter": "*", "ext-hash": "*", "ext-json": "*", "ext-tokenizer": "*", "fidry/cpu-core-counter": "^1.2", "php": "^7.4 || ^8.0", - "react/child-process": "^0.6.5", + "react/child-process": "^0.6.6", "react/event-loop": "^1.0", - "react/promise": "^2.0 || ^3.0", + "react/promise": "^2.11 || ^3.0", "react/socket": "^1.0", "react/stream": "^1.0", - "sebastian/diff": "^4.0 || ^5.1 || ^6.0 || ^7.0", - "symfony/console": "^5.4 || ^6.4 || ^7.0", - "symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0", - "symfony/filesystem": "^5.4 || ^6.4 || ^7.0", - "symfony/finder": "^5.4 || ^6.4 || ^7.0", - "symfony/options-resolver": "^5.4 || ^6.4 || ^7.0", - "symfony/polyfill-mbstring": "^1.31", - "symfony/polyfill-php80": "^1.31", - "symfony/polyfill-php81": "^1.31", - "symfony/process": "^5.4 || ^6.4 || ^7.2", - "symfony/stopwatch": "^5.4 || ^6.4 || ^7.0" + "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0", + "symfony/console": "^5.4.45 || ^6.4.13 || ^7.0", + "symfony/event-dispatcher": "^5.4.45 || ^6.4.13 || ^7.0", + "symfony/filesystem": "^5.4.45 || ^6.4.13 || ^7.0", + "symfony/finder": "^5.4.45 || ^6.4.17 || ^7.0", + "symfony/options-resolver": "^5.4.45 || ^6.4.16 || ^7.0", + "symfony/polyfill-mbstring": "^1.32", + "symfony/polyfill-php80": "^1.32", + "symfony/polyfill-php81": "^1.32", + "symfony/process": "^5.4.47 || ^6.4.20 || ^7.2", + "symfony/stopwatch": "^5.4.45 || ^6.4.19 || ^7.0" }, "require-dev": { "facile-it/paraunit": "^1.3.1 || ^2.6", "infection/infection": "^0.29.14", - "justinrainbow/json-schema": "^5.3 || ^6.2", - "keradus/cli-executor": "^2.1", + "justinrainbow/json-schema": "^5.3 || ^6.4", + "keradus/cli-executor": "^2.2", "mikey179/vfsstream": "^1.6.12", - "php-coveralls/php-coveralls": "^2.7", + "php-coveralls/php-coveralls": "^2.8", "php-cs-fixer/accessible-object": "^1.1", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", - "phpunit/phpunit": "^9.6.22 || ^10.5.45 || ^11.5.12", - "symfony/var-dumper": "^5.4.48 || ^6.4.18 || ^7.2.3", - "symfony/yaml": "^5.4.45 || ^6.4.18 || ^7.2.3" + "phpunit/phpunit": "^9.6.23 || ^10.5.47 || ^11.5.25", + "symfony/polyfill-php84": "^1.32", + "symfony/var-dumper": "^5.4.48 || ^6.4.23 || ^7.3.1", + "symfony/yaml": "^5.4.45 || ^6.4.23 || ^7.3.1" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -10607,7 +10518,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.75.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.82.2" }, "funding": [ { @@ -10615,20 +10526,20 @@ "type": "github" } ], - "time": "2025-03-31T18:40:42+00:00" + "time": "2025-07-08T21:13:15+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.13.1", + "version": "1.13.3", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" + "reference": "faed855a7b5f4d4637717c2b3863e277116beb36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/faed855a7b5f4d4637717c2b3863e277116beb36", + "reference": "faed855a7b5f4d4637717c2b3863e277116beb36", "shasum": "" }, "require": { @@ -10667,7 +10578,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.3" }, "funding": [ { @@ -10675,7 +10586,7 @@ "type": "tidelift" } ], - "time": "2025-04-29T12:36:36+00:00" + "time": "2025-07-05T12:25:42+00:00" }, { "name": "nikic/php-parser", @@ -12981,16 +12892,16 @@ }, { "name": "symfony/maker-bundle", - "version": "v1.63.0", + "version": "v1.64.0", "source": { "type": "git", "url": "https://github.com/symfony/maker-bundle.git", - "reference": "69478ab39bc303abfbe3293006a78b09a8512425" + "reference": "c86da84640b0586e92aee2b276ee3638ef2f425a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/69478ab39bc303abfbe3293006a78b09a8512425", - "reference": "69478ab39bc303abfbe3293006a78b09a8512425", + "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/c86da84640b0586e92aee2b276ee3638ef2f425a", + "reference": "c86da84640b0586e92aee2b276ee3638ef2f425a", "shasum": "" }, "require": { @@ -13018,6 +12929,7 @@ "symfony/http-client": "^6.4|^7.0", "symfony/phpunit-bridge": "^6.4.1|^7.0", "symfony/security-core": "^6.4|^7.0", + "symfony/security-http": "^6.4|^7.0", "symfony/yaml": "^6.4|^7.0", "twig/twig": "^3.0|^4.x-dev" }, @@ -13053,7 +12965,7 @@ ], "support": { "issues": "https://github.com/symfony/maker-bundle/issues", - "source": "https://github.com/symfony/maker-bundle/tree/v1.63.0" + "source": "https://github.com/symfony/maker-bundle/tree/v1.64.0" }, "funding": [ { @@ -13069,20 +12981,20 @@ "type": "tidelift" } ], - "time": "2025-04-26T01:41:37+00:00" + "time": "2025-06-23T16:12:08+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v7.3.0", + "version": "v7.3.1", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "2eabda563921f21cbce1d1e3247b3c36568905e6" + "reference": "71624984d8bcad6acf7a790d4e3ceafe04bc2485" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/2eabda563921f21cbce1d1e3247b3c36568905e6", - "reference": "2eabda563921f21cbce1d1e3247b3c36568905e6", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/71624984d8bcad6acf7a790d4e3ceafe04bc2485", + "reference": "71624984d8bcad6acf7a790d4e3ceafe04bc2485", "shasum": "" }, "require": { @@ -13134,8 +13046,11 @@ ], "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", + "keywords": [ + "testing" + ], "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v7.3.0" + "source": "https://github.com/symfony/phpunit-bridge/tree/v7.3.1" }, "funding": [ { @@ -13151,7 +13066,7 @@ "type": "tidelift" } ], - "time": "2025-05-23T07:26:30+00:00" + "time": "2025-06-04T10:09:06+00:00" }, { "name": "symfony/web-profiler-bundle", diff --git a/src/BusProNet/ApiClient.php b/src/BusProNet/ApiClient.php index 9548b78..2dc973e 100644 --- a/src/BusProNet/ApiClient.php +++ b/src/BusProNet/ApiClient.php @@ -13,8 +13,8 @@ use App\BusProNet\Model\Notification; use App\BusProNet\Model\PersonalData; use App\BusProNet\Traits\ApiClientTrait; use App\BusProNet\XmlParser\ApiResponseParser; -use App\Form\Model\BookingData; -use App\Form\Model\RegistrationData; +use App\Form\Model\BookingEditDto; +use App\Form\Model\RegistrationDto; use League\Flysystem\FilesystemException; use League\Flysystem\FilesystemOperator; use Psr\Log\LoggerInterface; @@ -65,7 +65,7 @@ class ApiClient /** * @throws ApiClientException */ - public function register(RegistrationData $registrationData): Notification + public function register(RegistrationDto $registrationData): Notification { $data = [ 'user' => $this->config['bpn_username'], @@ -184,7 +184,7 @@ class ApiClient /** * @throws ApiClientException */ - public function updateBooking(BookingData $formData, bool $debug = false): Notification|BookingUpdate + public function updateBooking(BookingEditDto $formData, bool $debug = false): Notification|BookingUpdate { $payload = (new BookingDataProcessor())->createUpdateRequestPayload($formData); diff --git a/src/BusProNet/Constants.php b/src/BusProNet/Constants.php new file mode 100644 index 0000000..71c0184 --- /dev/null +++ b/src/BusProNet/Constants.php @@ -0,0 +1,22 @@ +booking; $travelData = $formData->travel; // Reset mappings - foreach ([...$bookingData->additionalServices, ...$bookingData->transportationServices, ...$bookingData->pickupsTo, ...$bookingData->pickupsFro] as $service) { + $servicesToReset = [ + ...$bookingData->additionalServices, + ...$bookingData->transportationServices, + ...$bookingData->pickupsTo, + ...$bookingData->pickupsFro, + ]; + foreach ($servicesToReset as $service) { $service->mapping = []; } + // Update mappings, add services and pickups foreach ($formData->participants as $participant) { // skip canceled participants diff --git a/src/BusProNet/Model/Address.php b/src/BusProNet/Model/Address.php index 42e1427..7a8a8c6 100644 --- a/src/BusProNet/Model/Address.php +++ b/src/BusProNet/Model/Address.php @@ -1,25 +1,42 @@ The payload array for API transmission + */ public function toPayload(): array { return [ diff --git a/src/BusProNet/Model/Availability.php b/src/BusProNet/Model/Availability.php index 6e6826a..1336234 100644 --- a/src/BusProNet/Model/Availability.php +++ b/src/BusProNet/Model/Availability.php @@ -1,7 +1,16 @@ The serialized availability data + */ public function jsonSerialize(): array { return [ diff --git a/src/BusProNet/Model/BankAccount.php b/src/BusProNet/Model/BankAccount.php index 92ff70e..a7ff8fa 100644 --- a/src/BusProNet/Model/BankAccount.php +++ b/src/BusProNet/Model/BankAccount.php @@ -1,7 +1,15 @@ items; } + /** + * Retrieves a specific item by its key. + * + * @param string $key The key to search for + * + * @return mixed The item value or null if not found + */ public function getItemByKey(string $key): mixed { return $this->items[$key] ?? null; diff --git a/src/BusProNet/Model/Booking.php b/src/BusProNet/Model/Booking.php index 1e94cdc..eefed04 100644 --- a/src/BusProNet/Model/Booking.php +++ b/src/BusProNet/Model/Booking.php @@ -1,7 +1,16 @@ payment) { @@ -46,6 +63,16 @@ class Booking return $this->price - $this->payment; } + /** + * Retrieves additional services filtered by group. + * + * Filters the additional services array based on the provided group(s). + * Supports both single group strings and arrays of groups. + * + * @param mixed $group The service group(s) to filter by + * + * @return array The filtered services array + */ public function getAdditionalServicesByGroup(mixed $group): array { $group = (array) $group; @@ -55,6 +82,17 @@ class Booking }); } + /** + * Retrieves additional services for a specific participant by group. + * + * Filters additional services by group and participant index mapping. + * Returns services that are assigned to the specified participant. + * + * @param int $participantIndex The participant index to filter by + * @param mixed $group The service group(s) to filter by + * + * @return array The filtered services for the participant + */ public function getAdditionalServicesForParticipantByGroup(int $participantIndex, mixed $group): array { $selectedServices = $this->getAdditionalServicesByGroup($group); @@ -64,6 +102,17 @@ class Booking }); } + /** + * Retrieves transportation service for a specific participant and direction. + * + * Finds the transportation service that matches the participant index + * and travel direction (e.g., 'H' for outbound, 'R' for return). + * + * @param int $participantIndex The participant index to search for + * @param string $direction The travel direction ('H' or 'R') + * + * @return Service|null The matching transportation service or null if not found + */ public function getTransportationServiceForParticipantAndDirection( int $participantIndex, string $direction @@ -80,6 +129,16 @@ class Booking return null; } + /** + * Retrieves pickup service for a specific participant. + * + * Finds the pickup service assigned to the specified participant + * from the outbound pickup services. + * + * @param int $participantIndex The participant index to search for + * + * @return Pickup|null The matching pickup service or null if not found + */ public function getPickupForParticipant(int $participantIndex): ?Pickup { foreach ($this->pickupsTo as $pickup) { @@ -91,6 +150,16 @@ class Booking return null; } + /** + * Retrieves room assignment for a specific participant. + * + * Finds the room assigned to the specified participant + * based on the room mapping configuration. + * + * @param int $participantIndex The participant index to search for + * + * @return Room|null The matching room or null if not found + */ public function getRoomForParticipant(int $participantIndex): ?Room { foreach ($this->rooms as $room) { @@ -102,6 +171,16 @@ class Booking return null; } + /** + * Calculates the total price for a specific participant. + * + * Sums up all services, surcharges, and room costs assigned to the participant. + * Includes mandatory services that apply to all participants. + * + * @param int $participantIndex The participant index to calculate for + * + * @return float The total price for the participant + */ public function getPriceForParticipant(int $participantIndex): float { $price = 0.0; @@ -126,6 +205,15 @@ class Booking return $price; } + /** + * Retrieves surcharges for a specific participant. + * + * Filters surcharges based on participant index mapping. + * + * @param int $participantIndex The participant index to filter by + * + * @return array The surcharges assigned to the participant + */ public function getSurchargesForParticipant(int $participantIndex): array { return array_filter($this->surcharges, function (Surcharge $surcharge) use ($participantIndex) { @@ -133,6 +221,13 @@ class Booking }); } + /** + * Calculates the total price for all participants. + * + * Sums up the individual prices for all participants in the booking. + * + * @return float The calculated total price for all participants + */ public function getCalculatedTotalPrice(): float { $totalPrice = 0.0; @@ -144,6 +239,14 @@ class Booking return $totalPrice; } + /** + * Determines if the booking is editable. + * + * A booking is editable if the travel date is in the future and + * the status is not cancelled ('S') or unknown ('U'). + * + * @return bool True if the booking can be edited, false otherwise + */ public function isEditable(): bool { return $this->travelDate > new \DateTimeImmutable() && false === in_array($this->status, ['S', 'U']); diff --git a/src/BusProNet/Model/BookingUpdate.php b/src/BusProNet/Model/BookingUpdate.php index 10cfbae..2dece6b 100644 --- a/src/BusProNet/Model/BookingUpdate.php +++ b/src/BusProNet/Model/BookingUpdate.php @@ -1,7 +1,15 @@ The payload array for API transmission + */ public function toPayload(): array { return [ diff --git a/src/BusProNet/Model/Country.php b/src/BusProNet/Model/Country.php index 5c5d12b..c1a9f76 100644 --- a/src/BusProNet/Model/Country.php +++ b/src/BusProNet/Model/Country.php @@ -1,7 +1,15 @@ */ public static array $includedServicesMapping = [ 7 => 'Skipass', @@ -32,6 +41,14 @@ class CrmSelectionGroup #[Groups(['api:single'])] public ?array $selections = null; + /** + * Retrieves only the mutable selections from the group. + * + * Filters the selections array to return only items that are marked + * as mutable for user interface management. + * + * @return array The mutable selections array + */ public function getMutableSelections(): array { return array_filter($this->selections, function (CrmSelection $selection) { @@ -39,6 +56,14 @@ class CrmSelectionGroup }); } + /** + * Determines if the selection group should be visible. + * + * A group is considered visible if it contains at least one + * mutable selection for user interaction. + * + * @return bool True if the group has mutable selections, false otherwise + */ #[Groups(['api:single'])] public function isVisible(): bool { diff --git a/src/BusProNet/Model/Error.php b/src/BusProNet/Model/Error.php index d3a37a8..bde02f0 100644 --- a/src/BusProNet/Model/Error.php +++ b/src/BusProNet/Model/Error.php @@ -1,9 +1,21 @@ + */ private static array $errors = [ 100 => 'Anfrageknoten fehlt', 101 => 'Satzknoten fehlt in Anfrageknoten', diff --git a/src/BusProNet/Model/File.php b/src/BusProNet/Model/File.php index db92a78..d054f78 100644 --- a/src/BusProNet/Model/File.php +++ b/src/BusProNet/Model/File.php @@ -1,7 +1,15 @@ code; diff --git a/src/BusProNet/Model/PersonalData.php b/src/BusProNet/Model/PersonalData.php index d64128d..bd83eca 100644 --- a/src/BusProNet/Model/PersonalData.php +++ b/src/BusProNet/Model/PersonalData.php @@ -1,31 +1,43 @@ communication = new Communication(); } + /** + * Converts the personal data to API payload format. + * + * Transforms the personal data object into an array structure suitable + * for API communication with the BusProNet system. + * + * @return array The payload array for API transmission + */ public function toPayload(): array { // Ensure date of birth is populated if (null === $dob = $this->dateOfBirth) { - $dob = new \DateTimeImmutable('18 years ago'); + $dob = new \DateTimeImmutable(self::DEFAULT_AGE_YEARS . ' years ago'); } return [ @@ -56,8 +76,8 @@ class PersonalData 'titel' => $this->title, 'vorname' => $this->firstName, 'name' => $this->name, - 'anschrift' => $this->address?->toPayload(), - 'kommunikation' => $this->communication?->toPayload(), + 'anschrift' => $this->address->toPayload(), + 'kommunikation' => $this->communication->toPayload(), 'sonstiges1' => $this->height, 'sonstiges2' => $this->weight, 'sonstiges3' => $this->shoeSize, @@ -65,6 +85,14 @@ class PersonalData ]; } + /** + * Extracts user claims for authentication and profile information. + * + * Creates a structured array containing user profile information + * suitable for JWT claims or user session data. + * + * @return array The claims array with user profile data + */ public function getClaims(): array { return [ diff --git a/src/BusProNet/Model/Pickup.php b/src/BusProNet/Model/Pickup.php index 5cbb80a..ad981d3 100644 --- a/src/BusProNet/Model/Pickup.php +++ b/src/BusProNet/Model/Pickup.php @@ -1,11 +1,20 @@ The filtered and sorted services array + */ public function getAdditionalServicesByGroup(mixed $group, bool $availableOnly = true): array { $group = (array) $group; @@ -91,6 +111,17 @@ class Travel return $services; } + /** + * Retrieves transportation services filtered by direction and availability. + * + * Filters transportation services based on travel direction and optionally + * by availability. Services are sorted by subtype. + * + * @param string $direction The travel direction to filter by + * @param bool $availableOnly Whether to include only available services + * + * @return array The filtered and sorted transportation services + */ public function getTransportationServicesByDirection(string $direction, bool $availableOnly = true): array { $services = array_filter($this->transportationServices, function (Service $service) use ($direction, $availableOnly) { @@ -106,6 +137,14 @@ class Travel return $services; } + /** + * Retrieves included services from selection groups. + * + * Maps selection group IDs to their corresponding services based on + * the predefined included services mapping. + * + * @return array The included services from selection groups + */ public function getIncludedServices(): array { $services = []; @@ -118,4 +157,27 @@ class Travel return $services; } + + /** + * Retrieves rooms filtered by their IDs. + * + * Filters the rooms array to return only rooms whose IDs match + * the provided array of IDs. Returns an empty array if no matching + * rooms are found. + * + * @param array $ids The array of room IDs to filter by + * + * @return array The filtered rooms array + */ + public function getRoomsByIds(array $ids): array + { + if (empty($ids)) { + return []; + } + + return array_filter($this->rooms, function (Room $room) use ($ids) { + return in_array($room->id, $ids, true); + }); + } + } diff --git a/src/BusProNet/XmlLoader/TravelLoader.php b/src/BusProNet/XmlLoader/TravelLoader.php index d20edd2..d68406f 100644 --- a/src/BusProNet/XmlLoader/TravelLoader.php +++ b/src/BusProNet/XmlLoader/TravelLoader.php @@ -2,6 +2,7 @@ namespace App\BusProNet\XmlLoader; +use App\BusProNet\Constants; use App\BusProNet\Model\BaseData; use App\BusProNet\Model\CrmSelection; use App\BusProNet\Model\CrmSelectionGroup; @@ -192,8 +193,8 @@ class TravelLoader extends AbstractLoader $serviceId = (int) $serviceNode->attr('idbuspro'); $service = new Service(); - $service->source = Service::SOURCE_TRAVEL; - $service->category = Service::CATEGORY_ADDITIONAL; + $service->source = Constants::SOURCE_TRAVEL; + $service->category = Constants::CATEGORY_ADDITIONAL; $service->id = $serviceId; $service->subType = $serviceNode->attr('unterart'); $service->mandatory = $this->stringToBool($serviceNode->attr('pflicht')); @@ -236,8 +237,8 @@ class TravelLoader extends AbstractLoader $serviceId = (int) $serviceNode->attr('idbuspro'); $service = new Service(); - $service->source = Service::SOURCE_TRAVEL; - $service->category = Service::CATEGORY_TRANSPORTATION; + $service->source = Constants::SOURCE_TRAVEL; + $service->category = Constants::CATEGORY_TRANSPORTATION; $service->id = $serviceId; $service->subType = $serviceNode->attr('unterart'); $service->dateFrom = $this->stringToDate($serviceNode->attr('termin')); @@ -311,12 +312,12 @@ class TravelLoader extends AbstractLoader $room->category = $roomNode->attr('kat'); $room->boardId = (int) $roomNode->attr('idbuspro_vp'); $room->label = $roomNode->attr('zimmertext'); - $room->minPax = (int) $roomNode->attr('MinPax'); - $room->maxPax = (int) $roomNode->attr('MaxPax'); + $room->minPax = (int) $roomNode->attr('minpax'); + $room->maxPax = (int) $roomNode->attr('maxpax'); $room->nights = (int) $roomNode->attr('naechte'); $room->price = $roomNode->attr('preis') ? $this->stringToFloat($roomNode->attr('preis')) : null; - $room->status = $this->getStringOrNullValue($roomNode->filterXPath('//status')); + $room->status = $roomNode->attr('status'); $room->available = (int) $roomNode->attr('verfuegbar'); $rooms[$roomId] = $room; diff --git a/src/BusProNet/XmlParser/BookingParser.php b/src/BusProNet/XmlParser/BookingParser.php index 55ff8a3..913cf7d 100644 --- a/src/BusProNet/XmlParser/BookingParser.php +++ b/src/BusProNet/XmlParser/BookingParser.php @@ -2,6 +2,7 @@ namespace App\BusProNet\XmlParser; +use App\BusProNet\Constants; use App\BusProNet\Model\Address; use App\BusProNet\Model\BankAccount; use App\BusProNet\Model\Booking; @@ -38,7 +39,7 @@ class BookingParser extends AbstractParser $travelData = $node->filterXPath('//reise'); - $booking->travel = $travelData->attr('bezeichnung'); + $booking->travelName = $travelData->attr('bezeichnung'); $booking->travelId = $this->getIntOrNullValue($node->filterXPath('//idreise')); $booking->travelCode = $travelData->attr('code'); $booking->travelDate = $this->stringToDate($travelData->attr('termin')); @@ -72,14 +73,14 @@ class BookingParser extends AbstractParser if (0 < $transportationData->count()) { $booking->transportationServices = $this ->servicesParser - ->parse($transportationData, Service::CATEGORY_TRANSPORTATION, Service::SOURCE_BOOKING); + ->parse($transportationData, Constants::CATEGORY_TRANSPORTATION, Constants::SOURCE_BOOKING); } $additionalServicesData = $node->filterXPath('//zusatzleistungen/zusatzleistung'); if (0 < $additionalServicesData->count()) { $booking->additionalServices = $this ->servicesParser - ->parse($additionalServicesData, Service::CATEGORY_ADDITIONAL, Service::SOURCE_BOOKING); + ->parse($additionalServicesData, Constants::CATEGORY_ADDITIONAL, Constants::SOURCE_BOOKING); } $roomsData = $node->filterXPath('//ferienzielunterbringungen/ferienzielunterbringung'); diff --git a/src/BusProNet/XmlParser/BookingsParser.php b/src/BusProNet/XmlParser/BookingsParser.php index 2b6766d..29d2a42 100644 --- a/src/BusProNet/XmlParser/BookingsParser.php +++ b/src/BusProNet/XmlParser/BookingsParser.php @@ -26,7 +26,7 @@ class BookingsParser extends AbstractParser $booking->participantCount = $this->getIntOrNullValue($node->filterXPath('//personen')); $booking->price = $this->getFloatOrNullValue($node->filterXPath('//preis')); $booking->bookingDate = $this->getDateTimeOrNullValue($node->filterXPath('//buchungsdatum')); - $booking->travel = $this->getStringOrNullValue($node->filterXPath('//reise')); + $booking->travelName = $this->getStringOrNullValue($node->filterXPath('//reise')); $booking->travelId = $this->getIntOrNullValue($node->filterXPath('//idreise')); $booking->travelDate = $this->getDateOrNullValue($node->filterXPath('//reisedatum')); $booking->hasDocuments = $this->getBoolValue($node->filterXPath('//reisedokument')); diff --git a/src/BusProNet/XmlParser/ServicesParser.php b/src/BusProNet/XmlParser/ServicesParser.php index 7142821..5983c26 100644 --- a/src/BusProNet/XmlParser/ServicesParser.php +++ b/src/BusProNet/XmlParser/ServicesParser.php @@ -2,6 +2,7 @@ namespace App\BusProNet\XmlParser; +use App\BusProNet\Constants; use App\BusProNet\Model\Service; use Symfony\Component\DomCrawler\Crawler; @@ -30,7 +31,7 @@ class ServicesParser extends AbstractParser }, $this->stringToArray($node->attr('einzelpreis', ''), '/') ); $service->individualPrice = array_combine($mapping, $individualPrices); - if (Service::CATEGORY_TRANSPORTATION === $category) { + if (Constants::CATEGORY_TRANSPORTATION === $category) { $service->direction = $node->attr('richtung'); } diff --git a/src/Controller/Booking/CreateController.php b/src/Controller/Booking/CreateController.php new file mode 100644 index 0000000..b574879 --- /dev/null +++ b/src/Controller/Booking/CreateController.php @@ -0,0 +1,50 @@ +query->getInt('travel_id'); + $hotelId = $request->query->getInt('hotel_id'); + + $roomsIdsAndQuantities = $this->getRoomsIdsAndQuantities($request); + + $travelData = $this->travelDataLoader->loadById($travelId, $hotelId); + + if (null === $travelData) { + throw $this->createNotFoundException('Travel data not found'); + } + + $participantsCount = 0; + + $rooms = $travelData->getRoomsByIds(array_keys($roomsIdsAndQuantities)); + + foreach ($rooms as $room) { + $roomCount = $roomsIdsAndQuantities[$room->id] ?? 0; + $participantsCount += $room->minPax * $roomCount; + } + + return $this->render('booking/create.html.twig', [ + 'travelData' => $travelData, + ]); + } + + private function getRoomsIdsAndQuantities(Request $request): array + { + $rooms = $request->request->all('rooms'); + + return array_map('intval', array_filter($rooms, 'strlen')); + } +} \ No newline at end of file diff --git a/src/Controller/Booking/EditController.php b/src/Controller/Booking/EditController.php index 4bed922..309dd17 100644 --- a/src/Controller/Booking/EditController.php +++ b/src/Controller/Booking/EditController.php @@ -10,7 +10,7 @@ use App\BusProNet\XmlLoader\TravelLoader; use App\Controller\Traits\BookingDataTrait; use App\Entity\User; use App\Form\BookingType; -use App\Form\Model\BookingData; +use App\Form\Model\BookingEditDto; use App\Security\Crypt; use Psr\Cache\InvalidArgumentException; use Psr\Log\LoggerInterface; @@ -90,7 +90,7 @@ class EditController extends AbstractController $this->pickupDataLoader->patchPickupsDetails($travelData); // Create DTO for form - $formData = BookingData::fromBooking($bookingData, $travelData); + $formData = BookingEditDto::fromBooking($bookingData, $travelData); $form = $this->createForm(BookingType::class, $formData, [ 'attr' => ['novalidate' => 'novalidate'], diff --git a/src/Controller/RegistrationController.php b/src/Controller/RegistrationController.php index eebe01d..0202112 100644 --- a/src/Controller/RegistrationController.php +++ b/src/Controller/RegistrationController.php @@ -4,7 +4,7 @@ namespace App\Controller; use App\BusProNet\ApiClient; use App\BusProNet\Exception\ApiClientException; -use App\Form\Model\RegistrationData; +use App\Form\Model\RegistrationDto; use App\Form\RegistrationType; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -25,7 +25,7 @@ class RegistrationController extends AbstractController #[IsGranted('PUBLIC_ACCESS')] public function index(Request $request): Response { - $registrationData = new RegistrationData(); + $registrationData = new RegistrationDto(); $form = $this->createForm(RegistrationType::class, $registrationData, [ 'action' => $this->generateUrl('app_registration'), ]); diff --git a/src/Form/BookingType.php b/src/Form/BookingType.php index 603117f..3847d3a 100644 --- a/src/Form/BookingType.php +++ b/src/Form/BookingType.php @@ -2,8 +2,9 @@ namespace App\Form; +use App\BusProNet\Constants; use App\BusProNet\Model\Service; -use App\Form\Model\BookingData; +use App\Form\Model\BookingEditDto; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\FormBuilderInterface; @@ -16,7 +17,7 @@ final class BookingType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options): void { $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { - /** @var BookingData $data */ + /** @var BookingEditDto $data */ $data = $event->getData(); $form = $event->getForm(); @@ -24,11 +25,11 @@ final class BookingType extends AbstractType $form->add('participants', CollectionType::class, [ 'entry_type' => ParticipantType::class, 'entry_options' => [ - 'selectable_courses' => $this->mergeSelectableServices($data, Service::TOKEN_COURSES), - 'selectable_ski_passes' => $this->mergeSelectableServices($data, Service::TOKEN_SKI_PASS), - 'selectable_services' => $this->mergeSelectableServices($data, Service::TOKEN_ADDITIONAL), - 'selectable_board' => $this->mergeSelectableServices($data, Service::TOKEN_BOARD), - 'selectable_rentals' => $this->mergeSelectableServices($data, Service::TOKEN_RENTALS), + 'selectable_courses' => $this->mergeSelectableServices($data, Constants::TOKEN_COURSES), + 'selectable_ski_passes' => $this->mergeSelectableServices($data, Constants::TOKEN_SKI_PASS), + 'selectable_services' => $this->mergeSelectableServices($data, Constants::TOKEN_ADDITIONAL), + 'selectable_board' => $this->mergeSelectableServices($data, Constants::TOKEN_BOARD), + 'selectable_rentals' => $this->mergeSelectableServices($data, Constants::TOKEN_RENTALS), 'selectable_transportation_services_to' => $travelData ->getTransportationServicesByDirection('HIN', false), 'selectable_transportation_services_fro' => $travelData @@ -46,7 +47,7 @@ final class BookingType extends AbstractType }); } - private function mergeSelectableServices(BookingData $data, mixed $subType): array + private function mergeSelectableServices(BookingEditDto $data, mixed $subType): array { // combine selectable services from travel data with additional services // from booking data @@ -67,7 +68,7 @@ final class BookingType extends AbstractType public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ - 'data_class' => BookingData::class, + 'data_class' => BookingEditDto::class, 'anti_xss' => true, ]); } diff --git a/src/Form/Model/BookingData.php b/src/Form/Model/BookingEditDto.php similarity index 87% rename from src/Form/Model/BookingData.php rename to src/Form/Model/BookingEditDto.php index 511a1b7..48a3217 100644 --- a/src/Form/Model/BookingData.php +++ b/src/Form/Model/BookingEditDto.php @@ -2,13 +2,13 @@ namespace App\Form\Model; +use App\BusProNet\Constants; use App\BusProNet\Model\Booking; use App\BusProNet\Model\PersonalData; -use App\BusProNet\Model\Service; use App\BusProNet\Model\Travel; use Symfony\Component\Validator\Constraints as Assert; -class BookingData +class BookingEditDto { public ?Booking $booking = null; public ?Travel $travel = null; @@ -25,19 +25,19 @@ class BookingData foreach ($booking->participants as $index => $participant) { /** @var PersonalData $participant */ - $participantData = ParticipantData::fromPersonalData($participant); + $participantData = ParticipantDto::fromPersonalData($participant); $participantData->index = $index; $participantData->courses = $booking - ->getAdditionalServicesForParticipantByGroup($index, Service::TOKEN_COURSES); + ->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_COURSES); $participantData->skiPass = $booking - ->getAdditionalServicesForParticipantByGroup($index, Service::TOKEN_SKI_PASS); + ->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_SKI_PASS); $participantData->additionalServices = $booking - ->getAdditionalServicesForParticipantByGroup($index, Service::TOKEN_ADDITIONAL); + ->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_ADDITIONAL); $participantData->board = $booking - ->getAdditionalServicesForParticipantByGroup($index, Service::TOKEN_BOARD); + ->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_BOARD); $participantData->rentals = $booking - ->getAdditionalServicesForParticipantByGroup($index, Service::TOKEN_RENTALS); + ->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_RENTALS); // Different keys for direction used in booking data (H <=> HIN, R <=> RUECK)! $participantData->transportationServiceTo = $booking ->getTransportationServiceForParticipantAndDirection($index, 'H'); diff --git a/src/Form/Model/ParticipantData.php b/src/Form/Model/ParticipantDto.php similarity index 99% rename from src/Form/Model/ParticipantData.php rename to src/Form/Model/ParticipantDto.php index 2334f30..c08a876 100644 --- a/src/Form/Model/ParticipantData.php +++ b/src/Form/Model/ParticipantDto.php @@ -9,7 +9,7 @@ use App\Validator\Constraints as AppAssert; use Symfony\Component\Validator\Constraints as Assert; #[AppAssert\Participant] -class ParticipantData +class ParticipantDto { public ?int $index = null; public ?int $addressId = null; diff --git a/src/Form/Model/RegistrationData.php b/src/Form/Model/RegistrationDto.php similarity index 96% rename from src/Form/Model/RegistrationData.php rename to src/Form/Model/RegistrationDto.php index 8cac18f..d714d36 100644 --- a/src/Form/Model/RegistrationData.php +++ b/src/Form/Model/RegistrationDto.php @@ -4,7 +4,7 @@ namespace App\Form\Model; use Symfony\Component\Validator\Constraints as Assert; -class RegistrationData +class RegistrationDto { #[Assert\NotBlank(message: 'Bitte angeben')] public ?string $firstName = null; diff --git a/src/Form/ParticipantType.php b/src/Form/ParticipantType.php index 6a81ac8..f8d7c1c 100644 --- a/src/Form/ParticipantType.php +++ b/src/Form/ParticipantType.php @@ -2,10 +2,11 @@ namespace App\Form; +use App\BusProNet\Constants; use App\BusProNet\Form\CountryType; use App\BusProNet\Model\Pickup; use App\BusProNet\Model\Service; -use App\Form\Model\ParticipantData; +use App\Form\Model\ParticipantDto; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\BirthdayType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; @@ -21,7 +22,7 @@ class ParticipantType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options): void { $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($options) { - /** @var ParticipantData $participantData */ + /** @var ParticipantDto $participantData */ $participantData = $event->getData(); $participantIndex = $participantData->index; @@ -166,12 +167,12 @@ class ParticipantType extends AbstractType } // disable selection of services only available in booking data - if (Service::SOURCE_BOOKING === $service->source) { + if (Constants::SOURCE_BOOKING === $service->source) { $attributes['class'] = 'text-pink'; } // disable selection of services that are unavailable according to their status - if (Service::STATUS_BLOCKED === $service->status) { + if (Constants::STATUS_BLOCKED === $service->status) { $attributes['checked'] = false; $attributes['readonly'] = true; $attributes['tooltip'] = 'Diese Leistung ist derzeit leider nicht buchbar'; @@ -191,8 +192,8 @@ class ParticipantType extends AbstractType // remove choices only available in booking data and // which are not mapped to the current participant if ( - Service::SOURCE_TRAVEL === $service->source - || Service::CATEGORY_ADDITIONAL !== $service->category + Constants::SOURCE_TRAVEL === $service->source + || Constants::CATEGORY_ADDITIONAL !== $service->category ) { return true; } @@ -249,7 +250,7 @@ class ParticipantType extends AbstractType $attributes['readonly'] = true; $attributes['tooltip'] = 'Diese Leistung kann nicht mehr geändert werden'; } - if (Service::STATUS_BLOCKED === $service->status) { + if (Constants::STATUS_BLOCKED === $service->status) { $attributes['checked'] = false; $attributes['readonly'] = true; $attributes['tooltip'] = 'Diese Leistung ist derzeit leider nicht buchbar'; @@ -341,7 +342,7 @@ class ParticipantType extends AbstractType $participantIndex = $form->getData()->index; return true === $service->mandatory - || (Service::SOURCE_BOOKING === $service->source && in_array($participantIndex, $service->mapping)); + || (Constants::SOURCE_BOOKING === $service->source && in_array($participantIndex, $service->mapping)); }); if (0 < count($mandatoryServices)) { @@ -364,7 +365,7 @@ class ParticipantType extends AbstractType public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ - 'data_class' => ParticipantData::class, + 'data_class' => ParticipantDto::class, 'selectable_courses' => [], 'selectable_ski_passes' => [], 'selectable_services' => [], diff --git a/src/Form/RegistrationType.php b/src/Form/RegistrationType.php index b0b86a2..cfbf1ce 100644 --- a/src/Form/RegistrationType.php +++ b/src/Form/RegistrationType.php @@ -2,7 +2,7 @@ namespace App\Form; -use App\Form\Model\RegistrationData; +use App\Form\Model\RegistrationDto; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\EmailType; @@ -39,7 +39,7 @@ class RegistrationType extends AbstractType public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ - 'data_class' => RegistrationData::class, + 'data_class' => RegistrationDto::class, 'anti_xss' => true, ]); } diff --git a/src/Validator/Constraints/BookingValidator.php b/src/Validator/Constraints/BookingValidator.php index b7f002b..725a537 100644 --- a/src/Validator/Constraints/BookingValidator.php +++ b/src/Validator/Constraints/BookingValidator.php @@ -5,7 +5,7 @@ namespace App\Validator\Constraints; use App\BusProNet\ApiClient; use App\BusProNet\Model\BookingUpdate; use App\BusProNet\Model\Notification; -use App\Form\Model\BookingData; +use App\Form\Model\BookingEditDto; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; @@ -17,7 +17,7 @@ class BookingValidator extends ConstraintValidator public function validate(mixed $value, Constraint $constraint): void { - /** @var BookingData $booking */ + /** @var BookingEditDto $booking */ $bookingData = $value; $result = $this->apiClient->updateBooking($bookingData); diff --git a/src/Validator/Constraints/ParticipantValidator.php b/src/Validator/Constraints/ParticipantValidator.php index 616c51b..d988355 100644 --- a/src/Validator/Constraints/ParticipantValidator.php +++ b/src/Validator/Constraints/ParticipantValidator.php @@ -2,7 +2,7 @@ namespace App\Validator\Constraints; -use App\Form\Model\ParticipantData; +use App\Form\Model\ParticipantDto; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; @@ -10,7 +10,7 @@ class ParticipantValidator extends ConstraintValidator { public function validate(mixed $value, Constraint $constraint): void { - /** @var ParticipantData $participant */ + /** @var ParticipantDto $participant */ $participant = $value; $this->assertBodyMeasurementsValid($participant); @@ -18,7 +18,7 @@ class ParticipantValidator extends ConstraintValidator $this->assertPickupSelected($participant); } - public function assertBodyMeasurementsValid(ParticipantData $participant): void + public function assertBodyMeasurementsValid(ParticipantDto $participant): void { if (0 === count($participant->rentals)) { return; @@ -34,7 +34,7 @@ class ParticipantValidator extends ConstraintValidator } } - public function assertTransportationSelected(ParticipantData $participant): void + public function assertTransportationSelected(ParticipantDto $participant): void { // no transportation services required for canceled participants if (true === $participant->isCanceled()) { @@ -51,7 +51,7 @@ class ParticipantValidator extends ConstraintValidator } } - public function assertPickupSelected(ParticipantData $participant): void + public function assertPickupSelected(ParticipantDto $participant): void { if ( null !== $participant->transportationServiceTo diff --git a/templates/booking/edit.html.twig b/templates/booking/edit.html.twig index dab627d..96308a4 100644 --- a/templates/booking/edit.html.twig +++ b/templates/booking/edit.html.twig @@ -35,7 +35,7 @@

Reise

- {{ bookingData.travel }} + {{ bookingData.travelName }}

diff --git a/templates/booking/index.html.twig b/templates/booking/index.html.twig index 20ea033..8d56aae 100644 --- a/templates/booking/index.html.twig +++ b/templates/booking/index.html.twig @@ -36,7 +36,7 @@ - {{ booking.travel }} + {{ booking.travelName }}