1. 09 Nov, 2026 3 commits
  2. 06 Nov, 2026 4 commits
    • Symfony 8.1, DoctrineBundle 3, API Platform 5 · f67f1b6a
      - Symfony 8.1, DoctrineBundle 3.3, API Platform 5.0, monolog-bundle 4,
        geocoder-bundle 6, doctrine-fixtures-bundle 4, PHPMD 3.
      - Removed Symfony aliases: Routing\Attribute\Route and
        Serializer\Attribute\Groups/MaxDepth instead of the Annotation ones (the
        routes and the serialization groups were silently ignored).
        AttributeClassesTest checks that every attribute class exists.
      - Attribute routes loaded with their namespace (PSR-4 loader).
      - SonataFormatterBundle removed (no Symfony 8.1 support): FOSCKEditorBundle
        required directly, CKEditor media browser and upload ported
        (App\Admin\CkeditorAdminExtension, CkeditorAdminController), with
        CkeditorMediaTest.
      - cron/cron-bundle removed (its cron/cron library does not support
        Symfony 8; the crons call the kohinos:* commands); its tables are kept.
      - monolog: excluded_http_codes instead of excluded_404s; dead EasyLog
        handler configuration removed.
      - composer audit.block-insecure enabled again; unused abandoned packages
        removed (package-versions-deprecated, deployer/recipes).
      Damien Moulard authored
    • Prepare Symfony 8 on Symfony 7.4 · df06149b
      - Request::get() (removed in Symfony 8): App\Utils\RequestParameter::get()
        keeps the same lookup (route, query, posted data) where the source is not
        certain; route attributes used directly for the admin id and _route.
      - Validation constraints configured with named arguments instead of option
        arrays; Url requireTld and UrlType default_protocol explicit (current
        values kept, their defaults change in Symfony 8).
      - UserChecker::checkPostAuth() token argument; eraseCredentials() no longer
        used (the plain password is cleared by UserFieldsUpdater).
      - #[MapEntity] for the {slug} routes, Doctrine controller auto mapping off
        (removed from DoctrineBundle 3).
      - Doctrine native lazy objects; ClassUtils replaced.
      - PHP routing files instead of the XML ones (Sonata Admin, Sonata Media,
        profiler, errors), Payum YAML routing.
      - Explicit property_info.with_constructor_extractor, profiler serializer
        data, Liip Imagine lazy Twig mode, translation_domain instead of
        label_catalogue, Lexik fallback locales from the framework.
      - AdminExportTest: dates computed from the current date normalised.
      Damien Moulard authored
  3. 05 Nov, 2026 13 commits
    • Fix the home page and the admin assets (reported after step 4) · ffbfe0b0
      - MenuManager::getMenuItems(): undefined constant as default value
        (self::ALL_ELEMENTS, since the copy of prodigious/sonata-menu in step 1b),
        evaluated by the debug tools in dev: 500 error on the home page, hence the
        Symfony error page JS error and the toolbar 404 loop.
        ConstantExpressionsTest evaluates all default values and constants of src/.
      - Admin stylesheet: default asset package (Encore manifest), Sonata Admin
        4.3x uses its own package for extra_stylesheets: 404 with a prod build.
      - Admin layout: jQuery UI datepicker initialisation removed (jQuery UI is no
        longer loaded since Sonata 4, $.datepicker was undefined; the fields are
        native HTML5 date fields).
      Damien Moulard authored
    • Doctrine DBAL 4 · 645dd2f1
      - DBAL 4.5 (required by DoctrineBundle 3, needed for Symfony 8).
      - array/object types (removed from DBAL 4): App\Doctrine\Type\Serialized
        ArrayType/ObjectType, same storage as DBAL 3 (roles, Flux::$data, Gedmo
        log entries, Payum tokens): no data migration.
      - Migration: the DC2Type column comments are removed (162 columns, comment
        only: types, nullability and defaults checked unchanged; down() restores
        the original schema exactly, tested).
      - Explicit decimal precision (10, the former DBAL default) and string length
        (classification context id), now required.
      - Old migrations: platform check without getName() (removed), and
        IdToUuidMigration getLocalColumns(): a fresh install (all migrations on an
        empty database) works and gives the mapped schema.
      Damien Moulard authored
    • Symfony 7.4, Doctrine ORM 3, API Platform 4, Lexik Translation 8 · 068be70f
      - Symfony 7.4, Doctrine ORM 3.7 (DBAL 3), API Platform 4.4 (security
        advisories fixed), Lexik Translation 8.1, ramsey/uuid-doctrine 2,
        Knp Paginator 6, Vich 2, GrumPHP 2, Flex 2; proxy-manager-bridge removed.
      - Doctrine subscribers -> listeners: Symfony 7 silently ignores the
        doctrine.event_subscriber tag (UserFieldsDoctrineListener, FluxListener,
        UnitOfWorkListener were no longer called). ListenersTest added.
      - ORM 3 stricter mapping: JoinTable removed from inverse sides (they were
        ignored), wrong inversedBy removed (AchatMonnaieAConfirmer, SolidoumeParameter),
        fully qualified target entities; the mapping is now valid.
      - JSON columns kept in LONGTEXT (App\Doctrine\Type\JsonTextType, as the
        removed Sonata json type) instead of native JSON columns.
      - Migration: Sonata Media 4.20 / Lexik 8 column changes.
      - Impersonation: IS_IMPERSONATOR instead of ROLE_PREVIOUS_ADMIN (no longer
        granted since Symfony 6: the exit link was hidden), SwitchUserSubscriber
        token rebuilt without the removed SwitchUserRole.
      - Security class, SecurityRequestAttributes, repositories getEntityManager(),
        setParameter() instead of array setParameters().
      - API Platform 4: use_symfony_listeners, docs formats, OpenAPI parameters;
        responses unchanged except the Content-Type charset.
      - JSON adherent export: the cotisation profile as in the CSV export (the
        Doctrine proxy was exported).
      - Baseline: PHP errors are now 500 responses (handle_all_throwables).
      Damien Moulard authored
    • Sonata latest (Admin 4.43, Block 5, Intl 3...), Guzzle 6 removed · 1790ffdd
      - Sonata Admin 4.43, Block 5.5, Classification 4.11 (no longer pinned),
        Media 4.20, DoctrineORMAdmin 4.21, Formatter 5.5, Intl 3.3, Translation
        3.7, twig/form/doctrine-extensions 2.x: they all support Symfony 6.4,
        7.3+ and 8.0. StimulusBundle registered (required by Sonata Admin).
      - Datepicker form theme: the form-extensions 2 one (ours was an exact copy
        of the form-extensions 1 theme).
      - doctrine-extensions 2 has no JsonType: Doctrine's json type is used.
      - Filter\Configurator: the Sonata 4 actions (dashboard, search,
        autocomplete, ajax form fields...) replace the Sonata 3 CoreController
        and HelperController. Since the Sonata 4 upgrade, the enabled_filter was
        no longer disabled for them (disabled entities missing in the admin
        autocompletes). ConfiguratorTest added.
      - php-http/guzzle6-adapter (13 security advisories) removed: Payum uses
        symfony/http-client (HTTPlug), geocoding uses Psr18Client. psr/log 3.
      - lib/ekyna/payum-payzen: psr/log 1-3, no Guzzle requirement.
      - /admin/search works again for 3 profiles (baseline updated); still a 500
        for the 5 others, as before the migration.
      Damien Moulard authored
    • Prepare Doctrine ORM 3 · 1390f064
      - Lifecycle callbacks and listeners: Doctrine\Persistence LifecycleEventArgs,
        getObject()/getObjectManager() (getEntity()/getEntityManager() removed).
      - ImportController: find() instead of merge() (removed) to re-attach the
        logged in user.
      - Export iterator: Query::toIterable() instead of iterate() (removed).
      - DQL StrToDate: TokenType instead of Lexer constants; ClassMetadata
        instead of ClassMetadataInfo.
      - AdminExportTest: the adherent, prestataire and money purchase exports
        (CSV, JSON) are compared to a snapshot taken with the previous code.
      Damien Moulard authored
    • Remove doctrine/annotations · 53b8d2f6
      - cron/cron-bundle 3 (attribute mapping, same commands and tables).
      - SonataTranslationBundle: Gedmo integration disabled (no translatable
        entity, its listener needed the annotation reader).
      - Smoke test: lint the dev and prod containers in debug mode, so that a
        stale cache is rebuilt.
      Damien Moulard authored
    • Remove SensioFrameworkExtraBundle (abandoned, no Symfony 7 support) · 896a78be
      - #[IsGranted] of Symfony instead of the Sensio one.
      - #[Security("expression")] -> #[IsGranted(new Expression("expression"))].
      - #[ParamConverter] mappings -> #[MapEntity(mapping: ...)].
      - Entity arguments resolved by the route parameters with DoctrineBundle's
        EntityValueResolver (controller_resolver.auto_mapping, explicit).
      
      Routes identical, access codes unchanged for the 12 smoke test profiles.
      Damien Moulard authored
    • Doctrine DBAL 3 and DoctrineBundle 2.19 · fe0acb79
      - DBAL 3.10, DoctrineBundle 2.19, Doctrine Migrations 3.9 (ORM still 2.20).
      - Raw SQL: executeQuery()->fetchAllAssociative() instead of
        execute()/fetchAll() (same associative rows).
      - Migration: payment.details type comment json_array -> json (json_array
        no longer exists, the schema introspection failed).
      - json_array registered as an alias of json for the old migrations, and
        IdToUuidMigration adapted: a fresh install (all migrations on an empty
        database) works and gives exactly the mapped schema.
      - Decimal defaults written as strings, like the database ('0.00').
      Damien Moulard authored
    • Convert the annotations to PHP attributes · 25dd1d3d
      Done with Rector (attributes sets for Symfony, Doctrine, Gedmo and Sensio):
      Doctrine mapping (driver: attribute), routes, serializer groups, validation
      constraints, Gedmo extensions, Sensio IsGranted/Security/ParamConverter
      (still provided by SensioFrameworkExtraBundle for now).
      
      Checked identical before/after: routes (debug:router), Doctrine, validator,
      serializer and Gedmo metadata of every entity.
      Damien Moulard authored
  4. 04 Nov, 2026 11 commits
    • Prod: error emails with symfony/mailer instead of SwiftMailer · 15144e04
      The prod environment no longer booted (SwiftMailerHandler class not found).
      whatfailuregroup: symfony/mailer sends synchronously, a mail server failure
      must not prevent the critical file log.
      Damien Moulard authored
    • Fix the deprecations blocking Symfony 7 and PHP 9 · 0b1bdea5
      - Native return types required by Symfony 7 (form types, commands, Twig
        extensions, subscribers, transformers, Doctrine types...): only the 311
        methods reported by the DebugClassLoader.
      - Commands: #[AsCommand] instead of the static $defaultName (removed in
        Symfony 7).
      - Migrations: App\Utils\ContainerAwareMigrationInterface instead of
        ContainerAwareInterface (removed in Symfony 7, all migrations are loaded
        by doctrine:migrations).
      - Declared properties instead of dynamic ones (deprecated since PHP 8.2).
      - Explicit nullable parameters (PHP 8.4), number_format(null), ${var}
        strings, optional parameters before required ones.
      - ApiNormalizer: $context argument and getSupportedTypes().
      - Kernel: .container.dumper.* parameters.
      Damien Moulard authored
    • Upgrade to Symfony 6.4 and API Platform 3 · dea5c895
      - Symfony 6.4.*, API Platform 3.4 (resources converted to the new
        metadata with api:upgrade-resource), Twig 3.
      - config/bootstrap.php: Dotenv(false) no longer means "no putenv" with
        Symfony 6: the env was not detected and .env.test.local not loaded, so
        the tests ran on the dev database. tests/bootstrap.php now refuses a
        database whose name does not contain "test".
      - API responses unchanged (ApiTest compares them to a snapshot taken with
        the previous version): null values kept, read group on /api/public/poi/all.
      - NelmioApiDocBundle removed: /api/doc and /api/doc.json redirect to the
        API Platform documentation (/api/docs).
      - gamez/ramsey-uuid-normalizer (abandoned) ported in App\Serializer.
      - sonata-project/classification-bundle kept on 4.4 (later versions need
        a newer Sonata Admin).
      - Twig 3: spaceless tag, for ... if, blocks under if (Twig 2 ignored these
        conditions: same output kept), Twig_* classes.
      - Container: ContainerInterface bound to service_container, token storage
        injected in the admins, AbstractController::get() removed.
      - Session storage factory, RoutingConfigurator, new handler signatures.
      Damien Moulard authored
    • Prepare Symfony 6 on Symfony 5.4: authenticators, mailer, session, twig/extensions · 47c7200a
      - Security: authenticator manager instead of Guard (LoginAuthenticator,
        EmailTokenAuthenticator, ApiKeyAuthenticator), UserAuthenticatorInterface
        for programmatic logins, password_hashers, PUBLIC_ACCESS, new
        UsernamePasswordToken signature, loadUserByIdentifier, getUserIdentifier.
      - Role choice while impersonating: rebuild the SwitchUserToken (was a 500
        error since Symfony 5: getRoles()/SwitchUserRole no longer exist).
      - Unknown email token: 401 instead of a 500 error.
      - LoginListener listens to LoginSuccessEvent and uses the request session.
      - Session: RequestStack::getSession() instead of the session service
        (removed in Symfony 6) in 36 classes.
      - SwiftMailer replaced by symfony/mailer (MAILER_DSN instead of MAILER_URL).
        DeferredMailer sends after the response and logs the errors, like the
        former memory spool.
      - twig/extensions removed: the truncate filter is ported in App\Twig\TextExtension.
      - Tests: AuthenticationTest (remember me, API key, email token, role choice
        while impersonating), email assertions, DeferredMailer and truncate unit tests.
      Damien Moulard authored
    • Fix payment terminal security holes, add payment tests · b92370dc
      - Payment code: crypt() with an empty salt returns '*0' for any code since
        PHP 8, and password changes left the salt empty since FOSUser removal:
        any code was accepted. Generate a salt again on password change and on
        code definition; PaymentCodeHasher rejects empty salts/hashes and uses
        hash_equals.
      - /encaissement: account, payment code and conventionnement maximum checks
        are now also done at the validation step, which could be posted directly.
      - tests/Smoke/PaymentTerminalTest: terminal access, success (prestataire,
        caissier), errors (no code, wrong code, insufficient balance, disabled
        account, unsalted code), conventionnement mode.
      - Shared functional test helpers moved to SmokeClientTrait.
      Damien Moulard authored
  5. 03 Nov, 2026 9 commits
    • Fix role choice routes broken by the App:Entity alias removal · daa7a9fe
      doctrine/persistence 3 no longer supports the short "App:Usergroup"
      entity notation: the role choice routes (/login/{presta,caissier,
      comptoir,groupe}/choice/...) failed with a 500 error. Use the full
      class names in the ParamConverter annotations.
      
      Add tests logging in, choosing each role and reaching a page reserved
      to it.
      Damien Moulard authored
    • Apply php-cs-fixer 3 to IndexController · 55200d5b
      Formatting only, no behavior change.
      Damien Moulard authored
    • Upgrade to Symfony 5.4 and PHP 8.5 · a8735855
      Move to Symfony 5.4 running on PHP 8.5 (composer requires PHP >= 8.4).
      Only the dependencies requiring it are upgraded: API Platform 2.7, ORM
      2.20 (DBAL stays on 2.13), knp-paginator 5, lexik translation 6,
      sensio extra 6, shivas versioning 4, exporter 3, nelmio api-doc 3.10.
      SwiftMailer and the Guard authenticators still work on 5.4 and will be
      replaced with Symfony 6.
      
      Code adapted to Symfony 5: kernel event classes, contracts translator,
      token role names, form extension return types, legacy event base class,
      kernel.root_dir, Lexik controllers, decimal fields of the geoloc form.
      
      Fix regressions found by the tests:
      - @IsGranted with several roles meant "any of them"; Symfony 5.4 no
        longer supports several attributes and denied access to everybody on
        12 routes. Use explicit security expressions.
      - A comptoir form template rendered fields twice through parent().
      
      Tooling: php-cs-fixer 3 (.php-cs-fixer.dist.php), GrumPHP 1, the custom
      translation:update command is removed (use translation:extract). The
      smoke test keeps cookies around stateless API requests (mock session
      storage artifact, checked against native sessions).
      Damien Moulard authored
    • Apply php-cs-fixer 3 to files touched by the Symfony 5.4 upgrade · 53d494f6
      Formatting only, no behavior change (php-cs-fixer 3 rules, same
      configuration).
      Damien Moulard authored
    • Test prestataire creation from the admin · bf1f5bfc
      Covers the encrypted IBAN storage and the creation of a user linked to
      the new prestataire (MLCEvents::REGISTRATION_PRESTATAIRE).
      Damien Moulard authored
    • Fix event dispatching and inconsistent Doctrine associations · e9ec6c0d
      The business events (MLCEvents::REGISTRATION_*, FLUX) were dispatched
      with the legacy argument order dispatch($name, $event), which Symfony
      4.4 only accepts for events extending the legacy Event class: since
      FOSUserBundle's UserEvent was replaced, creating an adherent, a
      prestataire, a caissier or a user failed. Use dispatch($event, $name),
      also required by Symfony 5. Add a test creating an adherent from the
      admin.
      
      Fix four inconsistent bidirectional associations reported by
      doctrine:schema:validate (wrong mappedBy/inversedBy, Allocation's two
      one-to-one relations sharing the same inverse side) and a lowercase
      target entity. No schema change.
      Damien Moulard authored
    • Apply php-cs-fixer to entities touched by the mapping fixes · 42119226
      Formatting only, no behavior change.
      Damien Moulard authored
    • Fix untranslated labels of the user and group admins · fe2b789e
      LexikTranslationBundle replaces Symfony's translator and ignores
      framework.translator.paths, so the translations of the removed
      FOSUserBundle and SonataUserBundle copied in config/translations were
      never loaded: the user admin showed raw keys (users,
      list.label_username...). Move the keys the project does not define
      to translations/vendor/ (no overlap, so the project files still win).
      
      Sonata 4 translates tab and group labels with the admin label strategy:
      give the user and group admin tabs and groups their former labels, and
      the former classname label to the group admin (breadcrumbs).
      
      Add a test checking that the user and group admin pages show no raw
      translation key.
      Damien Moulard authored
    • Upgrade to Sonata 4 and replace the abandoned bundles · da2bfaab
      Sonata Admin 3 only supports Symfony 4.4. Upgrade to the latest Sonata 4
      versions still compatible with Symfony 4.4 / PHP 7.4 (admin 4.22,
      doctrine-orm-admin 4.9, media 4.6, classification 4.3, block 4.19,
      formatter 5.0, translation 3.1), which requires DoctrineBundle 2.7,
      ORM 2.14 and doctrine/common 3. DBAL is kept on 2.13 for now.
      
      Bundles incompatible with DoctrineBundle 2 or Sonata 4 are replaced:
      - specshaper/gdpr-bundle: the prestataire IBAN uses a new
        encrypted_text Doctrine type (same algorithm and key). A reversible
        migration unwraps the stored values from the GDPR serialized object;
        the 33 existing IBAN are checked to decrypt identically.
      - prodigious/sonata-menu-bundle and pixassociates/sortable-behavior-
        bundle: their code is copied in the application (MIT), keeping the
        same tables and admin codes (roles stored in database).
      - Unused bundles removed: doctrine-encrypt, JMS serializer, knp
        markdown, roromix spreadsheet, doctrine cache, easy extends.
      
      Admins, CRUD controllers, the security handler, the export data
      sources and the templates are adapted to Sonata 4 without behavior
      change; the admin layout now extends Sonata's one and only overrides
      the Kohinos blocks. Migrations handle the Sonata Media/Classification 4
      schema changes and the renamed gallery item roles.
      
      The smoke baseline only changes for removed pages (/gdpr, public media
      galleries, CKEditor browser URL) and admin AJAX/search URLs called
      without parameters. See doc/migration-symfony8.md.
      Damien Moulard authored