diff --git a/composer.lock b/composer.lock index 20ab9bf..be431b2 100644 --- a/composer.lock +++ b/composer.lock @@ -1005,16 +1005,16 @@ }, { "name": "doctrine/migrations", - "version": "3.9.6", + "version": "3.9.7", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "ffd8355cdd8505fc650d9604f058bf62aedd80a1" + "reference": "96cb2a89b56c9efb0bac38e606dc0b0f13e650ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/ffd8355cdd8505fc650d9604f058bf62aedd80a1", - "reference": "ffd8355cdd8505fc650d9604f058bf62aedd80a1", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/96cb2a89b56c9efb0bac38e606dc0b0f13e650ec", + "reference": "96cb2a89b56c9efb0bac38e606dc0b0f13e650ec", "shasum": "" }, "require": { @@ -1088,7 +1088,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.9.6" + "source": "https://github.com/doctrine/migrations/tree/3.9.7" }, "funding": [ { @@ -1104,7 +1104,7 @@ "type": "tidelift" } ], - "time": "2026-02-11T06:46:11+00:00" + "time": "2026-04-23T19:33:20+00:00" }, { "name": "doctrine/orm", @@ -1196,19 +1196,20 @@ }, { "name": "doctrine/persistence", - "version": "4.1.1", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "b9c49ad3558bb77ef973f4e173f2e9c2eca9be09" + "reference": "49ab73e0d3e2ac8d1f5ecda3dd8acd5503781e8b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/b9c49ad3558bb77ef973f4e173f2e9c2eca9be09", - "reference": "b9c49ad3558bb77ef973f4e173f2e9c2eca9be09", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/49ab73e0d3e2ac8d1f5ecda3dd8acd5503781e8b", + "reference": "49ab73e0d3e2ac8d1f5ecda3dd8acd5503781e8b", "shasum": "" }, "require": { + "doctrine/deprecations": "^1", "doctrine/event-manager": "^1 || ^2", "php": "^8.1", "psr/cache": "^1.0 || ^2.0 || ^3.0" @@ -1219,13 +1220,13 @@ "phpstan/phpstan-phpunit": "^2", "phpstan/phpstan-strict-rules": "^2", "phpunit/phpunit": "^10.5.58 || ^12", - "symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0", - "symfony/finder": "^4.4 || ^5.4 || ^6.0 || ^7.0" + "symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/finder": "^4.4 || ^5.4 || ^6.0 || ^7.0 || ^8.0" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Persistence\\": "src/Persistence" + "Doctrine\\Persistence\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1269,7 +1270,7 @@ ], "support": { "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/4.1.1" + "source": "https://github.com/doctrine/persistence/tree/4.2.0" }, "funding": [ { @@ -1285,7 +1286,7 @@ "type": "tidelift" } ], - "time": "2025-10-16T20:13:18+00:00" + "time": "2026-04-26T12:12:52+00:00" }, { "name": "doctrine/sql-formatter", @@ -3657,16 +3658,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.51", + "version": "3.0.52", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "d59c94077f9c9915abb51ddb52ce85188ece1748" + "reference": "2adaefc83df2ec548558307690f376dd7d4f4fce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d59c94077f9c9915abb51ddb52ce85188ece1748", - "reference": "d59c94077f9c9915abb51ddb52ce85188ece1748", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/2adaefc83df2ec548558307690f376dd7d4f4fce", + "reference": "2adaefc83df2ec548558307690f376dd7d4f4fce", "shasum": "" }, "require": { @@ -3747,7 +3748,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.51" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.52" }, "funding": [ { @@ -3763,7 +3764,7 @@ "type": "tidelift" } ], - "time": "2026-04-10T01:33:53+00:00" + "time": "2026-04-27T07:02:15+00:00" }, { "name": "phpstan/phpdoc-parser", @@ -7520,16 +7521,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.36.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "ad1b7b9092976d6c948b8a187cec9faaea9ec1df" + "reference": "4864388bfbd3001ce88e234fab652acd91fdc57e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/ad1b7b9092976d6c948b8a187cec9faaea9ec1df", - "reference": "ad1b7b9092976d6c948b8a187cec9faaea9ec1df", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/4864388bfbd3001ce88e234fab652acd91fdc57e", + "reference": "4864388bfbd3001ce88e234fab652acd91fdc57e", "shasum": "" }, "require": { @@ -7578,7 +7579,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.36.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.37.0" }, "funding": [ { @@ -7598,11 +7599,11 @@ "type": "tidelift" } ], - "time": "2026-04-10T16:19:22+00:00" + "time": "2026-04-26T13:13:48+00:00" }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.36.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", @@ -7666,7 +7667,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.36.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.37.0" }, "funding": [ { @@ -7690,7 +7691,7 @@ }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.36.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -7753,7 +7754,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.36.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.37.0" }, "funding": [ { @@ -7777,7 +7778,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.36.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -7838,7 +7839,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.36.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.37.0" }, "funding": [ { @@ -7862,7 +7863,7 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.36.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", @@ -7923,7 +7924,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.36.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.37.0" }, "funding": [ { @@ -7947,7 +7948,7 @@ }, { "name": "symfony/polyfill-php83", - "version": "v1.36.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", @@ -8003,7 +8004,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.36.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.37.0" }, "funding": [ { @@ -8027,7 +8028,7 @@ }, { "name": "symfony/polyfill-php84", - "version": "v1.36.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php84.git", @@ -8083,7 +8084,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.36.0" + "source": "https://github.com/symfony/polyfill-php84/tree/v1.37.0" }, "funding": [ { @@ -8107,7 +8108,7 @@ }, { "name": "symfony/polyfill-uuid", - "version": "v1.36.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", @@ -8166,7 +8167,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.36.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.37.0" }, "funding": [ { @@ -11740,11 +11741,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.51", + "version": "2.1.53", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc3b523c45e714c70de2ac5113b958223b55dc59", - "reference": "dc3b523c45e714c70de2ac5113b958223b55dc59", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ef67586798c003274797b288a68b221e4270dca7", + "reference": "ef67586798c003274797b288a68b221e4270dca7", "shasum": "" }, "require": { @@ -11789,7 +11790,7 @@ "type": "github" } ], - "time": "2026-04-21T18:22:01+00:00" + "time": "2026-04-28T16:09:00+00:00" }, { "name": "phpstan/phpstan-doctrine", diff --git a/docs/SYMFONY_7.4_UPGRADE_PLAN.md b/docs/SYMFONY_7.4_UPGRADE_PLAN.md deleted file mode 100644 index 8757c13..0000000 --- a/docs/SYMFONY_7.4_UPGRADE_PLAN.md +++ /dev/null @@ -1,484 +0,0 @@ -# Symfony 7.4 Upgrade Plan - -**Project:** MyEP Next Booking -**Current Version:** Symfony 6.4.x (6.4.33) -**Target Version:** Symfony 7.4 (LTS) -**Date:** 2026-02-23 -**Status:** Ready for Upgrade - ---- - -## Executive Summary - -**Estimated Effort: LOW** -**Risk Level: LOW** -**Status: READY FOR UPGRADE** - -The MyEP Next Booking application is well-positioned for a Symfony 7.4 upgrade. The codebase follows modern Symfony best practices, uses PHP 8 features extensively, and avoids most deprecated patterns. All pre-upgrade fixes have been completed. - -**Key Facts:** -- Symfony 7.4 was released on November 27, 2025 -- Requires PHP 8.2.0+ (current: PHP 8.3.30) -- LTS version with bug fixes until November 2028, security fixes until November 2029 -- Symfony 8.0 = Symfony 7.4 minus deprecations (same features, PHP 8.4 required) - -**Pre-Upgrade Status:** -- PHP version: 8.3.30 (compatible; Symfony 7.4 requires 8.2+) -- OAuth2 Server Bundle: 1.1.0 (compatible) -- Stimulus Bundle: 2.32.0 (compatible) -- Doctrine ORM: 3.6.0 (compatible) -- All 433 tests passing -- Email validation mode: Configured (html5) -- 18 test-only deprecation warnings (cosmetic, do not affect runtime) - ---- - -## Previous Plan Status - -The previous upgrade plan (dated 2025-12-06) has been updated. All pre-upgrade tasks are now complete. - -### Completed Items -| Item | Previous Status | Current Status | -|------|----------------|----------------| -| OAuth2 Server Bundle | 1.0.0 | **1.1.0 installed** | -| Stimulus Bundle | 2.31.0 | **2.32.0 installed** | -| PHP 8.2 deprecations (ParticipantDto::$touched) | Planned | **Completed** | -| Doctrine config (controller_resolver) | Planned | **Completed** | -| SecurityController null safety | Needs verification | **Completed** (uses `?->` and `??`) | -| Email validator "loose" mode deprecation | Needs fix | **Completed** (validator.yaml configured) | -| Failing test in BookingDataProcessorTest | Unrelated to upgrade | **Resolved** (test now passes) | - ---- - -## Current State Analysis - -### PHP Version Compatibility - -- **Current Runtime:** PHP 8.3.30 -- **Composer Platform:** PHP 8.3.30 -- **Symfony 7.4 Required:** PHP 8.2.0+ -- **Status:** Compatible - -### Installed Dependencies - -#### Core Symfony Packages (6.4.x) -All 33 Symfony packages currently at 6.4.x need version constraint updates to 7.4.* - -#### Third-Party Bundles - Compatible -| Package | Installed | Symfony 7.4 Compatible | -|---------|-----------|------------------------| -| `doctrine/orm` | 3.6.0 | Yes | -| `doctrine/doctrine-bundle` | 2.18.1 | Yes | -| `doctrine/doctrine-migrations-bundle` | 3.7.0 | Yes | -| `league/oauth2-server-bundle` | 1.1.0 | Yes | -| `symfony/stimulus-bundle` | 2.32.0 | Yes | -| `symfony/webpack-encore-bundle` | 2.4.0 | Yes | -| `symfony/monolog-bundle` | 3.11.0 | Yes | -| `zenstruck/schedule-bundle` | 1.9.0 | Yes | -| `league/flysystem-bundle` | 3.6.1 | Yes | -| `league/flysystem-sftp-v3` | 3.30.0 | Yes | -| `nelexa/zip` | 4.0.2 | Yes (verify post-upgrade) | -| `spatie/crypto` | 2.1.1 | Yes | -| `easycorp/easyadmin-bundle` | 4.29.1 (^4.27) | Yes | - -### Code Quality Assessment - -The codebase implements modern Symfony/PHP patterns: -- All controllers use PHP 8 attributes (`#[Route]`) -- Constructor property promotion used throughout -- Strict types enforced on all files -- Typed properties and return type declarations -- Entities use PHP 8 attributes for ORM mapping -- Modern security system (AbstractLoginFormAuthenticator) -- No deprecated annotation usage - ---- - -## Pre-Upgrade Fixes - COMPLETED - -### 1. Email Validator "loose" Mode Deprecation - DONE - -**Issue:** The default mode for `#[Assert\Email]` is "loose", which is deprecated in Symfony 6.2+ and removed in Symfony 7.0. - -**Resolution:** Framework default configured in `config/packages/validator.yaml`: - -```yaml -framework: - validation: - email_validation_mode: html5 -``` - -All Email constraints in the codebase also explicitly use `mode: 'strict'`: -- `src/Form/Model/ParticipantDto.php` - Has `mode: 'strict'` -- `src/Form/Model/RegistrationDto.php` - Has `mode: 'strict'` -- `src/BusProNet/Model/Communication.php` - Has `mode: 'strict'` -- `src/Controller/ResetPasswordController.php` - Has `mode: 'strict'` - -### 2. Test Deprecation Warnings - COSMETIC ONLY - -**Issue:** 18 deprecation warnings appear during test runs. - -**Cause:** `ParticipantEditDtoTest` creates a standalone validator using `Validation::createValidatorBuilder()` which bypasses the framework's `validator.yaml` configuration. - -**Impact:** These warnings are cosmetic and do not affect: -- Runtime behavior (all Email constraints use explicit `mode: 'strict'`) -- Symfony 7.4 compatibility (no code changes needed) -- Test results (all 433 tests pass) - -**Note:** Warnings can be silenced with `SYMFONY_DEPRECATIONS_HELPER=disabled` if desired. - ---- - -## Required Changes - -### 1. Update Composer Version Constraints - -**File:** `composer.json` - -#### Symfony Core Packages -Update all packages from `6.4.*` to `7.4.*`: - -```json -{ - "require": { - "symfony/asset": "7.4.*", - "symfony/console": "7.4.*", - "symfony/doctrine-messenger": "7.4.*", - "symfony/dom-crawler": "7.4.*", - "symfony/dotenv": "7.4.*", - "symfony/expression-language": "7.4.*", - "symfony/form": "7.4.*", - "symfony/framework-bundle": "7.4.*", - "symfony/html-sanitizer": "7.4.*", - "symfony/http-client": "7.4.*", - "symfony/intl": "7.4.*", - "symfony/lock": "7.4.*", - "symfony/mailer": "7.4.*", - "symfony/mime": "7.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/string": "7.4.*", - "symfony/translation": "7.4.*", - "symfony/twig-bundle": "7.4.*", - "symfony/uid": "7.4.*", - "symfony/validator": "7.4.*", - "symfony/web-link": "7.4.*", - "symfony/yaml": "7.4.*" - } -} -``` - -#### Development Packages - -```json -{ - "require-dev": { - "symfony/browser-kit": "7.4.*", - "symfony/css-selector": "7.4.*", - "symfony/debug-bundle": "7.4.*", - "symfony/maker-bundle": "^1.0", - "symfony/phpunit-bridge": "7.4.*", - "symfony/stopwatch": "7.4.*", - "symfony/web-profiler-bundle": "7.4.*" - } -} -``` - -Keep `symfony/maker-bundle` at `^1.0` (compatible with Symfony 7.4). - -### 2. Update Symfony Flex Configuration - -**File:** `composer.json` - -```json -{ - "extra": { - "symfony": { - "allow-contrib": true, - "require": "7.4.*", - "docker": true - } - } -} -``` - ---- - -## Potential Breaking Changes - -### 1. Symfony Core Changes (Symfony 7.0 -> 7.4) - -Symfony 7.0 removed all deprecated features from 6.4. Our codebase is fully compliant: - -- **Native Return Types:** Already implemented -- **Attribute-based Configuration:** Already implemented -- **Security System:** Modern authenticator pattern in use -- **Form System:** Modern approach in use -- **No Annotation Usage:** All using PHP 8 attributes - -### 2. Email Validation Mode - -**Breaking Change:** The default `mode` for `Email` constraint changes from `loose` to `html5` in Symfony 7.0. - -**Status:** Already handled - all constraints use explicit `mode: 'strict'` and framework default is set to `html5`. - -### 3. Deprecation Cleanup - -Deprecations accumulated in Symfony 7.1-7.4 will need review: -- Check Symfony Profiler after upgrade for any new deprecation warnings -- Review [UPGRADE-7.0.md](https://github.com/symfony/symfony/blob/7.0/UPGRADE-7.0.md) -- Review [UPGRADE-7.4.md](https://github.com/symfony/symfony/blob/7.4/UPGRADE-7.4.md) - ---- - -## Upgrade Procedure - -### Phase 1: Preparation (15 minutes) - -1. **Create Feature Branch** - ```bash - git checkout -b feature/symfony-7.4-upgrade - ``` - -2. **Backup Current State** - ```bash - git tag before-symfony-7.4-upgrade - ``` - -### Phase 2: Dependency Updates (30 minutes - 1 hour) - -1. **Update composer.json** - - Update all Symfony package constraints to `7.4.*` - - Update `extra.symfony.require` to `"7.4.*"` - - Consider tightening `php` to `>=8.2` (Symfony 7.4 requires 8.2+; optional if already on 8.3) - -2. **Run Composer Update** - ```bash - ddev composer update - ``` - -3. **Review Recipe Updates** - ```bash - ddev composer recipes - ``` - Review any recipe updates from Symfony Flex and apply as needed. - -4. **Clear All Caches** - ```bash - ddev exec bin/console cache:clear - ddev exec bin/console cache:warmup - ddev exec "php -r 'opcache_reset();'" - ``` - -### Phase 3: Testing & Validation (1-2 hours) - -1. **Run PHPUnit Test Suite** - ```bash - ddev exec ./vendor/bin/phpunit - ``` - Check for: - - Test failures - - Deprecation warnings - - Fatal errors - -2. **Run PHP-CS-Fixer** - ```bash - ddev php vendor/bin/php-cs-fixer fix --dry-run --diff - ``` - -3. **Manual Testing - Critical Paths** - - [ ] User authentication (BPN API login) - - [ ] OAuth2 token generation (`/token` endpoint) - - [ ] OAuth2 authorization flow (`/authorize` endpoint) - - [ ] API endpoints (all `/api/*` routes) - - [ ] Booking creation flow (Steps 1-4) - - [ ] Participant form rendering and submission - - [ ] Dynamic field updates (HTMX) - - [ ] Real-time pricing calculations - - [ ] Insurance selection and filtering - - [ ] Transportation service selection - - [ ] Payment method selection - - [ ] Final booking submission to BPN API - - [ ] Booking edit functionality - - [ ] PDF/XML download functionality - - [ ] User registration - - [ ] Password reset - - [ ] Personal data management - - [ ] EasyAdmin CRUD / admin panels - -4. **Check Symfony Profiler** - - Review deprecation warnings (should be minimal) - - Check performance metrics - - Verify no errors in logs - -5. **Test Frontend Assets** - ```bash - npm run build - ``` - - Verify Stimulus controllers load correctly - - Test HTMX interactions - - Verify Toastify notifications - - Check TailwindCSS compilation - -6. **Verify ZIP File Functionality** - - Test any features using `nelexa/zip` (package last updated 2022) - - Verify document generation and downloads work correctly - -### Phase 4: Bug Fixes (0-2 hours) - -Address any issues discovered during testing: - -1. **Review Error Logs** - ```bash - ddev logs - ``` - -2. **Fix Any Remaining Deprecations** - - Use Symfony Profiler to identify deprecations - - Update code to use modern alternatives - -### Phase 5: Deployment (1 hour) - -1. **Deploy to Staging** - ```bash - ddev exec vendor/bin/dep deploy staging - ``` - -2. **Staging Validation** - - Full regression testing - - Performance testing - -3. **Production Deployment** - - Schedule maintenance window - - Deploy during low-traffic period - - Monitor error logs closely - ---- - -## Rollback Plan - -### Immediate Rollback - -If critical issues are discovered: - -1. **Git Revert** - ```bash - git checkout master - git reset --hard before-symfony-7.4-upgrade - ``` - -2. **Restore Dependencies** - ```bash - ddev composer install - ``` - -3. **Clear Caches** - ```bash - ddev exec bin/console cache:clear - ``` - -### Production Rollback - -If issues occur in production: - -```bash -ddev exec vendor/bin/dep rollback production -``` - ---- - -## Testing Checklist - -### Unit Tests -- [ ] All PHPUnit tests pass (433 tests) -- [ ] No new deprecation warnings -- [ ] Code coverage maintained - -### Integration Tests -- [ ] BusProNet API integration -- [ ] XML parsing and data processing -- [ ] Booking price calculations -- [ ] Insurance assignment logic -- [ ] Field handler system - -### Functional Tests -- [ ] User authentication flow -- [ ] OAuth2 token generation -- [ ] API endpoints respond correctly -- [ ] Booking creation (all steps) -- [ ] Form validation -- [ ] HTMX partial updates -- [ ] Dynamic field state changes -- [ ] Real-time pricing updates -- [ ] Toast notifications - -### Browser Testing -- [ ] Chrome (latest) -- [ ] Firefox (latest) -- [ ] Safari (latest) -- [ ] Mobile browsers - ---- - -## Timeline Estimate - -| Phase | Estimated Time | Notes | -|-------|---------------|-------| -| **Phase 1:** Preparation | 15 min | Branch creation | -| **Phase 2:** Dependency Updates | 30 min - 1 hour | composer.json updates, composer update | -| **Phase 3:** Testing & Validation | 1-2 hours | Automated + manual testing | -| **Phase 4:** Bug Fixes | 0-2 hours | Address any issues | -| **Phase 5:** Deployment | 1 hour | Staging deployment | -| **Total** | **2.5-6 hours** | Average: **3.5 hours** | - ---- - -## Future Considerations: Symfony 8.0 - -Symfony 8.0 was released alongside 7.4 (November 2025) with identical features but: -- Requires PHP 8.4 -- No deprecation layers (all deprecated code removed) -- Shorter support window (8 months) - -**Recommendation:** Stay on Symfony 7.4 LTS for stability. Plan PHP 8.4 upgrade separately, then consider Symfony 8.x path. - ---- - -## Success Criteria - -- [ ] All PHPUnit tests pass (433 tests) -- [ ] No deprecation warnings in Symfony Profiler -- [ ] All critical user flows functional -- [ ] OAuth2 authentication working -- [ ] BPN API integration operational -- [ ] Booking creation flow complete -- [ ] Frontend assets compile and load -- [ ] Performance metrics comparable or better -- [ ] No errors in production logs after 24 hours - ---- - -## Additional Resources - -### Official Symfony Documentation -- [Upgrade Major Version Guide](https://symfony.com/doc/current/setup/upgrade_major.html) -- [UPGRADE-7.0.md](https://github.com/symfony/symfony/blob/7.0/UPGRADE-7.0.md) -- [UPGRADE-7.4.md](https://github.com/symfony/symfony/blob/7.4/UPGRADE-7.4.md) -- [Symfony 7.4 Release Notes](https://symfony.com/releases/7.4) -- [Preparing for Symfony 7.4 and 8.0](https://symfony.com/blog/preparing-for-symfony-7-4-and-symfony-8-0) - -### Bundle-Specific Documentation -- [OAuth2 Server Bundle](https://github.com/thephpleague/oauth2-server-bundle) -- [Doctrine ORM 3.x Documentation](https://www.doctrine-project.org/projects/orm.html) - ---- - -**Document Version:** 7.0 -**Previous Version:** 6.0 (dated 2026-01-09) -**Last Updated:** 2026-02-23 -**Status:** Ready for Symfony 7.4 Upgrade (updated for current project state) diff --git a/docs/contingent-api-plan.md b/docs/contingent-api-plan.md deleted file mode 100644 index 120c85c..0000000 --- a/docs/contingent-api-plan.md +++ /dev/null @@ -1,39 +0,0 @@ -# Contingent API Status - -## Summary -The contingent API is implemented on `master`. It serves cached availability data from `HotelZimmer_*.xml` files in `var/xmlexportzimmer`, using Flysystem and the tag-aware `bpn.cache` pool. XML sync now covers both travel and contingent datasets, invalidates `xml-sync` tagged cache entries, and logs dataset transfer errors without aborting the command. - -## Implemented -- OAuth-protected endpoints: - - `GET /api/contingents?hotelRef={hotelRef}&dateRef={dateRef}` - - `GET /api/contingents/rooms?hotelRef={hotelRef}&dateRef={dateRef}&dateFrom={Y-m-d}&dateTo={Y-m-d}` - - `GET /api/contingents/calendar?hotelRef={hotelRef}&dateFrom={Y-m-d}&dateTo={Y-m-d}` -- `hotelRef` and `dateRef` accept numeric IDs or business codes; date codes are sanitized before lookup. -- Parser/loader/service/controller flow is implemented via `ContingentParser`, `ContingentLoader`, `ContingentDataService`, and `ContingentController`. -- Room responses include per date + room availability, pricing, status, and `bookingUrl`. -- BelKal control-room rows override date status and set room availability to `0` for affected dates. -- Room-level contingent links and one-hop root-level file links are supported. -- `app:bpn:xml-sync` syncs travel and contingents, invalidates `xml-sync` cache tags, and refreshes travel snapshots only when travel data synced. -- `app:bpn:xml-cache-invalidate` checks both travel and contingent local XML exports. - -## Config -- `.env` defines `XML_EXPORT_CONTINGENTS_PATH` and `SFTP_XML_EXPORT_CONTINGENTS_*`. -- `config/packages/flysystem.yaml` defines: - - `xml_export_contingents.storage` - - `xml_source_contingents.storage` -- `config/services.yaml` wires contingent storage, `bpn.cache`, and `APP_BASE_URL` for booking URL generation. - -## Behavior Notes -- Missing contingent XML returns empty data. -- Unknown travel/date or hotel/date mismatches return `404` from the API. -- Invalid date ranges or formats return `400`. -- Dataset transfer failures are shown and logged as warnings, but `app:bpn:xml-sync` still completes with exit code `0`. - -## Remaining TODOs -- Decide whether room responses still need travel metadata fields such as `summer`, `servicesIncluded`, and `servicesOptional`; these are not currently implemented. -- If the XML files grow materially or cold-cache parsing becomes slow, revisit whether `ContingentParser` should move from DOM/Crawler parsing to a streaming parser. -- Validate the deployed contingent SFTP environment variables before enabling scheduled sync in production. - -## Verification -- Covered by parser, loader, data service, controller, booking URL, XML sync, and cache invalidation tests. -- Current verification command: `php bin/phpunit`. diff --git a/src/Controller/Api/NewsletterSubscriptionController.php b/src/Controller/Api/NewsletterSubscriptionController.php index 6421266..c0df923 100644 --- a/src/Controller/Api/NewsletterSubscriptionController.php +++ b/src/Controller/Api/NewsletterSubscriptionController.php @@ -96,6 +96,9 @@ class NewsletterSubscriptionController extends AbstractController ], $extra), Response::HTTP_BAD_REQUEST); } + /** + * @return array + */ private function responsePayload(NewsletterSubscriptionRequestResult $result): array { return [ diff --git a/src/Controller/Booking/Create/Step4Controller.php b/src/Controller/Booking/Create/Step4Controller.php index 136da78..435b283 100644 --- a/src/Controller/Booking/Create/Step4Controller.php +++ b/src/Controller/Booking/Create/Step4Controller.php @@ -109,7 +109,7 @@ class Step4Controller extends AbstractBookingCreateController && $form->has('newsletterOptIn') && true === $form->get('newsletterOptIn')->getData(); - if (true === $newsletterOptInSelected && null !== $newsletterTargetEmail) { + if (true === $newsletterOptInSelected) { try { $targetParticipant = $this->resolveNewsletterTargetParticipant($bookingCreateDto); $this->doubleOptInService->requestDefaultListSubscription(