Appearance
<div style="display: none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /changelog/Changelog.4.116.md for this page in Markdown format</div>
Version 4
version 4.116
[4.116.0] feat(forms): add a product return form
- Why. There was no structured way for a customer to request a product return — return requests arrived as free-text contact-form messages with no order reference and no dedicated recipient, so shops triaged them by hand out of the generic contact inbox.
- The change. A new
returnFormcontact form (name / phone / email / order number / comment, config-driven viacontact_forms.php) served atforma-epistrofis. Submission is validated and stored incontact_emails, then the request is emailed immediately to the shop's recipient — a new Return form recipient e-mail field in admin Notification Settings (registryRETURN_FORM/RECIPIENT_EMAIL, falling back to the contact-form admin email) — and a copy is sent to the customer. Email subjects are overridable via registryEMAIL_SUBJECTS/returnForm(customer) andEMAIL_SUBJECTS/returnFormRecipient(shop), with language-key defaults. New base controller actionAdv_forms::returnForm(), a newAdv_mailer::sendReturnFormEmail(), front viewsreturn_form/return_form_success, and thereturn_formmail template. The front view renders optionalreturn-form-contentsub-content above the form. - Language keys. 13 new keys across all 8 languages: form labels and
return.form.*messages/subjects inadv_theme_lang,widgets.contact.*email labels inadv_external_lang, and the admin setting label inadv_advisable_lang. - No REST API changes.
[4.116.0] fix(build): content-address CSS bundle filenames to stop rolling-deploy CDN caching from serving stale styles (Advisable-com/ecommercen#431)
- Why. CSS bundles were versioned with a query string (
name.css?id=<manifestHash>) on an otherwise fixed filename. Nginx ignores the query string when serving the static file, so during a rolling deploy a request could land on a pod still holding the previous build'sname.cssbytes while carrying the new deploy's?id=; Cloudflare caches by full URL (query string included), so it would then cache those stale bytes under the new?id=URL for the full ~4h edge TTL — silently serving unstyled/broken pages to visitors for hours after a deploy, with no way out short of a manual edge purge. - The change.
webpack.mix.front.jsandwebpack.mix.admin.jseach gained a post-buildmix.then()step that content-hashes the compiled CSS (name.<hash>.css), writes the hashed file alongside the original, and rewrites the mix manifest so the bare key resolves to the hashed path — everyassetUrl()call site picks up the new filename automatically with no query string involved, so a stale filename can never resolve to new bytes (or vice versa) regardless of which pod or edge cache answers the request. The one hardcoded CSS<link>inapplication/views/admin/site_mode/main.phpwas converted toassetUrl()so it benefits too. - No REST API, DB migration, or language-key changes.
- Why. CSS bundles were versioned with a query string (
[4.116.0] chore(build): add a
job/check-containerCLI command as a lightweight DI-container compile check (Advisable-com/ecommercen#429)- Why. The agent
/deliververify step usedphp cli.php job/GenerateOpenApiJsonas a "does the DI container still compile" proxy, but that job rewrites three git-tracked spec files (public/openapi.json,openapi-v1.json,api-versions.json) even when no@OAannotation changed and takes >2 min — polluting the working tree and exceeding the agent's default command timeout. - The change. A new additive
AdvJob::checkContainer(), reached via a dedicatedjob/check-containerroute registered above thejob/(.+)catch-all (so it does not flow throughAdvJob::index(), whosecatchswallows failures and returns exit 0), boots and compiles the DI container viadi()and reports the result via exit code — 0 = compiled clean, 1 = DI/compile error (message echoed), 2 = wrong environment (fail-loud; onlydevelopmentguarantees a fresh compile) — while writing no files. It catches\Throwable(a missing class during compile surfaces as a PHP\Error, not an\Exception). Adds acomposer run check-containeralias mirroringopenapi-jsonand documents the command in CLAUDE.md. - No REST API, DB migration, or language-key changes.
- Why. The agent
Notes
- [4.116.0] Check for overrides: CSS bundle filenames are now content-hashed (
name.<hash>.css) instead of?id=-query-string versioned on a fixed filename:- Any client
application/views/**override with a hardcoded bare/ui/.../name.css<link>(bypassingassetUrl()) will keep serving the stale unhashed file — route CSS<link>s throughassetUrl(). - Clients maintaining their own
webpack.mix.front.js/webpack.mix.admin.js(or adding SCSS page bundles / a PurgeCSS profile) must port the newmix.then()CSS-hashing pass and extend its entry-name array to cover their extra bundles. - New hashed
name.<hash>.cssartifacts now appear inpublic/ui/main/css/andpublic/ui/admin/dist/— build tooling that enumerates CSS output by exact bare filename should account for them.
- Any client