Commit Graph
116 Commits
Author SHA1 Message Date
frommeandClaude Opus 5.5 26a7d5f78a chore: extension icons from the E&P logo, ep_theme is stable
The icon is the E&P signet on a square canvas. ep_theme's
Resources/Public is build output, so its icon is copied there by
the asset build from Resources/Private/Assets/icons.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 11:46:36 +01:00
frommeandClaude Opus 5.5 8f667e92ee chore: EXT:felogin removed
Not in use: no login form in the content, and no group grants it.
Its TypoScript and the felogin_login content type are gone with it;
the TypoScript of all other keys and the frontend output are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 11:46:36 +01:00
frommeandClaude Opus 5.5 0ac58c1033 feat: sites get their TypoScript from the site set ep/theme
The set includes the same ep_theme TypoScript the root templates
included statically, and config/sites/*/settings.yaml hold the
constants of each site's root template, generated with TYPO3's own
TypoScript parser and kept under their old names, so no TypoScript
changes. They are plain values without definitions, so nothing is
type-converted.

Rolling out takes a second step: the root templates, with their clear
flags, still replace everything the set provides, so this deploy alone
changes nothing. .ddev/plans/sql/2026-10-27-site-sets.sql then hides
them and moves their setup (date picker presets, partner IDs, ...) into
extension templates editors keep maintaining. Extension templates
further down the tree keep applying on top.

Verified locally on a prod copy:
- the resolved constants and setup of 43 pages (every site root, every
  page with an extension template below it, every page layout) are
  identical before the deploy, between deploy and SQL, after the SQL
  and after its rollback
- a crawl of all 1912 frontend URLs is identical before and after

Rollback: always run 2026-10-27-site-sets-rollback.sql BEFORE rolling
back this code, or the sites have no TypoScript at all in between.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 11:46:26 +01:00
frommeandClaude Opus 5.5 903292d84c feat: products can have their own text in the subsite popup
The popup that announces the switch to another site (e.g. from a
teaser on ep-reisen.de to semesterende-skireisen.de) showed the text of
the product's concept for every product. A product now has an optional
popup text (new "Popup" tab) that replaces the concept's; empty, the
concept's text stays. Title, image and button remain the concept's, and
whether a popup appears at all is still up to the concept.

Teasers pass the product to the popup request. Pages cached before the
deploy request it without one and get the concept's text, as before.

The new column tx_epproducts_domain_model_product.popup_text is the only
pending schema change; the deploy's extension:setup adds it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 11:41:18 +01:00
frommeandClaude Opus 5.5 170e14dae5 fix: product pages no longer serve one visitor's back link to everyone
The "back to search results" link took ?ref= as it came and was cached
with the page, which ignores ref: the first visitor of a product page
set the link for every later one, and a javascript: URL in ref put
script into the page for all of them (verified locally).

The page now always renders the link hidden and without a target; the
backlink Stimulus controller fills in the visitor's own ?ref= and shows
it, only for URLs of the same origin. The label stays "zurück zum
Suchergebnis": refs only come from the search, and the old check
(strpos() !== -1) always picked that label anyway.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 11:28:11 +01:00
frommeandClaude Opus 5.5 b428ce9086 feat: ddev anonymize-db removes personal data from production dumps
Runs automatically after every `ddev import-db`. Drops all zzz_deleted_
tables (renamed in production but still holding their data, e.g. the
retired address check and form answers), replaces names and emails of
backend and frontend users, sets every password to the local dev
password "password" and clears reset tokens and MFA secrets. Sessions,
record locks, CSP reports and logs are emptied (IP addresses, user
agents). Usernames stay, so everybody logs in locally as their own user.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 10:13:02 +01:00
frommeandClaude Opus 5.5 9265e0d1c1 fix: CKEditor 5 list item ids no longer end up in the content
CKEditor 5 saves a data-list-item-id attribute on every list item, which
it only needs inside the editor; it bloated the frontend HTML and the RTE
content the API and the content feed hand to MyE&P. Both RTE presets now
import ep_theme's Processing.yaml, which removes the attribute on the way
into the database (exitHTMLparser_db); everything else passes unchanged.

Content saved since the go-live is cleaned once by hand after the
deploy (.ddev/plans/sql/2026-10-26-rte-list-item-ids.sql).

Checked locally as an editor: an RTE field with list item ids is stored
without them, other attributes (class on li, data-* on links) stay;
without the change the ids are stored.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 13:05:46 +01:00
frommeandClaude Opus 5.5 c61dddfb1d chore: travel dates are no longer translatable
Dates are written by the import only and are never translated (all rows
are in the default language). Like the matchcodes, the table loses
languageField, transOrigPointerField, transOrigDiffSourceField, its
language columns and the Language tab in TCA; the database columns stay
until the schema clean-up.

Checked locally: frontend crawl (~1,900 URLs incl. the English pages) and
the backchannel APIs render the same as before, the editor check creates
records in all other tables.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 13:00:17 +01:00
frommeandClaude Opus 5.5 7d3b6faf6c fix: editors can create facts and lineup items again
New facts failed with "Field 'keywords' doesn't have a default value":
the column is TEXT NOT NULL without a database default and not part of
the form. It now gets a TCA default, like the passthrough text columns of
dates that are not in the form either.

Lineup items are inline children of the lineup content element on
standard pages. TYPO3 10 allowed the table there with
allowTableOnStandardPages(); the migration to
ctrl.security.ignorePageTypeRestriction only covered the slides, so
adding a lineup item failed with "Attempt to insert record on pages:...
where table is not allowed".

Checked locally as an editor: a new record of every table of ep_products
and ep_theme goes through FormEngine and DataHandler (dates excepted:
hidden, written by the import only).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 12:55:06 +01:00
frommeandClaude Opus 5.5 99cd3c1898 fix: editors can create records in the folders outside the sites again
Editors got "recordEditAccessInternals() check failed [ERROR: The
"languageField" field named "sys_language_uid" was not found in testing
record!]" for every new record of our tables, e.g. a hotel's additional
code or a new hotel. The record folders lie on the root level, outside
every site, and no form submitted the language field. TYPO3 10 then took
language 0 from sys_language; since TYPO3 11, DataHandler only takes the
default language from the record's site and sets none without a site, so
the access check for non-admins fails.

As stock TYPO3 expects it, the forms now submit the language: a Language
tab with sys_language_uid (default 0) and l10n_parent in the 27
language-aware tables of ep_products and ep_theme. Matchcodes (a hotel's
additional codes) are no longer translatable at all: none was ever
translated, and the feed, the API and the import read them without
language handling.

LabelService no longer reads from a missing record when the form of a
new record asks for a label.

Checked locally as an editor: FormEngine preselects language 0, and new
hotels, products, FAQs and additional codes are saved.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 12:31:55 +01:00
frommeandClaude Opus 5.5 ecd5ea66c5 refactor: type declarations via Rector
rector.php gets the typeDeclarations set: return types (void, array,
unions) where the code proves them, typed closures and arrow functions,
typed properties from constructors and assignments in the DTOs.

Skipped: rules that infer scalar or array parameter types from call
sites or docblocks, and the removal of casts the docblocks call
redundant. Values from the database, form input and the import feeds
arrive as strings and would throw instead of being converted (e.g. the
(int) cast of the newsletter list ids stays).

Checked locally: cache warmup, frontend crawl (~1,900 URLs), the
backchannel APIs and the newsletter form validation behave as before.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 11:21:12 +01:00
frommeandClaude Opus 5.5 4fe06267c9 refactor: code quality via Rector, strict types where safe
rector.php gets the codeQuality set: declare(strict_types=1) in the 85
files where Rector finds no call relying on scalar type juggling (mostly
TCA and configuration, models, the content feed API and the import
command), "or die" as "|| die", instanceof instead of null checks for
object types, early returns and self:: in final classes.

Hotel::setRooms() goes instead of getting the property Rector wanted to
declare: nothing calls it, and there is no rooms column any more.

Checked locally: cache warmup, the ep:* commands load, frontend crawl
(~1,900 URLs) and the backchannel APIs render the same as before.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 11:15:38 +01:00
frommeandClaude Opus 5.5 f4556ee75c refactor: remove dead code via Rector
rector.php gets the deadCode set: @param/@return/@var tags that only
repeat native types, === true comparisons, three unused constructor
dependencies (DateService, ProductDataService, AjaxWatchlistController),
the unused reseller lookup in ContextProcessor and an always-false check
in AbstractMappedFinisher (trimExplode with removeEmpty never yields an
empty remote name).

Checked locally: frontend crawl (~1,900 URLs) and the backchannel APIs
render the same as before.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 11:10:20 +01:00
frommeandClaude Opus 5.5 9347112d6b refactor: private instead of protected where nothing relies on it, constructor promotion
Members (properties, methods, constants) become private when they are
declared in the class itself, no parent class or interface declares them,
no ancestor in packages/ uses them and the class has no subclass in
packages/: 115 members in 36 files. Extbase domain objects keep protected
properties, AbstractDomainObject sets them from the parent class.

With the properties private, Rector's constructor promotion now also
applies to the controllers and services that still assigned their
dependencies by hand (26 files).

Checked locally: frontend crawl (~1,900 URLs) and the backchannel APIs
render the same as before.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 11:05:45 +01:00
frommeandClaude Opus 5.5 b51fa4ddad refactor: PHP 8.5 language features via Rector
rector.php gets the PHP sets up to 8.5. Mostly constructor promotion with
readonly properties, typed class constants, ??=, arrow functions,
str_contains/str_starts_with, catch without unused variables, array_any
and #[\Override] on overridden properties; array_key_exists() keys are
cast to string (null keys are deprecated in PHP 8.5). Long promoted
constructor signatures are wrapped one parameter per line.

Checked locally: a crawl of ~1,900 frontend URLs over all sites and the
backchannel APIs (/api/hotel, /api/product, content feed manifest and
records of every type) render the same as before.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 10:59:53 +01:00
frommeandClaude Opus 5.5 96632edf44 fix: hotel and product images in the API no longer depend on cache order
The image services cached under images-<table>-<uid> without the field, so
the teaser images (teaser_images, rendered by the frontend) and the full
image lists for MyE&P (images, /api/hotel and /api/product) shared one
cache entry. Once a page had shown a hotel teaser, the API answered with
that single teaser image instead of all images. The field is now part of
the key.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 10:59:16 +01:00
frommeandClaude Opus 5.5 fe3af34063 fix: one-column teasers without an image no longer break the page
f:image threw when the teaser had no image (teaserImage false), and
production showed "Oops, an error occurred!" instead of the element, e.g.
three times on the snowzone privacy page. The image is now skipped like in
the disturber partials.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 10:52:11 +01:00
frommeandClaude Opus 5.5 3fa4a81e97 chore: remove the outdated copyright notices
The GPL headers named dreipunktnull and an old address and no longer
match the license of the code.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 10:41:24 +01:00
frommeandClaude Opus 5.5 4a3ef91dd0 chore: fileadmin is a shared dir of the TYPO3 13 deployment
fileadmin moves from the TYPO3 10 release
(ep-reisen-typo3/shared/public/fileadmin) to
ep-reisen-typo3-13/shared/public/fileadmin, so Deployer links it like the
other shared dirs (relative symlink) and the typo3:fileadmin task with
its absolute fileadmin_path goes.

deploy:shared creates a missing shared dir empty, which would leave the
sites without any file: deploy:check:fileadmin aborts the deploy before
anything happens on the server if the shared fileadmin is missing. Deploy
this only after the directory has been moved.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 09:48:17 +01:00
frommeandClaude Opus 5.5 ff45147964 chore: remove the one-off ep:scheduler-tasks command
It replaced the TYPO3 10 import tasks with scheduler tasks, which ran in
production on 2026-10-24 (tasks 26-28). The soft-deleted TYPO3 10 rows it
left are hard-deleted by hand on the database.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 09:44:32 +01:00
frommeandClaude Opus 5.5 386d89a1e0 chore: forms post to their own page instead of the form page type
The form page type (/form, 1704) existed because on the static pages of the
hybrid setup the page URL never reached TYPO3. With static rendering
retired, forms post to the page they are on, like the newsletter form:
the additionalParams in FormSetup.yaml, Page/Form.typoscript and the /form
entries of the PageType enhancers are gone.

Each form island gets the id form-island-<form identifier> (EXT:form
appends the content element uid), and Form.html targets and selects that
id instead of .form-island. With two forms on one page, a submission no
longer swaps in the first form's island.

Kept: hx-boost on the forms, HtmxRedirectMiddleware (Redirect finishers
under htmx) and /captcha (bw_captcha's image type).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 09:33:32 +01:00
frommeandClaude Opus 5.5 114a45aed3 chore: retire the snow report and search bar islands
They only served the static pages of the hybrid setup, which are retired:
TYPO3 13 renders search bar and snow reports in the page itself. Removed
are the page types 1705 (/snowreport) and 1706/1707 (/searchbar,
/searchbar-collapsed), their PageType enhancer entries and the id wrapper
of the snow report list that the static pages selected.

Also gone: the remarks about static pages and docroots in
ReferrerMiddleware and .htaccess.

The form page type (/form, 1704) stays for now; forms move off it in a
separate step.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 09:31:55 +01:00
frommeandClaude Opus 5.5 f0b23b37b9 feat: the newsletter form submits with htmx and reports failed signups
The newsletter subscription plugin now sits in a form island like the
EXT:form forms: hx-boost posts to the page itself and only
#newsletter-island is swapped (validation errors, confirmation), with the
spinner overlay while the request runs. The id keeps htmx away from other
islands on the same page (both newsletter pages have hidden EXT:form
forms). Without JavaScript the form still posts normally.

The island markup moves from Form/Render.html into Partials/Form/Island.html,
shared by both; the form plugin's partial path is now Partials/ for that.
The comment about static pages is gone with it, static rendering is retired.

When the MyE&P API call fails, the result page shows an error with a link
back to the form instead of the thank-you message.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 09:17:16 +01:00
frommeandClaude Opus 5.5 88fac7313e fix: deploys reset OPcache before flushing the TYPO3 caches, as on TYPO3 10
After a deploy, pages showed unstyled content until the caches were
flushed by hand in the backend. Every vhost points at current/public
since 2026-10-24 and keeps running the previous release after the
switch; pages it renders after the deploy's flush reference that
release's hashed CSS/JS, which the new release does not have, and stay
in the page cache and as staticfilecache files.

As in TYPO3 10's deploy.php, cachetool resets OPcache right after the
switch (and after a rollback), before the flush. Its web adapter puts
the temp script into the shared typo3temp/assets, which every release
resolves to the same directory, and requests it through
www.ep-reisen.de. cachetool is pinned to 10.0.0 for PHP 8.5.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 08:20:21 +01:00
frommeandClaude Opus 5.5 de3bbbe2f5 feat: bring back the newsletter subscription plugin
The "Newsletter-/RA-Registrierung" plugin (epproducts_newsletter_subscription)
subscribes to the Mailjet lists through the MyE&P API and is still in use on
the newsletter, travel alert and travel for groups pages; retiring it in
49b96df was a mistake. Controller and templates come back from a46918d,
ported to TYPO3 13 (actions return responses). The DTO and the API client
calls were still in place. The "newsletter" result message plugin (index
action) is not part of this.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 07:58:04 +01:00
frommeandClaude Opus 5.5 b794257f61 chore: FlexForm select items in the TYPO3 13 format
The select items of twelve plugin FlexForms were still numbered
<numIndex index="0">/<numIndex index="1"> pairs, and the team members
FlexForm set enableMultiSelectFilterTextfield, which TYPO3 12 removed (the
filter field is always shown now). The core migrated both on the fly on
every request and logged a deprecation each time ("FlexFormTools did an
on-the-fly migration"). The items are converted to <label>/<value> with
Fractor (MigrateItemsIndexedKeysToAssociativeFractor) and the setting is
removed.

The parsed data structures are identical to what the on-the-fly migration
produced, so the backend forms and stored values stay the same.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 19:22:25 +01:00
frommeandClaude Opus 5.5 f4e024a9f8 chore: slim deploy.php down to what every deploy needs
Removed the one-off tasks of the first deploys, all done now: host:check
(host checks before the first deploy, including the static vhosts),
typo3:secrets:init and typo3:secrets:check (secrets.php is filled in), and
typo3:settings:init (the shared settings.php exists since the deploy after
3f88229). Also removed what the Deployer 8 recipe already provides with the
same result: typo3/public_dir and bin/typo3 (read from composer.json),
typo3:extension:setup and the unlock after a failed deploy. The build always
runs through ddev exec, as deploys run on the host.

The resolved configuration (rsync excludes, flags and filter, shared and
writable directories, build path) and the task order are unchanged.
contrib/rsync.php replaces the recipe's rsync settings, so the recipe's
var/ exclude never applied: var/labels is deployed with the release, as
before.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 18:32:21 +01:00
frommeandClaude Opus 5.5 73fe876c78 fix: the n8n chat and the CleverPush service worker are served again
The ep-reisen footer loads the chat widget from /chat.bundle.es.js and
/chat.styles.css (@n8n/chat 0.65.0), and browsers subscribed to push
notifications update their service worker from /cleverpush-worker.js
(manifest: /cleverpush-manifest.json). These files were in the TYPO3 10
docroot but not in this repository, so since the switch to TYPO3 13 all
four returned 404: no chat button, and push subscriptions could no longer
update their worker.

public/* is ignored except for listed files, so they are added as
exceptions; a service worker has to be served from the root to control
the whole site.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 18:18:00 +01:00
frommeandClaude Opus 5.5 c7f6a6ec44 chore: remove the last legacy favicons from the theme
ski-boarderweek, snowzone and ser have a realfavicongenerator set in
fileadmin now, and their templates no longer set page.shortcutIcon, so
favicon_sbw.ico, favicon_sz.ico and favicon_ser.ico are unused.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 18:02:42 +01:00
frommeandClaude Opus 5.5 8302214657 feat: ICO and web manifest files can be uploaded to fileadmin
TYPO3 13 only accepts uploads whose extension is in textfile_ext,
mediafile_ext or miscfile_ext (security.system.enforceAllowedFileExtensions),
so the favicon.ico and site.webmanifest of a realfavicongenerator set were
rejected ("Resource consistency check failed"). Both are appended to
miscfile_ext in additional.php, which is deployed with the code;
settings.php, which production leads, stays untouched.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 17:34:20 +01:00
frommeandClaude Opus 5.5 1d7fadbd19 feat: favicons as a realfavicongenerator set per site, like ep-reisen and snowbreak
The theme registered 26 icons (16 to 196 px PNGs, a GIF, eleven Apple touch
icons) that current browsers no longer need. It now renders the five tags of
the set realfavicongenerator.net generates (96 px PNG, SVG, ICO, 180 px
Apple touch icon, web manifest) plus apple-mobile-web-app-title, from two
constants: faviconPath, the folder in fileadmin the set was uploaded to
(default: the E&P set), and faviconAppTitle.

The ICO also matches the favicon parser of yoast's snippet preview now
(rel="shortcut icon" directly followed by href), which missed the old tags
and fell back to a /favicon.ico none of the sites has.

cllt and alvac, which showed the theme's E&P icon, get the E&P set. Sites
whose own template sets page.shortcutIcon and removes headerData.333
(ski-boarderweek, snowzone, ser) keep their icon until they have a set; the
remaining ICOs of these three stay until then. ep-reisen and snowbreak still
override the tags with the same markup in their templates.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 15:19:05 +01:00
frommeandClaude Opus 5.5 c0c81317aa chore: remove the unused myEP API settings from the theme
The app config JSON carried "myEpApiBaseUrl" from the TypoScript setting
myEpApiEndpointUrl, which only the alvac and cllt sys_template records set:
the other sites rendered the unresolved "{$plugin.tx_eptheme.settings...}"
into the page. No JavaScript reads the key (only paCode and externalDomains
are used), and the MyE&P API client takes its URL, credentials and timeout
from the ep_products extension configuration, so the theme's
myEpApiEndpointUrl, myEpApiToken and myEpApiTimeout settings had no reader.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 15:07:13 +01:00
frommeandClaude Opus 5.5 32c0c89785 feat: theme constant googleSiteVerification for the Google site verification
The verification code of alvac and cllt came from EXT:metaseo, which is not
installed in TYPO3 13, so their google-site-verification meta tag was
missing. The theme renders the new constant as
page.meta.google-site-verification; empty, it renders no tag. Sites whose
own setup sets the tag (ep-reisen, ski-boarderweek, snowbreak, snowzone, ser)
keep their value.

.ddev/plans/sql/2026-10-25-metaseo-sourceopt.sql renames the metaseo
constants to the new one after the deploy, removes the remaining metaseo
and sourceopt leftovers from the sys_template records, and sets the core
no_index/no_follow flags on the booking links (page 634 and subpages),
which metaseo had kept out of search engines.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 14:56:46 +01:00
frommeandClaude Opus 5.5 4ca38821fb fix: the backend may load images from cdn.ep-reisen.de
TYPO3 13 enforces a Content Security Policy in the backend whose img-src
only allows the backend's own host, data: URIs and the YouTube/Vimeo CDNs.
The frontend references its favicons on the CDN, so yoast's snippet preview
showed a broken favicon (CSP report: img-src blocked
https://cdn.ep-reisen.de/fileadmin/user_upload/favicon/ep/favicon.ico).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 14:53:01 +01:00
frommeandClaude Opus 5.5 b39f17886f feat: bring back EXT:yoast_seo
Editors need its focus keyword and readability analysis in the page form.
Version 12.1 supports TYPO3 13.4 and keeps the existing tx_yoastseo_* data
of the TYPO3 10 database.

The deploy's extension:setup adds its new pages columns and tables. After
the deploy, run the upgrade wizard yoastDashboardWidgetMigrate (it moves the
yoast "pages without meta description" dashboard widget to the core one).

In the frontend, yoast adds WebSite and BreadcrumbList JSON-LD to every page.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 14:47:49 +01:00
frommeandClaude Opus 5.5 d9f74e271e fix: the date fields of the product teaser group plugin are datetime fields
settings.dateFrom and settings.dateTo were still type=input with eval=date.
TYPO3 13 only migrates renderType=inputDateTime to type=datetime, so these
were rendered as text inputs whose JavaScript expects an ISO 8601 value. It
got the stored timestamp (e.g. 1793491200), threw "Invalid ISO8601 DateTime
string", and the edit form of these plugin elements never finished loading.

The datetime element converts the stored timestamps itself and, without a
dbType, saves timestamps again, so stored values and the frontend stay as
they are.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 14:41:53 +01:00
frommeandClaude Opus 5.5 3f88229a70 feat: settings.php is shared on the server and no longer in git; production is leading
Every deploy replaced settings.php with the committed version, so changes
made in the production backend (extension configuration, install tool) were
lost with the next deploy or rollback. As LocalConfiguration.php on TYPO3 10,
it is now a shared file. typo3:settings:init seeds it once from the live
release; deploy:shared would otherwise seed it from the new release, i.e.
from git, and drop production's settings one last time.

The file is no longer tracked: it holds the encryptionKey and the install
tool password hash, and git has no use for it once production is leading.
Local copies stay in place (ignored).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 20:31:21 +02:00
fromme 6edd0fab6e feat: add logo in png format for email templates 2026-10-24 20:08:43 +02:00
frommeandClaude Opus 5.5 3c27cd84b9 fix: file names stay ASCII as on TYPO3 10 (UTF8filesystem off)
The fresh TYPO3 13 installation got UTF8filesystem = true from the core's
factory configuration; TYPO3 10 ran with the default false, so uploads
turned umlauts into ASCII (Bärenhütte.jpg -> Baerenhuette.jpg) and no file
in sys_file has a non-ASCII name. With true and no UTF-8 system locale,
escapeshellarg() drops those characters and image processing misses the
file (environment check warning). Back to false: the TYPO3 10 behaviour,
no locale needed, and file URLs and CDN paths stay free of encoded umlauts.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 19:57:02 +02:00
frommeandClaude Opus 5.5 283f54c56c feat: EXT:staticfilecache serves cached pages without PHP again, as on TYPO3 10
Every page view goes through TYPO3 13 since the switch; staticfilecache
15.2 writes a gzip copy of each cacheable page, and the TYPO3 10 rewrite
rules in public/.htaccess let Apache deliver it directly (GET, no query
string, no backend login). Pages answer in about 2 ms instead of
0.5-4 s; static and dynamic output are identical for a sample of 22
sitemap URLs.

A flush of the pages cache group (travel data and snow report imports,
"clear frontend caches", deploys) removes the files; a page's own cache
lifetime still applies through the generated per-page .htaccess.

X-SFC-Tags is not passed on: with every record of a page as a tag it
reaches 100+ KB, more than Apache accepts from PHP-FPM, and it would
expose internal record ids. Debug headers stay off for the same reason.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 19:05:21 +02:00
frommeandClaude Opus 5.5 df3d823de4 feat: page, hash and rootline caches in Redis again, as on TYPO3 10
Since every page view goes through TYPO3 13, the page cache is on the hot
path; TYPO3 10 kept it in Redis, TYPO3 13 had it in MySQL. Same socket and
options as TYPO3 10, but databases 3-5 instead of 0-2, which may still
hold TYPO3 10 entries in a format TYPO3 13 must not read. DDEV gets the
redis add-on for the same setup locally.

Without a Redis connection the backend logs an alert and misses, so pages
still render (slower); a missing PHP redis extension, however, fails hard.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 18:51:57 +02:00
frommeandClaude Opus 5.5 520feb003f feat: scheduler runs the imports and the housekeeping tasks again
typo3/cms-scheduler 13.4 replaces the three direct cron jobs with one
scheduler:run cron job. ep:scheduler-tasks (one-off, idempotent) soft-deletes
the TYPO3 10 tasks TYPO3 13 cannot run (import task classes that are gone, one
groups.swiss task per house with the API keys in the database, the retired
E&P Events log) and adds "Execute console commands" tasks for ep:import-dates,
ep:import-snowreport and ep:groups-swiss with the TYPO3 10 schedules. The core
garbage collection, IP anonymization and file indexing tasks keep working as
they are; tx_epproducts_log is registered for garbage collection again.

The first execution is the next cron match, so adding the tasks never starts
an import or a groups.swiss export right away.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 18:27:50 +02:00
frommeandClaude Opus 5.5 f193d356cb feat: schneereisen.com redirects to www.ep-reisen.de
An alias of the ep-reisen vhost; path kept, 301.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 15:24:13 +02:00
frommeandClaude Opus 5.5 fcf04dbca7 chore: no delayed cache flush after deploys
Waiting 150 s at the end of every deploy is impractical. The flush right
after the switch stays; the window in which the previous release can
still fill the page cache is documented in deploy.php.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 15:03:23 +02:00
frommeandClaude Opus 5.5 837fca3b4c feat: unisnow.de and unisnow.com redirect to snowbreak.ep-reisen.de
Like unichamp.de: path kept, 302.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 14:58:09 +02:00
frommeandClaude Opus 5.5 fec781d634 feat: ep-reisen.com and ep-reisen.info redirect to www.ep-reisen.de
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 14:57:29 +02:00
frommeandClaude Opus 5.5 cd7d347006 feat: every ep-events.de URL redirects to the company trips page
E&P Events is retired; www and bare domain go to
www.ep-reisen.de/reisen-fuer-gruppen/gruppenreisen/firmenreisen/ (301).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 14:54:36 +02:00
frommeandClaude Opus 5.5 4b6dfdd390 fix: skiwochenenden.de redirects to www.ski-wochenenden.de
An alias of the ski-wochenenden vhost that the static docroot answered
regardless of the host; TYPO3 13 rejected it (trusted hosts pattern).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 14:50:47 +02:00
frommeandClaude Opus 5.5 4bfa0f258a fix: deploys flush the TYPO3 caches again after PHP has picked up the release
A vhost on current/public (alvac since today) keeps running the previous
release until PHP's realpath cache expires (120 s by default); pages it
rendered after the first flush stayed in the page cache with old paths.
A second flush 150 s after the switch (also after a rollback) removes them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 14:45:36 +02:00
frommeandClaude Opus 5.5 419ffe42b8 fix: TYPO3 caches are flushed after a rollback too
Pages cached while the other release was live survived the switch
(seen after the rollback test: alvac served old favicon paths until a
manual cache:flush). The flush task runs in current_path, which is the
new release after a deploy and the previous one after a rollback.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 14:44:08 +02:00