Skip to content

<div style="display: none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /changelog/Changelog.4.115.md for this page in Markdown format</div>

Home | Changelog

Version 4

version 4.115

  • [4.115.1] chore(claude): enable the ecommercen-frontend agent slice + marketplace auto-update (Advisable-com/ecommercen#428)

    • Why. The frontend-developer agent (Vue 2 storefront/admin, CI3 view templates, SCSS, assets/**, the laravel-mix/Vite build) ships in the ecommercen-frontend marketplace slice, but a slice declared in the catalog is not active in a consuming repo until that repo enables it — otherwise the agent coordinators (/deliver, /work-issue) fall back to a convention-unaware general-purpose agent for presentation-layer work.
    • The change. .claude/settings.json enables ecommercen-frontend@ecommercen-platform (the slice was promoted to this repo's pinned stable channel first) and sets autoUpdate: true on the ecommercen-platform marketplace so plugins stay current team-wide. Developer tooling only — no application runtime, REST API, or language-key changes. Enabling in committed settings is not installing; each developer completes a one-time first-trust install / /reload-plugins.
  • [4.115.1] fix(payment/xpay): accept the real Nexi/XPay Greece S2S payment-notification shape in XPay::parsePaymentNotification() (Advisable-com/ecommercen#427)

    • Why. parsePaymentNotification() required a top-level order object and read the merchant order id from order.orderId — but real Nexi/XPay Greece server-to-server notifications carry no top-level order; the merchant order id lives in operation.orderId (with the outcome in operation.operationResult). Every S2S notification was rejected at parse time, so orders relying on the webhook were never confirmed instantly — only rescued minutes later by the reconcile/status-poll path.
    • The change. parsePaymentNotification() now sources the order id from operation.orderId, falling back to the top-level order.orderId (the order-creation shape), and no longer requires a top-level order to be present. The checkout webhook's CALLBACK audit-log tag in Adv_checkout.php also now reads operation.orderId so it no longer logs UNKNOWN. Both S2S webhook consumers — regular checkout and gift cards — are fixed. No method signature or visibility change; the acceptance contract only widened, so there's no BC break for subclasses. The SeaJets fork ships a Custom\PaymentGateway\Nexi shim that normalises operation.orderId to order.orderId to work around this bug — once this lands upstream, that shim is redundant and can be removed.
    • Tests. Corrected the XPay unit tests to the real notification shape — they previously asserted the operation-only shape should throw, i.e. they blessed the bug.
    • No REST API or language-key changes.
  • [4.115.1] chore(docker): make Xdebug toggleable via XDEBUG_MODE / XDEBUG_START_WITH_REQUEST env vars in the Docker dev stack (Advisable-com/ecommercen#341)

    • Why. Xdebug was always on in the dev containers — configs/xdebug.ini hardcoded xdebug.mode=debug,profile and xdebug.start_with_request=yes — so every dev page load and CLI run paid the (profiling-heavy) Xdebug overhead, and the only way to opt out was editing tracked compose/ini files.
    • The change. The php-fpm (web-dev.compose.yml) and php-cli (dev.compose.yml) services now pass XDEBUG_MODE (native Xdebug 3 runtime override of xdebug.mode) and XDEBUG_START_WITH_REQUEST (consumed via ${ENV} interpolation in xdebug.ini) into the containers, with compose-level defaults debug,profile / yes preserving the previous always-on behavior — an existing .docker/integration/.env without the new vars changes nothing. A developer sets XDEBUG_MODE=off (or XDEBUG_START_WITH_REQUEST=trigger) in their gitignored .env and restarts the containers — no rebuild, no tracked-file edits. Documented in .env.example and docs/guides/docker/local-development.md ("Toggling Xdebug"). Dev/integration tooling only — prod images still strip xdebug.so; no application runtime, REST API, or language-key changes.
  • [4.115.0] refactor(piraeus): add an overridable CardholderName seam at the Piraeus IssueNewTicket sites (Advisable-com/ecommercen#423)

    • Why. The customer name sent as CardholderName to the Piraeus/Paycenter IssueNewTicket call was assembled inline at all three construction sites — the modern src/Piraeus/Piraeus request builder, the legacy Adv_checkout::_piraeus, and AdvGiftCardPage::piraeusFormData. A client needing gateway-specific name sanitization (stripping characters the gateway rejects) had to copy a whole action to change one line; the joypharmacy fork carried a ~99-line copy of Checkout::_piraeus solely for this.
    • The change. Each site now routes the name through a protected formatPiraeusCardholderName() seam whose base implementation returns it unchanged — byte-for-byte identical behavior, fully backwards-compatible — so a client subclass overrides one method instead of duplicating the action. Whether core should sanitize by default (a charset decision dependent on the Paycenter spec and which clients run Piraeus) is tracked in #425. The modern src/Piraeus/Piraeus seam is overridable by subclass but not yet reachable via DI at its new Piraeus(...) construction site in PaymentInitializerFactory::registerPiraeus() — a noted follow-up.
    • Tests. PiraeusTest asserts the modern seam sends the name unchanged (incl. non-ASCII) and that a subclass override reaches the gateway request; AdvCheckoutTest and AdvGiftCardPageTest add reflection parity coverage for the two legacy seams (surname-then-name concatenation, non-ASCII pass-through, empty-parts spacing).
    • No REST API or language-key changes.
  • [4.115.0] refactor(admin): add no-op extension seams to Adv_orders_admin and Adv_transporters_admin (Advisable-com/ecommercen#424)

    • Why. Following the #417 template-method retrofit of the admin controllers, two sites still forced client forks to copy a whole action just to inject 1–2 lines: Adv_orders_admin's add()/edit()/repeat() built the Vue jsonState inline, and Adv_transporters_admin::pricingOptions() assembled its view data inline before defaultRender().
    • The change. Two additive, protected, no-op template-method seams mirroring the #417 pattern: extendJsonState(array $jsonState, string $action) — invoked immediately before each jsonEncodeForVue() on the orders add/edit/repeat paths (the $action string identifies the caller), returning the state unchanged by default; and pricingOptionsViewData(int $transporterId, object $transporter) — merged into $this->render just before defaultRender(), returning [] by default. Zero behavior change, fully backwards-compatible; a fork overrides one method instead of copying the whole action. Both seam names were verified collision-free against the joypharmacy fork (the #417/PR-#67 class-load guard).
    • Tests. AdvOrdersAdminHooksTest and AdvTransportersAdminHooksTest — no-DB reflection parity guards: hook contract (visibility/return type/signature), the no-op default (state returned unchanged for each action; [] view data), and independent subclass overridability.
    • No REST API or language-key changes.
  • [4.115.0] refactor(admin): expose a sampleCurrencyId() seam on AdvEmailViewer (Advisable-com/ecommercen#422)

    • Why. AdvEmailViewer::index() hard-coded the sample currency id (getCurrencyData(1)) used to build the email-preview order data, so a client wanting to preview with its own currency had to copy the whole method.
    • The change. A protected sampleCurrencyId(): int seam replaces the two hard-coded literals; its base implementation returns the original value (1), so behavior is unchanged and a fork overrides one method.
    • Tests. AdvEmailViewerHooksTest — reflection parity guard: hook contract, the preserved default (1), and subclass overridability.
    • No REST API or language-key changes.