15. Oktober 2026 · Changelog
CDPCMS 2.2.0
- Themes page (1141): Appearance → Themes lists every theme under `cms/themes/<theme>/` of the website with title, version, description, screenshot and status (active = `cms/theme.json` "theme"). The version is mandatory: file `VERSION` or `theme.json` "version"; a theme without one receives `VERSION` 1.0.0 and a `CHANGELOG.md` (done for cdpdefault, cdpmega, cdpwiki). Preview shows the website with a theme without activating it (signed-in editors only, token in `cms/theme-preview.json`, 2 hours, `no-store` + `noindex`), desktop or phone width, page selectable, "Open in new tab"; the chosen page is rendered with the templates of the previewed theme (`Publisher::previewForTheme`, `content/_vorschau/theme-<theme>/`, served through `cdpcms_theme_content()`), so the preview shows the page as that theme would publish it. A theme names its showcase template in `theme.json` (`screenshot_template`, e.g. `wiki-index`) for the screenshot; descriptions in `theme.json` are English and translated through `lang/de.json`. Activate asks in a CDP modal (`cms/assets/cdp-confirm.js`, replaces the browser's confirm/alert in the CMS) and shows the loading indicator; the theme that was active is kept as "previous" in `cms/theme.json` and comes back with "Restore previous theme". Add theme: upload a ZIP or install from the theme catalog (`storage/app/theme-catalog.json`, sha256 checked) with the checks of the module installer (`App\Services\ThemeInstaller`: one folder, lowercase name, no unsafe paths or links, allowed file types, version required, minimum CDPCMS version, update only with a higher version, previous folder kept in `storage/app/theme-backups/`). Screenshots: `cms/themes/<theme>/screenshot.webp`, served through the CMS (`/cms/design/themes/<theme>/screenshot.webp`); missing ones are requested from the root helper `cdpcms-theme-shot` (systemd path unit on `/var/lib/cdpcms/theme-shots/`, Chromium headless 1280×800, event driven).
- Theme runtime (1141): `cms/assets/theme.php` reads the theme in use (`cms/theme.json` or the preview token) and loads `cms/themes/<theme>/connect/*.php`. A theme adds its parts through optional hooks `<theme>_lang()`, `_css()`, `_body_class()`, `_header($path)`, `_footer()`, `_fill($html, $lang)`, `_js()`; a part without a hook stays as the website itself renders it. The front controller of cdpcms.cdpdev.com uses these hooks instead of the fixed cdpmega include.
- CDPPayPal (1143): PayPal as a payment module like CDPStripe/CDPRevolut – `app/Modules/CdpPaypal` (title and menu CDPPayPal, page `/cms/payments/paypal`: status per shop, environment, client ID / secret / webhook ID stored or missing, webhook address, latest events). Shop runtime (cdpf.shop, dev): switch `paypal_enabled` (default On, behaviour unchanged), label `paypal_label`, webhook `/api/paypal/webhook/` confirmed with PayPal (`verify-webhook-signature`, `paypal_webhook_id` / `paypal_live_webhook_id`), exactly once, `PAYMENT.CAPTURE.COMPLETED` → paid through `shop_order_paid()` as before; simulation without credentials (`/api/paypal/checkout/`, `/zahlung-sim/<token>-paypal/`). The existing PayPal buttons, create/capture and the credential fields stay unchanged. All three payment modules are named CDPPayPal, CDPStripe, CDPRevolut; their routes are now registered like the other modules (the `cms` prefix of 904 made the Stripe/Revolut pages unreachable). Module descriptions in German (`module.json` "description_de", shown when the CMS runs in German – all seven modules). Sidebar: modules with the same `"group"` in their menu entry form one group with the modules as children (the three payment modules → "Payments"); "Install modules" is the first entry of the Modules list instead of the last, so it no longer looks like a child of the last module.
- Release check green again (15 Oct, evening): the Redis switches (776) are no longer applied while tests run (`RedisSwitches::apply()` returns in the testing environment – the publish job went into the Redis queue and the login throttle into Redis, so 9 CmsTest cases failed with "draft"/missing files/429). Missing German translations added (Redis settings box, CDPDrive, payment modules, background publishing); German comments of the shop runtime copies (payment modules) translated, customer-facing German shop strings marked `german-data`; module descriptions are English in `module.json` and translated on the Modules page. `php artisan test`: 32 passed.