Was behoben wurde
- •Updater-Fehler: Schreibfehler bei Dateien und
version.json, nicht unterstützte Patches und Änderungsvorschau, Repository nicht erreichbar und erfolgreiche Verbindung.
- •Update-Seite: Serverantwortfehler, „N Dateien geändert · N Commits“, fertig, wird angewendet, Auftrag registriert, Zeitüberschreitung und Rollback abgeschlossen.
- •Hinweise zur Auftragsregistrierung: die Meldung, dass ein Update-, Patch- oder Rollback-Auftrag eingereiht wurde.
- •Der Berechtigungs-Worker (cron) hinterlässt seine Fortschrittsmeldungen sowie die Erfolgs- und Fehlerbenachrichtigungen jetzt in der richtigen Sprache.
Seite „Änderungsprotokoll“ (`/changelog`)
- •Relative Zeitangaben wie „5 months ago“ gab es nur auf Koreanisch und Englisch; jetzt gibt es sie in 13 Sprachen.
Der Hinweis bei leerer Liste, die Kennzeichnung „KI-Übersetzung“, der Hinweis „keine Übersetzung — angezeigt in KO“ und „nur die neuesten N werden angezeigt“ sind ebenfalls übersetzt.
- •Die Sprache der Seite richtet sich jetzt nach der Sprache, die die Website tatsächlich verwendet, und nicht nur nach dem Sitzungswert (
?lang=, Sitzung, Cookie, Standardsprache).
Früher fiel ein Erstbesuch auf Koreanisch zurück, sodass koreanische Beschriftungen in japanische und englische Websites gerieten.
- •Lange Bezeichner und Pfade (Text ohne Leerzeichen) laufen nicht mehr aus der Karte heraus und rutschen nicht mehr unter die Installationsschaltfläche am rechten Rand.
Gut zu wissen
- •Der Berechtigungs-Worker hat keinen angemeldeten Benutzer und damit keine Sprache. Er schreibt seine Meldungen in der Standardsprache der Website.
(Früher startete er das Übersetzungssystem nicht, sodass Schlüssel wie updater.write_failed unverändert ausgegeben werden konnten. Der Worker startet es jetzt.)
- •Serverprotokolle (
error_log) und Debug-Protokolle für Entwickler werden von Administratoren gelesen und blieben deshalb unverändert.
- •Auf einer installierten Website führt der bereits installierte alte Updater das Update aus; diese Verbesserungen zeigen sich daher erstmals bei dem Update nach dem Wechsel auf 2.8.2.
v2.8.1
2026-10-12 · vor 7 Tagen
Mehr Mehrsprachigkeit (App-Name, Suchdaten, `?lang=`) · Updates schützen eigene Kernänderungen einer Website
Mehrsprachigkeit
- •App-Name und Beschreibung beim „Zum Startbildschirm hinzufügen“ und im Installationshinweis erscheinen jetzt in der Sprache der Besucher. Früher wurde der gespeicherte Wert (zum Beispiel Japanisch) unverändert angezeigt.
Übersetzungen liegen unter Schlüsseln wie pwa.front.name in rzx_translations. manifest.php übergibt nur noch an die offizielle Ausgabe.
- •Strukturierte Daten (JSON-LD): Übersetzungen der Einstellungswerte werden zuerst berücksichtigt. Behoben wurden der zweite Brotkrumen-Eintrag, in dem auch der Websitename stand, und „Home“, das in allen Sprachen auf Englisch erschien.
- •Statistik-Widget: Zahl und Einheit (
suffix) nehmen jetzt wie die Beschriftung Werte pro Sprache an. Ein einzelner Wert funktioniert genau wie bisher.
- •Der Offline-Bildschirm und der letzte Hinweistext des Service Workers erscheinen jetzt auf Koreanisch, Japanisch und Englisch.
Die Cache-Version des Service Workers steigt von v5 auf v6, damit auch bereits installierte Geräte den neuen Bildschirm erhalten.
- •„Keine Suchergebnisse“ in der Nachrichtensuche war fest auf Koreanisch codiert und gibt es jetzt in 13 Sprachen.
Suchmaschinen und KI
- •Es werden
<meta property="og:locale"> und alternative Sprachen (og:locale:alternate) ausgegeben. Beim Teilen in sozialen Netzwerken wird so die Sprache der Seite mitgeteilt.
- •Öffentliche Systemseiten, die per Code erzeugt werden, erscheinen jetzt in
sitemap.xml (sie fehlten).
- •Die erste Zeile von
llms.txt (die Website-Beschreibung) erscheint in der Sprache der Besucher.
- •Die robots-Einstellung pro Seite (im Admin-Bereich gab es das Eingabefeld, gelesen wurde es aber nirgends) wird jetzt tatsächlich angewendet.
Behobene Probleme
- •Der Wert von
?lang= wird erst nach einem Abgleich mit der Liste der unterstützten Sprachen akzeptiert. Früher blieb ein nicht unterstützter Wert ein Jahr lang im Cookie,
und beim späteren Öffnen dieser Sprache konnte ein Besucher gegen seinen Willen auf diese Seite wechseln. Die Sprachauswahl folgt derselben Regel.
- •Widget-Builder: Übersetzungen für Sprachen ohne Eingabefeld auf dem Bildschirm wurden bei jedem Speichern gelöscht.
- •Nachrichtensuche der Community: Namen werden verschlüsselt gespeichert, deshalb ergab kein Name ein Ergebnis. Es wird jetzt zuerst entschlüsselt und dann verglichen.
Updates schützen eigene Kernänderungen einer Website
- •Wenn Sie in
storage/custom/update-preserve.txt Pfade angeben, einen pro Zeile (# ist ein Kommentar, Ordner sind erlaubt), überschreibt das Update diese Dateien nicht.
Verwenden Sie das, um direkt in Kerndateien eingefügte Änderungen zu schützen, etwa eine websitespezifische Anmelderegel. Absolute Pfade und .. werden nicht akzeptiert,
und wenn die Datei nicht gelesen werden kann, bricht das Update nicht ab, sondern läuft mit der Standardliste weiter.
- •Gut zu wissen: Die Seite, die das Update ausführt, muss diese Funktion bereits haben. Sie wirkt ab dem Update nach dem Wechsel auf 2.8.1.
Was sich geändert hat
Das Zahlungsmodul hatte schon für jeden Anbieter eine eigene Datei, aber „welche Anbieter es gibt“ stand an mehreren Stellen im Code.
Für einen neuen Anbieter mussten Zahlungsverwaltung, Einstellungsseite und Webhook geändert werden.
- •Legen Sie einen Ordner (
gateway.json plus Implementierungsdatei) in rzxlib/Modules/Payment/Gateways/ ab, und der Kern erkennt ihn von selbst.
Anbieterauswahl, Schlüsselfelder und Webhook-Adresse auf der Admin-Einstellungsseite werden aus dieser Spezifikation erzeugt.
- •Eine Website wählt auf der Einstellungsseite weiterhin einen Anbieter (wie bisher). Es ist keine Funktion, um mehrere Anbieter gleichzeitig zu nutzen.
- •Wie man einen Anbieter hinzufügt, steht in
docs/PAYMENT_GATEWAYS.md.
Square
- •Unterstützt werden Kartenzahlungen, Erstattungen und Abfragen, gespeicherte Karten (für wiederkehrende Abbuchungen) und Webhooks (mit Signaturprüfung).
- •Das Karteneingabeformular durchläuft die Kundenauthentifizierung (SCA) und zeigt bei einem Fehlschlag den Grund auf dem Bildschirm. 13 Sprachen.
- •Die Admin-Einstellungsseite hat eine neue Schaltfläche „Verbindungstest“. Im Testmodus führt sie eine kleine Zahlung, eine Abfrage und eine Erstattung aus,
um zu prüfen, ob die Schlüssel stimmen. Es wird kein echtes Geld bewegt, und im Live-Modus läuft der Test nicht.
- •Solange Sie Square nicht auswählen, ändert sich für keine Website etwas.
Bestehende Anbieter (PAY.JP und Stripe) bleiben unverändert
- •Die Implementierungsdateien der beiden Anbieter wurden nicht angetastet. Alte Einstellungen (einzelner Schlüssel, v2, v3) werden wie bisher gelesen.
- •Selbst wenn die Spezifikationsdateien aus irgendeinem Grund nicht gelesen werden können, sorgt ein Sicherheitsnetz dafür, dass PAY.JP und Stripe auf die alte Weise erzeugt werden.
- •Mit den echten Einstellungen produktiver Websites und vielen synthetischen Einstellungen haben wir den alten und den neuen Code verglichen und bestätigt, dass sie denselben Anbieter, denselben Modus und dieselben Schlüssel wählen
(scripts/test-payment-parity.php).
Zahlungseinstellungen pro Website lesen
Wenn eine Datenbank für jede Website eine eigene Zahlungseinstellung enthält, liest das Zahlungsmodul jetzt die Einstellung der eigenen Website.
Früher war nicht festgelegt, welche Einstellung gewählt wurde. Hat eine Website keine eigene Einstellung, verhält sie sich wie bisher.
Gut zu wissen
- •Es wurde eine gemeinsame Webhook-Adresse hinzugefügt (
/api/webhook-payment.php?gateway=…). Die bestehenden Webhook-Adressen von PAY.JP und Stripe bleiben unverändert.
- •Die Anbieterliste auf der Einstellungsseite behält ihre alte Reihenfolge; Anbieter, die über eine Spezifikation hinzukommen, folgen danach.
Was war das Problem
Die Sitemap (sitemap.xml) und der KI-Leitfaden (llms.txt) enthielten nur, was der Kern kennt.
Damit ein Plugin eigene Seiten aufnehmen konnte, blieb nur, Kerndateien direkt zu ändern, und diese Änderung
ging bei jedem Update verloren. Außerdem riet der Kern, wie die Plugin-Tabelle zu lesen ist, sodass es an einigen Stellen unbemerkt schiefging.
- •Immobilienangebote wurden nur unter einer separaten Adresse (
/properties-sitemap.xml) ausgegeben; wenn nirgends auf diese Adresse verwiesen wurde,
konnten Suchmaschinen sie nicht finden.
- •Marktplatz-Artikel waren nie in der Sitemap erschienen, wegen einer Abfrage, die nach einer nicht existierenden Spalte suchte.
Der Fehler wurde verschluckt, sodass es niemand bemerkte.
- •Einige Websites gaben Geschäftsadressen in der falschen Form aus, sodass Suchmaschinen Adressen indexierten, hinter denen keine Seite existiert.
Plugins veröffentlichen ihre Seiten jetzt selbst
- •Wenn ein Plugin in seiner
plugin.json seo angibt, liest der Kern das und führt es in Sitemap und KI-Leitfaden zusammen.
Es funktioniert wie bei Widgets, Layouts und Intranet-Modulen, und bei gleichen Adressen gewinnt der Kern.
- •Adressen für mehrere Sprachen und die Sprachkennzeichnungen ergänzt der Kern selbst. Ein Plugin muss nur seine Adressen liefern.
- •Ein defektes Plugin legt nicht mehr die ganze Sitemap lahm. Nur der Anteil dieses Plugins fehlt.
- •Adressen deaktivierter Plugins entfallen automatisch; die Seiten eines deaktivierten Plugins lassen sich ohnehin nicht öffnen.
Chinesische Alternativadressen wurden ignoriert
Die Sitemap schrieb die Sprachkennzeichnung als zh_CN, der Standard lautet aber zh-CN, sodass Google diese Zeile komplett ignorierte.
Die Seiten selbst waren korrekt geschrieben, sodass dieselbe Website an zwei Stellen Unterschiedliches sagte.
Die Alternativadressen für vereinfachtes und traditionelles Chinesisch werden jetzt korrekt erkannt.
KI
- •
llms.txt gab es nur in der Standardsprache. Jetzt werden Sprachausgaben wie ?lang=en erzeugt.
Namen und Beschreibungen erscheinen in dieser Sprache, und am Anfang des Leitfadens steht, um welche Ausgabe es sich handelt.
- •Auf mehrsprachigen Websites können KI-Antwortmaschinen diese Website nun Nutzern in jedem Sprachraum vorlesen.
Mitarbeiter können ihre eigene Personalkarte sehen (Intranet)
- •Die Personalkarte, die nur das Personalwesen sehen konnte, kann jetzt auch vom Mitarbeiter selbst eingesehen werden. Man erreicht sie über das Profilmenü oben.
- •Sie ist nur lesbar. Ein Ablauf, bei dem man eine Korrektur beantragt und das Personalwesen sie genehmigt, ist in Vorbereitung.
- •Beurteilungen sind für den Mitarbeiter nicht sichtbar. Das Gleiche gilt für Auszeichnungen und Disziplinarmaßnahmen. Bei angehängten Dokumenten wird nur die Liste angezeigt.
- •Durch Ändern der Adressleiste lässt sich keine fremde Karte öffnen; wessen Karte es ist, bestimmen allein die Anmeldedaten.
- •Man kann auch prüfen, wer die eigenen Personaldaten eingesehen hat.
Forum
Alle Links auf einer Forum-Seite werden aus einem einzigen Wert ($boardUrl) gebildet, aber der Kern überschrieb diesen Wert immer.
Wer ein Forum innerhalb einer Admin-Oberfläche nutzt, etwa das Intranet, musste deshalb die bereits fertig gerenderte Seite Zeichen für Zeichen austauschen.
Wenn der Kern die Form eines Links nur geringfügig änderte, ging es unbemerkt schief.
- •Wenn der Aufrufer die Basisadresse vorher festlegt, wird dieser Wert verwendet. Wenn nicht, bleibt alles wie bisher.
- •Auch der Zahnrad-Link (Forum-Einstellungen) wird an einer Stelle festgelegt. Vorher bildeten Liste, FAQ, Q&A und Link-Skin jeweils ihren eigenen.
Layouts können im Plugin liegen
- •Layouts werden zuerst im Kern unter
skins/layouts/ gesucht, und falls dort nicht vorhanden, im Plugin unter plugins/{id}/skins/layouts/.
Das ist dieselbe Regel wie bei Widgets und Intranet-Modulen, und bei gleichem Namen gewinnt der Kern.
- •In der Layout-Auswahl im Admin-Bereich erscheinen die Plugin-Layouts ebenfalls.
- •Bisher musste ein Plugin-eigenes Layout im Kernordner liegen. Ein Update löscht es nicht,
aber wenn der Kern später ein Layout mit demselben Namen mitbringt, wird es überschrieben, und beim Umzug des Plugins auf eine andere Website musste der Ordner von Hand mitgenommen werden.
Plugins deklarieren Intranet
Die Liste für die Intranet-Oberfläche (Menü links und Einstiegspfade) stand nur in einer einzigen Kern-Einstellungsdatei.
Damit ein Plugin sein eigenes Modul aufnehmen konnte, musste eine Kerndatei geändert werden, und diese Änderung ging beim Update verloren.
- •Wenn ein Plugin in seiner
plugin.json intranet_module angibt, liest der Kern es und führt es zusammen. Es funktioniert wie bei Menüs und Systemseiten.
- •Als Wert kann man direkt ein Array angeben oder einen Dateipfad wie
"data/intranet-module.php".
- •Bei gleichem Namen gewinnt der Kern. Ein Plugin kann ein Kernmodul nicht übernehmen, um dessen Standardverhalten zu ändern.
- •Alle fünf Stellen im Kern, die diese Liste lasen, nutzen jetzt die neue Methode. Auch wenn ein Update die Einstellungsdatei überschreibt, bleiben die Plugin-Module erhalten.
Japanische Ären (和暦) bei der Datumseingabe
- •In japanischen Oberflächen füllt sich das gregorianische Jahr automatisch, wenn man im Datumsfeld eine Ära (令和, 平成, 昭和, 大正, 明治) auswählt und die Jahreszahl eingibt.
Werte, die man nach Ära im Kopf hat, etwa das Geburtsdatum, muss man nicht jedes Mal umrechnen.
- •Das Feld für die Wochentagsanzeige bleibt unverändert.
Forum
- •Selbst wenn im Admin-Bereich pro Forum ein Layout gewählt wurde, zeigte die Seite das Standardlayout der Website.
Der Ort, an dem gespeichert wurde, und der Ort, an dem gelesen wurde, waren verschieden.
- •Behebung: Beim Speichern eines Forums wird auch die Einstellung geschrieben, die die Seite liest.
Bestehende Foren sehen bis zum erneuten Speichern genauso aus wie jetzt (das Aussehen ändert sich nicht plötzlich).
Beiträge wurden beim Schreiben nicht gespeichert
- •Beim Speichern eines Beitrags wurde die Titelspalte übergangen, sodass auf Websites, auf denen diese Spalte noch existiert, das Speichern fehlschlug.
Auf dem Bildschirm erschien nur „Unexpected end of JSON input“.
- •Behebung: Wenn die Spalte noch existiert, wird sie ebenfalls befüllt. Websites, die die Spalte entfernt haben, verhalten sich wie bisher.
Forum
- •Die Suche sah in der alten Spalte nach, sodass auf Websites, die sie entfernt haben, die ganze Liste nicht mehr aufging, sobald man einen Suchbegriff eingab.
- •Auch auf Websites, die die Spalte behalten haben, gab es ein Problem. Das Bearbeiten eines Beitrags aktualisierte die Spalte nicht, sodass nur der Text vor der Bearbeitung gefunden wurde.
- •Behebung: Die Suche läuft jetzt über die Übersetzungstabelle. Sie findet nun die gerade angezeigte Sprache und auch übersetzte Inhalte.
Beiträge in Listen, Widgets und „Meine Seite“ waren nicht sichtbar
- •Das Widget mit den Tätigkeitsbereich-Tabs und das Forum-Raster-Widget zeigten immer eine leere Liste (der Fehler wurde intern verschluckt).
- •Unter „Meine Kommentare“ auf „Meine Seite“ fehlten die Forum-Kommentare vollständig.
- •Beim Link-Forum-Skin war der Titel immer leer.
- •Behebung: Alle lesen Titel und Text jetzt aus der Übersetzungstabelle. Vorschaubilder werden außerdem wieder aus dem Text ermittelt.
KI
- •Wir haben behoben, dass die KI-Übersetzung von Beiträgen beim Lesen des Originaltexts scheiterte und alle Übersetzungsaufträge fehlschlugen.
- •Wir haben behoben, dass bei der Neuinstallation die Titel und Texte in der Originalsprache der Beispielbeiträge nicht in die Übersetzungstabelle gelangten, sodass der Titel leer aussah.
Sonstiges
- •Wir haben behoben, dass die Liste nicht aufging, wenn die Forum-Sortierung auf „nach Empfehlungen“ stand (es wurde auf eine nicht existierende Spalte verwiesen).
Fremder Text landete unverändert im Hinweisfenster
Das gemeinsame Hinweisfenster der Verwaltung (Ergebnis-Dialog) fügte Menütitel, Skin-Namen und Servermeldungen unverändert in die Seite ein.
Stand in einem Namen etwas wie <script>, konnte das beim Öffnen der Seite durch andere Administratoren ausgeführt werden (gespeichertes XSS).
- •Behoben: Jeder Text im Hinweisfenster (Überschrift, Inhalt, Schaltfläche, Bestätigungszeile) wird vor dem Einfügen so umgewandelt, dass er als reiner Text erscheint.
- •Auch der Hinweis bei fehlgeschlagener Datenbankverbindung nutzt jetzt einen übersetzten Text und dieselbe Umwandlung.
Die Schaltflächen erschienen in jeder Sprache auf Koreanisch
- •„Bestätigen“ und „Abbrechen“ waren im JavaScript fest auf Koreanisch hinterlegt. Sie erscheinen nun in der angezeigten Sprache.
Der Server stellt die Texte der aktuellen Sprache bereit, das Skript liest diese Werte.
Verwaltungstexte in 13 Sprachen
Fest eingetragene koreanische Texte in den Ansichten für Design (Skin), Menü und Seiteneinstellungen wurden durch Übersetzungsschlüssel ersetzt und für 13 Sprachen gefüllt.
- •Skins: Ergebnisse von Umbenennen, Duplizieren und Löschen; die Bestätigung „Skin-Dateien und Einstellungen werden endgültig gelöscht“; Ergebnis des Bild-Uploads
- •Menüs: Hinweis, dass eine Systemseite nur aus dem Menü entfernt wird; Bestätigung „die verknüpfte Seite (Forum) wird ebenfalls gelöscht“
- •Seiteneinstellungen: Hinweise zu Dateityp, fehlgeschlagenem Speichern und doppelter URL
Private Beiträge waren in der Liste sichtbar
Ein als privat markierter Beitrag zeigte in der Liste weiterhin Titel, Vorschaubild und Auszug. Verborgen war nur der Text.
- •Behoben: Auch in Listen sehen nur die verfassende Person, Administratorinnen und Administratoren oder wer das Passwort eingegeben hat Titel und Vorschau.
- •Ebenfalls geschlossen: der Blick auf Inhalte über die URL eines Anhangs. Anhänge prüfen jetzt dieselbe Berechtigung.
- •Auch die Titel von vorherigem und nächstem Beitrag auf der Leseseite bleiben verborgen.
- •Widgets, die Listen einbinden (Forenkarten, Raster, Reiter), schließen private Beiträge bereits in der Abfrage aus.
Der erste Seitenaufbau dauerte zu lange
Auf dem Smartphone erschienen die ersten Zeichen sehr spät. Ursache waren die Schriften.
- •Das Schriften-CSS (Google Fonts 152 KB + Pretendard 29 KB) blockierte das Rendern.
Jetzt wird zuerst mit Systemschriften gezeichnet; Webfonts werden ersetzt, sobald sie eintreffen.
- •Pretendard wird nur auf koreanischen Seiten geladen. Auf japanischen Seiten steht eine japanische Schrift vorn, sodass nur Fragmente geladen und verworfen wurden.
- •Zwei kleine Stylesheets (Schriftgröße, Forentext) stehen jetzt direkt in der Seite statt als eigene Datei.
- •Beim ersten Besuch ließ der Seiten-Cache (Service Worker) das Dokument zweimal laden – das entfällt.
- •Die Breitenberechnung des horizontalen Menüs erfolgt erst nach dem Laden der Seite (vorher blockierte sie 0,5 s).
Damit Suchroboter und KI den Sprachseiten folgen können
- •Sprachlinks führen jetzt auf echte Adressen (
?lang=…). Zuvor waren es JavaScript-Links, denen Crawler nicht folgen konnten.
Verwaltung
- •In der Seitenliste erschien dieselbe Seite je Sprache mehrfach; diese Zeilen sind nun zu einer zusammengefasst.
- •Wurde nur der Menütitel geändert, gingen die Übersetzungen der anderen Sprachen verloren. Sie werden jetzt nur noch bereinigt, wenn die verlinkte Seite wechselt.
- •Eine geplante Blog-Veröffentlichung mit vergangener Uhrzeit wurde einfach gespeichert; jetzt erscheint ein Hinweis, und der Status bleibt unverändert (13 Sprachen).
Benachrichtigungen und Texte
- •Der Betreff der Community-Nachrichten war fest auf Koreanisch eingestellt. Er geht nun in der Sprache der empfangenden Person heraus.
- •Der Linktext im Cookie-Hinweis war zu dunkel und ist jetzt heller.
Aufräumarbeiten
- •Versehentlich doppelt vorhandene Ordner der Verwaltungsansichten (
admin/site/site, admin/components/components) wurden entfernt.
Genutzt werden die ursprünglichen Ordner. Auch der Build der Distribution schließt diese Ordner aus.
Private Foren wurden in die Sitemap aufgenommen
Selbst die Adressen von Foren, die nur Administratoren sehen (z. B. Eingangsfächer für Anfragen), landeten in der Sitemap.
Suchmaschinen-Crawler erhielten dort nur 403 (Zugriff verweigert), und die Existenz privater Foren wurde sichtbar.
- •Korrektur: Es werden nur Foren aufgenommen, die Nichtmitglieder sehen können. Maßgeblich sind Foren, bei denen die Berechtigung für Liste und Beiträge auf „Alle“ steht.
- •Geheime Beiträge sowie Foren, die in den Foreneinstellungen von der Suche ausgeschlossen sind (noindex), werden ebenfalls weggelassen.
- •Eine Seite mit demselben Namen wie ein Forum wird nach dem Forum beurteilt, weil das Forum die Adresse zuerst belegt.
- •Mehrsprachige Seiten werden ebenfalls in die Sitemap aufgenommen.
- •Seiten, die auf einer bestimmten Website nicht aufgenommen werden sollen, tragen Sie in der Einstellung
sitemap_exclude ein. llms.txt folgt derselben Einstellung.
Gesendete E — Mails landeten im Spam oder kamen zurück
- •In den E-Mails fehlten Sendezeit (Date) und eindeutige Nachrichtenkennung (Message-ID), sodass empfangende Server sie leicht als Spam einstuften.
Beides wird jetzt gesetzt, und der Text wird als base64 gesendet. Damit werden auch abgeschnittene lange Zeilen und durch einen „.“ am Zeilenanfang abgebrochene Texte verhindert.
- •Lag die Empfängeradresse in derselben Domain wie der Absender (z. B. eine Kopie an die Firmenadresse), lehnte das Postfach dieser Domain die E-Mail als Fälschung ab.
Nur in diesem Fall wird jetzt über die Adresse des SMTP-Kontos gesendet; Antworten gehen weiterhin an die ursprüngliche Adresse.
SEO — und KI-Sucheinstellungen erweitert
- •In den SEO-Einstellungen des Admins gibt es jetzt Felder für Betreiberangaben (strukturierte Daten „Organization“). Felder ohne Wert werden nicht ausgegeben.
- •Die SEO-Einstellungen pro Seite werden jetzt tatsächlich verwendet, und wenn derselbe Inhalt unter mehreren Adressen erreichbar ist, wird eine kanonische Adresse (canonical) festgelegt.
- •Ein Feld für den Bing-Bestätigungscode wurde hinzugefügt. Die ChatGPT-Suche verwendet den Bing-Index.
- •Beschreibungen werden passend zur Anzeigebreite der Suchergebnisse gekürzt – am Satzende statt mitten im Satz.
Sprachanzeige bereinigt
- •Die 404-Seite erschien immer auf Koreanisch. Jetzt wird sie in der angezeigten Sprache ausgegeben (Japanisch, Koreanisch oder Englisch; andere Sprachen erhalten Englisch).
- •„Gerade eben“ in der Benachrichtigungsglocke war fest auf Koreanisch hinterlegt – behoben.
- •Japanische Seiten verwenden zuerst japanische Schriftarten. Der Schrift-Helper je Sprache wird immer geladen, sodass auch Seiten ohne Layout (z. B. Freigabeseiten) nicht mehr wegen der Schrift abbrechen.
- •Unter „Bevorzugte Sprache“ auf „Meine Seite“ werden keine Sprachen mehr aufgeführt, für die es keine Texte gibt.
- •Bei der Registrierung wird die Sprache der gerade angezeigten Seite als bevorzugte Sprache gespeichert (bisher blieb sie leer). Auch E-Mails zum Zurücksetzen des Passworts werden in dieser Sprache gesendet.
Eingabe und Anmeldung
- •Datumsangaben wie das Geburtsdatum werden jetzt in drei Feldern für Jahr, Monat und Tag eingegeben. Früher hing die Darstellung von der Browsersprache ab.
- •Behoben: Bei manchen Skins fehlte die reCAPTCHA-Prüfung bei Anmeldung und Passwort-Wiederherstellung.
Zahlung
- •Für jeden Zahlungsdienstleister werden Test- und Live-Schlüssel getrennt gespeichert. Den Testmodus wählen Sie nur noch aus; beim Wechseln gehen keine Schlüssel mehr verloren.
Widgets
- •Die Schaltfläche des Hero-Widgets kann in einem neuen Fenster öffnen.
- •Wiederholte Elemente im Widget-Builder lassen sich ebenfalls pro Sprache bearbeiten (Globus-Schaltfläche).
Build
- •Konfigurationsdateien (.env) und ihre Backups werden unabhängig vom Namen nie in die Distribution aufgenommen.
- •Beim Bearbeiten entstandene Backup-Dateien (
.bak, auch mit angehängtem Datum) werden ebenfalls nicht aufgenommen.
- •Skripte, die nur für den Betrieb der Zentrale verwendet werden (Website-Synchronisierung, Hosting, Mailserver, Aktualisierung der Nutzungsbedingungen usw.), sowie Cronjobs, die nur von nicht enthaltenen Plugins genutzt werden, wurden aus der Distribution entfernt. Skripte, die Kundenseiten benötigen – etwa die Update-, Installations- und Übersetzungs-Worker –, sind weiterhin enthalten.
- •Nach dem Erstellen der ZIP-Datei wird noch einmal geprüft; befinden sich darin Konfigurations- oder Backup-Dateien, wird die Veröffentlichung gestoppt.
- •Testskripte speichern keine Passwörter mehr in der Datei, sondern lesen sie aus der Konfiguration.
Nach dem Update änderten sich Versionsname und Erscheinungsdatum nicht
Nur die Nummer stieg, und der Titel der vorherigen Version blieb unverändert stehen.
Im Admin Bildschirm erschien etwa „2.7.9 · Japanische Schriften · Hinweis zur Vertragsverlängerung…“, Nummer und Name passten also nicht zusammen.
Allein am Bildschirm war nicht zu erkennen, was man erhalten hatte.
- •Ursache:
version.json ist eine Datei, die absichtlich nicht überschrieben wird, um die individuellen Einstellungen jedes Kunden zu schützen.
Deshalb füllt der Updater sie selbst aus, tauschte aber nur die Nummer und die Uhrzeit aus und ließ Titel und Erscheinungsdatum stehen.
- •Behebung: Titel und Erscheinungsdatum der neuen Version werden nun aus dem empfangenen Paket gelesen und mit übernommen.
Bei Teilaktualisierungen ohne Paket werden sie aus der Verteilungsliste (manifest.json) gelesen.
Die kundenspezifischen Einstellungen (github usw.) bleiben unverändert erhalten.
Hinweis — auch nach dem Update auf diese Version kann der Bildschirm noch den alten Namen zeigen. Das Update führt nämlich
der Updater der aktuell installierten Version aus.
Ab der Version nach dem Erhalt von 2.7.10 wird es korrekt angezeigt.
Build Prüfung
Der Ausfall des Builders in 2.7.8 (in 2.7.9 behoben) bestand die Regressionstests unbeanstandet.
Die bisherigen Prüfungen schauten nämlich nur darauf, ob die Datei vorhanden ist und ob der String darin vorkommt.
- •Nun wird das Skript, das in den Builder kommt, tatsächlich erzeugt und auf Syntax geprüft (
node --check).
- •Gibt es Code, der eine mehrzeilige Datei unverändert in einen JS-String einfügt, wird der Build unter Nennung der Zeilennummer gestoppt.
- •Wir haben es mit einer Datei getestet, die 2.7.8 nachbildet, und bestätigt, dass die Prüfung es tatsächlich abfängt.
Symptome
- •In der Palette ist kein einziges Widget zu sehen
- •Bereits platzierte Widgets werden nicht auf die Arbeitsfläche gezeichnet — Videos, Bilder und Ähnliches scheinen verschwunden zu sein
- •Speichern funktioniert nicht
Ursache
In 2.7.8 haben wir die Schriftdeklarationen an einer Stelle, partials/fonts.php, zusammengeführt. Die Stelle, an der die Vorschau des Builders erzeugt wird, lag jedoch
innerhalb einer einzigen Zeile eines JS-Strings, und die 33 Zeilen lange Schriftdeklaration wurde unverändert dort eingesetzt.
Im selben Moment, in dem die Zeile umbrach, wurde der String abgeschnitten, und das gesamte Builder-Skript starb, noch bevor es überhaupt gelesen wurde.
Da es ein Fehler ist, der die ganze Datei lahmlegt, wirkt es nicht wie „einige Funktionen sind seltsam“, sondern so, als täte der Builder gar nichts.
2.7.5 und früher haben dieses Problem nicht.
So haben wir es behoben
Die Schriftdefinitionen bleiben an dieser einen Stelle, fonts.php, und nur beim Einfügen in den Builder wird die Ausgabe auf eine Zeile gefaltet und die Anführungszeichen werden behandelt.
Es gibt weiterhin nur eine Stelle, an der man Schriften ändert.
Standardschrift nun auf Japanisch ausgerichtet
Bisher war die Standardschrift auf Koreanisch ausgerichtet. Unsere Hauptnutzer sitzen in Japan, doch die Bildschirme wirkten unpassend,
und beim Wechsel der Sprache blieb die Schrift gleich, sodass japanische Texte in einer koreanischen Schrift gesetzt wurden.
- •Die Standardwerte lauten jetzt Mincho für Überschriften und Pretendard JP für den Fließtext.
- •Auf dem Bildschirm der Spracheinstellungen lässt sich für jede Sprache eine eigene Schrift festlegen. Ohne Angabe bekommt die Sprache einen passenden Standardwert.
- •Dieselbe Regel gilt für alle Bildschirme in Verwaltung, Mitgliederbereich und Frontend sowie für alle Skins (default, modern, minimal, shop).
Hinweis zu Vertragsverlängerung und Ende der kostenlosen Bereitstellung
Manchmal bemerkte man den Ablauf eines Vertrags erst, nachdem er vorüber war. Jetzt wird man rechtzeitig benachrichtigt, wenn das Verlängerungsdatum näher rückt.
- •Anstehende Verlängerungen und das Ende der kostenlosen Bereitstellung werden vor dem Datum als Benachrichtigung angezeigt.
- •Es läuft über eine einzige Cron-Zeile (
cron.d-voscms-contract-notice), und die Installationsanleitung erklärt, wie man sie einträgt.
Kartenzahlung
Zahlungen, die die Authentifizierung der japanischen Kartenunternehmen (3-D Secure) durchlaufen hatten, bestanden die Authentifizierung, doch die Abbuchung wurde abgelehnt.
- •PAY.jp sperrt ein für die Authentifizierung erzeugtes Token, wenn es unverändert bleibt. Nach bestandener Authentifizierung muss der Server einen abschließenden Aufruf machen,
erst dann ist es für eine Abbuchung nutzbar, und genau dieser eine Schritt fehlte.
- •Außerdem haben wir einen Weg geöffnet, vorab zu prüfen, ob die Kundendaten beim Zahlungsdienstleister noch vorhanden sind — das verhindert Fehlschläge durch Abbuchungsversuche mit gelöschten Kunden.
Benachrichtigungsglocke und Rückerstattungsrichtlinie in allen Sprachen
- •In der Benachrichtigungsglocke der Kopfzeile waren Texte wie „Keine Benachrichtigungen“ und „vor Minuten“ fest auf Koreanisch eingebaut. Sie wechseln jetzt je nach Sprache.
- •Die verbliebenen festen Formulierungen im Hinweistext der Rückerstattungsrichtlinie wurden bereinigt.
Buchhaltung
In die Bücher der japanischen Gesellschaft mischten sich Won-Transaktionen, sodass die Summen nicht stimmten.
- •Für Belege in einer anderen Währung als der Buchwährung (Yen) werden keine Buchungssätze erzeugt. Der Eintrag bleibt erhalten, geht aber nicht in die Bücher ein.
Aufräumen der Distribution
- •Beim Bearbeiten entstandene Sicherungsdateien wurden mit der Distribution ausgeliefert (Namen wie
Dateiname.php.bak.Zahl).
Die Ausschlussregel filterte nur .bak und übersah Namen mit angehängter Zahl. Wir sperren jetzt auch .bak., .orig und *~.
- •Die Verkaufsunterlagen des THEVOS AI Dienstes (Preistabelle, Paketberechnung, Cron für den Zahlungsabgleich) wurden aus der Distribution entfernt.
Alles, was sie liest, war bereits entfernt, sodass sie in der Distribution Dateien waren, die niemand benutzt.
„DB
039_ai_knowledge_base legt die Tabellen für die Beratungs-KI der NaitoWork X Geschäfte an,
wurde aber unverändert in der Distribution ausgeliefert. Dazu kam, dass die letzte Zeile dieser Datei so lautete:
ALTER TABLE rzx_shop_inquiries ADD COLUMN IF NOT EXISTS ai_meta ...
rzx_shop_inquiries ist eine Tabelle, die das Plugin vos-store anlegt.
In der Distribution gibt es kein vos-store — der Kern wollte die Tabelle eines nicht vorhandenen Plugins verändern.
Daher bei jeder neuen Installation: 4 Tabellen werden angelegt und es scheitert an der letzten Zeile → da es nie bis zum Ende kam,
wird es nicht als „angewendet“ verbucht → das Banner bleibt dauerhaft stehen, und ein Klick scheitert an derselben Stelle erneut.
Wir haben die KI-Beratung (RAG) komplett aus der Distribution genommen:
039 · rzxlib/Core/AI/{Knowledge,Embedding,Generate} ·
scripts/{ai-kb-ingest,ai-rag-test,cron-ai-consult,hanesbot-ingest}.php
Die KI-Übersetzung (rzxlib/Core/AI/Translation) bleibt erhalten. Sie ist die Engine des kostenpflichtigen Plugins vos-ai
und folgt wie Buchhaltung und Hosting der Regel: „Die Engine liegt im Kern, und das Plugin schaltet die Funktion frei.“
„1 Plugin ist nicht lizenziert (vos
Der Kern führt eine Liste der „mitgelieferten Plugins, die ohne Lizenz funktionieren“, und diese Liste war veraltet.
Was der Code als mitgeliefert kannte | vos-autoinstall · vos-marketplace |
Was tatsächlich mitgeliefert wird | vos-autoinstall · vos-community |
vos-marketplace ist aus der Distribution herausgefallen und vos-community an seine Stelle getreten,
doch nur diese Liste wurde nicht angepasst. Wir haben es mitgeliefert und dann eine Warnung ausgegeben, weil wir nicht wussten, dass es mitgeliefert wird.
Damit das nicht wieder passiert
Die Ursache ist, dass die Liste der mitgelieferten Plugins an zwei Stellen steht —
in der Ausschlussliste des Build-Skripts und in LicenseStatus::BUNDLE_PLUGINS.
Wir haben dem Build einen Abgleichsschritt hinzugefügt. Weichen beide voneinander ab, wird keine zip erzeugt und der Build bricht ab.
Das ist nichts, was sich Menschen merken sollten.
Im Forum fehlte der Schreiben
In Q&A und FAQ hatten selbst Personen mit Schreibrecht keinen Button. Es gab zwei Ursachen.
- •Administratoren wurden ausgesperrt — bei der Prüfung des Schreibrechts wurde zuerst gefragt, ob es ein Mitglied ist, und erst danach wurden Administratoren betrachtet.
Administratoren stehen nicht in users und scheiterten deshalb an der ersten Hürde. Wir haben die Reihenfolge getauscht, sodass Administratoren zuerst durchgelassen werden.
- •Ohne jeden Beitrag verschwand auch der Button — der Button saß innerhalb der Liste,
und beim Wechsel auf die Ansicht „Keine Beiträge“ verschwand er mit. Wer als Erstes schreiben wollte, konnte nicht schreiben.
Wir haben den Button aus der Liste herausgenommen.
- •FAQ hat sogar direkt
admin_id ausgewertet — und das Schreibrecht aus den Forumseinstellungen ignoriert.
Forumstitel und Untertitel erschienen in einer anderen Sprache
Ein koreanischer Bildschirm, auf dem nur der Untertitel auf Japanisch erschien.
- •Übersetzungen wurden gar nicht gelesen. Titel und Untertitel werden in den Skin-Einstellungen als ein einziger String gespeichert,
die Übersetzungen liegen dagegen getrennt in rzx_translations. Der Bildschirm gab einfach den gespeicherten String aus.
- •Es gab keine Unterscheidung nach Forum. Der Übersetzungsschlüssel lautete
skin_config.subtitle_text, sodass Q&A und FAQ
sich denselben Platz teilten. Wer das eine änderte, veränderte auch das andere.
Wir haben ihn in board.{Forumsnummer}.{Eintrag} aufgeteilt.
- •Der Inhalt wurde gezeichnet, bevor die Sprache feststand. Der Kern erzeugt zuerst den Inhalt und hängt die Kopfzeile danach an,
die Sprache wurde aber in der Kopfzeile bestimmt. Wir haben die Entscheidung auf die Inhaltsseite vorgezogen.
Bei der Installation fehlten die Kern
install-core.php hat database/migrations überhaupt nicht angesehen.
Auf neu installierten Websites fehlten von Anfang an einige Tabellen, und beim späteren Einschalten der Funktion kam es dann zum Absturz.
Migrationen, die stillschweigend übersprungen wurden (Fortsetzung von 2.7.4)
In 2.7.4 wurden einzeilige Kommentare (--) behandelt, aber mehrzeilige Kommentare (/ /) waren noch übrig.
Ein Semikolon innerhalb eines solchen Blocks fasste die Datei zu einem einzigen Stück zusammen, sodass keine einzige Zeile ausgeführt wurde
und sie dennoch als „angewendet“ verbucht wurde. Wir haben den tatsächlichen Schaden bestätigt — bei einer Installation fehlten 9 Tabellen komplett.
Ein -- oder /* innerhalb eines Strings ist kein Kommentar. Wir entfernen Kommentare, während wir die Anführungszeichen mitzählen.
Sonstiges
- •Shop-Kopfzeile — im Kategorie-Pulldown steht ganz oben jetzt „Alle Kategorien“.
Wer hineingehen und stöbern wollte, hatte keinen Ort, an den er gehen konnte.
- •Widget-Builder — die Bearbeitung wiederholter Einträge (
repeater) wurde in eine eigene Datei ausgelagert.
- •Intranet-Seitenleiste — der Buchhaltungstext wird in allen drei Varianten (Salon, Online-Shop, allgemeines Unternehmen) gesucht.
Weil nur eine betrachtet wurde, zeigte das Menü bei anderer Buchhaltung den rohen Schlüssel an.
- •Meine Seite — Dashboard aufgeräumt.
- •Meldung kostenpflichtiger Plugins — die Lizenzprüfung sendet jetzt auch die eingeschalteten kostenpflichtigen Plugins mit.
Nur installierte, aber nicht eingeschaltete werden nicht gesendet — Geld hängt nur an den eingeschalteten.
Seiten nur für den Hauptsitz wurden im Release
config/system-pages.php kam komplett in das Release-Paket, sodass die „Systemseiten“ im Admin-Bereich der Installation eines Kunden
sechs Menüs erhielten, die man anklicken kann, hinter denen aber nichts steckt.
📥 downloads | Downloads des Release-Pakets — nur der Hauptsitz verteilt sie |
📋 changelog | Es ist die Produkthistorie des Hauptsitzes |
📧 contact | Kunden bauen es selbst mit einem Widget (es ist keine Systemseite) |
💼 recruit · 💃 casts | Nur für das Nachtgewerbe-Portal (NaitoWork X) |
🎟 coupons | Das Marktplatz-Plugin stellt es bereit |
- •Der Build-Schritt
[4e/8] wurde hinzugefügt (strip-system-pages.php). Nach dem Entfernen wird die Syntax mit php -l geprüft —
geht diese Datei kaputt, fällt der gesamte Admin-Bereich aus.
- •Im Release-Paket bleiben acht Systemseiten: home · terms · privacy · data-policy ·
refund-policy · hosting-terms · tokushoho · funds-settlement
Systemseiten von Plugins
- •Der Text
site.pages.blog wurde in 13 Sprachen ergänzt.
Auch wenn ein Plugin eine Systemseite registriert: Hat der Kern dafür keinen Text, erscheint site.pages.blog unverändert auf dem Bildschirm.
- •(Die Korrektur an der eigenen
plugin.json von vos-blog geht über den Marktplatz hinaus — es ist ein Plugin, das nicht im Release-Paket enthalten ist)
Bereits installierte Websites
Erscheint in den „Systemseiten“ des Admins ein Eintrag, den Sie nicht nutzen, löschen Sie den entsprechenden Block aus config/system-pages.php.
Der Seiteninhalt (rzx_page_contents) wird nicht gelöscht — er verschwindet nur aus der Liste.
① Migrationen, die mit einem Kommentar beginnen, wurden komplett übersprungen
- •Ein Kommentar in
DatabaseMigrator::splitSql() besagte „nach dem Entfernen der Kommentare aufteilen“, aber
tatsächlich wurde nur an Semikolons geteilt.
- •Ist die erste Zeile einer SQL-Datei
-- Beschreibung, wird die ganze Datei zu einem einzigen Fragment,
bleibt an str_starts_with($stmt, '--') im Ausführungsteil hängen, und keine einzige Anweisung wird ausgeführt.
- •Werden 0 Anweisungen ausgeführt, gibt es auch 0 Fehler, sodass es als
success behandelt und als angewendet aufgezeichnet wird.
Ist es einmal aufgezeichnet, läuft es nie wieder, sodass die Tabelle dauerhaft fehlt.
- •Betroffen waren alle Dateien, die mit
-- beginnen. Gemessen: Von 9 Dateien führten 6 gar keine Anweisung aus und 2 nur teilweise.
- •Jetzt werden vor dem Teilen die Zeilenkommentare mit
-- und # sowie / /-Blöcke entfernt.
Ein -- innerhalb einer Zeichenkette wird nicht angetastet (würde ein Wert wie 'a -- b' abgeschnitten, wären die Daten kaputt).
② Eine Neuinstallation führte die inkrementellen Migrationen gar nicht aus
- •Das Installationsskript führte nur
migrations/core und migrations/migrations aus
und übersah die oberste Ebene database/migrations/*.sql. Der Updater verfolgt dagegen nur die oberste Ebene.
- •Deshalb fehlten bei einer Neuinstallation 034 bis 042 von Anfang an und blieben bis zum nächsten Release leer.
- •Bei der Installation wird jetzt auch die oberste Ebene ausgeführt und als angewendet aufgezeichnet (damit das erste Update dieselben nicht noch einmal ausführt).
Bereits installierte Websites
Bitte drücken Sie unter Admin → Einstellungen → Update einmal auf Migrationen ausführen.
Falsch aufgezeichnete Einträge laufen nicht erneut. Ist eine Tabelle leer, können Sie das so prüfen.
SELECT migration FROM rzx_migrations; -- aufgezeichnet
SHOW TABLES LIKE 'rzx_home_notices'; -- tatsächlich
Was aus dem Release
- •
vos-cp (Service-Kontrollpanel) und vos-shopping (Onlineshop) reisten im Release-Paket mit.
Beide sind neu erstellte Plugins, die schlicht noch nicht auf der Ausschlussliste standen.
- •
vos-cp ist ein Panel für die eigenen Dienste von THEVOS. Es gibt keinen Grund, dass es in der Installation eines Kunden liegt
- •
vos-shopping ist noch in Entwicklung (v0.1.0), und die Regel lautet, dass Plugins im Marktplatz gekauft werden
- •
vos-review wurde ebenfalls herausgenommen — aus demselben Grund (Anweisung des Inhabers).
- •Im Release-Paket sind nur zwei Plugins enthalten:
vos-community und vos-autoinstall.
Alles andere bezieht man über den Marktplatz.
Was dem Kern hinzugefügt wurde
- •Ein zweistufiger Shopping-Kopfbereich (
skins/layouts/shop) — ein Pulldown mit allen Kategorien, Suche, eine Warenkorb-Vorschau und
ein Avatar-Menü nach der Anmeldung. Ganz oben im Kategorie-Pulldown steht „Alle Kategorien“, damit es einen Weg zurück gibt
- •Gesammelte Punkte, Guthaben und Mitgliedsstufe werden in „Meine Seite“ angezeigt. Die Namen übernehmen die eingestellten Werte
- •Unterstützung für Plugin-Widgets — legt ein Plugin einen Ordner
widgets/ an, erkennt der Kern-Builder ihn automatisch
- •Eine gemeinsame Komponente zur Adresssuche per Postleitzahl — Bestellformular und Mitgliedsangaben nutzen dieselbe
- •Eine Benachrichtigungsglocke in der oberen Leiste des Admin-Bereichs
- •Bereinigung der Menügruppen der Admin-Konsole (
config/intranet-modules.php)
- •Unterstützung für Wiederholungsfelder (repeater) im Widget-Builder
Was behoben wurde
- •Das Problem, dass mehrsprachige Eingabefelder die Originaldaten überschrieben
- •Ein Fehler bei der Aufzeichnung des Guthabenbuchs
- •Das Problem, dass das Release-Update Hosting-Seiten zu 404 machte
Was bei installierten Versionen zu prüfen ist
Auf Websites, die mit einem alten Release installiert wurden und seitdem nur Updates erhalten haben, bleiben Ordner nicht genutzter Plugins zurück
(ein Update löscht keine Plugin-Ordner). Alles, was unter Admin → Plugins als nicht installiert angezeigt wird,
kann samt Ordner aus plugins/ gelöscht werden.
Changed
- •Vereinheitlichtes Routing der URLs für Dienstanträge —
/service/hosting, /service/mail und /service/domain → per 302 auf /service/order (bis eigene Antragsseiten bereitstehen, werden Besucher zur integrierten Antragsseite geführt; später lassen sie sich durch eigene Seiten ersetzen).
Notes
- •Die Kern-Korrekturen von 2.7.1 (mehrsprachiges hreflang, Verhinderung stiller Updater-Fehler, Überführung der Preisseite
/pricing in /service/order) waren bereits korrekt im Paket von 2.7.1 enthalten. 2.7.2 ist ein Neubau, der darüber die Bereinigung des Routings für Dienstanträge hinzufügt.
- •Das Release-Paket enthält grundsätzlich nur den reinen Kern (kostenpflichtige und Branchen-Plugins ausgeschlossen). Die Hauptsitz-Websites (voscms.com und thevos.jp) sind kein Ziel des Selbst-Updates des Release-Pakets; sie werden aus dem Quellcode/git ausgeliefert.
SEO
- •Mehrsprachiges hreflang — ein sich selbst referenzierendes canonical pro Seite + automatisches hreflang für unterstützte Sprachen, Indexierung pro Sprache mit
?lang=xx, 301-Normalisierung des ?lang der Standardsprache auf die schlichte URL und eine erweiterte Sitemap.
Fixed
- •Stille Fehler des Updaters behoben — Fehler beim Schreiben von Kerndateien oder version.json werden jetzt als Ausnahmen behandelt. Schlägt das Anwenden wegen unzureichender Berechtigungen und Ähnlichem fehl, erhält man jetzt statt eines falschen „SUCCESS“ eine eindeutige Fehlermeldung und ein automatisches Rollback.
- •Der 500-Absturz der Preisseite, bei dem ein mehrsprachiges Feld als Array an htmlspecialchars übergeben wurde, wird jetzt abgefangen.
Changed
- •Der Schalter für reCAPTCHA v3 pro Formular wurde erweitert (blog_comment und andere).
- •Der Reiter „Benachrichtigungen der Inhaberkonsole“ in den Einstellungen wird nur angezeigt, wenn vos-store aktiv ist.
- •Die Preisseite
/pricing wurde in /service/order überführt (301), und der Tarif „System unbegrenzt“ ist nur für Administratoren.
Paketinhalt
- •Das Release-Paket ist auf einen reinen Kern verschlankt — nur 3 Kern-Plugins (
vos-autoinstall, vos-community, vos-review) sind enthalten. Die Branchen-Plugins (Nachtgewerbe / Salon / POS), Widgets und der Skin (story) sind vollständig ausgeschlossen. Allgemeine Funktionen wie Altersprüfung und Cookie-Banner gehören zum Kern (rzxlib) und sind daher enthalten.
Added/Changed (Kern
- •location-map — unterstützt schlüsselloses Einbetten (
map_embed), wodurch die Abhängigkeit von einem API-Schlüssel entfällt, und koppelt die Kartensprache an die Locale
- •practice-tabs (Tabs für Tätigkeitsbereiche) — ein neues mitgeliefertes Widget
- •Globale Einstellung der Seitenbreite (
widget_page_width) — vereinheitlicht die Breite von Widget-/Dokumentseiten
Websitespezifische Widgets, die nicht mitgeliefert werden (bundled:false) (hero-slideshow, overlap-cards, office-intro, page-hero, content-head, consult-cta, board-grid, clients-logos, der Profil-Skin des Forums), sind im Kern-Release-Paket nicht enthalten.
Removed
- •Die Prepaid-Widgets (
prepaid-charge, prepaid-pass, prepaid-purchase) — aus dem Release ausgeschlossen, weil vos-prepaid nicht mitgeliefert wird
Added (Einstellungen und Kern)
- •Das Tor für die Altersprüfung wurde zu einer allgemeinen Kern-Einstellung aufgewertet
- •Regelung der Hintergrunddurchsichtigkeit des Cookie-Einwilligungsbanners
- •Logobilder pro Sprache
- •Bankverbindung in den Unternehmensangaben + ein Hinweis zur Banküberweisung
- •Ein Hinweis auf „Akzeptierte Karten“ auf dem Zahlungsbildschirm (Markensymbole) + Admin-Einstellung
Fixed
- •Lokalisierung von Seitentiteln und Untertiteln in die Sprache des Besuchers (page-scoped db_trans) und das Problem, dass content_width nicht angewendet wurde
- •Viele Fehlerbehebungen bei Widgets/Admin/Seiten und Ergänzungen in 13 Sprachen
Added
- •Automatische Bereinigung veralteter Dateien — ein Update, das mit dem Vollpaket-ZIP überschreibt, kann aus der Quelle entfernte Dateien nicht löschen, sodass in installierten Versionen Reste (Orphans) zurückblieben (zum Beispiel blieb das monolithische
settings.php, das bei einem Refactoring aufgeteilt und entfernt wurde, in alten Installationen erhalten). Wir haben einen Mechanismus auf Basis einer ausdrücklichen Liste hinzugefügt, um sie aufzuräumen.
- •
config/obsolete-files.php — eine kumulative Liste der zu löschenden Pfade (auch Installationen, die mehrere Versionen übersprungen haben, werden in einem Zug bereinigt).
- •Unmittelbar nach
applyUpdate() des Updaters führt cleanupObsoleteFiles() ein sicheres unlink der Dateien in der Liste aus. Geschützte Ziele (.env, storage usw.), Pfadausbrüche und Verzeichnisse werden nie angefasst.
- •Zuerst eingetragen:
resources/views/admin/settings.php.
Fixed
- •Der Link „Systemeinstellungen“ im Dashboard — der Link in den Schnellaktionen zeigte auf den veralteten, abgetrennten und entfernten Pfad
/settings, sodass man auf einer falschen (Rückfall-)Seite landete. Korrigiert auf den Einstiegspunkt der Einstellungen /settings/general. (Nach dem Build von 2.6.22 übersehen.)
Behoben
- •Dashboard-Banner „DB-Migration erforderlich“ — CSRF token invalid — Die Schaltfläche für den erneuten Versuch sendete kein CSRF-Token an
/update-api.php (run_migrations) und wurde deshalb mit 419 abgelehnt. $_SESSION['csrf_token'] wird jetzt sichergestellt und im Header und im Body mitgesendet.
- •Banner verschwand auch nach der Migration nicht —
DatabaseMigrator::recordMigration setzte eine Spalte batch und das Präfix patch_ voraus. Beim Schema einer Installation (migration/version/executed_at) schlug das INSERT für den Eintrag daher fehl, und wegen des Präfixes stimmten auch die Dateinamen nicht überein. Jetzt wird passend zu den tatsächlichen Spalten der Dateiname unverändert eingetragen. (Ursache dafür, dass beim Update auf 2.6.20 Migrationen nur mit „OK“ protokolliert, aber nicht angewendet wurden)
Fixed
- •Rohe Schlüssel in der Seitenleiste von Kernseiten wie der Admin-Rechteverwaltung — weil das Intranet-Layout allein anhand der route_prefixes in
config/intranet-modules.php aktiviert wurde, wurde die Kernseite /staff/admins auf Websites ohne das passende Plugin (zum Beispiel ohne installiertes vos-salon) mit der Salon-Intranet-Seitenleiste gerendert, und die Schlüssel salon.intranet. und salon.section. erschienen als Rohtext. Behoben.
- •Ein gemeinsamer Helfer
resolve_intranet_module() wurde hinzugefügt — das Intranet wird nur aktiviert, wenn die lang-Ressourcen des Moduls (das Plugin) tatsächlich installiert sind; andernfalls Rückfall auf die Kern-Seitenleiste admin-sidebar.
- •Die doppelte Erkennungslogik in
_head.php / admin-sidebar.php wurde im Helfer vereinheitlicht. Auf Websites mit installiertem Plugin (salon, store usw.) bleibt das Verhalten unverändert.
Fixed
- •Fehler beim Speichern von Punktestufen — behoben, dass das Speichern einer Stufe im Punktemodul des Admins mit dem Fehler
Unknown column 'group_id' fehlschlug. Ursache war ein Schemakonflikt bei point_levels/member_points zwischen core/004 und migrations/019(v190) (das CREATE TABLE IF NOT EXISTS in 019 konnte einer bestehenden Tabelle keine neuen Spalten hinzufügen).
- •Migration
034_point_system_schema_reconcile (oberste Ebene, wird beim Update automatisch angewendet):
- •
point_levels — group_id hinzugefügt, name mit einem Standardwert versehen und ein eindeutiger Index auf level (damit Upsert funktioniert).
- •
member_points — point/balance/total_accumulated/level hinzugefügt.
- •Alles additiv (kein Datenverlust), ohne Auswirkung auf bestehende Spalten oder Nutzer (etwa vos-prepaid).
Added
- •3 Kauf-Widgets — ein integriertes (
prepaid-purchase, Anzeige wählbar: alles / nur Aufladung / nur Mehrfachkarten) + eines nur für Aufladungen (prepaid-charge) + eines nur für Mehrfachkarten (prepaid-pass). Eine gemeinsame Komponente purchase-widget.php steuert alle 3 Widgets (keine Duplikate) und verzweigt über den Filter $ppOnly.
- •Hintergrundbild für Produkte — Drag-and-drop-Upload (auch per Klick) im Admin-Modal zum Hinzufügen/Bearbeiten von Produkten, der Hintergrund wird in „Meine Seite“ und auf Widget-Karten angewendet. Migration 003
image_url.
- •Mehrsprachige Eingabe des Produktnamens + KI-Übersetzung — verwendet das gemeinsame
multilang-modal wieder (Globus-Schaltfläche), gespeichert auf Basis von rzx_translations und mit prepaid_name() in der Sprache des Besuchers angezeigt. Die KI-Übersetzung nutzt den Kern-Endpunkt /api/translations wieder.
- •Im Zahlungsformular wurde ein Eingabefeld für den Namen des Karteninhabers ergänzt (wird an
createToken von PAY.jp übergeben).
- •Kundenauswahl bei manueller Aufladung — von der direkten Eingabe einer user_id auf eine Autovervollständigungssuche nach Name/Telefon/E-Mail umgestellt (Aktion
customer_search). Auch die Kundenübersicht zeigt statt eines user_id-Hashs Name + E-Mail des Kunden.
- •Aktiv-Schalter — das Kontrollkästchen „Produkt aktiv“ wurde in einen Schalter umgewandelt.
Changed
- •Kaufbox mit 4 Spalten — das Raster der Produktkarten ist responsiv 2→3→4 (
lg:grid-cols-4), und die feste Widget-Breite max-w-3xl wurde entfernt → es passt sich der Breite des Platzierungscontainers an.
Fixed
- •Höhe von Palette und Mega-Menü im Widget-Builder — die Zeilenhöhe des Builders ist auf
calc(100vh - 88px) festgelegt, sodass die linken Kategorien und das Flyout automatisch die volle Bildschirmhöhe einnehmen und die Überlappung der Mega-Menü-Einträge behoben ist.
Added
- •Prüfung von link in
api/broadcast.php — fehlt das Schema, wird https:// automatisch vorangestellt (example.com → https://example.com); besteht die Eingabe filter_var FILTER_VALIDATE_URL nicht, kommt ein 400 mit dem Fehler field: 'link' zurück; mehr als 500 Zeichen werden abgelehnt.
- •Prüfung in Echtzeit im Client —
type="url", inputmode="url", und sofort bei der Eingabe:
- •Fehlendes Schema → emerald-Umrandung + ✓ + Hinweis „Wird beim Senden automatisch ergänzt: …“
- •Kein Punkt (.) im Host oder fehlerhaftes Format → red-Umrandung + ⚠ + „Dies ist kein gültiges URL-Format“
- •Gültig → emerald-Umrandung + ✓ + „Dies ist eine gültige URL“
- •Auch der Client ergänzt vor dem Senden → Vorschau und tatsächlich versendeter Text stimmen garantiert überein.
Added
- •Abschnittsüberschriften: ✉ Nachricht verfassen / 📡 Versandkanäle — visuelle Gruppierung + erklärender Text.
- •Zeichenzähler (Titel
0/255, Text 0/2000) — automatische Farben: ab 70 % amber, ab 90 % red.
- •Vorschaufeld für die Nachricht (gepunkteter Rand) — zeigt in Echtzeit, wie Titel, Text und Link zusammen in LINE aussehen werden + ein Zähler für die Gesamtzeichenzahl
n/5000 (über 4500 red).
- •Hilfetext für jedes Feld:
- •Titel: „Wird sowohl im Nachrichtenfach der Mitglieder als auch in der LINE-Benachrichtigung angezeigt“
- •Text: „Wenn Sie im Text eine URL schreiben, wird sie automatisch gekürzt und die Klicks werden verfolgt“
- •Link: „Wird automatisch nach einer Leerzeile am Ende des Textes angehängt. Schreiben Sie ihn zusätzlich in den Text, erscheint er zweimal — Vorsicht“
- •Statussymbol rechts im Link-Eingabefeld (
absolute) — ✓ / ⚠ erscheinen sofort.
Added
🔗 Regeln zur URL-Prüfung (neuer 5. Abschnitt):
- •Muss mit
http:// / https:// beginnen → wird in einen Klickverfolgungs-Token umgewandelt
- •Ein fehlendes Schema wird automatisch ergänzt
- •Hosts ohne Punkt oder mit fehlerhaftem Format werden abgelehnt
- •Begrenzung auf 500 Zeichen
- •Beispielkasten:
✓ https://voscms.com/event / ✓ example.com/page → automatisch ergänzt / ✗ asdfasdf (kein Punkt im Host)
Notes
- •Produktion (
voscms-com) und salon sind synchronisiert. API, Oberfläche und i18n wirken sofort.
- •i18n in 13 Sprachen:
community.broadcast.guide_url_, section_message, section_channels*, subject_hint, body_hint, link_hint, link_{invalid,autofixed,valid}, preview_{title,empty}.
Added
- •Layoutänderung von
/theadmin/community/broadcast — die bisherige einzelne Karte wird in lg:grid-cols-3 aufgeteilt. Das Hauptformular für den Versand belegt die linken 2 Spalten (lg:col-span-2), und rechts in 1 Spalte kommt ein neuer Hilfekasten (<aside>, sticky top-4).
- •Hilfeinhalt in 6 Abschnitten:
1. 📅 Was ist geplanter Versand? — automatischer Versand zu einem zukünftigen Zeitpunkt, nutzbar nachts, am Wochenende und bei Veranstaltungen
2. 🛠 So wird es verwendet — 4 Schritte (Zielgruppe wählen → LINE ankreuzen → Planung ankreuzen → Senden), Oberfläche mit nummerierten Abzeichen
3. ⏱ Genauigkeit des Versands — Erklärung des 5-Minuten-Intervalls von cron + ein Beispielkasten (10:00 → 10:00 bis 10:05)
4. 🆚 Sofort vs. geplant — der Unterschied im Verhalten der beiden Modi in Kartenform
5. 📋 Wartende Einträge in der Warteschlange prüfen — eine Schaltfläche als Abkürzung zu /history?status=queued
6. ⚠ Hinweise — mindestens 30 Sekunden in der Zukunft, In-App/Push lassen sich nicht planen, funktioniert nicht bei Hosting ohne cron, Abbrechen über die Oberfläche wird nicht unterstützt
- •Indigo-Farbverlauf als Hintergrund (
from-indigo-50 to-blue-50) — der Hilfekasten hebt sich optisch von der Hauptkarte ab und fügt sich zugleich weich ein.
- •i18n in 13 Sprachen — etwa 20 Schlüssel
community.broadcast.guide_* (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
Added
- •Karte „Bevorzugte Sprache“ in
/mypage/settings hinzugefügt — ein select mit 14 Optionen (automatisch / 13 Sprachen). Beim Speichern wird rzx_users.locale per UPDATE aktualisiert und $_SESSION['locale'] sofort übernommen.
- •Hook in Auth::loginUser — wenn beim Anmelden
$user['locale'] vorhanden und die Sitzungs-Locale leer ist, wird sie automatisch befüllt. Hat der Benutzer sie während der Sitzung manuell geändert, bleibt dieser Wert vorrangig erhalten.
- •i18n in 13 Sprachen —
auth.settings.language.{title,description,label,auto,hint,save,success,error_invalid,error_save} (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
- •Nach der Änderung wird die Oberfläche ab der nächsten Seite in der Sprache des Mitglieds angezeigt, und wenn ein Admin bei einer automatischen Versandregel
messages_by_locale gesetzt hat, wird dem Mitglied der passende Text per LINE gesendet.
Added
3 neue Karten oben auf /theadmin/community/broadcast/history (nach den bisherigen 4 Karten):
1. Gesamt-Klickrate (CTR) — SUM(rzx_broadcast_clicks.click_count) / SUM(rzx_line_broadcasts.recipient_count WHERE status='sent') × 100. Große Schrift in emerald.
2. A/B-Test (letzte 30 Tage) — für Sendungen mit variant IS NOT NULL Empfänger, Klicks und CTR pro Variant. Die Variant mit der höheren CTR wird in emerald hervorgehoben.
3. Verteilung nach Locale (letzte 30 Tage) — nur für Sendungen mit source='auto_rule' AND messages_by_locale IS NOT NULL wird die Locale zugeordnet, indem die Schlüssel des messages_by_locale-JSON der Regel mit den ersten 30 Zeichen des Broadcast-Textes verglichen werden → Empfänger/Klicks/CTR pro Locale. Sortiert mit ksort.
- •i18n in 13 Sprachen:
community.broadcast.stat_{ctr_title,ctr_breakdown,variant_title,variant_hint,locale_title,locale_hint,empty}.
Notes
- •Die Verzeichnisbäume
voscms-com und salon sind synchronisiert. Es gibt keine neuen DB-Spalten (sie waren bereits alle in den Migrationen 008/009/010 von Step 4 enthalten).
- •Die Logik zur Locale-Zuordnung vergleicht die ersten 30 Zeichen des Textes — stimmt der Text nach der Variablenersetzung überein, wird er derselben Locale-Gruppe zugerechnet. Ist der Text zu kurz oder wird er vollständig durch Variablenersetzung gefüllt, kann die Trefferquote sinken (künftig könnte direkt eine Locale-Spalte in der Broadcast-Zeile ergänzt werden).
Added
- •Migration 010 —
rzx_auto_broadcast_rules.messages_by_locale JSON NULL + rzx_users.locale VARCHAR(10) NULL + ein Index idx_locale.
- •AutoBroadcaster::lineUserIdsWithLocale — fragt Paare aus LINE-userId und Mitglieds-Locale ab. Umgebungen ohne die Spalte
users.locale fallen auf lineUserIds zurück.
- •AutoBroadcaster::pickLocaleMessage — Priorität: die user.locale des Mitglieds → die Standard-Locale der Website (rzx_settings.locale) → der erste Schlüssel des JSON (wenn alles fehlschlägt, null → Rückfall auf den A-Text).
- •AutoBroadcaster::fire — gibt es
messages_by_locale, wird pro Mitglied der zur Locale passende Text verwendet; sonst die A/B-Variant; und wenn auch diese fehlt, das einzelne A. Ergeben Locale, Variant und Standard denselben Text, werden sie als eine Gruppe per multicast gesendet (Effizienz).
- •Regel-Modal im Admin — „Mehrsprachiges Routing aktiviert“ und eine direkte JSON-Eingabe, aufklappbar über
<details>. Wird per Pretty-Print angezeigt. Validierung invalid_locale_json.
- •i18n in 13 Sprachen —
community.automation.locale_{toggle,placeholder,hint} + fields.messages_by_locale + error.invalid_locale_json (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
Notes
- •Die Stufen 1 bis 4 der LINE-Versandinfrastruktur sind abgeschlossen (2.6.9 bis 2.6.15):
1. Step 1 — CTA · Utility Stack · manueller Versand · audience nach Stufe · Mehrfachauswahl (7872c4b, 7c94a55, c4a3325)
2. Step 2 — Automatische Einordnung von Mitgliedergruppen (b24979c)
3. Step 3 — Ereignisbasierte automatische Versandregeln (60d47cd) + cron für geplanten Versand (8cf02ad)
4. Step 4 — Klickverfolgung (79c99a84) + A/B-Test (86e19b0b) + mehrsprachiges Routing (dieser)
- •Die Migration 010 wurde in der Produktion (
voscms.com) angewendet. users.locale ist eine neue Spalte — alle bestehenden Mitglieder sind NULL (es wird die Standard-Locale der Website verwendet → dasselbe Verhalten wie bisher).
- •Eine Oberfläche in „Meine Seite“, in der Mitglieder ihre bevorzugte Locale selbst einstellen können, ist der nächste Meilenstein.
- •Empfohlene cron-Einträge:
/5 /usr/bin/php8.3 /var/www/voscms-com/scripts/process-scheduled-broadcasts.php, 0 3 /usr/bin/php8.3 /var/www/voscms-com/scripts/recalculate-member-grades.php.
v2.6.14
2026-05-30 · vor 5 Monaten
A/B-Test (Step 4-B)
Added
- •Migration 009 —
rzx_auto_broadcast_rules.message_template_b TEXT NULL, rzx_line_broadcasts.variant CHAR(1) NULL, rzx_broadcast_clicks.variant CHAR(1) NULL + ein Index (source_rule_id, variant).
- •AutoBroadcaster::fire — ist
message_template_b nicht leer, werden die LINE-userIds per crc32 mod 2 im Verhältnis 50:50 in A/B aufgeteilt. Pro Variant wird der Versandverlauf vorab eingefügt (INSERT, logQueued) → Token-Wrap → multicast → finalize. Derselbe Benutzer erhält bei wiederholtem Versand immer dieselbe Variant (Hash-Konsistenz).
- •Regel-Modal im Admin — die Option „A/B-Test aktiviert“ und die Eingabe für Variant B, aufklappbar über
<details>. Standard ist der einfache Einzelversand, A/B ist ein ausdrückliches Opt-in.
- •ClickTracker — reicht die Variant-Metadaten weiter. Existiert die Spalte broadcast_clicks.variant, wird sie beim INSERT befüllt. Andernfalls greift ein Fallback (kompatibel mit Umgebungen, in denen Migration 009 nicht angewendet wurde).
- •logQueued-Fallback — funktioniert auch in Umgebungen ohne die Spalte variant (wenn Migration 009 nicht angewendet wurde).
- •i18n in 13 Sprachen —
community.automation.ab_{toggle,placeholder,hint} (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
Notes
- •Die 3 ALTER-Anweisungen der Migration 009 wurden in der Produktion (
voscms.com) getrennt ausgeführt. Bestehende Regeln haben message_template_b=NULL (das Verhalten des Einzelversands bleibt erhalten).
- •Regel bearbeiten → unter „A/B-Test aktiviert“ Variant B eingeben → nur speichern, dann erfolgt ab dem nächsten Auftreten automatisch die A/B-Verteilung.
Added
- •Migration 008 (
rzx_broadcast_clicks) — token (8 Zeichen base62, UNIQUE), broadcast_id, source_rule_id, original_url (2048), click_count, last_clicked_at, last_user_agent. Bei gleicher Kombination (broadcast_id, original_url) wird der Token wiederverwendet.
- •Klasse
ClickTracker — wrap($pdo, $siteId, $body, $meta) extrahiert http/https-URLs aus dem Text per regulärem Ausdruck → INSERT oder Wiederverwendung → ersetzt sie durch /t/{token}. consume($pdo, $token, $ua) wandelt einen Token in die ursprüngliche URL um und erhöht click_count.
- •Route
/t/{token} (index.php:330) — Einstieg in den Router mit regulären Ausdrücken. ClickTracker::consume → 302-Weiterleitung auf die ursprüngliche URL, sonst 404. Prüfung des URL-Tokens ([A-Za-z0-9]{4,16}).
- •Integration in automatische Versandregeln —
AutoBroadcaster::fire() arbeitet unmittelbar vor dem Versand in der Reihenfolge logQueued → broadcast_id sichern → ClickTracker::wrap → multicast → finalizeBroadcast. Die Verknüpfung von Token und broadcast_id ist gewährleistet.
- •Integration in den manuellen Versand — in
api/broadcast.php wird direkt nach dem Zusammensetzen des Textes für den Sofortversand gewrappt. In scripts/process-scheduled-broadcasts.php wird unmittelbar vor dem Versand aus der Warteschlange gewrappt (die broadcast_id ist bekannt).
- •Einstellung der Tracking-Domain —
rzx_settings.click_track_domain hat Vorrang, sonst APP_URL. Eine Kurzdomain (z. B. s.voscms.com) ist möglich.
Notes
- •Die Migration 008 wurde in der Produktion (
voscms.com) angewendet.
- •Integrationstest von wrap/consume: 2 URLs im Text → 2 Tokens zu 8 Zeichen EINGEFÜGT → beim Aufruf von consume wird die ursprüngliche URL zurückgegeben und click_count steigt korrekt.
Added
- •Migration 007 (
rzx_line_broadcasts): die Spalten scheduled_at DATETIME NULL und processed_at DATETIME NULL sowie ein Index (status, scheduled_at). scheduled_at NULL = sofort senden (wie bisher), ein zukünftiger Zeitpunkt = Warteschlange.
- •
scripts/process-scheduled-broadcasts.php — der cron-Einstiegspunkt. Er holt 50 Einträge mit status='queued' AND scheduled_at <= NOW() AND processed_at IS NULL ab → sperrt sie sofort mit processed_at = NOW() (Transaktion) → löst audience auf (all / grade_N, wie bei broadcast.php) → LineMessenger multicast in Einheiten zu 500 → aktualisiert status mit dem Ergebnis. Empfohlenes cron-Intervall: /5 *.
- •Oberfläche von broadcast.php: ein Kontrollkästchen
[Versand planen] + eine datetime-local-Eingabe. Bei Aktivierung ist der Vorgabewert die aktuelle Zeit + 1 Stunde (lokale Zeit des Benutzers). Ist es nicht aktiviert oder leer, wird wie bisher sofort gesendet. Nur der LINE-Kanal kann geplant werden (In-App und Push bleiben sofort).
- •api/broadcast.php: verarbeitet den POST-Parameter
scheduled_at. Bei einem zukünftigen Zeitpunkt (> NOW + 30s) mit send_line wird ohne Aufruf der LINE-API nur rzx_line_broadcasts (status='queued', scheduled_at) eingefügt (INSERT) und in der Antwort scheduled: true, scheduled_at zurückgegeben.
- •i18n in 13 Sprachen:
community.broadcast.schedule_{label,enable,hint,success} (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW).
Fixed
- •Die INSERT-Spalten wurden an das tatsächliche Schema von
rzx_line_broadcasts angepasst (title, body, audience varchar(20), recipient_count, status enum(queued|sent|failed)). Zuvor versuchte das INSERT Spaltennamen, die es nicht gibt (message_text, recipients_count, sent_count, failed_count, audience_value, partial), und selbst der Fallback schlug fehl, sodass der Verlauf des automatischen Versands fehlte.
Notes
- •Die Migration 007 wurde in der Produktion (
voscms.com) angewendet. Ein dry-run bestätigte, dass pickup 0 Einträge ergab.
- •Die Verzeichnisbäume von Produktion (
voscms-com) und salon sind synchronisiert. .env ausgenommen.
- •Das Einrichten des cron liegt bei der Hosting-Betriebsseite (falls nötig
/5 * /usr/bin/php8.3 /var/www/voscms-com/scripts/process-scheduled-broadcasts.php).
Added
- •Tabelle für automatische Versandregeln (
rzx_auto_broadcast_rules) — Migration 005_auto_broadcast_rules.sql. Regeln pro site_id getrennt, mit den Spalten trigger_type / trigger_filter (JSON) / audience (all|grade_X|custom) / message_template / is_enabled / fired_count / last_fired_at.
- •AutoBroadcaster-Dispatcher (
rzxlib/Core/Notification/AutoBroadcaster.php) — statischer Einstiegspunkt AutoBroadcaster::fire($triggerType, $ctx). Aktive Regeln abgleichen → Vorlagenvariablen ersetzen ({{title}}, {{url}}, {{author}}, {{board_name}}, {{site_name}}) → audience auflösen (gleiche Logik wie broadcast.php; bei der is_default-Stufe werden NULL-Mitglieder automatisch einbezogen) → LINE-userIds über rzx_user_social_accounts nachschlagen → multicast in Einheiten zu 500 → Verlauf in rzx_line_broadcasts aufzeichnen → Regelstatistik aktualisieren.
- •Hook für den automatischen Versand bei neuen Forumsbeiträgen (api-posts.php:184) — unmittelbar nach dem INSERT eines Beitrags (ohne private Beiträge) wird
AutoBroadcaster::fire('board_post', [post_id, board_id, title, url, author, board_name]) aufgerufen. Auch wenn der Versand fehlschlägt, bleibt die Antwort auf den Beitrag unberührt.
- •Admin-Seite zur Regelverwaltung (
/theadmin/community/automation) — Oberfläche als Kartenraster. Regel-CRUD + Ein/Aus-Schalter + Farbabzeichen je Auslöser (board_post=blue, review_created=amber, reservation_created=green). Auslöser / Filter (JSON) / Zielstufe / Nachrichtenvorlage werden im Modal bearbeitet.
- •Spalten zur Herkunftsverfolgung bei rzx_line_broadcasts — Migration
006_line_broadcasts_add_source.sql. source ('manual' | 'auto_rule') + source_rule_id (INT) + Index. Der Verlauf des automatischen Versands lässt sich in derselben Tabelle vom manuellen Versand unterscheiden.
- •Routen und Migrationen in plugin.json eingetragen — die Route
community/automation sowie die Migrationen 004/005/006 nach 003.
- •i18n in 13 Sprachen — alle Schlüssel
community.automation.* (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW). Auslöser-Beschriftungen, Felder, Hinweise, Erfolgs-/Fehlermeldungen und Standardvorlagen.
Notes
- •Die Migrationen 005/006 wurden in der Produktion (
voscms.com) angewendet. Es sind noch keine Regeln angelegt.
- •Die Verzeichnisbäume von Produktion (
voscms-com) und salon sind synchronisiert. .env ausgenommen.
- •Step 3-B (zeitgesteuerter Versand
scheduled_at + cron) ist der nächste Meilenstein.
Added
- •Automatische Zuweisung der Standardstufe bei der Anmeldung (
rzxlib/Core/Auth/Auth.php::register()) — unmittelbar nach der Registrierung wird in rzx_member_grades die Stufe mit is_default=1 abgefragt und die grade_id des neuen Mitglieds sofort gefüllt. Auf Websites ohne Tabelle member_grades (Altbestand oder nicht eingerichtet) wird per try-catch still übersprungen. Bestehende NULL-Mitglieder werden über ein separates Neuberechnungsskript bzw. die Schaltfläche befüllt.
- •CLI-Skript zur Neuberechnung der Stufen (
scripts/recalculate-member-grades.php) — auf Grundlage der Summe der Zahlungen in rzx_payments und der Zahl der Reservierungen in rzx_reservations (nur wenn die Tabelle existiert) durchläuft es die Stufen in der Reihenfolge sort_order DESC und ordnet die höchste erfüllbare Stufe zu. Stufen ohne gesetzte Regeln (min_spent=0 AND min_reservations=0) werden automatisch übersprungen — nur Stufen mit ausdrücklichen Regeln kommen für eine Beförderung in Frage. Mitglieder, die die Bedingungen nicht erfüllen, fallen auf die Standardstufe zurück.
- •Optionen:
--dry-run (Simulation ohne tatsächliches UPDATE), --user-id=UUID (nur ein bestimmtes Mitglied).
- •cron-Beispiel:
0 3 * /usr/bin/php8.3 /var/www/voscms/scripts/recalculate-member-grades.php
- •Admin-Schaltfläche „Jetzt neu berechnen“ (
/theadmin/members/groups) — in der Aktionsleiste wurde eine Schaltfläche im Smaragdton ergänzt. Beim Klick: Bestätigungsmodal → AJAX action=recalculate_grades → Ergebnisanzeige (Ziel/Aufstieg/Abstieg/neu) → automatisches Neuladen. Da dieselbe Logik wie im Skript inline enthalten ist, funktioniert es auch in Umgebungen ohne PHP-CLI-Berechtigung.
- •i18n in 13 Sprachen — neue Schlüssel
members.groups.recalculate* (ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW): recalculate, recalculate_hint, confirm_recalculate, recalculate_stat.{total,upgraded,downgraded,fallback}, success.recalculated, error.{no_grades,no_default_grade}.
Notes
- •In der Produktion (
voscms.com) wurden --dry-run → tatsächliche Ausführung → erneute Ausführung nach Ergänzung der Regeln geprüft. Alle 5 Mitglieder mit grade_id NULL wurden korrekt Normal (Standard) zugewiesen. VIP/Gold/Silber haben keine Regeln und bleiben bei 0 Mitgliedern, bis Regeln hinzugefügt werden (beabsichtigt).
- •Die Verzeichnisbäume von Produktion (
voscms-com) und salon sind synchronisiert. .env ausgenommen.
Added
- •LINE-Freunde-hinzufügen-CTA-Komponente für Mitglieder (
resources/views/components/line-friend-cta.php) — 5 Variants (card / button / bar / side-tab / bubble) × 6 Positionen (bottom-right/bottom-left/bottom-center/top-right/middle-right/middle-left) × 3 Größen, benutzerdefinierte Farben, Anzeigeverzögerung und 24 Stunden „Schließen merken“ (localStorage).
- •Änderbare Einstellungsoberfläche — neuer Abschnitt „LINE-Freunde-hinzufügen-CTA“ unten auf der LINE-Kanalkarte unter
/theadmin/settings/message-api. Basic ID, Aktivierungsschalter, Variant-Radio, Position-Auswahl, Größe, Farbwähler und Delay-Eingabe.
- •Automatische Anzeige in 5 Layouts — wird automatisch aus
skins/layouts/{default,modern,minimal,modern-copy-260413}/footer.php eingebunden. Auf Seiten für Zahlung, Dienstantrag und Installation wird er automatisch übersprungen.
Added
- •Neue Komponente
resources/views/components/utility-floating-stack.php — das Designmuster cameron_plugin von thevos.jp (ein quadratischer 80×80-Stack am rechten Rand + 1 px Abstand + Akzentfarbe pro Symbol). Position, Größe und Farbe kann der Betreiber anpassen.
- •Beide Modi nebeneinander —
utility_stack_mode = separate (Standard, jeder CTA einzeln) / unified (PWA + LINE gemeinsam als Stack). Im integrierten Modus ist die automatische Anzeige der 5 LINE-CTA-Variants deaktiviert, ebenso die automatischen Auslöser des PWA-Installationsmodals (Banner per setTimeout/DOMContentLoaded); das Modal öffnet sich nur durch Klick auf das PWA-Symbol im Stack.
- •Natürliche künftige Erweiterung — mit einem Muster zur Registrierung von Einträgen (Kakao-Kanal, WhatsApp, Newsletter-Abo, Dunkelmodus-Schalter usw.) lassen sich weitere Dinge allein durch Hinzufügen von Einstellungsschlüsseln in den Stack aufnehmen.
- •Garantierter automatischer Zeilenumbruch — Inline-CSS
word-break: break-all; overflow-wrap: anywhere; max-width: 72px umgeht die Breitenbegrenzung von Tailwind-Flex-Kindern. Auch CJK-Beschriftungen brechen im Kasten natürlich um.
- •i18n in 13 Sprachen — die Gruppe
line_cta. (22 Schlüssel) und die Gruppe utility_stack. (12 Schlüssel) in resources/lang/{13 locale}/messaging.php. Bei Japanisch und Chinesisch sorgen Leerzeichen an Sinngrenzen (etwa „アプリとして インストール“) für natürliche Umbruchstellen.
Added
- •
LineMessenger::broadcast(messages) + broadcastText(text) — sendet gesammelt an alle Freunde (bis zu 5 Nachrichtenobjekte; das Sendekontingent von LINE wird um Empfängerzahl × Nachrichtenzahl verringert).
- •
LineMessenger::multicast(userIds[], messages) — sendet an bis zu 500 angegebene userIds (Infrastruktur für gruppenweisen Versand).
- •Erweiterung der Oberfläche
/theadmin/community/broadcast — Kontrollkästchen „Auch an LINE-Freunde senden“ (grünes Banner) hinzugefügt. Unabhängig vom Push-Versand wird automatisch per multicast/broadcast an LINE-Freunde gesendet.
- •Versand nach Mitgliedsstufe —
rzx_member_grades wird dynamisch geladen, und Radio-Optionen pro Stufe erscheinen automatisch (Farbpunkt + Slug + Live-Zähler). Das Format von audience ist grade_<id>.
- •Mitglieder mit
grade_id IS NULL werden automatisch in die Stufe mit is_default=1 einbezogen — auch auf Websites, auf denen bei der Anmeldung keine Stufe automatisch vergeben wird, sind NULL-Mitglieder selbstverständlich in Zähler und Versand der Standardstufe enthalten.
- •Verlaufstabelle
rzx_line_broadcasts für den Versand — site_id-Trennung, method (broadcast/multicast), audience, title/body, recipient_count, line_request_id, api_status/error, status. Beim Senden wird automatisch eingefügt (INSERT).
- •Bei
audience=all broadcast, sonst multicast, automatisch gewählt — sammelt die LINE-userIds der Zielbenutzer mit user_social_accounts.line_friend=1 und sendet in Blöcken zu je 500.
- •Einheitliche Breite — in broadcast.php
max-w-3xl → max-w-7xl (passend zu anderen Admin-Seiten).
- •i18n in 13 Sprachen — die Schlüssel
send_line_label/desc und audience_grade_group wurden hinzugefügt.
Changed
- •
resources/views/admin/dashboard.php — der Kopfkommentar, der pageTitle-Fallback und das Update-Hinweisbanner RezlyX v... wurden alle auf „VosCMS“ korrigiert.
- •
resources/views/admin/partials/admin-topbar.php — Kopfkommentar korrigiert.
Fixed
- •
storage/.update_cache hielt einen alten Cache mit current: "2.6.4", sodass das Dashboard auch nach dem Update auf v2.6.8 noch das Banner „Neues Update verfügbar“ zeigte — nach dem Löschen des Caches wird er bei der nächsten Anfrage automatisch neu berechnet.
- •Angesammelte Änderungen von dev → Produktion waren nicht synchronisiert — außer in dieser Sitzung waren auch viele Dateien wie install-core.php (Patches für die Fehler #1 bis #7) und version.json nie mit der Produktion abgeglichen worden. Per rsync wurde dev in einem Zug mit der Produktion synchronisiert (342 Dateien geändert + 196 neu, 6,3 MB, ohne Benutzerdaten,
.env, storage/, uploads/, vendor/ und .git/).
Documentation
- •
docs/LINE_FRIEND_CTA_DESIGN_GUIDE.md — Part 3 (tatsächliche Umsetzung des integrierten Utility Floating Stack), Part 4 (tatsächliche Umsetzung des Versandbetriebs in Phase 1), Part 5 (Szenarien externer Nutzer — Wertanalyse des Versands mit Mehrfachauswahl) und Part 6 (Roadmap für Phase 2 bis 4) hinzugefügt. Von etwa 631 auf 920 Zeilen.
Regression Test
- •Prüft das Vorhandensein von
utility-floating-stack.php und der 5 Variant-Partial-Dateien von line-friend-cta.
- •Prüft das Vorhandensein der Methoden
LineMessenger::broadcast/multicast.
- •Prüft das Vorhandensein der Migrationsdatei
plugins/vos-community/migrations/004_line_broadcasts.sql.
- •Prüft das Vorhandensein der Schlüssel
messaging.utility_stack. + community.broadcast.send_line_ in 13 Sprachen.
- •Prüft automatisch, dass in dashboard.php / admin-topbar.php keine RezlyX-Reste übrig sind.
Fixed
- •vos-market Lizenztabellen-Konsolidierung — 6 API-Dateien fragten die falsche
{$pfx}vos_licenses Tabelle ab, was bei jeder Zahlung zu "Server error" 500 führte. Alle Lizenzprüfungen werden nun auf den einzigen Master vcs_licenses (verwaltet von vos-license-server) umgeleitet.
- •
sync.php unverifiziertes Master-Registrierungs-Sicherheitsloch entfernt — Bisheriger Code UPSERT-te in vos_licenses ohne vos_key-Validierung, was jedem erlaubte, beliebige Lizenzschlüssel per einfachem POST automatisch im Master zu registrieren. Tracking erfolgt nun durch die bestehende rzx_mkt_sync_reports (per-item).
- •
migrations/007 veraltet — Die fehlerhaft entworfene Migration ist nun ein no-op (SELECT 1), Grund und Änderungsverlauf in Kommentaren.
Added
- •4 Statistik-Karten — Verfolgte Sites / Sites mit Auffälligkeiten / Multi-Domain-Lizenzen / Inaktiv 30+ Tage. Karten-Klick = Wechsel zum entsprechenden Tab.
- •Verstöße-Tab (Anzeige auf Artikel-Ebene) — Auf einen Blick erkennen, welches kostenpflichtige Widget ohne Lizenz auf welcher Domain installiert ist. Preis, Version, vos_key und letzte Sichtung werden angezeigt.
- •Multi-Domain-Tab — Fälle, in denen ein einzelner Lizenzschlüssel von mehreren Domains gemeldet wird.
- •Inaktiv-Tab — Sites ohne Sync-Signal seit 30+ Tagen.
- •Verfeinerte Verstoßdefinition —
unknown_product und kostenlose Artikel sind ausgeschlossen. Nur kostenpflichtige Marketplace-Artikel im unlizenzierten Zustand zählen als Verstöße.
- •Eigene-Domains-Whitelist — In
settings.mkt_owner_domains gespeicherte Betreiber-Domains werden automatisch aus den Zählungen ausgeschlossen.
- •13-sprachige i18n — Seitenleiste, Karten, Tabs und Hilfetexte sind alle ordnungsgemäß übersetzt.
Changed
- •
settings/system/updates — "RezlyX vX.Y.Z" → "VosCMS vX.Y.Z".
- •
updates/ajax.php — DB-Name-Fallback und User-Agent korrigiert.
Regression Test
- •Automatische Überprüfung auf keinen
vos_licenses SQL-Rest in vos-market 6 Dateien
- •Erkennung der Regression des INSERT-Sicherheitslochs in
sync.php
- •Überprüfung des no-op-Zustands von
migrations/007
- •Automatische Überprüfung auf keinen RezlyX-Rest in 3 Updates-Screen-Dateien
Behoben
- •
site_url automatisch anlegen — Der Installationsassistent schrieb die vom Benutzer eingegebene siteUrl nur in APP_URL der .env, nicht aber in rzx_settings.site_url der Datenbank. Dadurch funktionierten auf neu installierten Websites alle von site_url abhängigen Funktionen (automatische Installation, SEO, Links in E-Mails usw.) nicht. site_url wurde dem Array $settings in install-core.php hinzugefügt.
- •
rzx_site_domains automatisch eintragen — Der Installationsassistent fügte die aktuelle Installationsdomain nicht automatisch in die Tabelle site_domains ein, sodass SiteRouter die Domain nicht erkannte. Die installierte Domain wird jetzt automatisch als primäre Domain mit site_id=1 eingetragen (INSERT).
- •
.env: MARKET_API_URL automatisch schreiben — Bei Neuinstallationen fehlte in der .env die Adresse der Marktplatz-API, sodass InstallerService keinen Aufrufpunkt fand. Der Standardwert https://market.voscms.com/api/market wird jetzt automatisch eingetragen (Lizenzbetrieb über einen einzigen Master).
- •Tippfehler im Tabellennamen der Marktplatz-Install-API —
vos-market/views/api/item/install.php fragte bei der Lizenzprüfung die nicht existierende Tabelle rzx_vos_licenses ab → jede automatische Installation antwortete mit „Server error“ 500. Korrigiert auf die tatsächliche Tabelle vcs_licenses (Lizenz-Master, fest ohne Präfix).
- •Automatische Rechte für die Verzeichnisse widgets/plugins/themes — Nach der Installation konnte der PHP-FPM-Benutzer nicht in diese Verzeichnisse schreiben, sodass automatische Installationen stillschweigend fehlschlugen. Der Installationsassistent setzt jetzt automatisch setgid und Gruppenschreibrechte (die PHP-Ausführungsgruppe wird automatisch erkannt, um unterschiedliche Umgebungen abzudecken).
- •Mehrstufiger Fallback in
install-handler.php — In Multisite-Umgebungen wurde site_url ohne site_id-Filter mit LIMIT 1 abgefragt und war dadurch unzuverlässig. Mit einem dreistufigen Fallback SiteRouter → site_id=1 → $_SERVER['HTTP_HOST'] wird die Domain in jeder Umgebung erkannt.
Hinzugefügt
- •
InstallerService::installTheme() — Liest die theme.json eines Produkts vom Typ type=theme und installiert die unter requires aufgeführten Plugins/Widgets/Skins rekursiv. Prüfung auf 13 Sprachen und Idempotenz (bereits installierte Elemente werden übersprungen).
- •
runPostInstall — Führt direkt nach der Theme-Installation die Seeds post_install/settings.json / boards.json / pages.json automatisch aus — Seiten, Widget-Anordnung und Grundeinstellungen werden komplett automatisch eingerichtet.
- •13 Sprachen verpflichtend (
REQUIRED_LOCALES) — Mehrsprachige Objekte (name, description, Seiten-title, Widget-config.title usw.) bestehen die Prüfung nur, wenn alle 13 Schlüssel vorhanden sind. Warnung bei fehlenden Sprachen.
- •Vereinheitlichung auf den
vcs_licenses-Master — Alle Lizenzausstellungen und -prüfungen werden über den Produktivmarktplatz (market.voscms.com) verwaltet. Auch dev-/test-Umgebungen nutzen denselben Master.
Hinzugefügt
- •Automatische Prüfung dieser 6 Fehler — 13 Prüfpunkte, darunter die Seed-Logik des Installationsassistenten, Verzeichnisrechte, Marktplatz-API, Erreichbarkeit des Lizenzservers, der Theme-Zweig von InstallerService und der mehrstufige Fallback von install-handler.
- •Automatischer Aufruf in build-voscms.sh — Wird am Ende des Builds automatisch aufgerufen. Schon bei einem einzigen FAIL endet der Build mit einem Exit-Code ungleich 0 und die Veröffentlichung wird blockiert. Tritt derselbe Fehler im nächsten Build erneut auf, wird er sofort erkannt.
Dokumentation
- •
docs/theme-package/THEME_PACKAGE_SPEC.md — Definiert den VosCMS-Standard für Theme-Pakete (theme.json). Enthält ein Beispiel für ein integriertes Salon-Theme, das ausführliche post_install-Schema und die 13-Sprachen-Regel.
Fixed
- •Update-Backups: nur eines pro Version behalten —
Backup::createFull() entfernt jetzt vor dem Anlegen eines Backups das bestehende Backup derselben Version. Damit ist das Problem behoben, dass sich bei wiederholten Updates oder Rollbacks auf derselben Version doppelte Einträge dieser Version in der Backup-Liste ansammelten (behalten wird nur der letzte Stand unmittelbar vor dem Update).
Fixed
- •Fehlende
update-api.php im Release-Paket wiederhergestellt — Das Build-Skript stufte update-api.php, das Update-Backend, fälschlich als „dev-Datei“ ein und entfernte sie aus dem Release. Dadurch war der Update-Reiter jeder installierten Release-Version unbenutzbar und zeigte „File not found“. Sie ist nicht mehr vom Build ausgeschlossen und wird jetzt korrekt in das Release aufgenommen.
- •Nicht erkannte Anmelde-Sitzung (Unauthorized) behoben —
update-api.php sah im Standardpfad für Sitzungen (/var/lib/php/sessions) nach; jetzt wird dasselbe storage/sessions wie bei index.php verwendet. Damit ist der Fehler Unauthorized behoben, der auch bei angemeldetem Administrator auftrat.
Changed
- •Core-Updates nutzen nur das eigene Release-Manifest als einzigen Kanal — Reste von GitHub-Tags, Token und Diagnose wurden aus
update-api.php entfernt (der Weg, auf dem check das Manifest-Ergebnis durch einen GitHub-Tag überschrieb, ist gesperrt). Im Marktplatz gibt es kein Core (nur Plugins).
- •Mehr Sicherheit —
update-api.php prüft jetzt CSRF und die Master-Berechtigung (Eigentümer).
- •Aufräumen der Update-Schutzliste —
skins und config wurden aus der Schutzliste genommen. Da applyUpdate nur kopiert, werden die Kern-Skins und die config aus dem Release-ZIP aktualisiert, während eigene Kundendateien, die nicht im ZIP enthalten sind, erhalten bleiben.
Changed
- •Die doppelte Schaltfläche „Nach Updates suchen“ wurde entfernt — beim Öffnen der Seite wird automatisch die neueste Version geprüft.
- •Das Verschwinden der Backup-Liste bei einem vorübergehenden Fehler wurde behoben → der Abschnitt bleibt erhalten und wird leer angezeigt.
- •Bei Fehlern erscheint statt Rohmeldungen wie
Unauthorized der Hinweis „Sie verwenden derzeit die neueste Version“.
Added
- •13-sprachiger
um-Abschnitt hinzugefügt — alle Sprachen von vos-community/lang/{locale}.php (ko·en·ja·de·es·fr·id·mn·ru·tr·vi·zh_CN·zh_TW): follow·following·message·block·unblock·report·report_about·report_reason/detail/placeholder·reason_spam/harassment/inappropriate/other·report_submit/sent/failed·msg_title/placeholder/send/sent/failed·block/unblock_confirm·block/unblock_done·cancel·failed·network_error
- •Vollständige i18n von
user-mention-menu.php — alle fest codierten koreanischen Texte im PHP-HTML durch __('community.um.*') ersetzt; JS-Laufzeit-Strings werden über UM_LANG = <?= json_encode(...) ?> als PHP-Objekt ausgegeben, der Helfer umT(key, name) ersetzt den Platzhalter :name
- •Erwähnungsmenü für Gäste erlaubt — Guard-Struktur in
community-overlays.php überarbeitet: Admin-/API-Pfade vollständig gesperrt, während user-mention-menu auch für Gäste enthalten ist (Folgen/Melden leiten zur Anmeldung); Seitenaktions- und Username-Guards bleiben nur für angemeldete Nutzer
Changed
- •
boardPreloadUsers(array $rows) hinzugefügt (board/_init.php) — lädt die user_id-Liste in einer einzigen IN-Abfrage, geteilt über den Cache $GLOBALS['_boardUserCache']
- •
boardAuthorMention() erweitert — Attribute data-user-username·data-user-avatar hinzugefügt (verknüpft die Story-URL /story/{username} präzise, zeigt das Avatarbild). Bevorzugt einen Preload-Cache-HIT, greift bei Miss auf eine Lazy-Einzelabfrage zurück
- •
board/list.php·board/read.php·skins/board/qna/_list-full.php — rufen vor dem Rendern boardPreloadUsers() auf, um N+1-Abfragen zu vermeiden
Fixed
- •Anzeige-Parser erweitert (
resources/views/system/changelog/index.php) — Rendering für Code-Fences (``), Tabellen (|...|), Markdown-Links (text), ####-Unterüberschriften und horizontale Linien (---`) hinzugefügt. Behebt, dass frühere Versionen (2.4.1·2.3.8·2.3.7 usw.) mit dieser Syntax als rohes Markdown angezeigt wurden
- •Versionsweises Locale-Fallback — vom Abruf der gesamten Liste in einer Sprache auf eine versionsweise Basis (
aktuelles Locale → en → ko) umgestellt. Jede Version erscheint nun in jeder Sprache, und noch nicht übersetzte Versionen zeigen ein Fallback-Sprachabzeichen
- •Blockgrenzen-Abgleich (
rzxlib/Core/Changelog/ChangelogParser.php) — verhindert, dass ein datumsloser ## [Unreleased]-Header in die vorherige Version (z. B. 1.5.0) aufgenommen wird, indem Blöcke an jedem ## [ getrennt werden
Added
- •Migration 056 Tabelle
dist_downloads (site_id·version·ip·user_agent·referrer·utm_*·is_bot·created_at)
- •Download-Endpunkt
api/dist-download.php — statt eines statischen /download/*.zip-Direktlinks läuft die Anfrage darüber, erfasst Statistiken pro Version / Tag / Herkunft (referrer·UTM) und leitet dann per 302 weiter. Bot-UAs werden separat gezählt; Versions-Whitelist (schützt vor Path-Traversal)
- •Admin-Statistikseite
resources/views/admin/dist-downloads.php (nur Master, 13 Sprachen) — Übersichtskarten (gesamt/heute/7T/30T), Balken pro Version, Tagestrend (30T), Top-10-Quellen, UTM. Eigene SVG/CSS-Diagramme (keine externe Bibliothek)
- •Download-Link des
download-hero-Widgets auf den Zähl-Endpunkt umgestellt
- •Admin-Menü „Download-Statistik" hinzugefügt (config/admin-menu.php, nur Master)
Added
- •
hero-cta-text — oberer Textbereich (Typing). Standardwerte entsprechen dem Live-Inhalt von hero-cta2 (13 Sprachen); Benutzereinstellungen haben Vorrang
- •
hero-cta-button — Download-Button (erkennt automatisch die neueste Version + zählt Downloads, keine Konfiguration) plus optionaler Marketplace-Button (ein Button, wenn leer)
- •Beschriftungen und Standardwerte der Einstellungsfelder in 13 Sprachen (Builder-
getLabel-Objektunterstützung)
- •Farbe/Hintergrund des Download-Buttons an hero-cta2 angeglichen (#2563eb)
Added
- •Eine Palettenkarte auf die Leinwand ziehen, um ein Widget hinzuzufügen (SortableJS-
pull:'clone'-Gruppe + Austausch durch echten Block im onAdd der Leinwand). Funktioniert neben dem bestehenden Klick-Hinzufügen und der ↑↓/Griff-Sortierung
- •Das Flyout bleibt während des Ziehens offen + Hervorhebung der Drop-Zone (
wb-drop-active)
Changed
- •Seiten-Wrapper-Abstand zwischen Widgets entfernt (
type-widget.php py-2 → 0)
- •Synchrone KI-Übersetzung von Kommentaren stabilisiert — nginx
fastcgi_read_timeout 150s (Board-vhost) · PHP-FPM request_terminate_timeout 150 · set_time_limit 150, OllamaProvider keep_alive 30 Min. (Modell bleibt resident, beseitigt Kaltstarts)
- •Kopier-Buttons für Webhook-URL und Redirect-URI in den Tabs Message-API und Social-Login hinzugefügt (13 Sprachen, mit Fallback für nicht sichere Kontexte)
Added
- •Migration 036 Spalten
withholding_tax · consumption_tax · tax_basis zu partner_earnings / payouts hinzugefügt
- •Migration 037 Spalten
fx_rate · fx_amount · fx_currency zu payouts hinzugefügt (USD-Umrechnungsüberweisung)
- •Migration 038 Spalte
vcs_developers.paypal_email hinzugefügt
- •Hilfsklasse
rzxlib/Core/Helpers/MarketTax::calculate() — japanisches Standardabzugsmodell
· Verkaufspreis ist inkl. Verbrauchsteuer (税込), Marktplatz überweist Verbrauchsteuer direkt an NTA
· freelance → 10,21% Quellensteuerabzug / invoice_eligible → Vorsteuerverrechnung / no_invoice → keine Verbrauchsteuerüberweisung
· Nicht klassifiziert / nicht eingegeben → erzwungen freelance (konservativ: Unterzahlung erstattbar, Überzahlung nicht rückforderbar)
- •Backfill-Skript
scripts/market-tax-backfill.php — berechnet bestehende earnings/payouts neu (schützt status='paid', unterstützt --dry-run)
- •Abrechnung 5-fache Aufschlüsselung: Umsatz → Provision → Verbrauchsteuerabzug → Quellensteuer (freelance) → Nettobetrag
- •
rzx_mkt_settings neue Schlüssel: min_payout_amount · consumption_tax_rate · default_commission_rate (settings haben überall Vorrang, hartcodierte Fallbacks entfernt)
Added
- •
/theadmin/market/partners/payouts Abrechnungsmodal — prompt() × 2 + alert() → einzelnes Modal
· vcs_developers JOIN füllt Bank/Filiale/Kontoinhaber/Kontonummer/Unternehmenstyp/T-Nummer automatisch vor (PII enc: automatische Entschlüsselung)
· Automatische 5-fache Berechnung + japanische Steuerbasis-Chips (freelance_withholding usw.) + Artikelverweise (§204, Rechnungssystem)
· Seiteninterner Toast, Modal schließt und lädt automatisch neu
- •Automatische USD-Umrechnung für Konten außerhalb des Betriebslandes (Migration 037)
· Frankfurter API automatischer Wechselkurs (storage/cache 24h TTL) + manuelle Admin-Überschreibung (Bank-TTS)
· Wählt automatisch method=paypal
· Für Ausländer: Bankkontokarte ausgeblendet, PayPal-E-Mail-Karte angezeigt (basierend auf bank_country == site_country)
- •Entwickler-Abrechnungsbetragangabe (
/mypage/developer/earnings)
· Gesamtguthaben → Betragseingabe + Gesamtbetrag-Schaltfläche + Mindestbetragsvalidierung
· Umsatzverlauf 5-fache Spalten, Abrechnungsinfobox (angewandtes Steuerrecht je Unternehmenstyp)
- •USD-Umrechnung und Wechselkurs in der Auszahlungshistorie angezeigt (Admin- und Entwicklerbildschirm)
- •Umsatztrenddiagramm durch SVG-Balkendiagramm ersetzt (behebt Sichtbarkeitsprobleme bei div-Balken)
Added
- •
tax_review_status-basierte Sperrrichtlinie (Entwicklerprofil)
· not_submitted / rejected → bearbeitbar
· pending / approved → Bearbeitungssperre (Schloss + Hinweis)
· rejected → bearbeitbar + Hinweis „wird beim Speichern erneut in die Prüfwarteschlange eingereiht"
· Serverseitiger Schutz HTTP 423 Locked (blockiert UI-Umgehung)
- •
update.php Teilaktualisierung sicher — dynamisches UPDATE nur für übertragene Felder (zuvor: vollständige Überschreibung riskierte NULL-Setzen nicht übertragener Felder)
- •Offizielle Verifizierungsseiten-Links (Admin-Verifizierungsbildschirm + Entwicklerprofil)
· 🇯🇵 NTA Unternehmensregisternummer-Veröffentlichungssite (https://www.houjin-bangou.nta.go.jp/)
· 🇯🇵 NTA Qualifizierter Rechnungsaussteller-Veröffentlichungssite (https://www.invoice-kohyo.nta.go.jp/regno-search/)
· 🇰🇷 Korea Hometax Gewerbeanmeldungsstatus-Abfrage
· Ein-Klick-Kopierschaltfläche neben Steuernummer / T-Nummer
Added
- •Neuregistrierung (
/mypage/developer) — Staatsangehörigkeitsauswahl an den Formularkopf verschoben, Betriebslandvergleich-Hinweis
· country == site_country → 🏠 Inländisches Formular (Unternehmenstyp / Bankkonto)
· country != site_country → 🌐 Ausländerformular (automatisch freelance + PayPal-E-Mail erforderlich)
· Alpine.js isDomestic Getter, globale Konstante OPERATING_COUNTRY
- •Profilbearbeitung (
/mypage/developer/profile) — gleiche Struktur ([feedback_admin_user_parity]-Regel)
· Ausländer: Unternehmensabschnitt ausgeblendet, Abrechnungsinfo = nur PayPal-E-Mail
· Staatsangehörigkeit gesperrt (Admin kontaktieren für Änderung), Modusanzeige oben
- •Register-API serverseitige Durchsetzung —
paypal_email für Ausländer erforderlich, freelance erzwungen, Unternehmens-/Kontoeingaben ignoriert
Added
- •
page.php Token-Automatikersetzung — einheitlich auf alle Systemseiten angewendet
· {{COMPANY_NAME}} {{COMPANY_ADDRESS}} {{COMPANY_PHONE}} {{COMPANY_EMAIL}} {{COMPANY_REG_NUMBER}} {{COMPANY_REPRESENTATIVE}}
· {{SITE_NAME}} {{SITE_URL}} {{DOMAIN}}
· Automatisch aus Admin-business_- oder site_-Einstellungen zugeordnet
· Benutzerdefinierte page_title / page_subtitle durchlaufen ebenfalls die Token-Ersetzung
- •
{{DOMAIN}} Priorität — official_domain (offizieller Bereich für Nutzungsbedingungen/Richtlinien) → site_url-Host
· Auch auf dem Entwicklungsserver vos.21ces.com behält der AGB-Text voscms.com-Anzeige bei
Added
- •
rzx_page_contents terms / privacy (je 13 Zeilen) vollständig ersetzt — RezlyX-Buchungsbedingungen → VosCMS-Freeware-Nutzungsbedingungen
- •Nutzungsbedingungen 18 Artikel: Zweck · Definitionen · Veröffentlichung & Überarbeitung · Regeln außerhalb der AGB · Vertragsschluss · Datenschutz · Mitteilungen · Unternehmenspflichten · Nutzerpflichten · Leistungserbringung · Änderungen · Nutzungsbeschränkungen · Lizenz (kostenlose Lizenz) · Dateneigentum & -aufbewahrung · Beitragsurheber · Haftungsausschluss (AS-IS) · Haftung · Streitbeilegung
- •Datenschutzrichtlinie 10 Artikel: Verarbeitungszweck · Elemente · Aufbewahrungsdauer · Drittanbieter & Auftragsverarbeitung · Betroffenenrechte · Sicherheitsmaßnahmen · Cookies · Datenschutzbeauftragter · Rechte & Rechtsmittel (PPC) · Änderungen
- •Japanisches Recht + ausschließlicher Gerichtsstand Bezirksgericht Fukuoka, APPI §33·§34·§35 zitiert
- •Unternehmensdaten nutzen Tokens → einmalige Admin-Bearbeitung synchronisiert AGB und Datenschutz automatisch
- •Japanische Version als maßgeblicher Text festgelegt, offizielle Übersetzungen in alle 13 Sprachen
- •Unternehmensinfokarte — nur 3 Punkte: Firmenname · Adresse · Telefon (Geschäftsführername entfernt, vermeidet AGB-Revisionsaufwand bei Handelsregisterwechsel)
- •Sicherungsskripte:
scripts/voscms-terms-update.php · scripts/voscms-privacy-update.php
Fixed
- •
menus-api.php in /theadmin/site/menus war 99 Zeilen hinter vos, was bei Menü-Speichern/-Bearbeiten fehlende Validierung und Übersetzung verursachte
- •menus-api.php von vos → market synchronisiert:
· mn_link_target_exists() — Shortcut-Menüs (Links) werden nur nach Prüfung der Zielseite (Systemseite · rzx_page_contents) gespeichert
· Menü-ID-Wiederverwendungsschutz — veraltete rzx_translations.menu_item.{id}.* für neue Menü-IDs werden automatisch bereinigt
· Übersetzungs-INSERT-Methode INSERT IGNORE → INSERT … ON DUPLICATE KEY UPDATE (ermöglicht Überschreiben)
· Bei title/url-Änderung: alte Übersetzung auf Clean Slate gesetzt + automatische Neuregistrierung bei Systemseiten-Match (config/system-pages.php)
- •
admin/site/menus*.php 4 Dateien zu sync-to-market.sh INCLUDES hinzugefügt
Fixed
- •Fehlende Tabelle
rzx_contact_messages → Migration 041_create_contact_messages.sql hinzugefügt (IF NOT EXISTS, vos-Idempotenz als No-Op bestätigt)
- •Doppeltes Layout in
contact-messages.php behoben — _head.php gibt bereits sidebar+topbar aus, aber die View inkludierte sie erneut, was doppeltes <body> + doppeltes main verursachte. Bereinigt nach vos-Muster (Header=_head einmal, Footer=_foot einmal) (market Einzelpatch)
Added
- •Migration 040
040_create_developer_platform.sql — erstellt 7 Tabellen gesammelter: vcs_developers + vcs_developer_earnings/payouts/activity/notes + vcs_review_queue + rzx_mp_items (IF NOT EXISTS, finales Schema nach Anwendung der ALTER 030~038)
· vcs_developers auf vos.21ces.com existierte nur im Dump ohne separate CREATE TABLE-Migration — behebt Fehler bei 030-ALTER auf Folgeseiten
- •
mypage/profile-sidebar.php synchronisiert — alte rzx_mkt_partners-Abfrage → neue vcs_developers-Abfrage (Entwickleraktivität in Meine Seite integriert)
- •market
index.php Routen-Patch (manuell, vermeidet vollständige Synchronisierung):
· /developer/ → /mypage/developer/ 301-Weiterleitung (login/dashboard/my-items/submit/earnings/profile/logout zugeordnet)
· Routen für mypage/developer/{register|items|items/new|earnings|profile} + mypage/developer/items/{N} + mypage/developer/items/{N}/edit
- •Migration 040 + profile-sidebar.php zu
sync-to-market.sh INCLUDES hinzugefügt
- •market-DB automatisch gesichert (
storage/backups/market-YYYYMMDD-HHMMSS/market_vos.sql) dann Migration 040 angewendet
Added
- •market.21ces.com betreibt ein Marktplatz-(3-Parteien-)Modell — separate AGB von VosCMS-Freeware-Bedingungen
- •AGB 18 Artikel (Marktplatz-Betriebsregeln):
· Artikel 8 Kaufvertrag kommt zwischen Käufer und Entwickler zustande, Unternehmen als Zahlungs-/Liefervermittler
· Artikel 9 Digitale Waren Rückerstattung 4 Ausnahmen (vor Download · Beschreibungsabweichung 7 Tage · Malware bestätigt · Systemfehler) — erfüllt Offenlegungsanforderungen §15-2 Gesetz über den besonderen Handelsverkehr
· Artikel 10 Abrechnung — Provisionsanteil % nicht angegeben (verweist auf „aktueller Satz separat veröffentlicht", ermöglicht Satzanpassung ohne AGB-Revisionsverfahren)
· Artikel 10 Japanisches Einkommensteuergesetz §204 Quellensteuer 10,21% / T-Nummer-Inhaber Verbrauchsteuer vom Marktplatz direkt an NTA / Konten außerhalb des Betriebslandes via USD-PayPal-Überweisung
· Artikel 14 Individuelle Entwickler-AGB haben Vorrang — außer bei Marktplatz-Betriebsangelegenheiten (Zahlung/Abrechnung/Rückerstattungsverfahren) haben individuelle AGB Vorrang
· Artikel 17 Haftungsobergrenze: Gesamtprovisionen/-abrechnungen der vorangegangenen 6 Monate
· Artikel 18 Japanisches Recht + ausschließlicher Gerichtsstand Bezirksgericht Fukuoka
- •Datenschutzrichtlinie 12 Artikel (3-Parteien-Marktplatz-Perspektive):
· Verarbeitungselemente — 6 Kategorien: Allgemein / Käufer / Entwickler (allgemein) / Japan-Ansässige / Overseas-Ansässige / Versand
· Aufbewahrungsfristen — Mitglied 1 Jahr · Transaktion 7 Jahre · Abrechnung/Quellensteuer 7 Jahre · Identitätsverifizierung 5 Jahre · Logs 6 Monate · Anfragen 3 Jahre
· Auftragsverarbeitung — Stripe · KOMOJU · PayPal · Frankfurter · SendGrid · NTA angegeben
· Internationaler Transfer — USA (PayPal/Stripe/SendGrid) · EU (Wechselkurse) · andere Länder (regionale PG/Banken) angegeben
- •Skripte:
scripts/market-terms-update.php · scripts/market-privacy-update.php (UPSERT — INSERT wenn nach UPDATE kein Datensatz)
- •market-DB angewendet (rzx_page_contents terms/privacy je 13 Zeilen), page-i18n mehrsprachiger Titel/Untertitel ebenfalls angewendet
Added
- •Fehlende Skin-Einstellungszuordnung behoben (
page_title · page_subtitle) — Einstellungsbildschirmeingabe wurde nicht auf der Seite angezeigt
- •Fehlenden
_page-title-bg.php-Partial neu erstellt (behebt frühere nginx-Fehlerlog-Include-Warnungen)
- •Farboption zu
title_bg_type + Feld title_bg_color hinzugefügt — automatisch als Farb-Fallback angewendet wenn Bild/Video fehlt
- •Weißer Kartenbox-Fallback bei
content_bg=transparent entfernt (behebt optisch enges max-w-5xl-Inhalt innerhalb der Karte)
- •
--page-content-width CSS-Variable automatisch ausgegeben — externe Auto-Include-Komponenten wie „Über diese Seite"-Aktionsleiste (vos-community) richten sich an gleicher Breite wie Seiten-content_width aus
Fixed
- •Abrechnungsseite PDOException — Verweis auf nicht existente Spalte
p.currency in rzx_mkt_partners entfernt
- •Umsatztrenddiagramm unsichtbar — div-Balken %-Höhe wurde in manchen Umgebungen nahezu 0px gerendert → durch SVG viewBox-basiertes Diagramm ersetzt (mindestens 4px Sichtbarkeit gewährleistet)
Added
- •Entwickler-Meine-Seite Artikeldetailbildschirm (
/mypage/developer/items/{id}) — Statistiken, Versionsverlauf, Download-Trends
- •Entwickler-Artikel-Bearbeitungsbildschirm (
/mypage/developer/items/{id}/edit) — gleiche 3-Tab-Oberfläche wie items-new, Vorausfüllen bestehender Werte, neuer ZIP-Upload folgt separatem Ablauf
- •Neue API:
/api/developer/item-update — aktualisiert name(JSON), short/desc(JSON), tags(JSON), price, license, repo/demo URL, Abhängigkeiten, Mindestversion, icon, screenshots
- •Neue API:
/api/developer/request-payout — Auszahlungsanforderung
- •Neue API:
/api/developer/update-bank — eigenes Abrechnungskonto aktualisieren
- •Neue API:
/api/developer/issue-reply — Q&A-Antwort verfassen (eigener Antwortkanal des Entwicklers)
- •Admin-Entwicklerdetailbildschirm (
/theadmin/developers/show) — Unternehmens-/Konto-/Dokumentkarte + Dokumentprüfung (Genehmigung/Ablehnung)
- •E-Mail-Verifizierung für Registrierung und Anmeldung (
/verify-email) verbessert + company-Feld in Auth::register gespeichert
- •13-sprachige offizielle Übersetzungsschlüssel hinzugefügt (
show_edit_btn, items_edit_*, items_back_detail, api_updated usw.)
Added
- •Bewertungs-, Issue- und Q&A-Eingabeformulare direkt in Widgets eingebettet (kein separater Seitenaufruf nötig)
- •Nur Käufer können einreichen — Nicht-Käufer sehen das Formular, erhalten aber beim Einreichen eine Hinweismeldung
- •Q&A-Antworten unterstützen Threads (Antworten auf Antworten) — DB-Migration 035 (
parent_reply_id)
- •Neue APIs:
/plugins/vos-market/views/api/item/post-issue.php, post-reply.php, post-review.php
- •Core
rzxlib/Core/Helpers/Notifications.php — Benachrichtigungs-Hilfsfunktion (zugehörig zu DB-Migration 034)
Added
- •13-sprachige Unterstützung auf allen Bildschirmen:
/theadmin/market/licenses, sync, orders, settings, submissions, partners/payouts, items
- •Marktplatz-Settings-Bildschirm — "Partner"-Label auf "Entwickler" vereinheitlicht (nur Anzeigetext; Variablennamen für Kompatibilität erhalten)
- •Marktplatz-Artikelnameneingabe nutzt das gemeinsame mehrsprachige Eingabe-Modal —
name_json wird in 13 Sprachen gleichzeitig bearbeitet
- •
plugins/vos-market/lang/* — neuer pluginspezifischer Sprachpool
- •
resources/lang/*/marketplace.php — alle 13 Sprachen in der jeweiligen Landessprache übersetzt (konform mit der i18n-Vollübersetzungsregel)
Added
- •
033_developer_notes_activity.sql — entwicklerspezifische Notizen und Aktivitätsprotokoll
- •
034_notifications.sql — rzx_notifications-Tabelle (Benutzerbenachrichtigungen)
- •
035_issue_reply_thread.sql — Spalte rzx_mkt_issue_replies.parent_reply_id hinzugefügt (Thread-Antworten)
Fixed
- •
/Market?item={slug} Slug fehlt — in items-show durch dedizierte Einzelspaltenabfrage korrigiert
- •
icon_url-Spaltenname in der Artikel-Update-API auf den tatsächlichen Spaltennamen icon korrigiert
- •Marktplatz-Settings-Seite leer — fehlende Migration 005 für
rzx_mkt_settings angewendet
Added
- •VARCHAR(12)
users.username + UsernameValidator (mindestens 6 Zeichen, Sonderzeichenbeschränkungen)
- •Gate-Modal beim ersten Besuch nach dem Login (AJAX
/api/username-set)
- •Vollständige Übersetzungen für 13 Sprachen (englischer Fallback entfernt)
Added
- •
/profile/{uuid} → /story/{username} 301-Weiterleitung
- •Kontextmenü-Label von „Profil anzeigen" → „Story anzeigen" geändert
Added
- •vos-story-Plugin aus dem Core ausgegliedert — dediziert für
/story/{username}
- •Facebook-ähnlicher Header + 5 feste Tabs (Alle / Info / Fotos / Follower / Gefolgte)
- •Beitrags-CRUD + SNS-Feed (
vos_story_posts, body_format = text/html)
- •TEXT/EDIT-Umschalter + Summernote-Integration
- •Bildanhänge (mehrere) + Fotos-Tab-Raster
- •Like- + Kommentarsystem
- •Story-Skin-System (
skins/story/default) + nutzerspezifisches Token (/mypage/story)
- •Admin-Richtlinienseite (
/admin/vos-story/policy)
- •Seiten-Aktionsleiste: i18n + Position (Ende des Hauptinhalts) + Inhaltsbreiten-Token
- •2:1-Raster (nur Inhaltsbereich) — rechte Seite: Anzeigen + Freunde (Follower-/Gefolgte-Tabs)
- •Header-Aktionsschaltflächen — nur Symbol ([Meine Story-Einstellungen] / [Profil bearbeiten] / [Folgen])
Added
- •D-1: 4-Menü-Seitenleiste (Dashboard / Story / Konto / Nachrichten)
- •D-2-A: Neues Dashboard — 8 Statuskarten + 8-Tab-Navigation + Konto-Info-Tab
- •D-2-B: Lesezeichen / Posteingang / Freunde-Tabs (jeweils mit „Alle anzeigen"-Link)
- •D-2-C: Gespeichert / Meine Beiträge / Meine Kommentare-Tabs (Board + Story + Seite vereint)
- •D-2-D: Auto-Login (remember tokens) Verwaltung
Added
- •Gemeinsamer Helfer
rzx_mirror_external_images() — cURL + SSRF-Schutz + GD-Größenänderung
- •E-1: Lesezeichen-Snapshot-Erfassung + Aufnahme externer Bilder
- •E-2: Aufnahme beim Story-Erstellen (story_attachments source-Spalte)
- •E-3: Aufnahme beim Board-Beitragserstellen
- •E-4: Aufnahme beim Seiteninhalt-Erstellen
- •Bildmarkierung:
data-source-original, data-source-mirrored
Added
- •Letzter Menüpunkt [Einstellungen] in der Hosting-Management-Seitenleiste — führt zu den 4 Tabs der Serviceantragsseite (general/domain/hosting/addons)
- •Rückerstattungsrichtlinie → Systemeinstellungen → Allgemein → separierte Karte (von Steuereinstellungen isoliert)
- •
rzx_settings.refund_policy Einzelschlüsselspeicherung
- •
settings.refund.*-Schlüssel für 13 Sprachen
Added
- •Migration 009: Spalten
page_contents.created_by / updated_by
- •Automatisch aufgezeichnet auf allen Seitenbearbeitungsoberflächen (admin/customer/system)
Added
- •Beitragsanzahl — erkennt die separate
rzx_translations-Struktur für Board-Beiträge (board_post.{id}.title)
Added
- •Admin-Einstellungen für hosting-spezifisches Speicherkontingent / Warnschwelle / Richtlinie (block/notify/none)
- •Speichernutzungs-Donutdiagramm im Mein-Bereich
- •
scripts/db-quota-monitor.php Hintergrundmonitor
Added
- •VosCMS-Neuinstallationsschaltfläche — Admin-Hosting-Tab
- •Hosting-[Status]-Änderungsaktion + Protokoll
- •Bearbeitungsformular „Serververbindungsinformationen" entfernt (verhindert unnötige Offenlegung)
Fixed
- •Scrap
add_scrap-Netzwerkfehler — Dateikonflikt bei vos-story API require
- •Scrap-Karte — Outline + Lösch-/Bearbeitungssymbole (Papierkorb)
- •Diskrepanz zwischen Beitragsanzahl und Liste (fehlender Status-Filter)
- •nick_name-Abgleich entfernt (verhindert Fehlerkennung von Seed-Daten mit NULL-user_id)
- •Story-Menüposition im Mein-Bereich — top → main (automatische Plugin-Erkennung)
- •Story-Menüsymbol im Core-Format (vollständiges
<path>-Tag)
- •Fehlende key-Spalte im settings-SELECT des Addon-Tabs (zwei Abschnitte ausgeblendet)
- •hosting_status-Aktion 500 — Definitionsposition der Hilfsfunktion
- •Seiten-Aktionsleiste — Inhaltsbreiten-Token angewendet
- •Fehler, bei dem vorhandene Beiträge beim Veröffentlichen neuer Beiträge verschwinden (sofortige Feed-Aktualisierung)
Added
- •Hosting-Detail → Domain-Tab → Schaltfläche
+ Domain hinzufügen → Modal
- •Optionen: kostenlose Subdomain / Neuregistrierung / bestehende Domain verbinden
- •WHOIS-Suche (
/api/domain-check.php wiederverwendet) + TLD-spezifische Preisanzeige
- •Zahlung: gespeicherte Karte (PAY.JP-Kunde des Hostings wiederverwenden) oder neue Karte (PAY.JP Elements)
- •10% Mehrwertsteuer automatisch aufgeteilt (Zwischensumme / Steuer / Gesamt)
- •Bei Zahlungsabschluss Anhängen an Hosting-Sub
metadata.added_domains[] (keine separate Sub erstellt)
- •Automatische Rückerstattungs-Sicherheitsnetz — bei DB-Verarbeitungsfehler wird PAY.JP-Belastung automatisch zurückerstattet
Added
- •Startdatum~Ablaufdatum + Prüf-Schaltfläche (DNS A/CNAME → Abgleich mit unserer Zone oder Cloudflare-IP-Bereich)
- •Auto-Verlängerungs-Toggle + Verlängerungsanfrage-Schaltfläche (pro Domain)
- •Bei registrar_pending / manual_attach_pending: Prüf-Schaltfläche → „In Bearbeitung"-Badge
- •Lila „Hinzugefügte Domain"-Badge
Added
- •Hosting-Verwaltungs-Seitenleiste: 2. Eintrag neu hinzugefügt
- •Einheitliche Liste: type='domain' Sub + Hosting-Sub.added_domains[] alle in zeitlicher Reihenfolge angezeigt
- •Statistik-Karten (Gesamt/ausstehend/abgeschlossen) + Filter (Status/Option/Suche)
- •Aktionen: [Als registriert markieren] / [Stornierung bearbeiten] (bei Stornierung: PAY.JP-Rückerstattung + Rückerstattungs-Row INSERT)
- •Automatische Entschlüsselung des Benutzernamens
Added
- •Hosting-Verwaltungs-Seitenleiste: 3. Eintrag neu hinzugefügt
- •
rzx_payments-basiertes Transaktionsjournal — Statistikkarten für Umsatz/Rückerstattung/Nettoumsatz/Steuer
- •Automatische Berechnung des Netto-Betrags für die japanische Mehrwertsteuererklärung (Bruttobetrag → Netto = total × 100/110, Steuer = total × 10/110)
- •Trendtabelle der letzten 12 Monate + Transaktionsjournaltabelle + Filter/Paginierung
Added
- •Meine Seite Add-on-Tab: Abschnitt „Verfügbar zur Beantragung" (Geschäfts-E-Mail automatisch ausgeschlossen)
- •Aktionen nach Preis:
- •Kostenlos (Installationssupport): Admin-Benachrichtigung + order_logs
- •Angebot (Anpassung): „Angebot anfragen"
- •Festpreis recurring (1-Jahres-technischer-Support): Kartenzahlungsmodal (
_addon-pay-modal.php)
- •Bei Zahlungsabschluss Addon-Sub automatisch erstellt + Zahlungseintrag
- •Bereits aktive Sub-Label-Übereinstimmung: Antrags-Schaltfläche automatisch deaktiviert
- •install_info-Zeile rechts: Schaltflächen [Zur Admin-Oberfläche / Zur Website]
Added
- •DB-Schema:
uk_payment_order UNIQUE entfernt → uk_payment_key (charge_id) UNIQUE ersetzt
- •Mehrere Zahlungs-Rows pro Bestellung erlaubt (Hosting + Domain + Add-on kumuliert)
- •Bei Rückerstattung: bezahlte Row unverändert, separate Rückerstattungs-Row INSERT (status='refund', Buchungsintegrität)
- •Japanische 7-Jahres-Aufbewahrungspflicht + PAY.JP-Händler-Streitbeilegungsstandard erfüllt
Added
- •composer require minishlink/web-push
- •VAPID-basierter Push-Sendehelfer für Admin/Supervisor
- •Automatische Bereinigung abgelaufener Endpunkte + automatische Protokollierung in rzx_push_messages
- •Aufrufpunkte: pay_domain (Domain-Zahlung abgeschlossen), service-order (Domain-Registrierungsantrag), request_addon
Added
- •Automatisches Matching eigener Zone-Subdomains (Wildcard-CNAME erkannt)
- •Cloudflare IPv4 15 CIDR-Bereichs-Matching (bei Proxy-Antwort)
- •„already_refunded"-Antwort als Erfolg behandelt (wenn PAY.JP bereits zurückerstattet hat)
Added
- •Unterabfrage summiert
rzx_payments-Gesamtbeträge (paid − refunded)
- •Hosting-Grundzahlung + Domain-Hinzufügen + Add-on-Zahlung kumuliert angezeigt
Added
- •
admin_cancel_addon — Sub-Status='cancelled' + PG-Rückerstattung + Rückerstattungs-Row INSERT
- •PG-Routing: basierend auf der Spalte
gateway der Zahlungs-Row (auch nach PG-Wechsel sicher)
Removed
- •Gemäß japanischer 7-Jahres-Aufbewahrungspflicht + PAY.JP-Streitbeilegungsrichtlinie alle „Löschen"-Schaltflächen der Admin-UI entfernt
- •Papierkorb-Symbol + adminDeleteAddon JS + admin_delete_addon API + 4 Labels in 13 Sprachen alle entfernt
- •Nur „Stornieren" — Daten-Rows werden niemals gelöscht (DELETE)
Fixed
- •Translator-Platzhalter-Doppelpunkt-Präfix-Konflikt —
[':count' => N] → ['count' => N] massenweise behoben
- •PayjpGateway::refund()
metadata[refund_reason] von PAY.JP abgelehnt → auf refund_reason geändert
- •service-manage.php Admin-Berechtigungsprüfung —
role === 'admin' → role IN ('admin','supervisor') für 5 Aktionen behoben
- •Serviceauftrag Domain-Tab: nach Rückerstattung zeigt Buchhaltungskarte negative Zahl → SQL-Logik korrigiert (status='paid' / 'refund' getrennte Summierung)
Added
- •ssh.21ces.com Cloudflare Tunnel registriert (Public Hostname: SSH → localhost:22)
- •Externer PC:
cloudflared access ssh --hostname ssh.21ces.com oder ~/.ssh/config ProxyCommand
- •Serverseite: PermitRootLogin no, thevos-Schlüssel registriert
Added
HostingProvisioner.php installVoscms() ruft install-core.php nach dem zip-Deploy sequenziell bei Step 3 → Step 4 auf (zuvor nur Step 2):
- •Neu:
runInstallCoreSteps() — Session-Umgehung über _db-POST-Fallback + .installed-Marker-Prüfung
- •Neu:
callInstallCore() — HTTP-Loopback (Port 80, Cloudflare-Edge-SSL genutzt; fehlende Origin-Zertifikate bei Rate-Limiting abgefangen)
- •Neu:
appendHostingEnv() — HOSTING_*-Variablen nach Überschreiben der .env durch install-core.php erneut injizieren
- •welcome.html wird nach erfolgreicher Installation automatisch entfernt (damit VosCMS index.php Vorrang erhält)
- •Zahlungsfluss service-order.php:567-576 — bei erfolgreichem Install werden
install_completed_at und install_admin_url automatisch in den Addon-Metadaten gespeichert (löst Mein-Bereich-Tab-Anzeige aus)
Added
admin/service-orders/detail.php:175-260 + partials/addon.php:
- •Zwei Schaltflächen im „Installations-Support"-Addon unter dem Zusatzleistungen-Tab:
- •VosCMS installieren (violett) — sichtbar, wenn
install_info vorhanden und install_completed_at fehlt
- •Admin-Seite (grün) — öffnet Admin-URL in neuem Fenster nach Abschluss der Installation
- •API-Aktion
admin_run_voscms_install — ruft HostingProvisioner.installVoscms() direkt auf; DB-Zugangsdaten aus metadata.server.db oder Kunden-.env als Fallback
- •Bei erfolgreichem Install: Addon-Metadaten +
voscms_installed-order_log-Eintrag gespeichert
Added
customer/mypage/service-partials/hosting.php:
- •🟢 Seiten-Backup-Schaltfläche —
service-manage.php?action=request_backup (neu)
- •mysqldump → DB-Dump + zip(public_html, .env, sql) als Paket
- •Signierte Download-URL (HMAC, 10 Minuten gültig) — api/backup-download.php neu
- •Automatische Bereinigung von Backups älter als 7 Tage
- •🟣 phpMyAdmin öffnen — öffnet
https://pma.voscms.com/?lang=<user_locale> in neuem Fenster
- •nginx vhost: pma.voscms.com.conf neu (automatisches Routing über Cloudflare-Tunnel-Wildcard
*.voscms.com)
- •Benutzer meldet sich mit eigenen DB-Zugangsdaten an
- •Anzeige der DB-Verbindungsdaten (Host / DB-Name / Benutzer / Passwort-Toggle)
- •13-sprachiges i18n:
btn_site_backup, btn_open_phpmyadmin, confirm_site_backup, backup_in_progress, backup_ready, f_password, password_notice, f_protocol
Added
customer/mypage/service-partials/_setup-monitor.php:
- •Hosting-Setup → VosCMS-Autoinstall-Schritt ausgelagert
- •
system_imported-Bestellungen (Hosting-Registrierungen für eigene Betreiber-Seiten wie vos.21ces.com) werden sofort aktiviert — Monitoring-Box wird nicht angezeigt
- •13-sprachige neue i18n:
setup_step_voscms_install
Changed
rsync-Exclude-Ergänzungen:
- •5 interne Plugins (dürfen nicht in Hosting-Kundenseiten enthalten sein):
- •
vos-developer, vos-hosting, vos-license-server, vos-market, vos-salon
- •7 Reservierungs-Migrations-SQL-Dateien (Hosting-Kunden haben das Reservierungssystem nicht installiert):
- •
001_create_reservation_tables.sql, 011_seed_service_translations.sql, 012_seed_service_translations_p2.sql, 013_add_source_to_reservations.sql, 014_add_payment_status_to_reservations.sql, 015_create_reservation_core.sql (neu), 016_alter_reservation_services.sql, 024_reservations_bundle_columns.sql
Ergänzungen bei der Entfernung von Dev-Dateien:
- •Verzeichnis
admin/ (offline.html-Überbleibsel) — leeres Verzeichnis verursacht nginx-Verzeichnisindex-403; sw.js referenziert nur root-/offline.html, daher ist admin/ überflüssig
- •Standard-Encoding →
obfuscate.php (früheres ionCube EVAL verursachte Runtime-Hang; ionCube nur bei USE_IONCUBE=1)
Changed
001_create_base_tables.sql erstellte bislang Base- und Reservierungs-Tabellen in einer Datei — nun getrennt:
- •Angepasst:
001_create_base_tables.sql — nur 5 Kerntabellen (rzx_admins, rzx_users, rzx_member_grades, rzx_settings, rzx_migrations) + Kern-Seeds (member_grades Standard, settings Standard)
- •Neu:
015_create_reservation_core.sql — 9 Reservierungs-Tabellen (rzx_categories, rzx_services, rzx_service_options, rzx_reservations, rzx_payments, rzx_point_transactions, rzx_business_hours, rzx_holidays, rzx_staff_positions, rzx_staff) + Reservierungs-Seeds (business_hours, point_*)
Beim Hosting-Dist-Build wird 015 ausgeschlossen → rzx_reservations-Tabelle wird nicht erstellt → admin/dashboard.php:25-27 $hasReservations = false → Kalender wird automatisch ausgeblendet.
Seiten, die das Reservierungssystem nutzen (voscms.com HQ, RezlyX usw.), wenden beide SQL-Dateien an → keine Änderung.
Changed
config/templates/nginx-vhost.conf.tpl + HostingProvisioner addHttpsToVhost():
- •Vorher: Port 80 (HTTPS-Redirect) + Port 443 (tatsächlicher Inhalt) → Endlosschleife durch Cloudflare-Tunnel + 80→443-Redirect
- •Nachher: Einheitlicher Server-Block für 80/443, gleicher Inhalt, kein Redirect
- •
fastcgi_read_timeout 60s → 300s (verhindert nginx-Timeout bei großen INSERT-Operationen)
Changed
- •
provision-hosting.php (CLI-Backfill-Tool): aktualisiert Hosting-Subscription-Metadaten automatisch (hosting_provisioned, server.{ftp,db,env}) — zuvor führte nur _autoProvisionHosting in service-order.php diesen Schritt aus
- •5 interne Plugins +
admin/-Verzeichnis werden automatisch entfernt
Added
scripts/install-cli.php neu:
- •Backfill für automatischen install-core.php-Aufruf nach dem Hosting-Provisioning
- •DB-Zugangsdaten: Subscription-Metadaten haben Vorrang, Fallback auf Kunden-Docroot-
.env
- •Verwendung:
sudo -u www-data php scripts/install-cli.php --order=<ORDER>
- •Bei Erfolg:
install_completed_at in Addon-Metadaten automatisch gespeichert + voscms_installed-Aktion in order_logs
Fixed
- •Fehlender
_autoProvisionHosting()-Aufruf im Kartenzahlungs-Branch — hinzugefügt
- •
install_info.admin_pw in den Zahlungs-Metadaten wurde im Klartext angezeigt → Toggle (👁)-Muster auf Mein-Bereich- und Admin-Seite vereinheitlicht
Migration Notes
- •Externe Hosting-Kunden: kein Handlungsbedarf. Nach dem Build von
voscms-2.4.3.zip nutzt der Auto-Install-Flow eine saubere zip-Datei.
- •HQ (voscms.com): keine Änderung (beide Reservierungs-SQL-Dateien sind angewendet).
- •Bestehende Hosting-Kunden (dwhahn usw.): Neuinstallation per Deprovision + Reprovision empfohlen (neue zip nach Trennung anwenden).
- •Manuelle Bereinigung:
/etc/nginx/sites-available/pma.voscms.com.conf wurde neu hinzugefügt — direkt im HQ-System deployen (außerhalb von rsync).
Added
Wird unmittelbar nach Zahlungsabschluss in service-order.php aufgerufen:
- •Neue Funktion
_autoProvisionHosting($pdo, $prefix, $orderId, $orderNumber) — läuft außerhalb der Zahlungstransaktion (DB-Integrität isoliert; Bestellung selbst bleibt bei Fehler unberührt)
- •
domain_option = 'free' wird sofort eingerichtet (Cloudflare-Subdomain — DNS-Autoregistrierung bereits abgeschlossen)
- •
new (wartet auf NS-Änderung nach Domain-Kauf) / existing (wartet auf NS-Änderung für bestehende Domain) sind deferred — Admin löst separat zum Zeitpunkt der Domain-Aktivierung aus
- •Wenn das 'install'-Addon
install_info enthält, werden voscms-Dateien bereitgestellt + .env automatisch erstellt (die Automatisierung des schrittweisen Session-Flows von install-core.php (Schritte 2–5) erfordert eine Neugestaltung der gesamten voscms-Installationspipeline — auf Phase 5 verschoben; Nutzer öffnet nach Zahlung https://<Domain>/install.php → durchläuft den Assistenten, DB-Daten bereits in .env vorausgefüllt)
- •ftp/db/env-Informationen werden automatisch in
metadata.server des Hosting-Abonnements gespeichert → automatische Anzeige im Hosting-Tab des Mein-Bereich (keine UI-Änderungen erforderlich)
- •order_logs-Aktionen:
hosting_provisioned / hosting_provision_skipped / hosting_provision_deferred / hosting_provision_failed
Aufruffolge: Zahlungscommit → _autoProvisionHosting() → _autoProvisionMailDomain()
Added
$actionLabels auf der Admin-Serviceauftragsdetailseite (detail.php:498-528) von 8 auf 31 Einträge erweitert. Behebt die Anzeige von Rohaktionscodes (z. B. mail_account_added) im Aktivitätslog.
Neu zugeordnete Aktionen:
- •Mail:
mail_account_added/deleted, mail_address_changed, mail_provisioned/_skipped/_failed, mail_domain_migrated/activated, bizmail_upgrade_request
- •Hosting:
hosting_provisioned, hosting_provision_skipped/deferred/failed, hosting_deprovisioned
- •Add-ons:
admin_add_storage_addon, admin_delete_addon, storage_addon_paid/requested
- •System:
customer_notified, setup_email_sent, server_info_updated, bulk_extended, manual_capacity_period_fix
Farbsemantik je Aktion: green (abgeschlossen/positiv), amber (ausstehend/Warnung), red (fehlgeschlagen/gelöscht), blue (Info/Benachrichtigung), violet (Admin/Spezial), zinc (neutral).
23 i18n-Schlüssel — services.admin_orders.act_* — in ko/ja/en hinzugefügt (Betreiberseite). Die anderen 10 Sprachen greifen auf Englisch zurück.
Changed
Bei der Hosting-Autoprovisioning beschränkt sich die automatische VosCMS-Installation auf Datei-Deployment + .env-Erstellung. Die Automatisierung des schrittweisen Session-Flows von install-core.php (Schritte 2–5) erfordert eine vollständige Neugestaltung der voscms-Installationspipeline — wird auf Phase 5 verschoben. Nach der Zahlung öffnet der Nutzer https://<Domain>/install.php → durchläuft den Assistenten (DB-Daten bereits in .env vorausgefüllt).
Rückgabewert von installVoscms() geändert — gibt jetzt install_url + note-Meldung zurück.
Added
HostingProvisioner.php — Hauptklasse für automatisches Setup bei Hosting-Bestellung. 9-schrittiger Transaktion (bei Fehler Rollback in umgekehrter Reihenfolge):
- •Linux-Benutzer erstellen (
vos_<order_number>, innerhalb der 32-Zeichen-Grenze, Groß-/Kleinschreibung bewahrt)
- •Verzeichnisstruktur:
/var/www/customers/<order>/{public_html,logs,tmp} (chmod 750/2775/750/1770)
- •Datenträgerkontingent (
setquota -u <user> <soft> <hard>, hard = soft × 1.1)
- •Verzeichniskonflikterkennung: Ablehnung bei Konflikt mit vorhandenem nginx vhost /
reserved_subdomains
- •1,9 TB SSD
/var/www Mount (ext4 + noatime + usrquota,grpquota)
- •Zentrale sudoers (
/etc/sudoers.d/voscms-hosting-provisioner) — www-data führt root-Befehle (useradd/setquota/nginx usw.) NOPASSWD aus
- •Argumentmusterbeschränkung pro Befehl (
vos_, /var/www/customers/, *.conf) — besteht visudo-Validierung
CLI-Tool scripts/provision-hosting.php:
php provision-hosting.php SVC260428AE7476 hotel.com 1GB
php provision-hosting.php --order SVC260428AE7476 # automatische DB-Abfrage
php provision-hosting.php --deprovision SVC260428AE7476 hotel.com
php provision-hosting.php --install-voscms <order> <domain> <capacity>
Vorlagen config/templates/:
- •
nginx-vhost.conf.tpl — HTTP + ACME-Challenge-Ort + benutzergebundener FPM-Socket
- •
welcome.html.tpl — Aktivierungs-Willkommensseite
Added
Jedes Hosting führt PHP unter seinem eigenen Benutzer aus (verhindert seitenübergreifende Angriffe) + SSL automatisch ausgestellt, auch hinter Cloudflare-Proxy.
config/templates/php-fpm-pool.conf.tpl:
- •
user = vos_<order> / group = www-data — UID-Isolation
- •
listen = /var/run/php/<order>.sock — benutzerspezifischer Socket
- •
pm = ondemand — speichereffizient für Traffic-armes Hosting
- •
php_admin_value[open_basedir] — Zugriff auf Website-Verzeichnis + /tmp + /usr/share/php begrenzt
- •
disable_functions — exec, passthru, shell_exec, system, proc_open, popen, pcntl_exec
- •
session.save_path / upload_tmp_dir — auf Benutzerverzeichnis isoliert
- •env: HOSTING_ORDER / HOSTING_USER / HOSTING_DOMAIN
Let's Encrypt SSL — Cloudflare DNS-01-Challenge:
- •
python3-certbot-dns-cloudflare Plugin
- •
/etc/letsencrypt/cloudflare/credentials.ini (root 0600, CLOUDFLARE_API_TOKEN aus .env)
- •Ausstellung unabhängig von Cloudflare-Proxy / externer Erreichbarkeit
- •HTTPS-Serverblock automatisch hinzugefügt (TLS 1.2/1.3, starke Verschlüsselung, HSTS, X-Frame-Options, X-Content-Type-Options)
- •HTTP → HTTPS 301 automatische Weiterleitung
- •
certbot.timer erneuert automatisch zweimal täglich (bereits aktiv)
Added
DB + Benutzerisolation pro Hosting-Bestellung.
- •
hosting_admin MySQL-Konto (einmalig erstellt, ALL PRIVILEGES + GRANT OPTION) — nur für DB-Verwaltung
- •DB-Name/Benutzer =
vos_<order> (identisch mit Linux-Benutzername)
- •Passwort: 32-Hex zufällig (
bin2hex(random_bytes(16)))
- •
GRANT ALL PRIVILEGES ON vos_<order>.* TO vos_<order>@localhost — Zugriff nur auf eigene DB
- •Isolationsverifikation: Zugriff auf andere Hosting-DB / voscms_prod gibt Access denied 1044
VosCMS-Autoinstall (installVoscms() — durch --install-voscms oder wenn Addon install_info hat):
- •Extrahiert neuestes
voscms-dist/voscms-X.Y.Z.zip → public_html
- •
.env automatisch generiert: APP_KEY=base64:<32Bytes> / DB-Info / HOSTING_ORDER injiziert
- •Berechtigungen: vos_:www-data, .env chmod 640
- •
install-core.php headless aufgerufen (aktuell 301-Weiterleitungsproblem, wird in Phase 4 behoben)
Verified
provision DEMO260429FULL demo07.21ces.com 1GB --install-voscms:
- •✅ Benutzer
vos_DEMO260429FULL (UID-Isolation, www-data-Gruppe)
- •✅ Datenträgerkontingent 1 GB soft / 1,05 GB hard
- •✅ PHP-FPM-Pool eigener Socket
- •✅ nginx vhost (HTTP + HTTPS, HSTS)
- •✅ Let's Encrypt SSL (
/etc/letsencrypt/live/demo07.21ces.com/)
- •✅ MySQL-DB
vos_DEMO260429FULL + Benutzer (Isolation verifiziert)
- •✅ VosCMS 2.3.9-Dateien + .env bereitgestellt
deprovision: Alle Ressourcen sauber entfernt (Benutzer/Home/DB/FPM-Pool/nginx/SSL).
Added
Statt der branchenüblichen Anniversary-Abrechnung (Registrierungsdatum bis zum selben Datum ein Jahr später) wird jetzt auf Kalender-Monatsende umgestellt (1. des Folgemonats bis zum letzten Tag des Ablaufmonats). Benutzer, die im selben Monat beitreten, haben dasselbe Ablaufdatum, was die Cron-Stapelverarbeitung und den Buchhaltungsabschluss vereinfacht. Entspricht dem japanischen Hosting-Standard (月末締め翌月1日請求).
- •DB: Spalte
rzx_subscriptions.billing_start DATETIME NULL hinzugefügt (Startdatum der regulären Abrechnung)
- •Helfer:
_proratedFirstAmount (Monatseinheit ÷ 30 × verbleibende Tage), _calendarBillingStart (1. des Folgemonats), _calendarExpires (letzter Tag 23:59:59)
- •Bestellformular:
hosting_prorated wird automatisch zu Hosting-Zahlungspositionen hinzugefügt (z.B. Beitritt am 4.2., 12 Monate ¥1.000/Mo. → Erstmonat ¥967 + regulär 12 Monate ¥12.000 = ¥12.967)
- •Domains behalten Anniversary-Abrechnung (1-Jahres-Registrierungszyklus); Hosting, Mail, Wartung und Add-ons verwenden Kalenderabrechnung
- •
-1 second → -1 day Behandlung in service-order.php ebenfalls vereinheitlicht
- •Add-on-Dienste (Extra-Webspeicher) verwenden ebenfalls dieselbe Tagesabrechnung + reguläre N-Monats-Summe, automatisch mit dem Hosting-Ablaufdatum synchronisiert
Added
Postfix + Dovecot + Rspamd + Roundcube + OpenDKIM + Let's Encrypt auf ConoHa VPS (133.117.72.149) eingerichtet. mail-tester 10/10, FCRDNS verifiziert. Domain-Auto-Setup bei Bestellung.
- •Automatische DNS-Registrierung (
CloudflareDns.php) — A / MX / SPF / DKIM / DMARC 5 Einträge in einem Schritt
- •DKIM-Schlüsselerzeugung — mx1 SSH
rspamadm dkim_keygen (dedizierter ed25519-Schlüssel storage/keys/mailsync_ed25519, www-data-Eigentümer, 0700)
- •3-Modus-Provisioning (
MailDomainProvisioner.php): free (Subdomain sofort) / new (Domain gekauft, Admin-Aktivierung) / existing (NS-Änderungsanleitung). Zustandsautomat: existing_pending / new_pending / active
- •Passwort: SHA512-CRYPT (
{SHA512-CRYPT}$6$...) — Dovecot-kompatibler Einweg-Hash. Migrationsskript für alte enc:-Passwörter (encrypt-Funktion): scripts/migrate-mail-passwords.php
- •mx1-Sync-Cron (
scripts/mail-sync-to-mx1.php) — voscms_prod → mx1 mail_lookup virtual_users alle 5 Minuten. Sofort-Trigger (triggerMailSyncToMx1()) für Hintergrund-Sync direkt nach Mail-Aktionen ebenfalls hinzugefügt
- •Cron-Auto-Registrierung:
/etc/cron.d/voscms-mail-sync
- •Benachrichtigungen: Admin (Provisioning erforderlich) / Kunde (Mail verfügbar) HTML-Mail-Vorlagen (
MailNotifier.php)
Added
Basis-Mail / Business-Mail gemeinsam mit Hosting verwaltet. Problem behoben, bei dem dieselbe Adresse in mail subscription + hosting metadata doppelt gespeichert und in der UI doppelt angezeigt wurde (Single Source of Truth: mail subscription).
- •Webmail-Schaltfläche — Roundcube
?_user=Adresse GET-Parameter für Benutzernamen-Vorausfüllung, target="_blank". URL-Priorität: metadata.mail_server.webmail_url → WEBMAIL_URL env → Standard https://mail.voscms.com/
- •E-Mail-Änderungs-Schaltfläche — zur Tippfehlerkorrektur. Domain ist fest; nur der lokale Teil ändert sich. Alle mail + hosting metadata derselben Bestellung werden synchronisiert
- •Deduplizierungslogik (
mail.php) — _seenAddresses zeigt jede Adresse nur einmal an, mail subscription hat Vorrang
- •service-detail.php virtuelle hosting → mail-Konvertierung läuft nur, wenn keine echte mail subscription vorhanden ist (Abwärtskompatibilität)
- •service-order.php speichert bei Neuanmeldungen keine hosting metadata.mail_accounts mehr (mail subscription ist die einzige Quelle)
Added
Add-on-Speicherkauf mit Zahlung im Add-on-Dienste-Tab der Meine Seite. PAY.JP-Kundenregistrierung + chargeCustomer.
- •Modal: Speicherauswahl (1 GB / 3 GB / 5 GB) + Kartendateneingabe (payjp.js v2 Elements)
- •Karte registrieren / mit anderer Karte zahlen / zur registrierten Karte zurückkehren — Umschalter
- •Automatische Erkennung abgelaufener/abgelehnter Karten (
expired_card, card_declined, invalid_* usw. PAY.JP-Fehlercodes) → Kartenformular öffnet sich automatisch + Hinweisbanner
- •Karteninhabernamen-Eingabefeld hinzugefügt (
addon-card-holder) — als Customer-Metadata gespeichert, nicht an Token übergeben (PAY.JP v2 Elements unterstützt keine name-Option)
- •Portal-Muster:
document.body.appendChild(), um aus transform-eingeschränkten Containern auszubrechen und den gesamten Viewport abzudecken (z-[9999])
- •Wenn Charge nach Erstellen eines neuen Customers fehlschlägt: automatische Rückerstattung + Customer-Löschung (Orphan-Verhinderung)
- •hosting metadata.extra_storage[] kumuliert, Hosting-Tab-Speicheranzeige zeigt kombinierten Gesamtwert
Added
14 Artikel (Definitionen, Antrag, Gebühren, automatische Verlängerung, Kündigung, Service, Backup, verbotene Nutzung, Sperrung, Wartung, Datenschutz, Haftung, Änderungen, Gerichtsbarkeit) in Anlehnung an StarServer und andere japanische Hosting-Standardbedingungen strukturiert. Kalenderabrechnung + Erstmonats-Tagesabrechnung + Rückerstattung ungenutzter Monate bei Kündigung festgelegt.
- •Systemseiten-Registrierung:
config/system-pages.php hosting-terms Slug, 🖥️ Indigo
- •Seiten-Editor-Mapping:
pages-document.php — pageMetaMap['hosting-terms']
- •DB-Seed: ja (Haupt) / ko / en — 3 Sprachen (rzx_page_contents)
- •i18n:
site.pages.hosting_terms + hosting_terms_edit (editor_title/desc)
Added
- •4 Tabs immer sichtbar (detail.php) — hosting/domain/mail/addon. Leerzustandsmeldung (empty_*) wenn keine Daten vorhanden
- •Add-on-Dienste-Tab —
+ Speicher hinzufügen-Schaltfläche (Admin-Gratiszuteilungs-Modal, Kapazitätsauswahl erstellt sofort eine aktive Addon-Subscription, billing_amount=0, expires=Hosting-Ablaufdatum) + Papierkorb-/Löschschaltfläche pro Element (Soft-Delete status=cancelled, entfernt aus hosting metadata.extra_storage[])
- •Liste — Antragsteller-Anzeigeverbesserung (index.php) — Bestellungen von Systemadministratoren mit
supervisor/admin-Rolle werden als user.name + lila Untertitel Superadmin: [email protected] angezeigt (umgeht Entschlüsselungsfehler des alten verschlüsselten applicant_name wie FKzGx9SE7xG/2)
- •Bestellerstellungs-Schaltfläche (
+ New Order) — nur UI, Funktionalität folgt später
- •i18n 13 Sprachen:
role_supervisor, role_admin, btn_create_order, empty_, btn_add_storage_addon, btn_delete_addon, modal_add_storage_, confirm_, alert_ und 20+ weitere Schlüssel
Added
- •
subdomain-check.php — DB (reserved_subdomains) Priorität + Cloudflare API Fallback. JS checkSubdomain() ruft Server auf und spiegelt Ergebnis wider
- •Serverseitige Revalidierung in service-order.php unmittelbar vor der Zahlung — verhindert clientseitige Umgehung
- •
reserved_subdomains Auto-Import — 11 bestehende Einträge aus der Cloudflare-Zone (vos/bestatech/bt/dev/ec430/ec431/salon/ssh/test/thevos/ai.21ces.com)
- •Menü INSERT IGNORE Bugfix (menus-api.php):
- •
add_menu_item: veraltete Übersetzungen direkt nach INSERT bereinigen + Überschreiben mit INSERT ... ON DUPLICATE KEY UPDATE
- •
update_menu_item: title/url-Änderungen erkennen, alle 13 alten Übersetzungen löschen + bei Systemseite neu registrieren
- •
rename_menu_item: alte Übersetzungen bei Titeländerung bereinigen
- •Regression behoben, bei der das alte Menü (id=38, „VosCMS-Einführung") auf das neue Hosting-AGB-Menü zeigte
Added
Ablauf aufgebaut: Servicebestellung → Zahlungsabschluss → automatisches Mail-Domain-Provisioning → Kundenbenachrichtigung.
- •
_autoProvisionMailDomain()-Aufruf in service-order.php hinzugefügt — läuft außerhalb der Zahlungstransaktion (DB-Integritätsisolierung)
- •DB:
rzx_reserved_subdomains (zone, subdomain, record_type, reserved_by, reason) — Verfügbarkeits-Cache
- •DKIM-Schlüssel automatisch generiert, in metadata.mail_provision als mode/origin/domain/zone/subdomain/provisioned_at gespeichert
- •Provisioning-Modus-UI-Verzweigung (service-detail.php):
pending / new_pending / existing_pending — Tabs ausgeblendet, nur Monitoring angezeigt (_setup-monitor.php); Tabs nur bei active sichtbar
Fixed
PHPs $arr['key'] ?? [] gibt einen temporären Wert zurück, sodass &$ref das ursprüngliche Array nicht beeinflusst. change_mail_password / change_mail_address gaben Success-Antworten zurück, aber das metadata UPDATE hatte keinen Effekt — Passwort- und Adressänderungen schlugen lautlos fehl.
- •Auf Index-basiertes direktes Update-Muster umgestellt:
foreach ($arr as $i => $item) { $arr[$i]['k'] = ... }
- •Neue Mail-Passwortspeicherung in service-order.php ebenfalls von
encrypt() (bidirektional) auf mail_password_hash() (SHA512-CRYPT) umgestellt
Fixed
- •Zahlungszusammenfassung leuchtend fluoreszierendes Grün → sauberere Farbe:
text-green-400 → text-green-600 dark:text-green-400 (7 Stellen)
- •i18n-Schlüssel für Subdomain-Verfügbarkeitsantwortmeldung fehlend (
order.php PHP→JS i18n-Mapping + :fqdn-Platzhalter vereinheitlicht)
- •Ablaufdatumberechnung präzisiert:
+N months -1 second (selber Tag) → +N months -1 day (genau 1 Tag vorher) → abschließend auf Kalendermethode vereinheitlicht
Database
- •
rzx_subscriptions.billing_start DATETIME NULL hinzugefügt (dev + prod)
- •
rzx_reserved_subdomains-Tabelle (Cloudflare-Zone-Kollisions-Cache)
- •
rzx_page_contents mit hosting-terms (ja/ko/en) befüllt
Added
Alle Texte in den 6 Bereichen (Domain, Hosting, Add-ons, Antragsteller, Zahlung, Zusammenfassung) und der Zahlungsbestätigungsseite wurden in 13 Sprachen übersetzt. Clientseitige Alert-/Modal-Texte werden über PHP mit dem Muster var I18N = {...} + t(key, replace) injiziert.
- •Speicherort: plugins/vos-hosting/lang/{13 locales}/services.php —
services.order.* 200+ Schlüssel
- •Meine Seite Servicedetail:
services.detail.* 70+ Schlüssel, service-detail.php
- •Admin Auftragsverwaltung:
services.admin_orders.* 115+ Schlüssel, admin/service-orders/
- •In der DB gespeicherte koreanische Labels (Hosting-Pläne, Wartung, Add-ons) werden per
_localizeLabel($sub)-Closure auf Settings-IDs gemappt und db_trans() angewendet → konsistente Verarbeitung auf Meine Seite und Admin
Added
Beim Klick auf den Zahlungsbutton werden die Bestelldetails (Domain/Plan/Add-ons/Antragsteller/AGB) validiert und ein Zusammenfassungsmodal angezeigt → Benutzer bestätigt → Zahlung läuft. Verhindert Fehler wie die Registrierung einer leeren Subdomain.
- •order.js —
showOrderConfirmModal(), closeOrderConfirmModal(), confirmAndPay()
- •Verbesserte Entfernung verbleibender Modal-Ebenen nach Zahlungsabschluss (DOM-Löschung + body/documentElement Overflow-Reset)
Added
Wenn in den Add-ons "Installationsunterstützung" (_id='install') ausgewählt wird, erscheint ein Formular für Admin-ID/E-Mail/Passwort/Seitenname. Passwort ist maskiert + Augen-Symbol-Toggle + Hinweis "nach Installation ändern". Werte werden als install_info in den Abonnement-Metadaten gespeichert und auf Meine Seite/Admin angezeigt.
- •Eingabe: _addons.php
- •Anzeige: Meine Seite/Admin partials/addon.php (blauer Hintergrundkasten + Passwort-Toggle)
Added
Das Memo, das am Add-ons-Tab hing, wurde auf die Auftragsebene (rzx_orders.admin_notes) verlagert. Es wird immer als 7-zeiliges Textfeld über dem Aktivitätsprotokoll auf der rechten Seite angezeigt, unabhängig davon, ob Add-ons vorhanden sind. AJAX-Aktion update_order_memo hinzugefügt.
Added
Ein section-Feld (top/main/bottom, Standard main) wurde eingeführt, um Core-Menüs visuell von Plugin-Menüs zu trennen. Zwischen Zonen wird automatisch eine Trennlinie eingefügt; wenn in einer Zone keine anzeigbaren Menüs vorhanden sind, wird die gesamte Zone einschließlich Trennlinie übersprungen.
Admin-Seitenleiste:
- •top: Dashboard / Benutzerverwaltung / Site-Verwaltung / Auto-Installer (
vos-autoinstall)
- •main: VosCMS-Lizenz (
vos-license-manager) / Hosting-Verwaltung (vos-hosting)
- •bottom: Plugins / Einstellungen
- •Änderungen: config/admin-menu.php, admin-sidebar.php
Meine Seite Seitenleiste:
- •top: Dashboard / Profil / Nachrichten
- •main: Dienste (
vos-hosting automatisch hinzugefügt) — werden automatisch akkumuliert, wenn andere Plugins Einträge hinzufügen
- •bottom: Einstellungen / Passwort / Kontolöschung / Abmelden
- •Änderungen: config/mypage-menu.php, mypage-sidebar.php
Plugin-Menüregistrierung: section + position in den menus.admin/menus.mypage-Einträgen der plugin.json geben die Zone an. Das services-Menü wurde von core mypage-menu.php → vos-hosting/plugin.json verschoben (automatische Registrierung).
Added
Da die Lizenzvalidierungs-API und die Entwicklerportal-API im Core lagen, wären sie bei der Bereitstellung auf allen voscms-Sites extern zugänglich. Beide APIs wurden in ein neues, nur für die Zentrale bestimmtes Plugin ausgelagert.
- •
vos-license-server (scope: hq_only): 7 Lizenz-Endpunkte verschoben (check, register, verify, stats, updates, register-plugin, _init)
- •
vos-developer (scope: hq_only): 7 Entwicklerportal-Endpunkte verschoben (register, login, submit, my-items, earnings, update-version, _init)
- •
api/_plugin_dispatch.php — Core-Wrapper prüft rzx_plugins.is_active vor dem Dispatch, gibt bei inaktiv 404 zurück
- •Core
/api/license/.php und /api/developer/.php behalten nur den Wrapper (externe Kompatibilität erhalten)
- •
/api/notices.php mit HQ_HOSTS-Env-Whitelist hinzugefügt (antwortet nur von HQ voscms.com-Domain)
- •Das Build-Skript (
build-voscms.sh) schließt api/license, api/developer, api/notices.php und vos-license-manager bereits aus
Fixed
- •Hosting-Vertragslaufzeit +1-Tag-Bug (
+12 months → +12 months -1 second) — auf 4 Stellen angewendet: subscription/free/paid/bank
- •Business-E-Mail: 2 oder mehr können nicht hinzugefügt werden (Selektor hat X-Schaltfläche erwischt)
- •Bestellübersicht: zusätzlicher Speicher nicht aggregiert (fehlendes
name-Attribut beim Speicher-Select)
- •Hosting-Plan-Label nicht lokalisiert — durch Abgleich von
service_hosting_plans._id mit db_trans() behoben
Added
_init.php fragt nun rzx_translations direkt nach board.{id}.{title|description|header_content|footer_content|seo_keywords|seo_description} ab (aktuelle Locale → en → Quelle). Auf jeder Seite — list/read/write/settings — wird $board[$field] automatisch mit dem übersetzten Wert befüllt. Der „← Zurück"-Button auf der Board-Einstellungsseite wird ebenfalls automatisch über denselben Mechanismus übersetzt.
13-Sprachen-Seed für title + header_content des Issue-Boards (id=6) — HTML-Struktur erhalten, nur Text übersetzt, Verarbeitungsstatus-Badges ebenfalls in jeder Sprache. Seed-Skripte: scripts/seed_issue_i18n.php + scripts/seed_issue_i18n_data.php.
Added
Übersetzung der Definitionen (Label/Beschreibung/Optionen/Standardwert) von rzx_board_extra_vars in 13 Sprachen. 4 Felder × 13 = 52 Zeilen.
- •
ExtraVarRenderer::renderAll($vars, $values, $mode, $boardId) — boardId-Argument hinzugefügt, applyDefTranslations() lädt alle Var-Übersetzungen in einer einzigen Abfrage.
- •
ExtraVarRenderer::getOptionLabel($boardId, $varName, $value) — Übersetztes Label einer einzelnen Option für Listenansichten (statischer Cache).
- •
renderStatusBadge($value, $size, $displayLabel = null) — Farbe verwendet die Quell-(ko-)Zuordnung, nur Text wird übersetzt → Farbe in allen Sprachen konsistent (eingegangen = Rose, gelöst = Smaragd).
- •select/radio/checkbox:
value=Quelle / label=Übersetzung-Muster. Beim Speichern von Beiträgen wird immer der Quellwert gespeichert, was Datenkompatibilität gewährleistet.
- •Aufrufstellen aktualisiert:
read.php, write.php, _list-row.php, Standard-Skin _list-card/_list-webzine/_list-gallery.
13-Sprachen-Seed für die status-Extravariable des Issue-Boards: scripts/seed_ev_status_i18n.php.
Added
Die extra_var_get-API gibt übersetzte Werte der aktuellen Locale als localized-Objekt über db_trans() zurück. Das JS-Modal zeigt localized.title || ev.title bevorzugt an → Im Japanisch-Modus erscheint beim Öffnen des Modals automatisch „処理ステージ".
extra_var_update verzweigt nach Locale:
- •Quell-Locale (ko) → gesamte Quellzeile aktualisieren (bisheriges Verhalten)
- •Nicht-Quell-Locale (ja/en/…) → nur Meta (
var_type/Berechtigungen/3 Checkboxen) in Quelle speichern; 4 Übersetzungsfelder (title/description/options/default_value) in rzx_translations unter der aktuellen Locale speichern → Quelldatenintegrität gewährleistet
Anzeigenamen in der Extravariablen-Übersicht verwenden ebenfalls db_trans('board_ev.{boardId}.{varName}.title').
Added
Der Abschnitt „Bearbeitungsberechtigung" (Label/Dropdown-Optionen/Hilfetext) des Extravariablen-Bearbeitungsmodals wurde in 13-sprachige Lang-Dateien ausgelagert. Neue Schlüssel: site.boards.ev_permission, ev_perm_all, ev_perm_member, ev_perm_admin, ev_permission_help.
Added
Bidirektionale Normalisierung des „Optionen"-Felds im Extravariablen-Bearbeitungsmodal:
- •Modal-Laden: konvertiert DB-JSON-Array (
["a","b","c"]) in Zeilenumbruchformat für die Textarea-Anzeige (passend zu den Anweisungen)
- •Speicher-API:
ev_normalize_options()-Helfer akzeptiert Zeilenumbruch- oder JSON-Eingabe und speichert konsistent als JSON-Array. Behebt einen Bug, bei dem Zeilenumbrucheingaben als NULL gespeichert wurden.
Added
Zwei neue Skins für Inhaltsmuster jenseits von Issues/Ankündigungen.
FAQ (skins/board/faq/) — Beitrag = Frage, Inhalt = Antwort. Inklusive Suchleiste, Kategorie-Filter und Seitenumbruch. Titelbereich-Anzeige-Toggle, mehrsprachiger Titel/Untertitel, Hintergrund (Bild/Video/keine) Unterstützung, Overlay-Transparenz-Einstellung. v1.0.1.
Q&A (skins/board/qna/) — Beitrag = Frage (Titel+Inhalt), Kommentar = Antwort. „Unbeantwortet"-Badge, erstes Element automatisch ausgeklappt, Baum-sortierte (parent_id/depth) Kommentaranzeige. Antworten auf Antworten eingerückt + „↳ Antwort"-Label (oberste Ebene = „A."). Inline Bearbeiten/Antworten-Formular (nur Autor/Admin kann bearbeiten, perm_comment-Berechtigung für Antworten). v1.0.0.
Beide Skins gemeinsam: Admin-Einstellungen-Zahnrad-Symbol unten rechts in der Suchleiste platziert (vom Titelbereich getrennt). boardSkinFile() arbeitet mit _list-full.php-Priorität.
Added
update-Aktion zu api-comments.php hinzugefügt. Nur comment.user_id == aktueller Benutzer oder Admin können bearbeiten. Nach Zeichenanzahl-Validierung wird content + updated_at aktualisiert.
Added
Das {year}-Token im copyright-Feld der Layout-Einstellungen wird zur Render-Zeit automatisch durch das aktuelle Jahr ersetzt. Die Datenbank behält das Original (mit {year}), sodass es nie manuell aktualisiert werden muss. Angewendet auf: default/minimal/modern/base-footer.php. Die Copyright-Beschreibung in 4 layout.json-Dateien wurde auf 13 Sprachen erweitert, mit {year}-Verwendungshinweisen in der jeweiligen Muttersprache.
Ebenfalls behoben: Ein Bug, bei dem $_lc['copyright'] in default/minimal-Fußzeilen ignoriert wurde — der Layout-Einstellungswert wird jetzt tatsächlich gerendert.
Added
13-Sprachen-Seed für menu_item.38.title (VosCMS-Einführung / About VosCMS / VosCMSについて / Über VosCMS / Acerca de VosCMS / À propos de VosCMS / Tentang VosCMS / VosCMS-ийн тухай / О VosCMS / VosCMS Hakkında / Giới thiệu VosCMS / 关于 VosCMS / 關於 VosCMS).
Added
Je ein Beispiel pro Verarbeitungsstufe + 1 vorhandenes gelöstes = insgesamt 4. Titel/Inhalt jedes Beitrags in 13 Sprachen übersetzt (104 Zeilen).
| Stufe | Titel (ko) | Status |
|---|
| Eingegangen | [Bug] Hamburger-Menü-X-Schaltfläche auf Mobilgeräten funktioniert nicht | Neu |
| Wird geprüft | [Funktionswunsch] E-Mail-Benachrichtigung an Beitragsautor bei neuem Kommentar | Neu |
| In Bearbeitung | [Performance] Ladegeschwindigkeit der Marktplatz-Detailseite verbessern | Neu |
| Gelöst | Im Board-Beitrag angehängtes Bild in den Text eingefügt... | Vorhanden |
Vorhandener Beitrag 34 (angesammelter Tailwind-Inline-Style-Testbeitrag) gelöscht.
Fixed
customer/board/list.php requirte den rzx_admin_icons-Helfer in Zeile 167, aber das Skin-Datei-Include in Zeile 161 kehrte mit return zurück — was beim Aufruf von rzx_admin_icons() in FAQ/Q&A-Skins zu 500-Fehlern führte. require_once über das Skin-Include verschoben.
Changed
Verbleibende Verweise auf den alten Namen /marketplace entfernt. Fehler behoben, bei dem das Suchformular per GET an /marketplace gesendet wurde und eine Weiterleitung zum Dashboard auslöste (Seitenverlassen beim Ändern von Suche/Sortierung/Filter). Alle Dateien browse.php, item-detail.php, item-submit.php, purchases.php und assets/js/marketplace.js auf /autoinstall vereinheitlicht.
Added
In install.php Schritt 4 unterhalb des Admin-Pfad-Eingabefelds einen gelben Hinweis + Echtzeit-URL-Vorschau + aufklappbaren Leitfaden „Warum sollte ich das ändern?" hinzugefügt. Drei Gründe in allgemein verständlicher Sprache: automatisierte Hack-Versuche (Brute Force), Schwachstellen-Scanning und die Grenzen starker Passwörter. Auf alle 13 Sprachen angewendet.
Added
Im Installationsabschlussschritt von install.php wird das Plugin vos-autoinstall automatisch registriert und aktiviert (durch direkten Aufruf von PluginManager::install()). Benutzer können den Marktplatz sofort nach dem Betreten des Adminbereichs verwenden, ohne einen separaten Installationsschritt.
Added
Parameter ?locale=xx für market.21ces.com/api/market/catalog und /item hinzugefügt. Mehrsprachige JSON-Felder für name, description, short_description, cat_name werden serverseitig als einzelner String zurückgegeben (Fallback: angefordertes Locale → en → erster Wert). Alle doppelten json_decode + Locale-Fallback-Logiken auf der VosCMS-Seite entfernt (browse.php, item-detail.php, _components/item-card.php).
Added
TTL des dateibasierten Marktplatz-API-Antwort-Caches in PluginManager-Einstellungen integriert. Hartkodierte 30 Minuten → Standard 5 Minuten, Optionen für 1/5/10/30/60 Minuten. Sowohl der Marktplatz-Cache-Bereich in https://vos.21ces.com/theadmin/settings/general als auch /theadmin/autoinstall/settings lesen und schreiben dieselbe Einstellung und synchronisieren automatisch. Sofortige Cache-Aktualisierungsschaltfläche auf der AutoInstall-Seite und der allgemeinen Einstellungsseite hinzugefügt. Bei TTL-Änderung wird vorhandener Cache automatisch ungültig gemacht.
Added
Dieselbe Tabelle wie in der Marktplatz-Verwaltung (Datentyp / Kurzbeschreibung / Slug / Product Key / Mindest-VosCMS- und PHP-Version / Partner / Preis / Lizenz) wird direkt nach dem Header angezeigt. Links:Rechts-Inhaltsverhältnis von 2:1 auf 3:1 geändert, um den Inhaltsbereich zu vergrößern.
Added
Schaltfläche „Rezension schreiben" oben rechts im Rezensions-Tab der Detailseite. Sterne-Bewertung / Spitzname / Text-Eingabe-Modal → VosCMS API → weitergeleitet an Marktplatz POST /api/market/item/review. VosCMS-Lizenzschlüssel + Domain automatisch angehängt, Ein-Einsendungs-Limit pro Domain, Käufer erhalten automatisch is_verified=1. Rezensionen werden im Marktplatz-DB (rzx_mkt_reviews) als status='pending' gespeichert und nach Betreibergenehmigung veröffentlicht. Neuer GET /api/market/item/reviews?slug=... Endpunkt gibt nur genehmigte Rezensionen zurück. Domain wird teilweise maskiert (mys***.com).
Added
Bisherige Checkbox Nur kostenlos → 3-Wege-Toggle Alle / Kostenlos / Kostenpflichtig erweitert. Parameter paid=1 zur Markt-Catalog-API hinzugefügt (i.price>0). Aus der Suchleiste herausgezogen, vor den Ansicht-Toggle-Bereich verschoben und zusammen mit dem Sortier-Select in eine Header-Symbolleiste integriert.
Changed
Suchfeld-Rahmen border-2 border-emerald-300, grünes Hintergrundfeld beim linken Suchsymbol, Suchschaltfläche bg-emerald-500. Suchleiste vereinfacht – nur Schlüsselworteingabe verbleibt; Sortier- und Filterfunktionen in den Inhaltsheader verschoben.
Changed
| Status | Anzeige |
|---|
| Kostenlos | Installieren + Herunterladen |
| Kostenpflichtig (nicht gekauft) | Kaufen (Marktplatz PAY.JP-Zahlungsmodal) |
| Kostenpflichtig (gekauft) | Installieren + Herunterladen |
| Bereits installiert | „Installiert" |
Dieselbe Verzweigung auf alle 4 Listenansichten (Liste/Webzine/Karte/Raster) angewendet. Der Satz gekaufter Slugs wird beim Seitenaufruf einmal abgefragt und wiederverwendet. Zahlung erfolgt über Marktplatz POST /api/market/item/purchase mit PAY.JP-Abrechnung + Lizenzausstellung.
Changed
- •Ansichtsstil-Toggle: Textbeschriftungen entfernt → nur Icons +
title / aria-label (Barrierefreiheit beibehalten)
- •Typ-Badge:
bg-<color>-100 heller Hintergrund → bg-zinc-900/85 backdrop-blur-sm dunkle Transluzenz + farbiger Text (verbesserte Lesbarkeit über Bildern)
- •Screenshots-Abschnitt: unmittelbar nach Header → unter Tab-Inhalt verschoben, Anzahl wie im Marktplatz als
(n) angezeigt
- •
dark:prose-invert auf Detailseite funktionierte nicht → Typography-Plugin zu CDN Tailwind hinzugefügt
- •Beschreibungsbereich der Detailseite: gleicher Ansatz wie Marktplatz-Admin — HTML-Markup wird unverändert gerendert, nur gefährliche Elemente wie
<script>/<iframe>/<style>/onXX werden entfernt
Fixed
- •PAY.JP-Kartenformular nimmt keine Eingabe an: vorab im versteckten Zustand eingebunden, sodass iframe mit 0px gerendert wurde. Mit Lazy-Initialisierung +
requestAnimationFrame-Mount behoben
- •Widget-Thumbnail fehlt: 28 Widgets in der Marktplatz-DB registriert, aber nur 12 kostenlose Widgets in
/var/www/market/widgets/ kopiert. 14 fehlende synchronisiert. Absolute URL-Konvertierung für screenshots + automatische Filterung nicht vorhandener Dateien zur catalog/item API hinzugefügt
- •Bundle-Plugin-Autorisierungswarnung:
vos-autoinstall wurde als unauthorizedPlugins erkannt. Konstante BUNDLE_PLUGINS = ['vos-autoinstall', 'vos-marketplace'] zu LicenseStatus.php hinzugefügt, Filterung in active()/fromCache()/canUsePlugin() angewendet. Gleiche Behandlung im Lizenzserver verify.php
- •Möglichkeit doppelter Widget-Hinzufügungen:
install.php-Seeding verwendete nur INSERT IGNORE, aber rzx_page_widgets hat keine UNIQUE-Einschränkung, sodass Duplikate möglich waren. Auf DELETE FROM page_widgets WHERE page_slug='home' vor INSERT geändert (DB UNIQUE-Einschränkung nicht hinzugefügt, da absichtliche Duplikate für Board-Widgets etc. vorkommen)
Migration Notes
- •Menü/Routen/Migrationen des
vos-autoinstall-Plugins werden bei Neuinstallationen automatisch aktiviert (bestehende Installationen müssen es einmal im Adminbereich aktivieren)
- •Standard-TTL des Marktplatz-API-Caches: 30 Minuten → 5 Minuten (für schnellere Spiegelung von Preis-/Inhaltsänderungen)
- •Plugin-Einstellung
vos-autoinstall.cache_ttl ist neu
Changed
- •
browse.php: von lokaler DB-Abfrage auf Live-API-Aufruf an market.21ces.com/api/market/catalog umgestellt
- •
item-detail.php: von lokaler DB auf /api/market/item- und /api/market/item/versions-API-Aufrufe umgestellt
- •
CatalogClient.php: API-Basis-URL von /api/v1 → /api/market geändert, Antwortfeld items[] → data[] angepasst
Fixed
Problem: Im Layout-Anwendungsblock von market.21ces.com/index.php fehlte die Behandlung des $__noLayout = true-Falls, wodurch alle Plugin-API-Routen (api/market/*) HTTP 200 + leere Antwort zurückgaben.
Lösung: elseif ($__pageFile && $__noLayout) { include $__pageFile; } am Ende von index.php hinzugefügt. api/market/catalog, api/market/item, api/market/updates/check usw. funktionieren nun korrekt.
Added
sort-, free- und featured-Parameter zu plugins/vos-market/views/api/catalog.php hinzugefügt, mit erweiterten Antwortfeldern (sale_price, rating_avg, is_featured usw.).
Added
mpApiFetch()-Hilfsfunktion: minimiert Anfragen an den Marketplace-Server durch 30-minütigen TTL-Datei-Cache. Zeigt ein Fehlerbanner bei API-Antwortfehler an.
Fixed
Problem: Im AdminRouter wurde nach dem Erstellen einer $licenseClient = new LicenseClient()-Instanz und dem Versuch einer automatischen Registrierung die Aktualisierung von $_ENV['LICENSE_KEY'] nicht im internen $this->licenseKey der Instanz reflektiert — sodass ein check()-Aufruf innerhalb derselben Anfrage weiterhin unregistered zurückgab.
Changed
- •Wenn
$this->licenseKey beim Eintritt in check() leer ist, sofort /api/license/register aufrufen
- •Bei Erfolg:
$this->licenseKey aktualisieren + $_ENV['LICENSE_KEY'] aktualisieren + .env-Datei speichern, dann mit verify-Schritt fortfahren
- •Nur bei Misserfolg (keine Serverantwort)
unregistered zurückgeben
- •Neue
saveKeyToEnv()-Methode: ersetzt eine leere LICENSE_KEY=-Zeile (fehlgeschlagener install.php-Fall) durch den tatsächlichen Schlüssel; überspringt, wenn bereits ein gültiger Schlüssel vorhanden ist
Wirkung
- •Benutzer, die manuell ohne install.php installiert haben → Lizenz wird beim ersten Admin-Zugriff automatisch registriert
- •Benutzer, die von einer älteren Version aktualisiert haben (kein LICENSE_KEY) → automatische Registrierung beim ersten Admin-Zugriff nach dem Update
- •Die Dashboard-Meldung „Lizenz nicht registriert" wird jetzt nur angezeigt, wenn der Lizenzserver selbst nicht erreichbar ist
Fixed
Die Seed-Datei database/seeds/legal_pages.php enthielt Tailwind-CSS-Variablen (--tw-scale-x, --tw-pan-x usw., 400+), die inline im style=""-Attribut jedes <h1>/<h2>/<p>-Tags eingebettet waren. Bei jeder Installation verbreitete sich diese Verunreinigung in die DB und ließ die Seiten terms und privacy aufblähen (insbesondere privacy/ko erreichte 128KB; normal sind 2KB).
- •
database/seeds/legal_pages.php: 442KB → 131KB (70% Reduzierung, Syntax gültig)
- •26 bereits verunreinigte Zeilen in der Entwicklungs-DB bereinigt: 1,04MB → 56KB (988KB entfernt, −95%)
- •Neues
scripts/clean-inline-styles.php — Massen-Bereinigungstool für style="... --tw-* ..." (wiederverwendbar bei erneutem Auftreten)
Changed
Das .board-content-CSS enthielt Regeln, die jede Dokumentseite zwangsweise konvertierten, indem sie „h2 als Kartenüberschrift und h2+p als Karteninhalt" behandelten. Dies zerstörte die Hero-Struktur von Seiten, die direkt mit Tailwind gestaltet wurden (z. B. Brand).
- •103 Zeilen Card-Block-Regeln entfernt (149 → 45 Zeilen)
- •Verbleibende Regeln: Grundtypografie (p/h·/blockquote/code/ul/ol/table), OG-Linkkarte, Dark-Mode-Textüberschreibung
- •Ergebnis: Originaldesign der
Brand-Seite wiederhergestellt (linke blaue Linie bei h2, zentrierter Hero usw.)
- •Rechtliche Dokumente (terms/privacy usw.) werden durch Standard-
<h1><h2><p>-Typografie ausreichend dargestellt — Card-Styling war übermäßige Dekoration
Changed
Hintergrund: In 2.3.1 wurden die Seiteninhalte in rzx_page_contents für das koreanische Original und rzx_translations für Nicht-Koreanisch aufgeteilt, und in 2.3.2 wurde ein separater Speicherpfad im Editor hinzugefügt. Nach einer Design-Überprüfung stellte sich jedoch heraus, dass die beiden Tabellen im Wesentlichen dieselbe Struktur (slug/key + locale + content) haben, dabei aber folgende Kosten verursachen:
- •Koreanischer Originaltext wird in beiden Tabellen doppelt gespeichert (für das db_trans-Fallback-Chain-Mirroring)
- •Die Editor-Speicherlogik erfordert eine Verzweigung für ko vs. Nicht-ko
- •Die Anzeige des Locale-Status in der Seitenverwaltungs-UI erfordert einen JOIN über zwei Tabellen
- •Die ursprüngliche Begründung ("integrierte KI-Übersetzungs-Pipeline-Queue") hat in der Praxis kaum Wert, da lange Seitentext-HTML (10 KB) und kurze UI-Zeichenketten (20 Bytes) unterschiedliche Workflows (Chunk-Aufteilung, Tag-Erhaltung usw.) erfordern
Wiederhergestellte Struktur: Einzeltabelle rzx_page_contents, eine Zeile pro Locale (ursprüngliches Design)
Migration
- •
rzx_translations.page.{slug}.title/content × 7 Slugs × 12 Nicht-ko-Locales (168 Zeilen) → in rzx_page_contents wiederhergestellt
- •Alle
page.*-Schlüssel aus rzx_translations gelöscht (234 Zeilen)
- •Ziele: Brand, terms, privacy, refund-policy, tokushoho, funds-settlement, data-policy
- •Auf Entwicklungs- und Produktionsdatenbank angewendet
Changed
- •
resources/views/admin/site/pages-edit-content.php — ko/Nicht-ko-Verzweigung entfernt, einfaches UPSERT
- •
resources/views/admin/site/pages-document.php — dasselbe
- •
resources/views/customer/page.php — db_trans('page.*.title/content') entfernt, liest direkt aus page_contents (Fallback-Kette locale → en → ko bleibt erhalten)
- •
resources/views/admin/site/pages.php — Seitenlistentitel werden ebenfalls direkt aus page_contents.title gelesen
Kept
rzx_translations selbst wird beibehalten — weiterhin genutzt für:
- •Foren (
board_post.{id}.title/content)
- •UI-Zeichenketten (
menu.*, Einstellungsbezeichnungen)
- •Seiten-SEO-Meta (
page.{slug}.browser_title|meta_keywords|meta_description) — kurze Zeichenketten, hier passend
Grundsatz: Kurze UI-/Meta-Zeichenketten → rzx_translations; langer Seiteninhalt → rzx_page_contents, getrennte Speicherung je nach Dateneigenschaften.
Changed
Nachdem in 2.3.1 die Seiteninhalt-Speicherstruktur auf Original-ko (rzx_page_contents) + Übersetzungs-DB (rzx_translations) migriert wurde, schrieb der Admin-Editor weiterhin alle Locales nur in rzx_page_contents — dies führte zu einem Widerspruch mit dem Migrationsformat und Abfragefehlern von db_trans() auf der Render-Seite. Dieses Release behebt das Problem.
Verzweigungsregeln (Quell-Locale = $_ENV['DEFAULT_LOCALE'] ?? 'ko'):
| locale | Speicherziel |
|---|
ko (Quelle) | rzx_page_contents + Spiegelung nach rzx_translations (Fallback für db_trans()) |
en/ja/zh_CN/... | nur rzx_translations (page.{slug}.title, page.{slug}.content) |
Beim Speichern eines Nicht-Quell-Locales wird automatisch eine Stub-Zeile erstellt, wenn keine Quell-Zeile in rzx_page_contents vorhanden ist (zur Beibehaltung von Menü-/Einstellungsverbindungen). is_active wird einheitlich auf die Quell-Zeile angewendet.
Changed
Beim Öffnen einer Nicht-Quell-Locale-Bearbeitungsseite:
1. Zuerst page.{slug}.title/content + locale aus rzx_translations abfragen
2. Falls nicht gefunden, Fallback auf veraltete rzx_page_contents-Zeile (Kompatibilität mit bei der Migration übergangenen Seiten)
Für das Quell-Locale wird wie bisher nur rzx_page_contents verwendet.
Changed
- •Seitenlöschung: auch
rzx_translations WHERE lang_key LIKE 'page.{slug}.%' löschen
- •Slug-Änderung: Massen-UPDATE
page.{old_slug}. → page.{new_slug}. in rzx_translations.lang_key
Changed
Die bisherige Methode, in rzx_page_contents pro Locale eine vollständige Inhaltszeile zu speichern, wurde auf die Methode Originaldaten ko + Übersetzungs-DB (rzx_translations) vereinheitlicht. Gewährleistet strukturelle Konsistenz mit dem Board-Speicherformat (board_post.*).
Betroffene 7 Seiten: Brand, terms, privacy, refund-policy, tokushoho, funds-settlement, data-policy
Before:
rzx_page_contents
├── Brand / ko (vollständiger Inhalt)
├── Brand / en (vollständiger Inhalt)
├── ... (13 Locale-Zeilen)
After:
rzx_page_contents
└── Brand / ko (1 Originalzeile)
rzx_translations
├── page.Brand.title × 13 locale (inkl. ko)
└── page.Brand.content × 13 locale
Migrationsergebnis:
- •
rzx_page_contents: 7 Slugs × 12 Nicht-ko-Zeilen = 84 Zeilen gelöscht
- •
rzx_translations: 7 Slugs × 13 Locales × (title + content) = 182 Zeilen migriert
- •Auf Entwicklungs- und Produktions-DB angewendet, Rendering-Validierung bestanden (je Locale korrekte Anzeige für ko/en usw.)
Changed
- •„Neue Seite"-Kopfzeilenbutton entfernt — war ein nicht funktionierender Platzhalter. Seiten werden über die Menüverwaltung als einziger Wahrheitsquelle erstellt.
- •Papierkorb-🗑-Symbol + AJAX-Handler +
deleteUserPage() JS entfernt — Seiten werden beim Löschen des Menüs gemeinsam bereinigt, ein eigenständiger Seitenlöschpfad ist daher unnötig. Verhindert fehlerhafte Menüs durch versehentliches Löschen.
- •Beibehalten: Einstellungen ⚙ · Bearbeiten ✏ · Vorschau 👁 Symbole
Fixed
- •
Einstellungen > Website > Logo-Bild-Upload schlägt fehl: move_uploaded_file() scheiterte lautlos wegen fehlendem Unterverzeichnis storage/logos/. Automatische Unterverzeichniserstellung zum Upload-Handler hinzugefügt + Verzeichnis auf Entwicklungs- und Produktionsservern erstellt (www-data:www-data, 775).
- •Layout-Logo-Priorität wiederhergestellt: kurzzeitig auf „Seiteneinstellungen zuerst" umgekehrt, dann entsprechend den Anforderungen „layoutspezifisches Logo" auf Layout > Site-Fallback zurückgesetzt. Ist kein Logo im Layout gesetzt, wird das Site-Logo automatisch verwendet.
- •Betrifft:
skins/layouts/{default, minimal, modern, modern-copy-260413}/header.php und footer.php
Fixed
- •Nur den ältesten Eintrag für
bi-guide / logo-guide Slug-Duplikate behalten (id=186, 187), Duplikate id=193, 194 gelöscht
- •Auf Entwicklungs- und Produktionsumgebung angewendet. Der Duplikat-INSERT-Bug in der Menü-API wurde bereits in v2.3.0 behoben
Added
Logo-Assets unter /var/www/_upload/ erstellt — bei Bedarf in die Produktion hochladen:
Icon (nur Markenzeichen)
- •
voscms-logo-color-{256,512,1024}.png · Farbe (deep·ocean·sky·ocean + Mitte deep)
- •
voscms-logo-mono-{256,512,1024}.png · sky einfarbig + Deckkraft 1/0.7/0.48/0.7 Verlauf
Horizontales Wortmarke (für Header) — 820×256 Verhältnis
- •
voscms-wordmark-{128h,256h,512h}.png · hell (Vos deep + CMS grau)
- •
voscms-wordmark-dark-{128h,256h,512h}.png · dunkel (Vos sky + CMS slate-300)
Vertikales Wortmarke (für App-Icon / OG-Bild) — 360×420 Verhältnis
- •
voscms-stacked-light-{256h,512h,1024h}.png
- •
voscms-stacked-dark-{256h,512h,1024h}.png
Alle SVG-Originale erhalten. librsvg2-bin installiert und stellt rsvg-convert CLI bereit. OKLCH-Farbunterstützungsproblem mit Hex-konvertierter Version (voscms-logo-mono-hex.svg) gelöst.
Added
- •DB-Tabelle
rzx_changelog neu — unabhängige Datensätze pro Version × Locale, Tracking von translation_source (original/ai/manual) + source_hash
- •Parser
RzxLib\Core\Changelog\ChangelogParser — Keep-a-Changelog-Standard + interne Abschnitts-Whitelist (Infrastructure/Internal/Refactor/Chore/Docs/Test sind privat)
- •Importer
ChangelogImporter — idempotentes Zusammenführen, Schutz manueller Übersetzungen, Änderungserkennung über content_hash
- •CLI-Skript
scripts/import-changelog.php — Optionen --file --locale --dry-run --silent, SemVer-Pre-Release-Unterstützung (2.1.1-hotfix)
- •Übersetzungsschnittstelle
RzxLib\Core\Translate\{TranslatorInterface, NullTranslator, TranslatorFactory} — nach GPU-Bereitstellung von Gemma 4 (ai.21ces.com) durch einfache Änderung des Treibers in config/translator.php aktivierbar
- •Systemseite
/changelog registriert (config/system-pages.php), Frontend-Ansicht resources/views/system/changelog/index.php
- •Dediziertes Skin
skins/page/changelog/skin.json — Kartenstile (filled/outlined/flat), abschnittsweise Farben, Versions-Badge, Datumsformat, relative Zeitanzeige, Umschalter für interne Abschnitte
- •Bearbeitungsseite
/changelog/edit ausgelagert — MD-Upload-Vorschau, mehrsprachige Abdeckungsmatrix, versionsweises Ein-/Ausblenden und Löschen, KI-Übersetzungsschaltfläche (in Vorbereitung)
- •Deployment-Automatisierung — Schritt
1.5/5 Changelog import zu deploy-voscms.sh hinzugefügt: automatische Erkennung und Zusammenführung von ko + 12 Locale .md-Dateien
- •Übersetzungsschlüssel
site.pages.changelog für 13 Locales hinzugefügt
Changed
- •Tab-Reihenfolge neu angeordnet:
[Grundinfo] [Berechtigungen] [Erweitert] [Skin] — Systemseiten können am Ende eigene Tabs hinzufügen
- •
settings_tabs-Schema eingeführt (config/system-pages.php) — Systemseiten deklarieren ein Top-Level-Tab-Array; jeder Eintrag wird dynamisch über key/label/icon/view gerendert. Altes settings_view-Bottom-Include-Legacy entfernt
- •Grundsatz etabliert: Einstellungen = Aussehen + Funktion / Bearbeiten = Daten — Datenverwaltungs-UIs wie Upload, Version und Übersetzung werden in
/changelog/edit ausgelagert
- •MERGE-Speicherstrategie —
save_settings-Handler führt mit bestehenden Einstellungen zusammen. Daten anderer Tabs werden nicht gelöscht, auch wenn Tabs aufgeteilt sind
- •
saveSettings() JS — sendet nur im DOM vorhandene Felder. Sicher, wenn einige Felder in einer Tab-Umgebung nicht gerendert werden
- •Position der Layout-/Skin-Karte — zurück in den Grundinfo-Tab verschoben (Benutzerfeedback berücksichtigt). Der Skin-Tab ist ausschließlich für skin.json-Variablen zuständig
- •Dopplung der Seitenbreite entfernt —
page_width-Feld aus dem Grundinfo-Tab entfernt (in content_width des Skins zusammengeführt)
- •Vereinfachung der sekundären Tabs in service/order —
general/domain/hosting/addons aus config/service-settings-tabs.php in settings_tabs migriert und zu Top-Level-Tabs hochgestuft
Changed
- •
/{slug}/settings und /{slug}/edit erkennen jetzt config/system-pages.php — bisher wurde nur die rzx_page_contents-DB abgefragt, was bei Systemseiten zu 404-Fehlern führte. Jetzt wird in der Reihenfolge DB → config abgefragt
- •
edit_view-Feld eingeführt — direkter Pfad zur Bearbeitungsansichtsdatei für Systemseiten. Klick auf /{slug}/edit lädt die entsprechende Ansicht direkt (Admin-Redirect-Hop entfernt)
- •pages-settings.php-Fallback — Systemseiten ohne DB-Datensatz erstellen
$pageData jetzt aus der Konfiguration, um eine Weiterleitung zur Seitenmanagementliste zu verhindern
- •Admin-Icon-URL vereinheitlicht —
/{slug}/settings und /{slug}/edit verwenden die standardmäßige Frontend-URL
Fixed
- •
menus-api.php: fehlende Duplikatprüfung vor INSERT für den external-Seitentyp behoben — verhindert doppelte Zeilen in rzx_page_contents beim zweifachen Klick auf „Menü speichern"
- •Fehlende Bereinigung von external-Typ + Widget-
page_contents beim Löschen eines Menüs behoben — verhindert verwaiste Datensätze
Fixed
- •Titelhintergrund (
title_bg_type, title_bg_image, title_bg_video, title_bg_overlay, title_text_color), show_title, show_breadcrumb, custom_css, custom_header_html, custom_footer_html — alle Standard-Seiten-Skin-Variablen werden jetzt in der öffentlichen Ansicht berücksichtigt
- •
_page-title-bg.php-Partial akzeptiert jetzt die Variable $_contentWidth — der Titelbereich folgt der Inhaltsbreite
- •Admin-Icon vom Titel getrennt — eigenständig oben rechts im Inhaltsbereich platziert; auch bei
show_title=0 immer sichtbar
- •20px oberen Abstand über dem Titelbereich hinzugefügt (Ausgewogenheit des Hintergrundlayouts)
Added
- •
site.pages.contact-Übersetzungsschlüssel für 13 Locales hinzugefügt (ko/en/ja/zh_CN/zh_TW/de/es/fr/id/mn/ru/tr/vi) — behebt bisherige Auslassung
- •Seitenmanagement-Systemleitfaden
docs/PAGE_ADMIN_GUIDE.md neu — dokumentiert Tab-Struktur, Schema, Routing, Berechtigungen und Erweiterungsmethoden
Added
- •Felder pro Element: Zahl, Suffix, Label (mehrsprachig), Symbol und Farbe
- •Admin-Widget-Builder unterstützt Hinzufügen/Bearbeiten/Löschen von Elementen (neue Bearbeitungs-UI für den Typ
stat_items)
- •16 Symboltypen (users, chart, star, heart, check-circle, clock, calendar, globe, shield, lightning, trophy, cart, dollar, building, chat) + 10 Farboptionen
- •Hochzähl-Animation beim Eintreten in den Viewport — IntersectionObserver + easeOutCubic 1.4s
- •Nur numerische Werte werden hochgezählt (Zeichenketten wie
24/7 werden unverändert angezeigt), Kommaformatierung und Dezimalstellen bleiben erhalten
- •
widget.json v1.1.0 → v1.2.0
Fixed
- •Fehler behoben, bei dem
admin_name mit dem Präfix enc: gespeichert und ohne Entschlüsselung angezeigt wurde
- •Fehler behoben, bei dem die Avatar-Abfrage fälschlicherweise eine nicht vorhandene
staff-Tabelle per LEFT JOIN verknüpfte — jetzt direkte Abfrage von rzx_users.profile_image gemäß der vereinheitlichten Struktur admin_id = users.id
- •Relative Avatarpfade erhalten automatisch ein baseUrl-Präfix
Added
- •Schaltflächen
[Vorschaubild abrufen] [Screenshot abrufen] werden automatisch neben jedem <input type="url">-Feld (einschließlich erweiterter Variablen vom Typ url) in allen Boards eingefügt
- •Vorschaubild: natives Rendering bei 1280×960 → 800×600 Ausgabe (Viewport des ersten Bildschirms)
- •Screenshot: natives Rendering bei 1280×volle Seite → 800×skaliert Ausgabe (gesamte Scrollseite, tatsächliche Seitenhöhe)
- •Schrittweise Fortschrittsanzeige-UI —
Serververbindung → Seite laden → Bildschirm aufnehmen → Bild erstellen → Datei speichern → Warte auf Antwort
- •Automatische Festlegung des aufgenommenen Vorschaubilds als Hauptbild — als
board_files.is_primary=1 markiert, vom board-showcase-Widget bevorzugt
- •Neue Route
/board/api/url-capture?type={thumbnail|screenshot}&url=... + api-url-capture.php-Proxy
- •
set_primary-Aktion zu /board/api/files hinzugefügt — legt einen vorhandenen Anhang als Hauptbild fest
Changed
- •Anhang-Bildabfrage
ORDER BY is_primary DESC, id ASC — aufgenommene Vorschaubilder werden zuerst angezeigt
- •Parameter
primary_file_pos beim Erstellen eines Beitrags an den Server übermittelt, um den Index der Hauptdatei anzugeben
v2.2.0
2026-04-18 · vor 6 Monaten
Marketplace-Trennung
Changed
- •Marketplace-Produkttrennung: Die vom Plugin
plugins/vos-marketplace/ gemeinsam genutzte Funktionalität wurde als eigenständiges Produkt ausgegliedert → github.com/THEVOSjp/Marketplace neues Repository, unabhängiges Deployment unter market.21ces.com
- •Das Plugin behält nur die „kundenseitige Oberfläche (Durchsuchen, Kaufen, Installieren, Lizenzieren)" — Daten, Verkäufer und Abrechnungen werden ausschließlich vom Marketplace-Server verwaltet
- •API-Integrationspunkte auf der Core-Seite aktualisiert
Added
- •Sprachauswahl-Modal — Hinweis zur Notwendigkeit der Sicherung von
.env + DB + storage/uploads/ und Warnung, dass bei Verlust des APP_KEY die Entschlüsselung nicht möglich ist
- •Zweistufige Bestätigung: Checkbox + Bestätigungsschaltfläche (bedingungslose Installation verboten)
- •Vollständige Übersetzungen für alle 13 Sprachen hinzugefügt (
backup_title/body/item_env/db/uploads/warn/check/confirm/cancel)
Added
- •
scripts/register-widgets-to-marketplace.php — registriert 28 dateibasierte Widgets in einem Schritt in rzx_mp_items
Changed
- •
plugins/vos-marketplace/src/CatalogClient.php — Standard-API-URL auf https://market.21ces.com/api/v1 geändert, fetchItem()-Pfad aktualisiert, checkUpdates()-Abfrageformat aktualisiert
- •
plugins/vos-marketplace/plugin.json — Standardwert marketplace_api_url aktualisiert
- •
rzxlib/Core/Modules/WidgetLoader.php — Thumbnail-URL enthält jetzt ?v={mtime} Cache-Buster (für Cloudflare Immutable Cache)
Fixed
- •
widgets/feature-tour/widget.json — Felder bereinigt
- •Thumbnails einiger Widgets aktualisiert (staff, testimonials, feature-tour, shop-map, shop-ranking, stylebook)
v2.1.5
2026-04-17 · vor 6 Monaten
Added
- •contact-info (v0.1.0) — Kontaktkarte (Adresse/Telefon/E-Mail/Öffnungszeiten + Bild + kleine Karte)
- •location-map (v0.1.0) — horizontale Karte (Google Maps + 3-spaltige Info unten, einstellbare Breite)
Added
- •Vollständige Überarbeitung der Artikeleinreichungsseite — 3 Tabs (Basisinformationen / Release / Verkauf)
- •Lizenz (GPL/LGPL/BSD/MIT/CC/PD/kommerziell), Repository-URL, Demo-URL, abhängige Plugins, Bannerbild
- •Release-Historie, Verkaufsinformationen (öffentlich/kostenpflichtig-Toggle, Rabattpreis/Enddatum), UX-Verbesserungen
Added
- •Entwicklermenü (ID:20) in 13 Sprachen, Hero CTA description/typing_words in 12 Sprachen ergänzt
Changed
- •Widget-Namensunterscheidung geklärt (Karte / Kontaktkarte),
page.php fullWidthTypes hinzugefügt
- •contact-form Kategorie → nur Beschriftung (Code entfernt, Widget-Einstellungen bearbeitbar)
Fixed
- •board-contents/board-showcase: file_type → mime_type
- •boards-api: fehlende is_shown_in_list + options JSON-Einschränkung
- •contact-form POST: vollständige ob-Puffer-Leerung
- •Hero CTA: typing_words/description
\n doppeltes Escaping
DB Changes
- •rzx_mp_items: license, repo_url, demo_url hinzugefügt
- •rzx_board_extra_vars: is_shown_in_list hinzugefügt
- •rzx_contact_messages: neue Tabelle
v2.1.4
2026-04-17 · vor 6 Monaten
Added
- •download-hero-Widget — Software-Download-Seite (Live-Integration mit version.json, 4 eingebaute Sprachen, Hauptfunktionen / Systemanforderungen / Versionsverlauf)
- •/downloads-Seite — Widget-Typ-Systemseite, 13-sprachige Menüübersetzungen,
is_system=1
- •contact-form-Widget (v0.1.0) — privates 1:1-Kontaktformular-Widget (für Gäste geeignet, Kategorieauswahl, Honeypot-Spam-Schutz, AJAX-Übermittlung)
- •contact-info-Widget — Kontaktinformations-Anzeige-Widget
- •location-map-Widget — Standortkarten-Widget
- •rzx_send_mail() gemeinsamer Helfer — neue SMTP-E-Mail-Versandfunktion in
rzxlib/Core/Helpers/mail.php
- •rzx_contact_messages-Tabelle — DB-Tabelle zur Speicherung von Anfragen
- •/contact-Seite — Widget-Typ-Systemseite, 13-sprachige Menüübersetzungen
Fixed
- •Schutz vor dem Löschen von Systemseiten — Seiteninhalte/Widgets bleiben erhalten, wenn eine Systemseite aus dem Menü entfernt wird (nur der Menüeintrag wird gelöscht)
- •
menus-api.php: Doppelprüfung über DB is_system + config/system-pages.php Slug
- •
menus-js.php: zeigt den Hinweis „Wird nur aus dem Menü entfernt" beim Löschen einer Systemseite
- •Mehrsprachige Systemseiten-Menüs — beim Hinzufügen einer Systemseite zum Menü werden 13-sprachige Labels automatisch aus den
site.pages.*-Übersetzungsschlüsseln registriert
- •Downloads-Seiten-Übersetzung —
site.pages.downloads-Übersetzungen für 13 Sprachen hinzugefügt
Changed
- •Homepage-Hero — Download-Schaltfläche → direkter Download unter
/download/voscms-latest.zip, Version auf v2.1.1 aktualisiert
- •Auth.php — ruft zuerst den gemeinsamen Helfer
rzx_send_mail() auf, bevor auf sendSmtpMail zurückgegriffen wird
- •index.php — automatisches Laden des
mail.php-Helfers hinzugefügt
v2.1.3
2026-04-17 · vor 6 Monaten
Changed
- •Hosting-Tab — Zusammenfassungskarte + Nutzungs-Fortschrittsbalken + FTP/DB-Verbindungsinfo-Tabelle (wird automatisch angezeigt, wenn vom Admin konfiguriert)
- •Domain-Tab — Domain-Karte + Haupteinstellung + Nameserver-Info-Tabelle (wird automatisch angezeigt, wenn vom Admin konfiguriert)
- •Mail-Tab — Mailserver-Informationen (IMAP/SMTP) + Karte pro Konto + Passwort-Inline-Änderung
- •Wartungs-Tab — Info-Karte + geplantes Datum + Arbeitshistorie (wird automatisch angezeigt, wenn vom Admin eingetragen)
- •Zusatzleistungen-Tab — einheitliches Karten-Layout
- •Einheitliche Informationsstruktur entsprechend dem Admin-Partial (Admin gibt in Metadaten ein → automatisch in Meine Seite übernommen)
Changed
- •Aktivitätsprotokoll-Bereich von 1/3 auf 1/5 Verhältnis reduziert
- •Hardcodierung des NS-Standardwerts im Admin-Domain-Tab entfernt (zur Vorbereitung der Cloudflare-API-Integration)
Changed
- •Provisioning-Workflow vollständig überarbeitet: Subdomain zuerst → gekaufte Domain wird anschließend verbunden
- •Provisioning-ID-Regel: Subdomain-Name oder SLD der gekauften Domain
- •Cloudflare-Wildcard-Tunnel genutzt (kein Hinzufügen von Subdomain-A-Records erforderlich)
- •Server-2-Festplattenkonfiguration geändert: NVMe 256 GB + SSD 2 TB + HDD 8 TB (3-Disk-Aufbau)
v2.1.2
2026-04-16 · vor 6 Monaten
Added
- •Service-Klassifizierungssystem —
service_class-Spalte hinzugefügt (recurring/one_time/free), completed_at Abschlussdatum für Einmalservices
- •Mein-Seite Service-Detail —
/mypage/services/{order} Tab-Verwaltung nach Typ (Hosting/Domain/Mail/Wartung/Zusatzservices)
- •Service-Management-API —
api/service-manage.php (Auto-Verlängerungs-Toggle, Verlängerungsantrag, Hauptdomain-Einstellung, Mail-Passwortänderung)
- •Admin-Auftragsverwaltung —
/admin/service-orders Auftragsliste + Detailseite, Einmal-Status-Modal (Eingegangen/In Bearbeitung/Ausstehend/Abgebrochen/Abgeschlossen)
- •Admin-Menü — „Service-Aufträge"-Menü zur Seitenleiste hinzugefügt (position: 65)
Added
- •phone-display — Telefonnummer-Anzeigekomponente (serverseitiger
format_phone()-Helfer), keine JS-Abhängigkeit
- •format_phone() — PHP-Funktion zur Formatierung internationaler Telefonnummern (Korea/Japan/USA/China/UK/Frankreich/Deutschland/Australien usw.)
- •Kostenlose Domain-Einrichtung — Verwaltung der kostenlosen Subdomain-Liste in den Admin-Einstellungen (
service_free_domains), Unterstützung für mehrere Domain-Selects
Fixed
- •Fehlende Abonnements für kostenlose Services — Kostenlose Bestellungen erstellten keine Abonnement-Datensätze für Domain/Zusatz/Wartung etc. → Refactoring zur Massenerstellung aller Services
- •Zahlungsbereich AGB-Zustimmung — AGB-Checkbox wurde bei kostenlosen Bestellungen zusammen mit dem Zahlungsbereich ausgeblendet → außerhalb des Abschnitts getrennt
- •updateSubmitButton isFree-Erkennung —
btn.closest('form') NULL → mit document.querySelector korrigiert
- •Admin-Seitenleiste aktiver Indikator —
$adminPath undefiniert führte dazu, dass alle Menüs inaktiv waren → Variablendeklaration hinzugefügt
- •Mein-Seite Avatar — fehlendes
use Auth + $user = Auth::user() in services.php/service-detail.php
- •Zusatzservice Einmal-Prüfung —
one_time-Flag in den Admin-Einstellungen wird jetzt korrekt bei der Bestellung in service_class übernommen
- •Einmalservice Anfangsstatus — wird jetzt als
pending (eingegangen) statt active erstellt
Changed
- •Bestellungs-API-Refactoring — Abonnement-Erstellungscode der 3 Zahlungswege (kostenlos/Karte/Banküberweisung) in gemeinsame Funktion
$subscriptionData + _insertSubscriptions() konsolidiert
- •Service-Listen-UI — Inline-Aufklappen → Karten-Link + separate Detailseite
- •Telefonnummernanzeige —
format_phone() auf Profil/Mitgliederliste/Mitarbeiterliste angewendet
- •Kostenlose Domain-Dynamisierung —
.21ces.net Hartcodierung → Referenz auf Admin-Einstellungswert
v2.1.1-hotfix
2026-04-16 · vor 6 Monaten
Fixed
- •Footer-Menü 404-Fehler — fehlende Daten für rechtliche Seiten (terms, privacy, refund-policy, data-policy, tokushoho, funds-settlement) in der Tabelle
rzx_page_contents → aus test-DB wiederhergestellt
- •Widget-Builder Bild-/Videoupload-Fehler — behoben:
FormData-POST vom Front-End-Wrapper (page-widget-builder.php) wurde nicht an den AJAX-Handler übergeben (Datei-Upload-Bedingung hinzugefügt + ob_end_clean/exit-Behandlung)
- •Upload-Verzeichnisberechtigungen — Eigentümer von
storage/uploads/widgets/ auf www-data geändert, um PHP-FPM-Schreibzugriff zu gewährleisten
Added
- •Mehrsprachige Serviceantragsmenüs —
menu_item.19.title-Übersetzungen für 13 Sprachen in der Tabelle rzx_translations hinzugefügt
- •Hero-CTA-Widget mehrsprachig — 13-sprachige Übersetzungen für Title, Subtitle und Button-Text des Dev-Seiten-Hero-Banners angewendet
- •Upload-Status-Vorschau — visuelles Feedback beim Bild-/Videoupload hinzugefügt: In Bearbeitung (Spinner), Erfolg (Häkchen) und Fehler (Fehlermeldung)
v2.1.1
2026-04-12 · vor 6 Monaten
Added
- •Schritt 0 Sprachauswahlbildschirm — Auswahl aus 13 Sprachen vor Installationsbeginn; gesamte UI erscheint ab da in der gewählten Sprache
- •Installationsübersetzungsdateien getrennt —
resources/lang/install.php (13 Sprachen × 45 Zeichenketten)
- •Mitgliedsstufe mehrsprachig — Normal/Silver/Gold/VIP automatisch in 13 Sprachen generiert
Added
- •config/admin-menu.php — Core-Admin-Menü in Konfigurationsdatei ausgelagert (bei Core-Updates erhalten)
- •admin-sidebar.php refaktoriert — 731 Zeilen hartcodiert → ~200 Zeilen dynamischer Renderer (config + plugin.json basiert)
- •vos-shop plugin.json — hartcodiertes Menü in das
menus.admin-Format migriert
Added
- •Slide-in-Menü — Mobil: Avatar+Name-Umschalt-Leiste → linkes Slide-in-Overlay (300ms ease-out)
- •Fade-Dimm-Hintergrund — schließen durch Klick auf Hintergrund oder X-Schaltfläche; Body-Scroll gesperrt
Added
- •force_locale — Standardsprache erzwingen (
?lang=xx-Parameter erlaubt Benutzeränderung)
- •default_language — install.php ↔ Translator-Konfigurationsschlüssel vereinheitlicht
- •URL-Parameter —
?lang=xx wird zuerst erkannt, in Session/Cookie gespeichert
Fixed
- •FAQ-Skin nicht angewendet — Migrations-SQL führte ein nacktes
INSERT für das Standard-Board vor install.php aus, wodurch das INSERT IGNORE stillschweigend ignoriert wurde; behoben
- •translations-Tabelle source_locale fehlend — Spalte in Core-Migration fehlend → db_trans() komplett fehlgeschlagen → Benutzerinfo/Menü/i18n nicht angezeigt; behoben
- •Einstellungs-Tab Seitenleiste aktiver Indikator —
route_prefix-Attribut hinzugefügt, damit das Einstellungsmenü auf allen Einstellungs-Sub-Routen aktiv bleibt
- •Installationssession-Rückstand-Bug — bei einer Neuinstallation ohne .env ließ eine veraltete PHP-Session Schritt 0 überspringen; behoben
- •nginx 403 — Konflikt zwischen physischem admin/-Verzeichnis und Route behoben (
try_files $uri/ entfernt)
- •Versionsnummer im Obfuscierungsskript hartcodiert — obfuscate.php liest Version jetzt dynamisch aus version.json
Changed
- •Grid-/board-contents-Widget-Mehrsprachansicht — rzx_translations-Suche hinzugefügt (aktuelles Locale → Englisch-Fallback)
- •Website-Branchenkategorien — von 15 auf 26 erweitert (hinzugefügt: Unternehmen, Einkaufszentrum, Recht, Buchhaltung, IT, Medien usw.; 13 Sprachen)
- •Grid-Widget-Einstellungen — grid-section render.php auf nativen Zelltyp (
board-list) geändert; 13-sprachiger Titel
- •Schritt 4 Sprachauswahl — von 5 auf 13 Sprachen erweitert; mit Installationssprache vorausgefüllt
- •Zeitzonenauswahl — auf 12 Zeitzonen für 13 Sprachbenutzerregionen erweitert
v1.26.0
2026-04-01 · vor 7 Monaten
Added
- •Bundle-(Set-)Dienste in 3 Spalten oben in der Dienstauswahl — Bernsteinfarben-Thema zur visuellen Unterscheidung von Einzeldiensten
- •SET-Badge, Veranstaltungsrabatt-Label, enthaltene Dienstnamen, Bundle-Preis, Originalpreis durchgestrichen, Rabattrate
- •Bundle-Auswahl wählt automatisch alle enthaltenen Dienste (Preis als Bundle-Preis berechnet)
- •Im Bundle enthaltene Dienste können nicht einzeln umgeschaltet werden (verhindert falsche Preisberechnung)
- •Nennungsmodus:
rzx_staff_bundles-Tabelle für mitarbeiterspezifische Bundle-Filterung
- •
bundles-Parameter an die Bestätigungsseite übergeben
- •Mehrsprachige Unterstützung: Bundle-bezogene Kiosk-Übersetzungsschlüssel für 13 Sprachen hinzugefügt
Added
- •Ansichtsumschalter —
[Monat] [Woche] [Tag]-Umschalter in der oberen Leiste (aktiver Zustand: blau)
- •Wochenansicht — links vertikal = Wochentag, oben horizontal = Zeitachse
- •Horizontales Scrollen, Reservierungsblöcke als Zeitbalken dargestellt
- •Lane-Algorithmus: erkennt Zeitüberschneidungen und platziert automatisch darunter, variable Zeilenhöhe
- •Linke Seitenleiste ↔ Gitter vertikales Scrollen synchronisiert
- •Tagesansicht — horizontal = Zeitachse, vertikal = Lanes (gleiche Methode wie Wochenansicht)
- •Geschäftszeitenbasierter Zeitbereich — basiert auf
business_hour_start/business_hour_end-Einstellungen; erweitert sich automatisch für Reservierungen außerhalb des Bereichs
- •Leerzellen-Klick-Zeitübergabe — in Wochen-/Tagesansicht: Klick-X-Koordinate → 15-Minuten-Einheit-Zeitberechnung → Startzeit im Reservierungsmodal automatisch ausgefüllt
- •Obere Navigationsleiste fixiert —
overflow-x-hidden + sticky angewendet; bleibt beim horizontalen Scrollen im Viewport
Added
- •Admin > Einstellungen > Allgemein — Benutzeroberfläche zur Einstellung von Geschäftsbeginn/-endzeit hinzugefügt
- •
business_hour_start, business_hour_end DB-Einstellungsschlüssel
- •Im Standard-Zeitbereich der Kalender-Wochen-/Tagesansicht angewendet
Fixed
- •POS
add-service fehlende Felder — start_time, end_time, staff_id, designation_fee, notes Übergabe hinzugefügt (zuvor: serverseitige Zeit hart kodiert, Mitarbeiter/Notizen fehlten)
- •end_time Mitternachts-Überschreitung verhindert —
% 24 → min(23:59) Obergrenze in ReservationHelper, start-service-API und Buchungsformular calcEnd() angewendet
- •POS In-Nutzung-Beurteilung Mitternachtsüberschreitung —
CustomerBasedAdapter behandelt end_time < start_time als Mitternachtsüberschreitung
- •Buchungs-Bundle-Validierung — korrigiert, um Reservierungserstellung zu ermöglichen, wenn nur ein Bundle ausgewählt ist
Changed
- •Tab-Namensänderungen: Empfang / Empfangsliste / Reservierungen
- •Empfangsliste:
walk_in, pos, kiosk, admin Quellen — alle Status angezeigt
- •Reservierungen:
phone, online Quellen — alle Status angezeigt
- •Sortierreihenfolge: Wartend → Bestätigt → In Nutzung → Abgeschlossen → Nicht erschienen → Storniert; innerhalb desselben Status nach Zeit sortiert
- •Abgeschlossen/Storniert/Nicht-erschienen-Zeilen: mit
opacity-50 blasser dargestellt, nicht zugeordnetes Badge angezeigt
Changed
- •Abgeschlossen-Badge: von Grau → Grün geändert
- •Storniert/Nicht-erschienen-Badges hinzugefügt (ausgeblendet, wenn Anzahl 0)
Added
- •Karten-Unterseite: Nicht-erschienen-Schaltfläche für Karten im Wartestatus hinzugefügt (Verbotssymbol), Stornieren-Schaltfläche rot
- •Detail-Modal: Nicht-erschienen-Aktionsschaltfläche für
pending und confirmed Status angezeigt
- •Gruppen-Sammel-Nicht-erschienen:
POS.noShowAllServices()-Funktion hinzugefügt
Fixed
- •Reservierungsdetail Zurück-Navigation —
<a href="/reservations"> → history.back(), kehrt zur vorherigen Seite zurück
- •Mehrsprachig: Kalenderansicht-Umschalter (Monat/Woche/Tag), Bundle, Geschäftszeiten-Schlüssel für 13 Sprachen hinzugefügt
v1.25.0
2026-04-01 · vor 7 Monaten
Architecture
- •POS als eigenständige Plugin-Struktur ausgegliedert
- •
resources/views/admin/reservations/pos-*.php → verschoben nach resources/views/admin/pos/
- •POS-Funktion wird anhand des Vorhandenseins des
pos/-Verzeichnisses automatisch aktiviert/deaktiviert (is_dir()-Prüfung)
- •Seitenleistenmenü: POS-Menü wird automatisch ausgeblendet, wenn
pos/-Verzeichnis fehlt
- •
index.php-Routing: POS-Routen werden deaktiviert, wenn pos/-Verzeichnis fehlt
- •
pos/_init.php → delegiert an gemeinsames Reservierungs-_init.php (geteilte DB, Auth, i18n)
- •API-Endpunkte verbleiben in
reservations/_api.php (Abwärtskompatibilität gewährleistet)
Added
- •Einheitliches Zahlungsmodal — gleichzeitige Nutzung von Guthaben + Bargeld + Karte (kombinierte Zahlung)
- •Guthaben: Kontostandabfrage, manuelle Eingabe oder Gesamtbetrag verwenden
- •Bargeld: Betragseingabe
- •Karte: Betragseingabe + Schaltfläche „Restbetrag übernehmen"
- •Ratenzahlung: Einmalzahlung / 2–12 Raten auswählen
- •Echtzeit-Berechnung von Gesamtsumme, Wechselgeld und Fehlbetrag
- •Bei Stripe-Kartenzahlung werden Bargeld/Guthaben erst nach erfolgter Kartenzahlung verarbeitet (sicher bei Abbruch)
- •Servicedetail-Modal — Guthabensanzeige
- •Guthabenstand des Mitglieds wird dauerhaft im Header-Bereich angezeigt (auch bei Kontostand 0)
- •Servicedetail-Modal — Verbesserung der Mitarbeiterbadges
- •Zugewiesen/Benannt-Badge wird vor dem Mitarbeiternamen angezeigt (bisher: unterhalb des Namens)
- •Schaltflächen Beleg/Druck verschoben
- •Über den Kundendetails positioniert, Beleg (links) + Druck (rechts)
- •Druckfunktion verbessert
- •Druckt den Inhalt des aktuellen Servicedetail-Modals statt einer externen Seite
Changed
- •Kartenlayout — grid-basiert → flex-wrap-Karten mit fester Größe
- •Feste Kartengröße: Standard 320×240px (small: 260×200, large: 380×280)
- •Kartengröße ändert sich nicht mit der Bildschirmgröße; automatischer Umbruch
- •Kartenzahlungsmodal — auf Breite 1030px, Höhe 800px vergrößert
Fixed
- •API-cross-origin-Fehler behoben
- •
$baseUrl war auf APP_URL aus .env festgelegt, was bei anderen Hosts/HTTPS Fetch-Fehler verursachte
- •Dashboard: Fetch-URL auf relativen Pfad geändert (
/update-api.php)
- •Reservierungs-
_init.php: $baseUrl auf leere Zeichenkette gesetzt, sodass alle Fetches relative Pfade verwenden
- •Mixed-Content-Problem in Cloudflare-HTTPS-Proxy-Umgebung vollständig behoben
- •DB-Migrationsfehler — „Failed to fetch" behoben (cross-origin-Problem)
- •Stripe-Kombinationszahlung: Bargeld-Vorabbuchungs-Bug bei Abbruch
- •Vorher: Bargeld zuerst verarbeitet → bei Abbruch der Kartenzahlung war Bargeld bereits gebucht
- •Nachher: Bargeld/Guthaben wird erst nach erfolgreicher Stripe-Kartenzahlung verarbeitet
i18n
- •
pos_pay_after_points — Betrag nach Guthabenabzug
- •
pos_pay_proceed — Zahlung fortsetzen
- •
pos_pay_remainder — Restbetrag vollständig verwenden
- •
pos_pay_installment — Ratenzahlung
- •
pos_pay_lump_sum — Einmalzahlung
- •
pos_pay_months — Monate
- •
pos_pay_total_pay — Gesamt
- •
pos_pay_short — Fehlbetrag
- •
show_receipt — Beleg
- •
show_print — Drucken
v1.18.0
2026-03-29 · vor 7 Monaten
Added
- •Mehrsprachige Datumsformatierungsfunktion —
formatReservationDate($dateString, $locale)
- •Unterstützt 13 Sprachen (ko, en, ja, zh_CN, zh_TW, de, es, fr, id, mn, ru, tr, vi)
- •Automatische Lokalisierung von Datum und Wochentag auf der Reservierungsdetailseite
- •Fallback: nicht unterstützte Locales → englisches Format
Changed
- •Mehrsprachige Verarbeitung der Reservierungsdetailseite
- •Servicename, Mitarbeitername und Paketname lokalisiert (auf Basis der DB-Translations-Tabelle)
- •Datumsformatierungsfunktion integriert
- •Zahlungsstatusbezeichnung lokalisiert (Feld payment_status)
- •Mehrsprachige Unterstützung des Zahlungsstatus
- •Abschnitt
payment zu allen Sprachdateien (11 Sprachen) hinzugefügt
- •Übersetzungen für ausstehend, bezahlt, teilweise bezahlt, erstattet
Fixed
- •Reservierungsdetailseite: Mitarbeitername und Servicename, die zuvor nicht lokalisiert wurden, werden jetzt korrekt angezeigt
- •Zahlungsstatusbezeichnung: Problem behoben, bei dem sie nur auf Koreanisch angezeigt wurde
- •Mehrsprachige Verarbeitung auf Basis der Funktion
_tr() vereinheitlicht
Layout & UI
- •Seitenbreite vereinheitlicht (max-w-5xl → max-w-7xl)
- •Board-Seiten (Liste, Lesen, Schreiben): max-w-5xl → max-w-7xl
- •Externe Seite (page.php): Standardwert und DB-Einstellungswerte aktualisiert
- •Reservierungsdetail / Reservierungsabfrage / Mitarbeiterseiten: DB-Einstellungswerte aktualisiert
- •Ergebnis: alle Seitenbreiten stimmen nun mit der Buchungsseite überein
Documentation
- •Detaillierte Dokumentation für
formatReservationDate() in COMPONENT_MANUAL.md hinzugefügt
- •Unterstützte Sprachen und Formattabelle
- •Anwendungsbeispiele und interne Struktur
- •Hinweise und verwandte Funktionen
v1.16.0
2026-03-23 · vor 7 Monaten
Added
- •Mobile untere Menüleiste — Personal / Reservierungen / Startseite / Anmelden (oder Mein Bereich) / Registrieren / Mehr, mit Hervorhebung der aktuellen Seite
- •Mobiles „Mehr"-Panel — Hauptmenü + Mein Bereich / Abmelden
- •Layout-/Skin-Einstellungen tatsächlich angewendet — site_layout, site_page_skin, site_board_skin, site_member_skin → im Rendering reflektiert
- •no_layout-Parameter — Nur Inhalt ohne Layout (für Vorschau)
- •Übersetzungsschlüssel hinzugefügt — common.nav.staff, common.nav.more (13 Sprachen)
Fixed
- •Layout auf Mitgliederseiten angewendet (login/register/forgot/reset): doppelter Header durch Extraktion des Skin-
<main> entfernt
- •Fehler bei doppelter Deklaration von ImageCropper/ProfilePhotoCropper im Mitglieder-Skin behoben
- •Menülader include_once-Problem behoben: fehlende base-header-Menüeinträge beim erstmaligen Laden innerhalb eines Skin-Closures
- •
apple-mobile-web-app-capable veraltet → mobile-web-app-capable (8 Dateien)
- •Header-Anmelde-/Registrierungsschaltflächen auf Mobilgeräten ausgeblendet (durch untere Menüleiste ersetzt)
- •iOS Safe-Area-Unterstützung für die untere Menüleiste
Changed
- •Mitgliederseiten vom eigenen Layout in das Standard-Layout zusammengeführt (login/register/forgot/reset)
- •Unterer Footer-Abstand entfernt (mobile Menüleiste verwendet Fixed-Positionierung)
v1.15.3
2026-03-22 · vor 7 Monaten
Added
- •Layout-Detaileinstellungspanel — AJAX-Laden des SkinConfigRenderer-basierten Einstellungsformulars
- •Layout-Menüeinstellungen — menus-Abschnitt von layout.json → automatische Erstellung des DB-Sitemap-Dropdowns
- •SkinConfigRenderer Tab-Unterstützung — Hinzufügen der
tab-Eigenschaft zu vars generiert automatisch eine Tab-UI
- •SkinConfigRenderer-Refactoring — einheitliche
renderVar()-Methode, Trennung von renderFormFlat/renderFormWithTabs, gemeinsames renderDependsOnJs
- •layout.json-Erweiterungen — menus (GNB/FNB), 14 vars (Header/Logo/Farbe/Footer/Custom), 13 Sprachen
- •Layout-Vorschau-Integration — "Deaktivieren" zeigt die Vorschau mit ?no_layout=1
Fixed
- •Layout-Verwaltungsmenü-Abfrage:
rzx_menus → rzx_sitemaps Tabellenname korrigiert
- •Mittlere Panelbreite angepasst + Aktionslink whitespace-nowrap
Pending
- •Anwendung der Layout-/Skin-Einstellungen auf das tatsächliche Seiten-Rendering (nächste Sitzung)
v1.15.2
2026-03-22 · vor 7 Monaten
Added
- •Layout-Verwaltungsseite — 3-Spalten-Layout: links Vorschau+Menü, rechts Skin-Liste, Detaileinstellungsbereich
- •Pro Skin-Element: Vorschaubild + Detaileinstellungen/Kopie erstellen/Löschen-Aktionslinks
- •Optionen „Deaktivieren" / „Anderen Skin installieren"
- •4-Kategorien-Speicherung: Layout, Seite, Board, Mitglied (
site_layout, site_page_skin, site_board_skin, site_member_skin)
Changed
- •„Design-Verwaltung" → „Layout-Verwaltung" umbenannt (13 Sprachen: admin.php + site.php)
v1.15.1
2026-03-22 · vor 7 Monaten
Changed
- •15 Seitenverwaltungsseiten → gemeinsamer
_head.php-Header angewendet
- •Boards: boards, boards-create, boards-edit, boards-trash
- •Menü: menus
- •Design: design
- •Seiten: pages, pages-settings, pages-edit-content, pages-document, pages-compliance, pages-widget-builder
- •Widgets: widgets, widgets-create, widgets-marketplace
- •Embed-Modus-Seiten (boards-edit, pages-settings, pages-edit-content) wenden
_head.php nur im Nicht-Embed-Modus an
- •Vollständige Vereinheitlichung von Header und Layout aller Admin-Seiten abgeschlossen
v1.15.0
2026-03-22 · vor 7 Monaten
Added
- •System-Widget-Modul — 4 Widgets: staff (Mitarbeitervorstellung), booking (Reservierung), lookup (Reservierungsabfrage), cta001 (Reservierungs-CTA-Banner)
- •Systemseiten — staff, booking, lookup in der DB registriert (is_system=1) + Routing (
/staff, /booking, /lookup)
- •Widget-basiertes Seitenrendering — staff/booking/lookup-Seiten rendern Widgets bei Platzierung, Fallback auf Legacy-Rendering wenn kein Widget vorhanden
- •Automatische Widget-DB-Registrierung —
syncToDatabase()-Aufruf registriert Widgets automatisch beim Hinzufügen eines Widget-Verzeichnisses
- •Widget-Kategorie
system — in 13 Sprachen übersetzt (widgets.categories + widget_builder.cat)
- •Seitenlisten-Vereinheitlichung — Systemseiten-Loop-Rendering + vereinheitlichte Zahnrad-/Bearbeiten-/Vorschau-Icons
- •Admin-Seitenkopf-Vereinheitlichung —
$pageSubTitle + $pageSubDesc (gemeinsame Ausgabe über _head.php)
- •Übersetzungsschlüssel hinzugefügt — staff.admins, staff.attendance.report/stats, points.description usw.
Fixed
- •Widget-Builder
page_slug = 'home' hartcodiert → dynamische $_GET['slug']-Verarbeitung
- •Widget-Builder AJAX save/preview
home hartcodiert → dynamisches $pageSlug
- •Widget-Builder-Vorschau-URL → dynamisches
$pageSlug (Startseite fest → je Seite)
- •Fehlende WidgetLoader-require in Widget preview_widget behoben
- •Servicekarten-Ansicht Bildpfad (
/storage/-Präfix)
- •Kiosk-Einstellungen Breite
max-w-3xl → 100% vereinheitlicht
- •POS-Kopfzeile „Reservierungsverwaltung" → „POS" umbenannt
Changed
- •10 Mitarbeiterverwaltungs- + 4 Mitgliederverwaltungsseiten → gemeinsamer
_head.php-Header angewendet
- •Kiosk-/Bundle-Seiten
_head.php angewendet
- •Kiosk-Spracheinstellungen grid → flex-wrap responsiv
- •Seitenliste: Systemseiten per datengesteuerter Schleife gerendert
v1.14.1
2026-03-22 · vor 7 Monaten
Added
- •Seiten-Skin-Tab — Skin-Basisinformationen + erweiterte Variableneinstellungen (SkinConfigRenderer-basiert)
- •Skin für alle Seitentypen — Skin-Einstellungen gelten für document/widget/external gleichermaßen
- •Titel-Hintergrund-System — Bild-/Videohintergrund + Overlay + Textfarbe (gemeinsames Partial
_page-title-bg.php)
- •depends_on-System — deklarative Feldabhängigkeiten in skin.json, Renderer generiert JS automatisch (checkbox/radio-Unterstützung)
- •Skin-Datei-Upload — Bild-/Video-Upload per Multipart (
storage/skins/page/{skin}/)
- •Kartenartiger Layout-/Skin-Selektor — im Modul-Infotab auf Thumbnail-Karten-UI umgestellt
- •SEO-System — SEO-Helfer, Titelmuster, OG/Twitter-Meta-Tags, Inhaltsextraktion
- •OG-Image-Upload — URL-Eingabe + Datei-Upload + Vorschau
- •Gemeinsames Ergebnis-Modal — einheitliches Speichern-Erfolg/Fehler-Modal (13 Sprachen)
- •Service-Kartenansicht — Vollbild-Hintergrundkarte + Tabellen/Karten-Umschalter
- •Drag-and-Drop-Sortierung für Services — Reihenfolge ändern + in DB speichern in beiden Ansichten
- •Reservierung: Personalzuweisung/Benennung — 2 Schaltflächen (Zuweisen/Benennen) in der Reservierungsdetailansicht
- •Reservierungsweg-UI — Telefonreservierung / Walk-in / Online-Auswahl
- •Telefonreservierungseinstellungen — Ein-/Ausschalten-Toggle in den Service-Grundeinstellungen
- •Sicherheitsheader — X-Frame-Options + CSP frame-ancestors
- •PAGE_SYSTEM.md — Entwicklungsdokumentation zum Seitensystem
- •PRD_OrderSystem.md — Planungsdokument für das Tischbestellungssystem
- •PRD_KioskSystem.md — Planungsdokument für das Kiosk-System
Fixed
- •Favicon-DB-Einstellung angewendet (Front / Admin / Skin-Layout — 4 Stellen)
- •Dashboard-Migrations-URL
window.location.origin → $baseUrl (Unterverzeichnisumgebungen)
- •Seiteneinstellungen Embed-Modus API-URL → Admin-Pfad direkt angegeben
- •Ergebnis-Modal i18n: verwendet Locale-Nachrichten beim Seitenrendering statt API-Antwort
- •Skin-Tab leerer Skin-Wert-Fallback (
"" → default)
- •
pages-settings.php php://input Doppelverbrauchsproblem behoben
Changed
- •Kiosk / Kiosk-Einstellungen / Bundle-Seiten → gemeinsamer
_head.php-Header angewendet
- •Skin-Einstellungen speichern JSON → FormData (Multipart) Übertragung (Datei-Upload-Unterstützung)
- •
$baseUrl-Parameter zu SkinConfigRenderer hinzugefügt (Bild-/Videovorschau)
- •13-sprachige Skin-Übersetzungen (skin.json + site.php + common.php)
v1.13.0
2026-03-21 · vor 7 Monaten
Added
- •Seitensystem abgeschlossen — automatische Seitenerstellung beim Anlegen von Dokument-/Widget-/externen Seiten aus dem Menü
- •Dynamischer Seitenrenderer —
page.php (Dokument→HTML, Widget→WidgetRenderer, Extern→iframe/include)
- •Seitenumgebungseinstellungen — 3 Tabs (Basis / Layout & Skin / SEO), gespeichert als
page_config_{slug} JSON
- •Seiteninhalt bearbeiten — sprachspezifische Titel- und Inhaltsbearbeitung, Slug-Änderung, Typänderung, Löschen
- •Dynamische Seitenverwaltungsliste — lädt Benutzerseiten automatisch aus der DB, typbasierte Icons & Badges
- •Frontend-Admin-Icons — Zahnrad (Einstellungen) + Bearbeiten (Inhalt) separat angezeigt
- •Externe Seiten-iframe — Hinweis „Im neuen Fenster öffnen" bei Ladefehler
- •Interne PHP/HTML-Dateien — per include im RezlyX-Layout gerendert
Fixed
- •Menü-Shortcut-URL
#menu_{id} → speichert echte Menü-URL
- •Menübearbeitung zeigt dieselbe Shortcut-UI-Struktur wie bei der Erstellung
- •Menü-Speicherung übernimmt Shortcut-URL (
formMenuType → Basis der Panel-Sichtbarkeit)
- •Menüübersetzungen für 13 Sprachen hinzugefügt (12 Menüpunkte × 13 Sprachen)
- •Übersetzungsschlüsselpfad des Seiten-Dokument-Editors korrigiert (
admin.site.pages. → site.pages.)
Changed
- •Spalte
page_type zu DB rzx_page_contents hinzugefügt (document/widget/external)
- •Menülöschung entfernt jetzt zugehörige Seite + Übersetzungsdaten gemeinsam
v1.12.5
2026-03-21 · vor 7 Monaten
Fixed
- •Menü-Shortcut-URL korrigiert — speichert jetzt die tatsächliche Menü-URL anstelle von
#menu_{id}
v1.12.4
2026-03-21 · vor 7 Monaten
Fixed
- •Listentyp der Skin-Einstellungen wurde nicht angewendet — Problem behoben, bei dem der localStorage-Cache die Skin-Einstellungen überschrieb
- •Bei deaktiviertem Stilwechsel werden ausschließlich Skin-Einstellungen verwendet; bei aktiviertem Stilwechsel hat localStorage Vorrang
- •Doppelte Übermittlung von versteckten Checkbox-Feldern entfernt (nicht aktivierter Zustand wird jetzt in JS verarbeitet)
v1.12.3
2026-03-20 · vor 7 Monaten
Fixed
- •Fehlende Board-Übersetzungsschlüssel für Englisch/Japanisch behoben (source_locale, reply, style, board_settings usw.)
- •Mehrsprachigen Fallback für Kategorienamen angewendet (Locale → en → Original)
- •Mehrsprachige Unterstützung für den Haupttext in der Board-Liste (Webzine/Karte/Galerie Vorschau)
v1.12.2
2026-03-20 · vor 7 Monaten
Fixed
- •Mehrsprachiger Fallback für den Beitragslisteinhalt — übersetzte Texte in Webzine/Karten/Galerie-Vorschauen angewendet (Locale → en → Original)
- •Fehlende Skin-Dateien in der Produktion — Verzeichnis
skins/default/board/ per FTP erstellt und skin.json/Vorschaubild hochgeladen
v1.12.1
2026-03-20 · vor 7 Monaten
Fixed
- •Skin-Einstellungen in der Produktion werden nicht angezeigt — vollständige Dateisynchronisierung neu organisiert
- •CLAUDE.md + BOARD_SYSTEM.md Dateistruktur vollständig aktualisiert
v1.12.0
2026-03-20 · vor 7 Monaten
Added
- •Skin-Einstellungssystem abgeschlossen — dynamische Formularerstellung auf Basis von skin.json + Anwendung auf reale Boards
- •Abschnittsgruppierung (Basis / Liste / Links / Design / Titelhintegrund / Benutzerdefiniert)
- •Radio- und Video-Eingabetypen hinzugefügt
- •Bild-/Videodatei-Upload (FormData Multipart)
- •Bild-/Videolöschfunktion
- •Skin-Info-Tabelle (Autor / URL / E-Mail / Datum / Version / Vorschaubild)
- •Titelhintergrundbild/-video — Einstellungen für Hintergrundtyp, Höhe, Overlay-Transparenz und Textfarbe
- •4 Listen-Layout-Stile — Liste / Webzine / Galerie / Karte; Skin-Dateien getrennt + Override-Unterstützung
- •Galerie: Vollbild-Cover + Hover-Slide-Animation
- •Webzine: Vorschaubild + Titel + Vorschau + Meta-Info-Karte
- •Ankündigungsbeiträge in obere Liste ausgelagert (_list-notices.php)
- •Skin-Einstellungen angewendet — primary_color, border_radius, posts_per_row, allow_style_switch, show_category, verknüpftes Board, Font Awesome, benutzerdefiniertes CSS/HTML
- •skin.json Standardwert-Auto-Merge — skin.json-Standardwerte werden auch ohne DB-Speicherung angewendet
Fixed
- •skin_config wird nicht in der DB gespeichert (boards-api.php Update-Aktion enthielt skin_config nicht)
- •Skin-Speicherung von URLSearchParams → FormData (Multipart) geändert, um Datei-Uploads zu unterstützen
- •Auto-Parse-Unterstützung für
$_POST['skin_config']-Array
v1.11.3
2026-03-20 · vor 7 Monaten
Fixed
- •Mehrsprachigen Fallback für vorherige/nächste Beitragstitel auf der Beitragsdetailseite angewendet (Locale → en → Original)
v1.11.2
2026-03-20 · vor 7 Monaten
Fixed
- •Mehrsprachiger Fallback für Beitragslistentitel — Übersetzungsabfrage über alle Locales hinweg (Beschränkung auf Koreanisch entfernt), englischer Fallback unter Berücksichtigung der Quellsprache
v1.11.1
2026-03-20 · vor 7 Monaten
Fixed
- •Verbesserte Erkennung einzelner URLs für OG-Karten — URLs, die in Inline-Tags wie
<font> / <span> eingebettet sind, werden jetzt bis zum übergeordneten Block-Element zurückverfolgt und korrekt verarbeitet
v1.11.0
2026-03-20 · vor 7 Monaten
Added
- •URL-Auto-Link — erkennt URLs im Board-Beitrag/Editor automatisch → wandelt sie in
<a>-Tags um
- •OG-Link-Vorschaukarte — SNS-Banner-Format (Vorschaubild + Titel + Beschreibung + Domain) wird automatisch generiert
- •Editor: URL eingeben/einfügen + Enter → ruft OG-API auf → fügt Karte ein
- •Inhalt: alleinstehender URL-Link → wird automatisch in OG-Karte umgewandelt
- •OgFetcher-Modul — OG/Twitter Card-Metadaten-Extraktion, Favicon, automatische Kodierungsverarbeitung
- •OG-API — Endpunkt
/board/api/og
- •board-autolink.js — vereinheitlichtes Auto-Link + OG-Karten-JS (global aus base-header geladen)
v1.10.2
2026-03-20 · vor 7 Monaten
Fixed
- •Bild-Ausrichtung in Editor/Inhalt — Überschreiben von Tailwind preflights
img { display: block }
- •
board-content.css gemeinsames CSS erstellt (Editor + Inhaltsanzeige vereinheitlicht)
- •Global aus
base-header.php geladen (alle Frontend-Seiten)
- •Globale Editor-Stile zu
multilang-modal.php hinzugefügt (alle Admin-Summernote-Instanzen)
- •
prose-Klasse aus dem Board-Inhalt entfernt; Inline-Stile des Editors werden nun 100% erhalten
Changed
- •Board-Inhaltsstilregeln in CLAUDE.md dokumentiert (
board-content-Klasse ist erforderlich)
v1.10.1
2026-03-20 · vor 7 Monaten
Fixed
- •Fehler behoben, bei dem beim Hinzufügen einer Board-Kategorie im mehrsprachigen Modal Daten der vorherigen Kategorie geladen wurden (eindeutiger temporärer langKey wird generiert)
- •Standardwert 3 für
comment_max_depth in Migration 021 hinzugefügt
v1.10.0
2026-03-20 · vor 7 Monaten
Added
- •Erweiterte Board-Variablen — ExtraVarRenderer-Komponentenmodul (15 Typen: Input-/Display-Rendering je Typ)
- •Mehrsprachigkeit für erweiterte Variablen — sprachlich unabhängige Speicherung erweiterter Variablenwerte (rzx_translations-Integration, Fallback-Kette)
- •Mehrsprachige Trennspeicherung für Board-Beiträge — Bearbeitung in der Originalsprache speichert direkt in board_posts; andere Sprachen speichern Übersetzungen in rzx_translations
- •Lese-Fallback-Kette für Board-Beiträge — Titel/Inhalt/Erweiterungsvariablen werden in der Reihenfolge angezeigt: aktuelles Locale → en → Original
- •Verschachtelte Antworten — 3-stufige verschachtelte Kommentarunterstützung, rekursive Baumsortierung, Inline-Antwortformular
- •Kommentar-Like/Dislike — Like-Button je Kommentar + API
- •Frontend-Zugriff auf Board-Einstellungen — Admin-Zahnrad-Symbol → /board/{slug}/settings Frontend-Layout
- •Admin-Titelverlinkung im Board — Klick auf den Titel in der Admin-Board-Liste navigiert zum jeweiligen Board
Fixed
- •Board-API-Admin-Berechtigungsprüfung:
$currentUser['role'] → $_SESSION['admin_id'] (4 Dateien aktualisiert)
- •Originalsprachen-Hinweis wird nur Autor/Admin angezeigt
- •Board-Einstellungen: Embed-Modus-Tab-Link unterstützt Frontend-URL
Changed
- •
extra_vars JSON-Spalte zu DB rzx_board_posts hinzugefügt
- •Standardwert
comment_max_depth von 0 → 3 geändert
- •Kommentar-Aktionsleiste vereinheitlicht (Like/Dislike/Antworten/Löschen-Icons)
v1.9.4
2026-03-20 · vor 7 Monaten
Added
- •Standard-Board-Daten — Migration von Ankündigungen, Fragen & Antworten, FAQ und freiem Board (020_default_boards_v193.sql)
v1.9.3
2026-03-20 · vor 7 Monaten
Added
- •Mitgliedergruppen-Zurücksetzen — Initialisierung mit Standarddaten (7 Gruppen + Übersetzungen in 13 Sprachen)
- •Punkte-Einstellungen zurücksetzen — Konfigurationswerte / Stufenpunkte / Gruppenverknüpfungen auf Standardwerte zurücksetzen (Mitgliedsguthaben nicht betroffen)
- •Mitgliedergruppen mehrsprachig —
rzx_multilang_input() gemeinsame Komponente für Gruppenname / Vorteilsbeschreibung angewendet
- •Mitgliedergruppen Drag & Drop — SortableJS Kartensortierung + automatisches Speichern
Fixed
- •Übersetzungsanzeige der Mitgliedergruppenkarte je nach Locale (Kartenansicht + Bearbeitungsmodal)
- •Datenbeschädigung bei mehrsprachigen Übersetzungsdaten der Mitgliedergruppen behoben (PHP UTF-8-Neuspeicherung)
- •Spaltenname der Einstellungstafel des Punkte-Moduls korrigiert (board_name → title)
- •Kollationskonflikte in der Punkte-Mitgliederliste behoben (einheitlich utf8mb4_unicode_ci)
- •Produktions-DB-Migration (019_point_system_v190.sql)
v1.9.0
2026-03-20 · vor 7 Monaten
Added
- •Prämien-/Punkteverwaltungssystem — 3-Tab-Struktur (Grundeinstellungen / Moduleinstellungen / Mitgliederpunkteliste)
- •3-Felder-Punktestruktur — point (Aktivitätspunkte), balance (Zahlungsguthaben), total_accumulated (Gesamtpunkte, Grundlage für die Levelberechnung)
- •Gewichtung der Gesamtpunkte — separate Zahlungsgewichtung / Aktivitätsgewichtung, Level-Up-Vorteile für zahlende Kunden
- •Punkteumtausch — Punkte → Guthaben (Verhältnis, Einheit, Mindestpunkte konfigurierbar)
- •17 Punkte-Vergabe/Abzugskategorien — gleiche Struktur wie Rhymix (Rückholung bei Löschung, Zeitlimit, Ankündigungen ausgeschlossen)
- •Moduleinstellungen — individuelle Konfiguration von 15 Punkteposten je Pinnwand
- •Mitgliederpunkteliste — 4 Spalten (Punkte/Guthaben/Gesamt/Level), Suche, Einzelbearbeitung
- •Level-Punkte — formelbasierte Berechnung, dynamische Anpassung des Maximallevels, Gruppenverknüpfung
- •Punktesystem-Dokumentation — POINT_SYSTEM.md detailliertes Designdokument
- •Mitgliedergruppe Drag-and-Drop — Kartenreihenfolge mit SortableJS ändern + automatisches Speichern
- •Mitgliedergruppe Mehrsprachigkeit —
rzx_multilang_input() gemeinsame Komponente für Gruppenname/Vorteilsbeschreibung angewendet
- •Mitgliedergruppe Seed-Daten — 7 Gruppen × 13 Sprachen mehrsprachige Übersetzungsdaten
Changed
- •Spalten
balance, total_accumulated zur DB rzx_member_points hinzugefügt
- •DB
rzx_point_levels.group_id von INT auf CHAR(36) geändert (UUID-kompatibel)
- •Kollation von
rzx_point_levels, rzx_member_points auf utf8mb4_unicode_ci vereinheitlicht
- •Bundle-Seitenlayout aktualisiert (
sidebar-main-content → flex-1 ml-64 Dashboard-Muster)
- •Währungseinheit der Bundle-Seite
$config['currency'] → $siteSettings['service_currency'] korrigiert
- •Servicedauer von Select → Input Number + Datalist geändert
- •Mehrsprachige Eingabe-UI-Regeln in CLAUDE.md dokumentiert (Pflichtverwendung von rzx_multilang_input)
v1.8.3
2026-03-20 · vor 7 Monaten
Added
- •Bundle-Detailverwaltungsseite — einzelne Bundle-Basisinfos bearbeiten, Titelbild hochladen, Service-Zusammensetzung bearbeiten, Mitarbeiter verknüpfen, Aktiv/Inaktiv umschalten
- •Eventrabatt — Eventpreis pro Bundle, Zeitraum (Start/Ende), Label-Einstellungen; automatische Aktivierung innerhalb des Zeitraums
- •Bundle-Listen-Kartendesign — Gitterkarten-Layout, Bild-Header, Event-/Rabatt-Abzeichen, fixierte untere Aktionsleiste
- •Hintergrundbild für empfohlenes Paket — Titelbild-Hintergrund + Farbverlaufsüberlagerung auf Bundle-Karten in der Kunden-Mitarbeiter-Detailseite
- •Direkte Eingabe der Servicedauer — select → number input (5–480 Min., 5-Minuten-Schritte) + Datalist-Empfehlungsliste
Changed
- •DB
rzx_service_bundles Spalten hinzugefügt: event_price, event_start, event_end, event_label
- •Bundle-Listen-API:
total_duration und Eventspalten hinzugefügt
- •Übersetzungsdateien (ko, en, ja): Bundle-Detailverwaltungs- + Eventrabatt-Schlüssel hinzugefügt
v1.8.1
2026-03-19 · vor 7 Monaten
Added
- •POS-Einstellungsseite — Kartengröße, Bild-/Preis-/Telefon-Anzeige, Transparenz, Standard-Tab, Auto-Refresh, Benachrichtigungston, Mitarbeiterzuweisung erforderlich, automatische Zuweisung
- •POS-Einstellungen angewendet — Kartengröße/Bild/Preis/Telefon/Transparenz/Auto-Refresh/Standard-Tab werden alle im POS übernommen
- •Automatische Mitarbeiterzuweisung — wenn in POS-Einstellungen aktiviert, wird beim Kiosk-Check-in automatisch zugewiesen (dienstfähiger Mitarbeiter + wenigste Reservierungen am selben Tag)
- •POS-Karten-Mitarbeiterabzeichen — zugewiesen/nicht zugewiesen; Weiter-Schaltfläche bei nicht zugewiesen deaktiviert
- •POS-Service-Bildhintergrund — repräsentatives Service-Bild als Hintergrund im Header + Kundenbereich des Service-Detail-Modals
- •Mitarbeiter is_visible — steuert Listensichtbarkeit; versteckte Mitarbeiter aus Reservierungen/POS/Kiosk ausgeschlossen
- •Mitarbeiterkarten-Banner — Bannerbild + Statusabzeichen auf der Admin-Mitarbeiterkarte
- •Kiosk-Automatikzuweisung — Check-in mit staff_id=NULL; Zuweisung erfolgt durch Admin im POS
Fixed
- •POS-Mitarbeiterzuweisung: Serviceliste wird nach der Zuweisung sofort aktualisiert (Cache-Vermeidung)
- •Parameterfehler der Mitarbeiterzuweisungs-API behoben (reservation_id → reservation_ids[])
- •Mehrere fehlende Tabellen/Spalten in der Produktion behoben (Migration 018 verstärkt)
- •Admin-Abmelderoute hinzugefügt
- •Kiosk-Vor-Auth-Routenplatzierung
v1.7.0
2026-03-18 · vor 7 Monaten
Added
- •Basis-Layout-System —
layouts/base-header.php + base-footer.php, ob_start wird in index.php automatisch angewendet, gemeinsame Kopf-/Fußzeile für alle Kundenseiten
- •Board-Frontend — Listen-, Detail-, Schreib-/Bearbeitungsseiten, Summernote-Editor, Drag & Drop-Dateianhänge
- •Board-Kurz-URLs — Zugriff auf
/free, /notice/3 etc. ohne das Präfix /board/; automatisches DB-Slug-Matching
- •Reservierungsabfrageseite — Kurz-URL
/lookup, Suche nach Reservierungsnummer / E-Mail / Telefonnummer
- •Reservierungsdetailseite —
/booking/detail/{Nummer}, Mitarbeiter-Begrüßungsblase, Service/Zahlungs-/Stornierungsinfo
- •Reservierungsstornierungsseite —
/booking/cancel/{Nummer}, Eingabe des Stornierungsgrunds
- •Meine Seite — Reservierungsdetail —
/mypage/reservations/{id}, Seitenleiste + Detailinformationen
- •Mehrsprachiges Board —
original_locale (Sprache des Erstentwurfs) + source_locale (aktuelle Inhaltssprache), Fallback-Kette (source → en → original)
- •Mitarbeiterbegrüßungen —
greeting_before (vor der Behandlung) + greeting_after (nach der Behandlung), mehrsprachig, je nach Reservierungsstatus angezeigt
- •Admin-Profil-Dropdown — Profilfoto/Initialen + Name + Links zu Homepage / Meine Seite / Abmelden
- •Kunden-Header-Admin-Link — beim Login als Admin zeigt das Dropdown einen Link zum Adminbereich
Changed
- •Einheitliches Layout für alle Kundenseiten (individuelle HTML-Strukturen entfernt, LayoutManager automatisch angewendet)
- •Board-Kategorieanzeige-Bedingung von
show_category auf hide_categories geändert
- •Board-URL standardmäßig von
/board/free auf Kurz-URL /free geändert
- •Admin-Topbar „Admin" durch tatsächlichen Anmeldenamen + Profilfoto ersetzt
Fixed
- •Fehlende Spalte
rzx_users.role → Admin-Erkennung jetzt auf Basis von $_SESSION['admin_id']
- •Fehlende Spalte
rzx_users.nick_name → Verwendung von name + Encryption-Entschlüsselung
- •
rzx_staff.profile_image → korrigiert auf Spaltenname avatar
- •Service-Modell
category_id int→string Typumwandlung
- •Reservierungsabfrage per E-Mail/Telefon verwendet Klartextsuche (Daten nicht verschlüsselt)
v1.6.1
2026-03-18 · vor 7 Monaten
Added
- •6 Board-Admin-Tabs — Grundeinstellungen, Kategorieverwaltung, Zusatzvariablen, Berechtigungen, Weitere Einstellungen, Skin
- •Konsolidierung des Grundeinstellungs-Tabs — Grundinfo + SEO + Layout-Auswahl + Skin-Auswahl + Anzeige + Liste + Erweitert (ein-/ausklappbar)
- •Gemeinsame Komponenten — 8
components/board/section-*.php-Dateien (basic, seo, layout-select, skin-select, display, list, advanced, js), wiederverwendbar auf Erstell-/Bearbeitungsseiten
- •Mehrsprachige Eingabekomponente —
rzx_multilang_input()-Funktion, Text/Editor-Modus, inliner Globus-Button
- •Erweiterte Kategorieverwaltung — Baumstruktur (parent_id), Bearbeitungsmodal (Name/Schriftfarbe/Beschreibung/erlaubte Gruppen/Ausklappen/Standardkategorie), SortableJS-Drag-Sortierung, dynamisches DB-Laden der Mitgliedergrade
- •Zusatzvariablen-Tab —
rzx_board_extra_vars-Tabelle, 15 Eingabetypen (inkl. text_multilang, textarea_multilang, textarea_editor), Mehrsprachigkeit, Drag-Sortierung
- •Berechtigungs-Tab — Zugriffsrechte (all/member/grade:*/admin_staff/admin), Moduladmin (gemeinsame Benutzersuche, Profilfoto, Berechtigungsumfang), Benachrichtigungsmail-Info
- •Weitere-Einstellungen-Tab — Integriertes Board, Dokumente (Verlauf/Empfehlung/Meldung), Kommentare (Anzahl/Tiefe/Genehmigung/Empfehlung/Meldung), WYSIWYG-Editor (Berechtigungsmatrix), Dateien (Download-Gruppe), Feeds (RSS öffentlich/Copyright)
- •Skin-System —
skin.json-Format, SkinConfigRenderer, "multilang": true-Unterstützung, Skin-Info-Karte
- •Layout-System —
layout.json-Format, Kartenauswahl in Grundeinstellungen
- •Gemeinsame Benutzersuche —
user-search.php-Komponente, Ver-/Entschlüsselung, Profilfoto, überall wiederverwendbar
- •Moduladmin —
rzx_board_admins-Tabelle, Beitrags-/Kommentar-/Einstellungsberechtigungen, Benachrichtigungsempfang
- •Erweiterung der erweiterten Einstellungen — Admin von Anonym ausschließen, Data-URL-Beschränkung, Unicode-Missbrauch, Beitrags-/Kommentarschutz (Kommentaranzahl/Antwortanzahl/Zeitraum), Super-Admin-Schutz, Absender-E-Mail-Adresse
- •Toggle-Switch-UI — alle Ja/Nein-Elemente als Toggles umgesetzt (Grund- + Weitere Einstellungen)
- •Übersetzungsschlüssel — ca. 300 Schlüssel, 13 Sprachen
Fixed
- •Papierkorb-SQL-Fehler —
LIMIT ?-Bindung String → Integer-Literal
- •Summernote nicht gerendert — jQuery/Summernote JS-Laden + Initialisierung nach Modal-Anzeige
- •Kollations-Fehler — COLLATE utf8mb4_unicode_ci bei board_admins JOIN explizit angegeben
- •Ein-/Ausklappen funktioniert nicht —
toggleSection-Funktion zuerst im <head> definiert
Changed
- •Eigenständige Tabs (Liste/Erweitert) → in Grundeinstellungs-Tab mit Ein-/Ausklappen integriert
- •Skin-Auswahl → in Grundeinstellungs-Tab verschoben; Skin-Tab zeigt nur Einstellungen
- •Admin-E-Mail → geändert zu "Absender-E-Mail-Adresse" in erweiterten Einstellungen
- •Moduladmin → in Berechtigungs-Tab verschoben
- •"Kategorie in Liste anzeigen" → aus Kategorieeinstellungen entfernt, an per-Skin-Einstellungen delegiert
- •"Kategorie in Liste anzeigen" → aus Kategorieeinstellungen entfernt, an per-Skin-Einstellungen delegiert
- •Erlaubte Schreibgruppen → dynamisch aus
rzx_member_grades-Tabelle geladen statt hartcodiert
v1.6.0
2026-03-17 · vor 7 Monaten
Added
- •Mehrsprachiges Fallback-System: eingebaute Fallback-Kette in
db_trans() (konfigurierte Sprache → en → Standardsprache → source_locale → irgendeine Übersetzung)
- •Mehrsprachige Schaltfläche in Board-Einstellungen: Mehrsprachigkeits-(Globus-)Schaltfläche zu 6 Feldern im Grundeinstellungs-Tab hinzugefügt
- •Mehrsprachiger Fallback in der Board-Frontansicht: Titel, Beschreibung, SEO, Header/Footer mehrsprachig in
_init.php angewendet
- •Mehrsprachiger Widget-Fallback:
WidgetRenderer::t(), tBtn() Leerstring-Behandlung verbessert
- •PWA-Übersetzungsschlüssel hinzugefügt (13 Sprachen:
admin.pwa.update_available, update, later)
Fixed
- •Features-Widget-Leerkartenproblem:
??-Operator behandelte leeren String "" als gültigen Wert → auf !empty()-basiertem Fallback korrigiert
- •Produktions-Mixed-Content-Fehler:
APP_URL http→https korrigiert + automatische JS-Protokollkorrektur
v1.5.2
2026-03-17 · vor 7 Monaten
Added
- •Servicelöschung aus der POS-Serviceverlaufsliste (Lösch-Schaltfläche + API + sofortige DOM-Aktualisierung)
- •Übersetzungsschlüssel für die Servicelöschung in 13 Sprachen hinzugefügt
v1.5.0
2026-03-17 · vor 7 Monaten
Added
- •Kiosk-Check-in-System: Service-Bestätigung → Kundendaten → Reservierungserstellung → Ausgabe der Wartenummer
- •Badge für Mitarbeiterverfügbarkeit: zeigt Beschäftigt/Verfügbar in Echtzeit bei der Mitarbeiterauswahl am Kiosk
- •Modul für internationale Telefonnummern: phone-input-Komponente im Kiosk-Check-in-Formular angewendet
- •Seed für Reservierungs-Beispieldaten:
database/seed_reservations.php (10 Einträge über POS/Kiosk/Online)
- •Gemeinsame Kiosk-Dateien ausgelagert (
_styles.php, _bg.php, _scripts.php)
- •11 Kiosk-Übersetzungsschlüssel in 13 Sprachen hinzugefügt
Changed
- •Kiosk-Serviceauswahl: Filterung nach Mitarbeiterfähigkeiten (Benennungsmodus)
- •Kiosk-Kategorie-Tabs zentriert
Fixed
- •Admin-Login in der Produktion nicht möglich (Passwort-Hash beschädigt — Problem mit der
$-Variablenersetzung in bash)
- •Stabilisierung des Update-Systems: erweiterte Aufbewahrungsliste, Health-Check, DB-Versionssynchronisierung
- •Einzige Versionsquelle vereinheitlicht (
version.json → index.php, automatische DB-Synchronisierung)