feat: Umfassende Verbesserungen des Maintenance AddOns#156
Conversation
- Emojis durch Font Awesome 6 Icons ersetzt - YRewrite Domain-Verwaltung hinzugefügt mit Migration - Settings in übersichtliche Unterseiten reorganisiert (Wartung, Einstellungen, Ankündigung, Domains) - Mehrsprachige Wartungstexte (Deutsch/Englisch) mit Sprachswitcher - Modernes upkeep-inspiriertes Design übernommen - Card-basiertes Layout mit Animationen - Dark Mode Support - Responsive Design - Dropdown-Sprachauswahl mit Globe-Icon - IP-Adressen per Klick zur Whitelist hinzufügen - Login-Formular nur bei gesetztem Passwort anzeigen - Intelligente Bypass-URL-Anzeige (nur für gesperrte Domains) - Sidebar-Komponente für alle Frontend-Seiten - Editor-Konfiguration in Einstellungen verschoben - Begriffe vereinheitlicht (Wartungsmodus -> Wartung) - Weiterleitungs-URL zu allgemeinen Einstellungen verschoben
|
Warning Rate limit exceeded@skerbis has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 10 minutes and 38 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (3)
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Moin, WalkthroughDas Maintenance-Addon wird von v3.4.0 auf v3.5.0 erweitert mit Domain-basierten Wartungsfunktionen (YRewrite-Integration), zeitgesteuerte Wartung via Cronjob, multilinguales Frontend, stille Wartung, IP-Whitelist-Verwaltung und erweiterte Einstellungen. Das Frontend wird in spezialisierte Seiten aufgeteilt und die CLI-Befehle werden mit neuen Aktionen erweitert. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Frontend as Frontend-Besucher
participant Boot
participant Cronjob
participant Maintenance as Maintenance.php
participant Config
rect rgb(200, 220, 255)
note over User,Config: Zeitgesteuerte Wartung
User->>Boot: Cronjob startet
Boot->>Cronjob: rex_cronjob_scheduled_maintenance::execute()
Cronjob->>Config: Lese scheduled_start/scheduled_end
Cronjob->>Maintenance: Zeit im Fenster?
alt Innerhalb des Zeitfensters & Frontend nicht gesperrt
Maintenance->>Config: Setze block_frontend = true
Cronjob-->>User: ✓ Wartung aktiviert bis [end_time]
else Nach scheduled_end & Frontend gesperrt
Maintenance->>Config: Setze block_frontend = false, lösche Zeiten
Cronjob-->>User: ✓ Wartung deaktiviert
else Keine Änderung
Cronjob-->>User: → Wartung aktiv/geplant (keine Änderung)
end
end
rect rgb(220, 255, 220)
note over Frontend,Maintenance: Domain-basierte Wartung Prüfung
Frontend->>Boot: REQUEST an FRONTEND
Boot->>Maintenance: checkFrontend() aufgerufen
Maintenance->>Maintenance: isDomainInMaintenance()?
alt Domain gesperrt oder global all_domains_locked
Maintenance->>Frontend: Wartungsseite mit Sprachumschalter
else Silent Mode aktiv
Maintenance->>Frontend: HTTP-Status-Code (silent_mode)
else Domain nicht in Wartung
Maintenance->>Frontend: Normale Seite
end
end
rect rgb(255, 240, 200)
note over User,Frontend: Mehrsprachige Frontend-Wartungsseite
Frontend->>Frontend: Lade Wartungsseite (frontend.php)
Frontend->>Frontend: Prüfe multilanguageEnabled
alt Mehrsprache aktiviert
Frontend->>Frontend: Zeige EN/DE Language-Switcher
User->>Frontend: Wähle Sprache (DE)
Frontend->>Frontend: sessionStorage[lang] = 'de'
Frontend->>Frontend: Blende maintenance_text_de ein
else Mehrsprache deaktiviert
Frontend->>Frontend: Zeige default Wartungsmeldung
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Bereiche mit erhöhter Aufmerksamkeit:
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull Request Overview
This PR refactors the maintenance addon to support per-domain maintenance mode management and improves the UI organization by splitting a monolithic frontend.php file into multiple focused subpages. The implementation adds granular control over YRewrite domains while maintaining backward compatibility.
- Introduces domain-specific maintenance control with
domain_statusandall_domains_lockedconfiguration options - Splits the frontend settings into separate pages: index (general), advanced (access control), and announcement
- Adds migration logic in update.php to convert legacy
allowed_yrewrite_domainswhitelist to the new domain status system - Updates the frontend maintenance page with improved styling and multi-language support
Reviewed Changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| update.php | Adds migration logic to convert old allowed_yrewrite_domains to new domain_status system |
| pages/frontend.php | Removed monolithic frontend page (replaced by split pages) |
| pages/frontend.index.php | New general settings page with core maintenance options |
| pages/frontend.advanced.php | New advanced settings page for IP control and HTTP settings (admin only) |
| pages/frontend.announcement.php | New announcement settings page (admin only) |
| pages/frontend.sidebar.php | Shared sidebar component showing preview, bypass URLs, and quick links |
| pages/domains.php | New domain management page for per-domain maintenance control |
| lib/Maintenance.php | Adds isDomainInMaintenance() method and integrates domain-based checks |
| boot.php | Integrates domain-based maintenance check in frontend blocking logic |
| package.yml | Updates page structure with subpages and new default config values |
| fragments/maintenance/frontend.php | Redesigned maintenance page with dark mode and language switcher |
| fragments/maintenance/login.php | Improved login form validation logic |
| lang/de_de.lang | Updated German translations for new features |
| assets/css/maintenance-icons.css | New CSS for icon-based status indicators |
Comments suppressed due to low confidence (3)
lib/Maintenance.php:1
- Missing closing brace after line 251. The code has an unclosed if-statement which will cause a syntax error. Add a closing brace
}after line 251.
<?php
lib/Maintenance.php:260
- Potential error if yrewrite addon is not installed. Similar to the boot.php issue, calling
rex_addon::get('yrewrite')without first checking if it exists withrex_addon::exists('yrewrite')could throw an exception.
// If YRewrite is installed and the domain is allowed, do not block the request
lib/Maintenance.php:1
- The imported function 'count' is never used in the new code additions. While it may be used elsewhere in the file, this import appears to be added unnecessarily in this PR.
<?php
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
pages/frontend.sidebar.php
Outdated
| $copy = '<ul class="list-group">'; | ||
|
|
||
| // Prüfen, ob YRewrite verfügbar ist | ||
| $yrewriteAvailable = rex_addon::get('yrewrite')->isAvailable(); |
There was a problem hiding this comment.
Potential error if yrewrite addon is not installed. The code assumes yrewrite exists but it may not be installed. Use rex_addon::exists('yrewrite') && rex_addon::get('yrewrite')->isAvailable() instead.
pages/domains.php
Outdated
| // Wenn YRewrite nicht verfügbar ist, Hinweis anzeigen | ||
| if (!rex_addon::get('yrewrite')->isAvailable()) { |
There was a problem hiding this comment.
Potential error if yrewrite addon is not installed. Check existence first with rex_addon::exists('yrewrite') before calling get() and isAvailable().
| // Wenn YRewrite nicht verfügbar ist, Hinweis anzeigen | |
| if (!rex_addon::get('yrewrite')->isAvailable()) { | |
| // Wenn YRewrite nicht installiert oder nicht verfügbar ist, Hinweis anzeigen | |
| if (!rex_addon::exists('yrewrite') || !rex_addon::get('yrewrite')->isAvailable()) { |
update.php
Outdated
| if ($addon->hasConfig('allowed_yrewrite_domains') && !$addon->hasConfig('domain_status')) { | ||
| $oldAllowedDomains = (string) $addon->getConfig('allowed_yrewrite_domains', ''); | ||
|
|
||
| if ('' !== $oldAllowedDomains && rex_addon::get('yrewrite')->isAvailable()) { |
There was a problem hiding this comment.
Potential error if yrewrite addon is not installed. The migration code should check rex_addon::exists('yrewrite') before calling get() to avoid exceptions.
| if ('' !== $oldAllowedDomains && rex_addon::get('yrewrite')->isAvailable()) { | |
| if ('' !== $oldAllowedDomains && rex_addon::exists('yrewrite') && rex_addon::get('yrewrite')->isAvailable()) { |
pages/frontend.advanced.php
Outdated
| $tokenfield.tokenfield('setTokens', tokens); | ||
| } | ||
|
|
||
| $(this).prop('disabled', true).addClass('btn-success').html('<i class="fa fa-check"></i> ' + ip + ' hinzugefügt'); |
There was a problem hiding this comment.
Hardcoded German text 'hinzugefügt' in JavaScript. This should use a translation key or variable from the i18n system to support internationalization.
pages/frontend.index.php
Outdated
| $field = $form->addSelectField('authentification_mode'); | ||
| $field->setLabel($addon->i18n('maintenance_authentification_mode_label')); | ||
| $select = $field->getSelect(); | ||
| $select->addOption($addon->i18n('maintenance_authentification_mode_url'), 'URL'); | ||
| $select->addOption($addon->i18n('maintenance_authentification_mode_password'), 'password'); |
There was a problem hiding this comment.
Corrected spelling of 'authentification' to 'authentication'. The word 'authentification' is a misspelling; the correct term is 'authentication'.
| $field = $form->addSelectField('authentification_mode'); | |
| $field->setLabel($addon->i18n('maintenance_authentification_mode_label')); | |
| $select = $field->getSelect(); | |
| $select->addOption($addon->i18n('maintenance_authentification_mode_url'), 'URL'); | |
| $select->addOption($addon->i18n('maintenance_authentification_mode_password'), 'password'); | |
| $field = $form->addSelectField('authentication_mode'); | |
| $field->setLabel($addon->i18n('maintenance_authentication_mode_label')); | |
| $select = $field->getSelect(); | |
| $select->addOption($addon->i18n('maintenance_authentication_mode_url'), 'URL'); | |
| $select->addOption($addon->i18n('maintenance_authentication_mode_password'), 'password'); |
package.yml
Outdated
| http_response_code: 503 # 503, 403 | ||
| allowed_ips: '' | ||
| allowed_yrewrite_domains: '' | ||
| authentification_mode: 'URL' # `URL`, `password` |
There was a problem hiding this comment.
Corrected spelling of 'authentification_mode' to 'authentication_mode'. The configuration key uses a misspelling; it should be 'authentication_mode'.
| authentification_mode: 'URL' # `URL`, `password` | |
| authentication_mode: 'URL' # `URL`, `password` |
| if (!rex_addon::get('yrewrite')->isAvailable()) { | ||
| return false; | ||
| } | ||
|
|
There was a problem hiding this comment.
Potential null pointer exception. The code calls rex_article::getCurrentId() and rex_clang::getCurrentId() which may return null if no current article or language is set. This should be guarded or checked for null values before use.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (7)
fragments/maintenance/frontend_old.php (1)
12-12: Moin! Type-Sicherheit für Meta-Refresh-Intervall verbessern.Das Update-Intervall sollte explizit als Integer gecastet werden, um potenzielle Injection-Probleme zu vermeiden, auch wenn rex_config vermutlich bereits sichere Werte liefert.
- <meta http-equiv="refresh" content="<?= $maintenanceFrontendUpdateIntervalNumber > 0 ? $maintenanceFrontendUpdateIntervalNumber : '' ?>"> + <meta http-equiv="refresh" content="<?= $maintenanceFrontendUpdateIntervalNumber > 0 ? (int) $maintenanceFrontendUpdateIntervalNumber : '' ?>">boot.php (1)
21-27: Moin! Domain-Maintenance-Check könnte vereinfacht werden.Die YRewrite-Verfügbarkeitsprüfung erfolgt hier und nochmal in
Maintenance::isDomainInMaintenance(). Man könnte den äußeren Check entfernen, da die Methode selbst bereits prüft. Allerdings ist die aktuelle Lösung defensiver und performanter (vermeidet unnötige Methodenaufrufe).Falls gewünscht, kann vereinfacht werden zu:
- // Check domain-based maintenance or global frontend maintenance - $domainInMaintenance = false; - if (rex::isFrontend() && rex_addon::get('yrewrite')->isAvailable()) { - $domainInMaintenance = Maintenance::isDomainInMaintenance(); - } - - if (rex::isFrontend() && ((bool) $addon->getConfig('block_frontend') || $domainInMaintenance)) { + if (rex::isFrontend() && ((bool) $addon->getConfig('block_frontend') || Maintenance::isDomainInMaintenance())) { Maintenance::checkFrontend(); }assets/css/maintenance-icons.css (1)
55-65: Moin! Pseudo-Elemente bei Option-Tags haben begrenzte Browser-Unterstützung.Die Verwendung von
::beforeauf<option>-Elementen funktioniert nicht zuverlässig in allen Browsern. Falls die Icons in den Dropdown-Optionen nicht erscheinen, sollte eine alternative Lösung erwogen werden (z.B. Custom-Dropdown oder Icons im Label).pages/domains.php (1)
123-133: Moin! Verwende strikte Vergleiche in JavaScript.Der lose Vergleich (
==) sollte durch einen strikten Vergleich (===) ersetzt werden, um unerwartetes Typumwandlungsverhalten zu vermeiden.- if ($(this).val() == '1') { + if ($(this).val() === '1') {pages/frontend.sidebar.php (2)
44-44: Moin! Verwende strikte Vergleiche für String-Checks.Der Vergleich
'default' == $keysollte strikt sein (===), um unerwartete Typumwandlungen zu vermeiden.- if ('default' == $key) { + if ('default' === $key) {
48-63: Moin! Strikte Vergleiche für Domain-Status verwenden.Die Prüfung des Domain-Status auf Zeile 51 verwendet einen losen Vergleich. Verwende strikte Vergleiche für mehr Typ-Sicherheit.
- $isDomainLocked = $allDomainsLocked || (isset($domainStatus[$key]) && 1 == $domainStatus[$key]); + $isDomainLocked = $allDomainsLocked || (isset($domainStatus[$key]) && 1 === $domainStatus[$key]);fragments/maintenance/frontend.php (1)
26-358: Moin! Inline-CSS ist funktional, könnte aber externalisiert werden.Das inline CSS (333 Zeilen) ist vollständig und modern (CSS-Variablen, Dark Mode, Responsive), erhöht aber die Dateigröße und verhindert Browser-Caching. Die Nonce-Verwendung für CSP ist korrekt.
Erwäge, das CSS in eine externe Datei auszulagern (z.B.
assets/css/maintenance-frontend.css) und per Asset-System zu laden. Das verbessert Caching und Wartbarkeit. Der Trade-off ist, dass die Wartungsseite dann von einem externen Asset abhängig ist.Pro extern: Caching, Wartbarkeit, kleinere HTML-Datei
Pro inline: Keine externe Abhängigkeit, funktioniert auch bei Asset-Problemen
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
assets/css/maintenance-icons.css(1 hunks)boot.php(2 hunks)fragments/maintenance/frontend.php(2 hunks)fragments/maintenance/frontend_old.php(1 hunks)fragments/maintenance/login.php(1 hunks)lang/de_de.lang(4 hunks)lib/Maintenance.php(4 hunks)package.yml(2 hunks)pages/domains.php(1 hunks)pages/frontend.advanced.php(1 hunks)pages/frontend.announcement.php(1 hunks)pages/frontend.index.php(1 hunks)pages/frontend.php(0 hunks)pages/frontend.sidebar.php(1 hunks)update.php(1 hunks)
💤 Files with no reviewable changes (1)
- pages/frontend.php
🧰 Additional context used
🧬 Code graph analysis (2)
boot.php (1)
lib/Maintenance.php (3)
Maintenance(29-407)isDomainInMaintenance(128-152)getConfig(395-398)
pages/domains.php (1)
lib/Maintenance.php (1)
getConfig(395-398)
🔇 Additional comments (19)
package.yml (1)
75-75: Moin! Editor-Wechsel könnte Breaking Change sein.Der Wechsel von Redactor zu CKEditor5 als Standard-Editor sollte in den Upgrade-Hinweisen dokumentiert werden, damit bestehende Installationen nicht überrascht werden.
Bitte stellt sicher, dass diese Änderung in der README oder im CHANGELOG dokumentiert ist.
fragments/maintenance/login.php (1)
2-6: Moin! Gute Absicherung des Login-Formulars.Die Bedingung stellt sicher, dass das Passwort-Formular nur angezeigt wird, wenn tatsächlich ein Passwort konfiguriert ist. Das verhindert eine verwirrende leere Login-Maske.
update.php (1)
67-93: Moin! Saubere Migration der Domain-Whitelist.Die Migrations-Logik invertiert korrekt die alte Whitelist (erlaubte Domains) in das neue System mit domain_status (gesperrte Domains). Die Kommentare erklären die Logik gut und die Implementierung ist korrekt.
assets/css/maintenance-icons.css (1)
13-13: Moin! FontAwesome-Abhängigkeit prüfen.Das CSS nutzt FontAwesome-Icons (font-family: 'FontAwesome'), setzt aber voraus, dass diese bereits geladen sind. Bitte stellt sicher, dass FontAwesome im REDAXO-Backend verfügbar ist (ist normalerweise der Fall).
pages/frontend.announcement.php (2)
16-19: Moin! Zugriffskontrolle korrekt implementiert.Die Admin-Prüfung ist korrekt umgesetzt und verhindert unautorisierten Zugriff.
30-32: Moin! Der Platzhalter wird korrekt ersetzt – kein Issue vorhanden.Die Verifizierung zeigt, dass die Platzhalter-Syntax vollständig implementiert ist:
- boot.php (Zeilen 47–49): Ein
OUTPUT_FILTER-Hook führtstr_replace()aus und ersetztclass="###maintenance-settings-editor###"mit dem tatsächlichen Editor-Klassennamen aus der Config (rex_config::get('maintenance', 'editor'))- pages/frontend.announcement.php (Zeile 31): Der Platzhalter wird korrekt gesetzt
Die Ersetzung erfolgt während der Output-Filterung, bevor das HTML an den Browser gesendet wird. Dies ist ein valides Muster für bedingte Klassenzuweisung in REDAXO. Der Code funktioniert wie beabsichtigt.
Likely an incorrect or invalid review comment.
pages/domains.php (3)
16-18: Moin! YRewrite-Verfügbarkeitsprüfung korrekt implementiert.Die Prüfung verhindert sauber Fehler, falls YRewrite nicht verfügbar ist.
29-51: Moin! Speicherlogik ist korrekt implementiert.Die Formularverarbeitung ist sauber strukturiert: Erst die globale Einstellung, dann die individuellen Domain-Einstellungen nur wenn nötig. Die Verwendung von
md5()für Feldnamen ist akzeptabel, um Sonderzeichen in Domain-Namen zu handhaben.
76-91: Moin! XSS-Schutz für Domain-URLs fehlt teilweise.Auf Zeile 80 wird
htmlspecialchars($domain->getUrl())verwendet, aber der Domain-Name selbst wird direkt ausgegeben. Obwohl YRewrite diese Daten kontrolliert, sollte zur Absicherung auch der Domain-Name escaped werden.Wende diesen Diff an:
- $content .= '<td><strong>' . htmlspecialchars($name) . '</strong><br><small class="text-muted">' . htmlspecialchars($domain->getUrl()) . '</small></td>'; + $content .= '<td><strong>' . rex_escape($name) . '</strong><br><small class="text-muted">' . rex_escape($domain->getUrl()) . '</small></td>';Likely an incorrect or invalid review comment.
pages/frontend.advanced.php (2)
16-19: Moin! Admin-Zugriffskontrolle korrekt umgesetzt.
83-110: Moin! IP-Hinzufügen-Logik ist gut implementiert.Die Implementierung prüft korrekt auf Duplikate, aktualisiert sowohl den Input-Wert als auch das Tokenfield-Widget und verhindert mehrfaches Hinzufügen durch Deaktivierung des Buttons.
lib/Maintenance.php (4)
20-20: Moin! Import der count()-Funktion ist korrekt.Der Import wird für die Domain-Zählung in der Indicator-Logik benötigt.
351-361: Moin! Domain-Indicator-Logik ist sauber implementiert.Die Anzeige unterscheidet korrekt zwischen "Alle Domains gesperrt" und individuellen Domain-Sperren. Die Verwendung von
array_filter()ist effizient.
125-153: Moin! Keine Probleme mit der Domain-Maintenance-Logik.Die Verifizierung zeigt:
$domainStatuswird konsistent mit booleschen Werten populiert:
- In
update.php(Zeile 82):!in_array()liefert boolean- In
pages/domains.php(Zeile 41):rex_post(..., 'bool', false)liefert booleanDer Truthiness-Check in Zeile 146 funktioniert deshalb einwandfrei. Keine Gefahr von unerwartetem Verhalten durch Strings oder andere Werte.
247-253: Moin! Die Verhaltensänderung ist intentional, aber verdient dokumentiert zu werden.Ich habe die Implementierung überprüft:
Alte Version (HEAD~1): Alle Prüfungen (IP, YRewrite, Host, Secret, User) liefen direkt und bedingungslos.
Neue Version (HEAD): Eine neue Domain-Maintenance-Prüfung wurde vorgeschaltet. Sie gatet alle anderen Checks – sie laufen nur noch, wenn die Domain im Wartungsmodus ist.
Dies ist kein Fehler, sondern beabsichtigte Architektur der umfassenden Verbesserung (Commit
6ed3e02). Die YRewrite-Domain-Verwaltung ist eine neue Feature.Potenzielle Auswirkungen:
- Wenn
isDomainInMaintenance()falsezurückgibt (keine Domains konfiguriert), wird sofort erlaubt – die bisherigen Checks werden übersprungen- Bestehende Installationen, die sich auf die alten Checks verlassen, könnten betroffen sein
Empfehlung: Dokumentiert diese Verhaltensänderung in den Release Notes. Prüft, ob Backward-Compatibility mit Installationen gewährleistet ist, die die neue Domain-basierte Logik nicht aktiviert haben.
pages/frontend.sidebar.php (1)
74-107: Moin! Quick-Links-Implementierung ist gut strukturiert.Die Navigation berücksichtigt korrekt die aktuelle Seite und zeigt Admin-Links nur für Admins an. Die YRewrite-Integration ist sauber implementiert.
fragments/maintenance/frontend.php (3)
2-9: Moin! Mehrsprachigkeits-Logik ist sauber implementiert.Die Prüfung ob beide Sprachen vorhanden sind erfolgt korrekt und ermöglicht eine konditionale Anzeige des Sprachschalters.
362-385: Moin! Sprachauswahl-UI ist gut umgesetzt.Der konditionale Sprachschalter mit SVG-Icon und Dropdown-Menü ist modern und benutzerfreundlich gestaltet. Die Default-Aktivierung von Englisch ist sinnvoll.
416-478: Moin! JavaScript für Sprachwechsel ist robust implementiert.Die Implementierung behandelt korrekt:
- Dropdown-Toggle und Außerhalb-Klicks
- Sprachwechsel mit visuellen Updates
- SessionStorage-Persistierung mit Try-Catch für Privacy Mode
- Wiederherstellung der Sprachpräferenz beim Laden
- Check rex_addon::exists('yrewrite') before calling methods
- Prevents exceptions when yrewrite addon is not installed
- Affected files: frontend.php, frontend.sidebar.php (2x), Maintenance.php (2x)
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
fragments/maintenance/frontend.php (1)
396-396: Moin! Redundante Bedingung im Ternary-Operator.Die Bedingung
'' === $maintenanceTextDeist überflüssig, da sie bereits durch!$multilanguageEnabledabgedeckt wird. Wenn$maintenanceTextDeleer ist, ist$multilanguageEnabledbereitsfalse(siehe Zeile 8).Vereinfache die Bedingung:
- <div class="maintenance-message maintenance-text <?= !$multilanguageEnabled || '' === $maintenanceTextDe ? 'active' : '' ?>" data-lang="en"> + <div class="maintenance-message maintenance-text <?= !$multilanguageEnabled ? 'active' : '' ?>" data-lang="en">
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
boot.php(2 hunks)fragments/maintenance/frontend.php(2 hunks)fragments/maintenance/frontend_old.php(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- fragments/maintenance/frontend_old.php
🧰 Additional context used
🧬 Code graph analysis (1)
boot.php (1)
lib/Maintenance.php (3)
Maintenance(30-408)isDomainInMaintenance(129-153)getConfig(396-399)
🔇 Additional comments (7)
boot.php (4)
21-25: Moin! Saubere Implementierung der Domain-basierten Wartung.Die Prüfung auf
rex_addon::exists('yrewrite')vorisAvailable()undisDomainInMaintenance()ist korrekt und verhindert Exceptions, wenn YRewrite nicht installiert ist.
27-27: Moin! Logische Verknüpfung der Wartungsbedingungen ist korrekt.Die Kombination aus globalem
block_frontendund domain-basiertem$domainInMaintenanceermöglicht flexible Wartungsszenarien. Die OR-Verknüpfung ist semantisch richtig.
41-41: Moin! CSS-Datei hinzugefügt.Die neue
maintenance-icons.cssergänzt das bestehende Styling. Keine Bedenken.
43-45: Moin! Erweiterte Seitenerkennung für OUTPUT_FILTER.Die zusätzlichen Pfade
maintenance/frontend/indexundmaintenance/frontend/announcementsind konsistent mit der Reorganisation in Unterseiten. Logik ist korrekt.fragments/maintenance/frontend.php (3)
26-26: Moin! Korrekte Verwendung von Content Security Policy Nonces.Die Verwendung von
rex_response::getNonce()für inline Styles und Scripts schützt effektiv gegen XSS-Angriffe. Gut gemacht!Also applies to: 416-416
393-393: Moin! Output Escaping korrekt implementiert.Die Verwendung von
rex_escape()für alle nutzergenerierten Inhalte (Headline und Wartungstexte) verhindert XSS-Vulnerabilities. Sicherheit wird gewährleistet.Also applies to: 397-397, 403-403
417-477: Moin! JavaScript-Implementierung ist solide.Die Sprachumschaltung ist gut strukturiert:
- Try-catch-Blöcke schützen vor sessionStorage-Fehlern (z.B. im Inkognito-Modus)
- Event-Propagation korrekt gestoppt
- Sprachauswahl wird persistent gespeichert und wiederhergestellt
- DOM-Manipulation ist sauber und verständlich
- Fix: Internationalize hardcoded German text 'hinzugefügt' Added maintenance_ip_added translation key - Fix: Correct spelling 'authentification' to 'authentication' Updated in package.yml, lang files, PHP code Added migration for existing installations - Already fixed: Ternary operator logic in frontend.php - Already fixed: YRewrite existence checks
- Fix login.php: Use authentication_mode instead of authentification_mode - Improve update.php migration: Always remove old config key - All files now consistently use 'authentication' (correct spelling)
README changes: - Set Thomas Skerbis as lead developer - Remove sponsor references - Update project team structure Console command enhancements: - Add 'status' command to show current maintenance state - Add 'frontend on/off' for frontend maintenance - Add 'backend on/off' for backend maintenance - Add 'all on/off' to toggle all modes at once - Add 'domain <name> --lock/--unlock' for YRewrite domains - Maintain backward compatibility with legacy 'on/off' commands - Add comprehensive documentation for all commands
Problem: When only German text (maintenance_text_de) was filled and English text was empty, no text was displayed because the DE block didn't receive the 'active' class. Solution: Add fallback logic for DE block: - DE is active if multilanguage is disabled OR only DE text exists - EN is active if multilanguage is disabled OR only EN text exists This ensures at least one text block is always visible when text is provided.
Removed overly restrictive condition that required both password mode AND a set secret. The login form should be displayed whenever password mode is selected, regardless of whether a secret is actually configured. This allows users to see the login form immediately after selecting password authentication mode, even before setting a password.
- Add id attribute to password input field for better accessibility - Add autocomplete='off' for better security - Improve code formatting and comments - Add debug comment placeholder for troubleshooting
Implements feature request for permanent site blocking without maintenance messaging, ideal for staging environments in deployment processes. Features: - New 'silent_mode' config option - Sends only HTTP status code (503/403) without HTML content - Prevents information disclosure about CMS - Perfect for staging systems that should be permanently offline - Accessible only via backend login, IP whitelist, or secret URL Changes: - Added silent_mode to package.yml default_config - Added silent_mode checkbox in advanced settings - Implemented logic in Maintenance::checkFrontend() - Added German translations - Updated README with Silent Mode documentation Use case: Production preview systems that need permanent protection without revealing 'maintenance mode' or CMS information.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
fragments/maintenance/frontend.php (1)
26-358: Moin! Optional: Erwäge Auslagerung der CSS-Styles in eine externe Datei.Der inline Style-Block umfasst ~332 Zeilen. Für bessere Wartbarkeit könnte man die Styles in eine separate CSS-Datei auslagern (z.B.
assets/css/maintenance-frontend.css). Dies würde die Lesbarkeit des Templates verbessern und CSS-Caching ermöglichen.Für eine eigenständige Maintenance-Page ist inline CSS jedoch akzeptabel, zumal die CSP-Nonce korrekt verwendet wird.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
README.md(3 hunks)fragments/maintenance/frontend.php(1 hunks)fragments/maintenance/login.php(1 hunks)lang/de_de.lang(4 hunks)lib/Maintenance.php(6 hunks)lib/command/maintenance_mode.php(3 hunks)package.yml(3 hunks)pages/frontend.advanced.php(1 hunks)pages/frontend.index.php(1 hunks)update.php(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- pages/frontend.index.php
- update.php
- pages/frontend.advanced.php
🧰 Additional context used
🧬 Code graph analysis (1)
lib/command/maintenance_mode.php (1)
lib/Maintenance.php (1)
getConfig(405-408)
🪛 LanguageTool
README.md
[grammar] ~50-~50: Ersetze das Satzzeichen
Context: ...staltung erfolgen. ### Silent Mode für Staging/Development-Umgebungen Der **Silent Mo...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_STAGINGSLASHDEVELOPMENTDASHUMGEBUNGEN_STAGINGDASHSLASHDEVELOPMENTDASHUMGEBUNGEN)
[grammar] ~50-~50: Hier könnte ein Fehler sein.
Context: ... Mode für Staging/Development-Umgebungen Der Silent Mode ist ideal für Stagin...
(QB_NEW_DE)
[grammar] ~52-~52: Hier könnte ein Fehler sein.
Context: ...gen, die permanent gesperrt sein sollen: * Sendet nur den HTTP-Status-Code (z.B. 50...
(QB_NEW_DE)
[uncategorized] ~54-~54: Uneinheitliche Verwendung von Bindestrichen. Der Text enthält sowohl ‚HTTP-Status-Code‘ als auch ‚HTTP-Statuscode‘.
Context: ...gesperrt sein sollen: * Sendet nur den HTTP-Status-Code (z.B. 503 oder 403) * Zeigt keine H...
(DE_COMPOUND_COHERENCY)
[grammar] ~54-~54: Ergänze ein Leerzeichen
Context: ...: * Sendet nur den HTTP-Status-Code (z.B. 503 oder 403) * Zeigt keine HTML-W...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_ORTHOGRAPHY_SPACE)
[uncategorized] ~55-~55: Fehlendes Komma: Teilsätze, Einschübe, Aufzählungen und direkte Rede müssen durch ein Komma vom Rest des Satzes getrennt werden.
Context: ...3) * Zeigt keine HTML-Wartungsseite an * Verhindert Rückschlüsse auf das verwe...
(AI_DE_KOMMA_MISSING_COMMA)
[grammar] ~57-~57: Hier könnte ein Fehler sein.
Context: ...ie nur nach Login zugänglich sein sollen Aktivierung: In den erweiterten Einste...
(QB_NEW_DE)
[grammar] ~59-~59: Passe das Symbol an
Context: ...n zugänglich sein sollen Aktivierung: In den erweiterten Einstellungen (Einst...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_OTHER)
[grammar] ~59-~59: Ersetze das Satzzeichen
Context: ...ten Einstellungen (Einstellungen) unter "HTTP-Einstellungen" die Option "Silent Mode"...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~59-~59: Ersetze das Satzzeichen
Context: ...nstellungen (Einstellungen) unter "HTTP-Einstellungen" die Option "Silent Mode" aktivieren. #...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~59-~59: Ersetze das Satzzeichen
Context: ...) unter "HTTP-Einstellungen" die Option "Silent Mode" aktivieren. ## Anzeige des aktue...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~59-~59: Ersetze das Satzzeichen
Context: ..."HTTP-Einstellungen" die Option "Silent Mode" aktivieren. ## Anzeige des aktuellen S...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~59-~59: Hier könnte ein Fehler sein.
Context: ...en" die Option "Silent Mode" aktivieren. ## Anzeige des aktuellen Status im REDAXO-H...
(QB_NEW_DE)
[grammar] ~81-~81: Verwende Bindestriche bei Nomen
Context: ...` wieder crawlen. 🕵🏻 ## Konsole Das Addon bietet verschiedene Konsolen-Befehle zu...
(QB_NEW_DE_OTHER_ERROR_IDS_ADD_ON_2)
[grammar] ~81-~81: Wähle ein passenderes Wort
Context: ... Konsole Das Addon bietet verschiedene Konsolen-Befehle zur Verwaltung des Wartungsmodus: ### ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_NOUN)
[grammar] ~81-~81: Hier könnte ein Fehler sein.
Context: ...efehle zur Verwaltung des Wartungsmodus: ### Status anzeigen Zeigt den aktuellen Sta...
(QB_NEW_DE)
[grammar] ~83-~83: Hier könnte ein Fehler sein.
Context: ... des Wartungsmodus: ### Status anzeigen Zeigt den aktuellen Status aller Wartung...
(QB_NEW_DE)
[grammar] ~85-~85: Hier könnte ein Fehler sein.
Context: ... aktuellen Status aller Wartungsmodi an: bash php redaxo/bin/console maintenance:mode status ### Frontend-Wartungsmodus Aktivieren: ```b...
(QB_NEW_DE)
[grammar] ~91-~91: Hier könnte ein Fehler sein.
Context: ...e status ### Frontend-Wartungsmodus Aktivieren:bash php redaxo/bin/conso...
(QB_NEW_DE)
[grammar] ~93-~93: Hier könnte ein Fehler sein.
Context: ... ### Frontend-Wartungsmodus Aktivieren: bash php redaxo/bin/console maintenance:mode frontend on Deaktivieren: ```bash php redaxo/bin/con...
(QB_NEW_DE)
[grammar] ~98-~98: Hier könnte ein Fehler sein.
Context: ...ance:mode frontend on Deaktivieren:bash php redaxo/bin/console maintenance:mode frontend off ### Backend-Wartungsmodus Aktivieren:ba...
(QB_NEW_DE)
[grammar] ~103-~103: Hier könnte ein Fehler sein.
Context: ...ntend off ### Backend-Wartungsmodus Aktivieren:bash php redaxo/bin/conso...
(QB_NEW_DE)
[grammar] ~105-~105: Hier könnte ein Fehler sein.
Context: ... ### Backend-Wartungsmodus Aktivieren: bash php redaxo/bin/console maintenance:mode backend on Deaktivieren: ```bash php redaxo/bin/con...
(QB_NEW_DE)
[grammar] ~110-~110: Hier könnte ein Fehler sein.
Context: ...nance:mode backend on Deaktivieren:bash php redaxo/bin/console maintenance:mode backend off ``` ### Alle Modi gleichzeitig Alle Wartungsmod...
(QB_NEW_DE)
[grammar] ~115-~115: Hier könnte ein Fehler sein.
Context: ...kend off ``` ### Alle Modi gleichzeitig Alle Wartungsmodi (Frontend, Backend und...
(QB_NEW_DE)
[grammar] ~117-~117: Hier könnte ein Fehler sein.
Context: ...d, Backend und alle Domains) aktivieren: bash php redaxo/bin/console maintenance:mode all on Alle Wartungsmodi deaktivieren: ```bash ...
(QB_NEW_DE)
[grammar] ~122-~122: Hier könnte ein Fehler sein.
Context: ... on Alle Wartungsmodi deaktivieren:bash php redaxo/bin/console maintenance:mode all off ``` ### Domain-spezifische Wartung (YRewrite) E...
(QB_NEW_DE)
[grammar] ~127-~127: Hier könnte ein Fehler sein.
Context: ...## Domain-spezifische Wartung (YRewrite) Einzelne Domain sperren: ```bash php red...
(QB_NEW_DE)
[grammar] ~129-~129: Hier könnte ein Fehler sein.
Context: ...ung (YRewrite) Einzelne Domain sperren: bash php redaxo/bin/console maintenance:mode domain example.com --lock Einzelne Domain entsperren: ```bash php ...
(QB_NEW_DE)
[grammar] ~134-~134: Hier könnte ein Fehler sein.
Context: ... --lock Einzelne Domain entsperren:bash php redaxo/bin/console maintenance:mode domain example.com --unlock ``` ### Legacy-Unterstützung Die alten Befehle ...
(QB_NEW_DE)
[grammar] ~139-~139: Hier könnte ein Fehler sein.
Context: ...m --unlock ``` ### Legacy-Unterstützung Die alten Befehle funktionieren weiterhi...
(QB_NEW_DE)
[grammar] ~141-~141: Hier könnte ein Fehler sein.
Context: ...terhin (steuern nur den Frontend-Modus): bash php redaxo/bin/console maintenance:mode on php redaxo/bin/console maintenance:mode off ## Autor Thomas Skerbis – [KLXM Crossm...
(QB_NEW_DE)
[grammar] ~148-~148: Hier könnte ein Fehler sein.
Context: ...nsole maintenance:mode off ``` ## Autor Thomas Skerbis – [KLXM Crossmedia](htt...
(QB_NEW_DE)
[grammar] ~150-~150: Hier könnte ein Fehler sein.
Context: ...r Thomas Skerbis – KLXM Crossmedia ## Projekt-Lead * [Thomas Skerbis](https:/...
(QB_NEW_DE)
[grammar] ~152-~152: Hier könnte ein Fehler sein.
Context: ...media](https://klxm.de) ## Projekt-Lead * [Thomas Skerbis](https://github.com/skerb...
(QB_NEW_DE)
[grammar] ~154-~154: Hier könnte ein Fehler sein.
Context: ....de) ## Projekt-Lead * Thomas Skerbis ## Credits Danke an: * [Christian Gehrke]...
(QB_NEW_DE)
[grammar] ~157-~157: Hier könnte ein Fehler sein.
Context: ...https://github.com/skerbis) ## Credits Danke an: * [Christian Gehrke](https://...
(QB_NEW_DE)
[grammar] ~159-~159: Hier könnte ein Fehler sein.
Context: ...hub.com/skerbis) ## Credits Danke an: * [Christian Gehrke](https://github.com/chr...
(QB_NEW_DE)
[grammar] ~161-~161: Wähle ein passenderes Wort
Context: ... Credits Danke an: * Christian Gehrke // first ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_NOUN)
🔇 Additional comments (4)
fragments/maintenance/frontend.php (1)
416-478: Moin! JavaScript-Implementierung ist solide.Die clientseitige Sprachverwaltung ist gut umgesetzt:
- Event-Handler korrekt gebunden
stopPropagation()verhindert sofortiges Schließen des Dropdowns- Try-catch um
sessionStorage-Zugriffe schützt vor Privacy-Modi- Sprachpräferenz wird persistent gespeichert und wiederhergestellt
Der Code ist CSP-konform (Nonce verwendet) und funktioniert auch bei deaktiviertem sessionStorage.
Hinweis: Die Sprachwahl funktioniert korrekt, aber der kritische Bug in den Textblöcken (Zeilen 395-405) muss behoben werden, damit beim Erstbesuch standardmäßig englischer Text angezeigt wird.
package.yml (3)
18-30: Moin! Subpage-Struktur ist sauber umgesetzt.Die neuen verschachtelten Unterseiten unter
frontendsind logisch strukturiert:
index: Allgemeine Einstellungen (Zugriff viamaintenance[frontend])advanced: Erweiterte Einstellungen (nur Admin)announcement: Ankündigung (nur Admin)Die Berechtigungszuordnung ist sinnvoll und folgt REDAXO-Konventionen.
35-38: Moin! Domains-Subpage korrekt konfiguriert.Die neue
domains-Unterseite ist sinnvoll für die YRewrite-Domain-Verwaltung implementiert. Icon-Wahl (fa-sitemap) passt gut zur Funktionalität, und die Berechtigungmaintenance[frontend]ist angemessen.
67-84: Moin! Neue Config-Keys sind sinnvoll definiert.Die hinzugefügten Konfigurationsschlüssel unterstützen die neuen Features gut:
allowed_yrewrite_domains,domain_status,all_domains_locked: Ermöglichen domain-spezifische Wartungauthentication_mode: Korrekte Schreibweise (✓ fix from "authentification")maintenance_text_en/maintenance_text_de: Mehrsprachige Wartungstexte mit vernünftigen Defaultssilent_mode: Praktisch für HTTP-Status ohne Contenteditor: Migration zu CKEditor 5 ist zeitgemäßDie Defaults sind sicher gewählt (Flags auf
false, Arrays leer, Strings leer).Hinweis: Die Editor-Migration sollte in
update.phpbehandelt werden (lt. PR-Beschreibung "Migrationen vorhanden").
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
- Behebt Ternary-Operator Fehler: EN-Text war immer als 'active' markiert - DE-Text ist jetzt standardmäßig 'active', EN-Text nur wenn kein DE-Text vorhanden
- DE-Text ist jetzt standardmäßig aktiv - EN-Text nur aktiv wenn kein DE-Text vorhanden - Konsistente Logik zwischen frontend.php und frontend_old.php
- Behebt kritischen Bug: Early-Return umging block_frontend-Schalter - checkFrontend() prüft jetzt sowohl block_frontend als auch domainbasierte Wartung - Frontend wird nur dann erlaubt, wenn BEIDE Flags inaktiv sind Fixes: #156 (comment)
- YRewrite Existenz-Check in domains.php hinzugefügt (verhindert Exception) - Redundanten Domain-Check in boot.php entfernt (isDomainInMaintenance in checkFrontend) - Silent Mode Check früher durchgeführt (direkt nach Maintenance-Check) * Spart unnötige IP/Host/Secret-Checks bei Silent Mode * Verbessert Performance für Staging-Umgebungen
Probleme behoben: - Button zum Hinzufügen der eigenen IP fehlte in Sidebar - JavaScript nutzt jetzt Event-Delegation (document.on) - Timeout für Tokenfield-Initialisierung hinzugefügt - Feedback für bereits vorhandene IPs Verbesserungen: - Zeigt eigene IP-Adresse in Sidebar (nur auf Advanced-Seite) - Button wechselt zu Erfolg (grün) oder Warnung (gelb) - CSP-Nonce für inline JavaScript - Neue Sprachschlüssel: maintenance_my_ip_title, maintenance_add_my_ip
- rex_i18n::msg() funktioniert nicht im Frontend (AddOn-Sprachdateien nicht geladen) - Hardcode 'Language' statt translate:maintenance_language - Behebt [translate:maintenance_language] Anzeige im Frontend
Fixes:
- $currentPage wird jetzt am Anfang der Sidebar definiert (Zeile 8 statt 94)
- Verhindert 'Undefined variable' Warning
IP-Button Verbesserungen:
- waitForTokenfield() Funktion für robuste Tokenfield-Initialisierung
- Verwendet tokenfield('getTokens') statt String-Splitting
- Besseres Timing-Handling mit Retry-Mechanismus
- Entfernt btn-xs Klasse bei Feedback für bessere Sichtbarkeit
- Console-Fehlerbehandlung
- Tokenfield-Abhängigkeit entfernt, einfaches Textfeld verwendet - IP-Sektion aus Sidebar entfernt - Vereinfachte JavaScript-Logik nach Upkeep-Vorbild - Verbesserte UI mit formatierten IP-Zeilen - Sprachschlüssel ergänzt (maintenance_your_ip, maintenance_server_ip, etc.)
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
lib/Maintenance.php (1)
142-143: Moin! Potenzieller Null-Pointer-Access beim Domain-Check.Die Methode
rex_yrewrite::getDomainByArticleId()kannnulloderfalsezurückgeben, wenn kein aktueller Artikel oder keine Sprache gesetzt ist. In Zeile 143 wird ohne Null-CheckgetName()aufgerufen.Füge einen expliziten Null-Check hinzu:
- if ($ydomain = rex_yrewrite::getDomainByArticleId(rex_article::getCurrentId(), rex_clang::getCurrentId())) { + $ydomain = rex_yrewrite::getDomainByArticleId(rex_article::getCurrentId(), rex_clang::getCurrentId()); + if ($ydomain && $ydomain instanceof rex_yrewrite_domain) { $domainName = $ydomain->getName();fragments/maintenance/frontend.php (1)
395-405: Moin! KRITISCHER BUG: Inkonsistente Sprach-Anzeige bei Mehrsprachigkeit!Die aktuelle Logik führt zu einem kritischen Darstellungsfehler, wenn beide Sprachtexte vorhanden sind:
Problem-Szenario: Beide Texte gefüllt (
maintenance_text_enUNDmaintenance_text_de)
multilanguageEnabled = true✓- Language-Dropdown zeigt EN als aktiv (Zeile 374) ✓
- EN-Textblock (Zeile 396):
'' === $maintenanceTextDe ? 'active' : ''=''(KEINE active-Klasse) ✗- DE-Textblock (Zeile 402): Hard-codiert
active✓- Ergebnis: DE-Text wird angezeigt, aber EN ist im Dropdown markiert → Inkonsistenz!
Frühere Reviews haben dieses Problem identifiziert, aber die Korrektur wurde nicht vollständig angewendet.
Korrigiere die Ternary-Operatoren:
<?php if ('' !== $maintenanceTextEn): ?> - <div class="maintenance-message maintenance-text <?= '' === $maintenanceTextDe ? 'active' : '' ?>" data-lang="en"> + <div class="maintenance-message maintenance-text <?= $multilanguageEnabled || '' === $maintenanceTextDe ? 'active' : '' ?>" data-lang="en"> <?= nl2br(rex_escape($maintenanceTextEn)) ?> </div> <?php endif ?> <?php if ('' !== $maintenanceTextDe): ?> - <div class="maintenance-message maintenance-text active" data-lang="de"> + <div class="maintenance-message maintenance-text <?= !$multilanguageEnabled && '' === $maintenanceTextEn ? 'active' : '' ?>" data-lang="de"> <?= nl2br(rex_escape($maintenanceTextDe)) ?> </div> <?php endif ?>Logik nach Korrektur:
- EN aktiv wenn: Multilanguage aktiviert (Standard EN) ODER nur EN vorhanden
- DE aktiv wenn: Nur DE vorhanden (kein Multilanguage, kein EN)
- JavaScript übernimmt dann die Sprachumschaltung bei Mehrsprachigkeit
🧹 Nitpick comments (7)
lib/Maintenance.php (1)
169-173: Moin! Doppelter Config-Read derauthentication_mode.Der Config-Wert
authentication_modewird in Zeile 169 gelesen und dann in Zeile 172 erneut. Die zweite Zeile ist redundant.Entferne die doppelte Zuweisung:
$maintenance_secret = rex_request('maintenance_secret', 'string', ''); $authentication_mode = (string) self::getConfig('authentication_mode', ''); // Authentifizierung prüfen - für URL-Parameter und auch bei leerem Modus - $authentication_mode = (string) self::getConfig('authentication_mode', ''); if (('' === $authentication_mode || 'URL' === $authentication_mode || 'password' === $authentication_mode)lib/cronjob/scheduled_maintenance.php (1)
32-41: Moin! Hardcodierte deutsche Strings im Cronjob.Die Log-Messages in Zeilen 35, 37 und 40 sind auf Deutsch hardcodiert, während
getTypeName()(Zeile 48) korrektrex_i18n::msg()verwendet. Das ist inkonsistent.Verwende i18n-Keys für die Messages:
// Log what happened if ('' !== $scheduledStart || '' !== $scheduledEnd) { if ($blockFrontend) { - $this->setMessage('Wartungsmodus ist aktiv (geplant bis: ' . $scheduledEnd . ')'); + $this->setMessage(rex_i18n::msg('maintenance_cronjob_active_until', $scheduledEnd)); } else { - $this->setMessage('Wartungsmodus ist inaktiv (geplanter Start: ' . $scheduledStart . ')'); + $this->setMessage(rex_i18n::msg('maintenance_cronjob_scheduled_start', $scheduledStart)); } } else { - $this->setMessage('Keine geplante Wartung konfiguriert'); + $this->setMessage(rex_i18n::msg('maintenance_cronjob_not_configured')); }Die entsprechenden Keys müssten dann in
lang/de_de.langergänzt werden.lang/de_de.lang (1)
24-25: Moin! Cronjob-Übersetzungskeys unvollständig.In Zeile 25 ist nur
maintenance_cronjob_scheduled_namedefiniert. Für die Cronjob-Messages (siehe Review zulib/cronjob/scheduled_maintenance.php) fehlen jedoch Keys wie:
maintenance_cronjob_active_untilmaintenance_cronjob_scheduled_startmaintenance_cronjob_not_configuredFalls die Messages im Cronjob internationalisiert werden sollen, ergänze diese Keys. Ansonsten können die deutschen Strings im Cronjob bleiben (ist dann aber inkonsistent mit
getTypeName()).pages/frontend.index.php (3)
31-39: Moin! Erwäge TextAreaField für längere Wartungstexte.Die Wartungstexte (
maintenance_text_enundmaintenance_text_de) verwendenaddTextField(), was für potenziell längere, mehrzeilige Nachrichten einschränkend sein könnte. Für bessere Benutzerfreundlichkeit könnteaddTextAreaField()geeigneter sein.Beispiel-Diff:
-$field = $form->addTextField('maintenance_text_en'); +$field = $form->addTextAreaField('maintenance_text_en'); $field->setLabel($addon->i18n('maintenance_text_en_label')); $field->setNotice($addon->i18n('maintenance_text_en_notice')); -$field = $form->addTextField('maintenance_text_de'); +$field = $form->addTextAreaField('maintenance_text_de'); $field->setLabel($addon->i18n('maintenance_text_de_label')); $field->setNotice($addon->i18n('maintenance_text_de_notice'));
47-51: Moin! Zufälliges Beispiel im Notice-Text könnte verwirren.Das Notice-Feld generiert bei jedem Seitenaufruf einen neuen Zufallswert via
bin2hex(random_bytes(16)). Das könnte Nutzer irritieren, da sich der Beispieltext ständig ändert. Erwäge einen festen Beispielwert im i18n-String.Beispiel:
-$field->setNotice($addon->i18n('maintenance_secret_notice', bin2hex(random_bytes(16)))); +$field->setNotice($addon->i18n('maintenance_secret_notice'));Und in der Lang-Datei einen festen Beispielwert ergänzen.
80-90: Moin! Erwäge datetime-local Input für bessere UX.Die Felder
scheduled_startundscheduled_endverwenden einfache Textfelder für Datetime-Eingaben. Das erhöht das Risiko von Formatfehlern. Erwäge die Verwendung vontype="datetime-local"für bessere Benutzerfreundlichkeit und Browser-native Datumspicker.Beispiel-Diff:
$field = $form->addTextField('scheduled_start'); $field->setLabel($addon->i18n('maintenance_scheduled_start_label')); $field->setNotice($addon->i18n('maintenance_scheduled_start_notice') . '<br><small>' . $addon->i18n('maintenance_scheduled_example') . '</small>'); -$field->setAttribute('placeholder', '2025-12-31 02:00:00'); +$field->setAttribute('type', 'datetime-local'); $field = $form->addTextField('scheduled_end'); $field->setLabel($addon->i18n('maintenance_scheduled_end_label')); $field->setNotice($addon->i18n('maintenance_scheduled_end_notice') . '<br><small>' . $addon->i18n('maintenance_scheduled_example') . '</small>'); -$field->setAttribute('placeholder', '2025-12-31 06:00:00'); +$field->setAttribute('type', 'datetime-local');Hinweis: Datetime-local verwendet ISO 8601 Format (YYYY-MM-DDTHH:MM), Backend-Validierung muss entsprechend angepasst werden.
fragments/maintenance/frontend.php (1)
26-358: Moin! Umfangreiches Inline-Styling mit CSP-Compliance.Das Inline-CSS mit Nonce (Zeile 26) ist CSP-konform und für eine Wartungsseite angemessen. Das Styling umfasst Dark Mode, Responsive Design und Animationen – gut umgesetzt.
Optionale Anmerkung: Für bessere Wartbarkeit könnte das CSS in ein separates Template-Fragment ausgelagert werden, aber für eine Wartungsseite ist die Inline-Variante akzeptabel.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
README.md(3 hunks)boot.php(2 hunks)fragments/maintenance/frontend.php(1 hunks)lang/de_de.lang(4 hunks)lib/Maintenance.php(6 hunks)lib/cronjob/scheduled_maintenance.php(1 hunks)package.yml(3 hunks)pages/domains.php(1 hunks)pages/frontend.index.php(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- pages/domains.php
- boot.php
🧰 Additional context used
🧬 Code graph analysis (2)
lib/cronjob/scheduled_maintenance.php (1)
lib/Maintenance.php (3)
Maintenance(30-461)checkScheduledMaintenance(244-277)getConfig(449-452)
pages/frontend.index.php (1)
lib/Maintenance.php (1)
getConfig(449-452)
🪛 LanguageTool
README.md
[grammar] ~24-~24: Hier könnte ein Fehler sein.
Context: ...rsion 3.5.0) ### Zeitgesteuerte Wartung Die zeitgesteuerte Wartung ermöglich...
(QB_NEW_DE)
[grammar] ~26-~26: Hier könnte ein Fehler sein.
Context: ...punkt zu aktivieren und zu deaktivieren: * Request-basiert: Wird bei jedem Seiten...
(QB_NEW_DE)
[grammar] ~28-~28: Ergänze ein Satzzeichen
Context: ...uf geprüft (keine Cronjob-Konfiguration nötig) * Optional per Cronjob: Für präzise...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_PUNCTUATION_PERIOD)
[grammar] ~29-~29: Ersetze das Satzzeichen
Context: ...ür präzisere Steuerung kann der Cronjob "Geplante Wartung prüfen" eingerichtet werden * *...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~29-~29: Ersetze das Satzzeichen
Context: ...rung kann der Cronjob "Geplante Wartung prüfen" eingerichtet werden * **Automatische Be...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~29-~29: Ergänze ein Satzzeichen
Context: ... "Geplante Wartung prüfen" eingerichtet werden * Automatische Bereinigung: Nach er...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_PUNCTUATION_PERIOD)
[grammar] ~30-~30: Hier könnte ein Fehler sein.
Context: ...ie geplanten Zeiten automatisch gelöscht Verwendung: 1. In den Frontend-Einste...
(QB_NEW_DE)
[grammar] ~32-~32: Hier könnte ein Fehler sein.
Context: ...iten automatisch gelöscht Verwendung: 1. In den Frontend-Einstellungen unter "Zei...
(QB_NEW_DE)
[grammar] ~34-~34: Ersetze das Satzzeichen
Context: ... 1. In den Frontend-Einstellungen unter "Zeitgesteuerte Wartung": - Startzeitpunkt einge...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~34-~34: Ersetze das Satzzeichen
Context: ...end-Einstellungen unter "Zeitgesteuerte Wartung": - Startzeitpunkt eingeben (z.B. ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~35-~35: Ergänze ein Leerzeichen
Context: ...g": - Startzeitpunkt eingeben (z.B. 2025-12-31 02:00:00) - **Endzeitp...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_ORTHOGRAPHY_SPACE)
[grammar] ~36-~36: Ergänze ein Leerzeichen
Context: ...:00) - **Endzeitpunkt** eingeben (z.B. 2025-12-31 06:00:00`) 2. Speichern - ...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_ORTHOGRAPHY_SPACE)
[grammar] ~37-~37: Ersetze das Satzzeichen
Context: ...ingeben (z.B. 2025-12-31 06:00:00) 2. Speichern - der Wartungsmodus wird zur konfiguriert...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_DASH_–)
[grammar] ~37-~37: Hier könnte ein Fehler sein.
Context: ...it automatisch aktiviert und deaktiviert Format: YYYY-MM-DD HH:MM:SS (z.B. `2...
(QB_NEW_DE)
[grammar] ~39-~39: Entferne ein Wort
Context: ...utomatisch aktiviert und deaktiviert Format: YYYY-MM-DD HH:MM:SS (z.B. `2025-12-31...
(QB_NEW_DE_OTHER_ERROR_IDS_UNNECESSARY_NOUN)
[grammar] ~39-~39: Ergänze ein Leerzeichen
Context: ...t Format: YYYY-MM-DD HH:MM:SS (z.B. 2025-12-31 23:59:59) ### Sperren de...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_ORTHOGRAPHY_SPACE)
[grammar] ~39-~39: Hier könnte ein Fehler sein.
Context: ...D HH:MM:SS(z.B.2025-12-31 23:59:59`) ### Sperren des REDAXO-Backends * Sperren d...
(QB_NEW_DE)
[grammar] ~68-~68: Ersetze das Satzzeichen
Context: ...staltung erfolgen. ### Silent Mode für Staging/Development-Umgebungen Der **Silent Mo...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_STAGINGSLASHDEVELOPMENTDASHUMGEBUNGEN_STAGINGDASHSLASHDEVELOPMENTDASHUMGEBUNGEN)
[grammar] ~68-~68: Hier könnte ein Fehler sein.
Context: ... Mode für Staging/Development-Umgebungen Der Silent Mode ist ideal für Stagin...
(QB_NEW_DE)
[grammar] ~70-~70: Hier könnte ein Fehler sein.
Context: ...gen, die permanent gesperrt sein sollen: * Sendet nur den HTTP-Status-Code (z.B. 50...
(QB_NEW_DE)
[uncategorized] ~72-~72: Uneinheitliche Verwendung von Bindestrichen. Der Text enthält sowohl ‚HTTP-Status-Code‘ als auch ‚HTTP-Statuscode‘.
Context: ...gesperrt sein sollen: * Sendet nur den HTTP-Status-Code (z.B. 503 oder 403) * Zeigt keine H...
(DE_COMPOUND_COHERENCY)
[grammar] ~72-~72: Ergänze ein Leerzeichen
Context: ...: * Sendet nur den HTTP-Status-Code (z.B. 503 oder 403) * Zeigt keine HTML-W...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_ORTHOGRAPHY_SPACE)
[uncategorized] ~73-~73: Fehlendes Komma: Teilsätze, Einschübe, Aufzählungen und direkte Rede müssen durch ein Komma vom Rest des Satzes getrennt werden.
Context: ...3) * Zeigt keine HTML-Wartungsseite an * Verhindert Rückschlüsse auf das verwe...
(AI_DE_KOMMA_MISSING_COMMA)
[grammar] ~75-~75: Hier könnte ein Fehler sein.
Context: ...ie nur nach Login zugänglich sein sollen Aktivierung: In den erweiterten Einste...
(QB_NEW_DE)
[grammar] ~77-~77: Passe das Symbol an
Context: ...n zugänglich sein sollen Aktivierung: In den erweiterten Einstellungen (Einst...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_OTHER)
[grammar] ~77-~77: Ersetze das Satzzeichen
Context: ...ten Einstellungen (Einstellungen) unter "HTTP-Einstellungen" die Option "Silent Mode"...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~77-~77: Ersetze das Satzzeichen
Context: ...nstellungen (Einstellungen) unter "HTTP-Einstellungen" die Option "Silent Mode" aktivieren. #...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~77-~77: Ersetze das Satzzeichen
Context: ...) unter "HTTP-Einstellungen" die Option "Silent Mode" aktivieren. ## Anzeige des aktue...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~77-~77: Ersetze das Satzzeichen
Context: ..."HTTP-Einstellungen" die Option "Silent Mode" aktivieren. ## Anzeige des aktuellen S...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~77-~77: Hier könnte ein Fehler sein.
Context: ...en" die Option "Silent Mode" aktivieren. ## Anzeige des aktuellen Status im REDAXO-H...
(QB_NEW_DE)
[grammar] ~99-~99: Ergänze ein Satzzeichen
Context: ...` wieder crawlen. 🕵🏻 ## Konsole Das Addon bietet verschiedene Konsolen-Befehle zu...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_PUNCTUATION_ADDDASHON)
[grammar] ~99-~99: Wähle ein passenderes Wort
Context: ... Konsole Das Addon bietet verschiedene Konsolen-Befehle zur Verwaltung des Wartungsmodus: ### ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_NOUN)
[grammar] ~99-~99: Hier könnte ein Fehler sein.
Context: ...efehle zur Verwaltung des Wartungsmodus: ### Status anzeigen Zeigt den aktuellen Sta...
(QB_NEW_DE)
[grammar] ~101-~101: Hier könnte ein Fehler sein.
Context: ... des Wartungsmodus: ### Status anzeigen Zeigt den aktuellen Status aller Wartung...
(QB_NEW_DE)
[grammar] ~103-~103: Hier könnte ein Fehler sein.
Context: ... aktuellen Status aller Wartungsmodi an: bash php redaxo/bin/console maintenance:mode status ### Frontend-Wartungsmodus Aktivieren: ```b...
(QB_NEW_DE)
[grammar] ~109-~109: Hier könnte ein Fehler sein.
Context: ...e status ### Frontend-Wartungsmodus Aktivieren:bash php redaxo/bin/conso...
(QB_NEW_DE)
[grammar] ~111-~111: Hier könnte ein Fehler sein.
Context: ... ### Frontend-Wartungsmodus Aktivieren: bash php redaxo/bin/console maintenance:mode frontend on Deaktivieren: ```bash php redaxo/bin/con...
(QB_NEW_DE)
[grammar] ~116-~116: Hier könnte ein Fehler sein.
Context: ...ance:mode frontend on Deaktivieren:bash php redaxo/bin/console maintenance:mode frontend off ### Backend-Wartungsmodus Aktivieren:ba...
(QB_NEW_DE)
[grammar] ~121-~121: Hier könnte ein Fehler sein.
Context: ...ntend off ### Backend-Wartungsmodus Aktivieren:bash php redaxo/bin/conso...
(QB_NEW_DE)
[grammar] ~123-~123: Hier könnte ein Fehler sein.
Context: ... ### Backend-Wartungsmodus Aktivieren: bash php redaxo/bin/console maintenance:mode backend on Deaktivieren: ```bash php redaxo/bin/con...
(QB_NEW_DE)
[grammar] ~128-~128: Hier könnte ein Fehler sein.
Context: ...nance:mode backend on Deaktivieren:bash php redaxo/bin/console maintenance:mode backend off ``` ### Alle Modi gleichzeitig Alle Wartungsmod...
(QB_NEW_DE)
[grammar] ~133-~133: Hier könnte ein Fehler sein.
Context: ...kend off ``` ### Alle Modi gleichzeitig Alle Wartungsmodi (Frontend, Backend und...
(QB_NEW_DE)
[grammar] ~135-~135: Hier könnte ein Fehler sein.
Context: ...d, Backend und alle Domains) aktivieren: bash php redaxo/bin/console maintenance:mode all on Alle Wartungsmodi deaktivieren: ```bash ...
(QB_NEW_DE)
[grammar] ~140-~140: Hier könnte ein Fehler sein.
Context: ... on Alle Wartungsmodi deaktivieren:bash php redaxo/bin/console maintenance:mode all off ``` ### Domain-spezifische Wartung (YRewrite) E...
(QB_NEW_DE)
[grammar] ~145-~145: Hier könnte ein Fehler sein.
Context: ...## Domain-spezifische Wartung (YRewrite) Einzelne Domain sperren: ```bash php red...
(QB_NEW_DE)
[grammar] ~147-~147: Hier könnte ein Fehler sein.
Context: ...ung (YRewrite) Einzelne Domain sperren: bash php redaxo/bin/console maintenance:mode domain example.com --lock Einzelne Domain entsperren: ```bash php ...
(QB_NEW_DE)
[grammar] ~152-~152: Hier könnte ein Fehler sein.
Context: ... --lock Einzelne Domain entsperren:bash php redaxo/bin/console maintenance:mode domain example.com --unlock ``` ### Legacy-Unterstützung Die alten Befehle ...
(QB_NEW_DE)
[grammar] ~157-~157: Hier könnte ein Fehler sein.
Context: ...m --unlock ``` ### Legacy-Unterstützung Die alten Befehle funktionieren weiterhi...
(QB_NEW_DE)
[grammar] ~159-~159: Hier könnte ein Fehler sein.
Context: ...terhin (steuern nur den Frontend-Modus): bash php redaxo/bin/console maintenance:mode on php redaxo/bin/console maintenance:mode off ## Autor Thomas Skerbis – [KLXM Crossm...
(QB_NEW_DE)
[grammar] ~166-~166: Hier könnte ein Fehler sein.
Context: ...nsole maintenance:mode off ``` ## Autor Thomas Skerbis – [KLXM Crossmedia](htt...
(QB_NEW_DE)
[grammar] ~168-~168: Hier könnte ein Fehler sein.
Context: ...r Thomas Skerbis – KLXM Crossmedia ## Projekt-Lead * [Thomas Skerbis](https:/...
(QB_NEW_DE)
[grammar] ~170-~170: Hier könnte ein Fehler sein.
Context: ...media](https://klxm.de) ## Projekt-Lead * [Thomas Skerbis](https://github.com/skerb...
(QB_NEW_DE)
[grammar] ~172-~172: Hier könnte ein Fehler sein.
Context: ....de) ## Projekt-Lead * Thomas Skerbis ## Credits Danke an: * [Christian Gehrke]...
(QB_NEW_DE)
[grammar] ~175-~175: Hier könnte ein Fehler sein.
Context: ...https://github.com/skerbis) ## Credits Danke an: * [Christian Gehrke](https://...
(QB_NEW_DE)
[grammar] ~177-~177: Hier könnte ein Fehler sein.
Context: ...hub.com/skerbis) ## Credits Danke an: * [Christian Gehrke](https://github.com/chr...
(QB_NEW_DE)
[grammar] ~179-~179: Wähle ein passenderes Wort
Context: ... Credits Danke an: * Christian Gehrke // first ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_NOUN)
🔇 Additional comments (20)
README.md (1)
1-185: LGTM! Umfassende und klare Dokumentation der neuen Features.Die Dokumentation der neuen Features (zeitgesteuerte Wartung, Silent Mode, erweiterte Konsolenbefehle, Domain-Verwaltung) ist sehr gut strukturiert und verständlich. Die Beispiele sind praxisnah und das Format für datetime-Angaben ist klar definiert.
lib/Maintenance.php (3)
240-277: Moin! Scheduled Maintenance Logik sieht solide aus.Die Auto-Aktivierung und Auto-Deaktivierung sind sauber implementiert mit entsprechenden Guards (
!$blockFrontendbzw.$blockFrontend). Das Cleanup nach erfolgreicher Deaktivierung ist gut gelöst.Kleiner Edge-Case-Hinweis: Wenn beide Zeiten (
scheduled_startundscheduled_end) bereits in der Vergangenheit liegen, wird die Wartung kurz aktiviert und sofort wieder deaktiviert. Das ist zwar kein Bug, könnte aber in den Logs etwas verwirrend sein.Optional: Überlege, ob ein zusätzlicher Check sinnvoll wäre, dass
startTime < endTimebeim Speichern der Zeiten validiert wird (z.B. in der Settings-Page).
282-367: Moin! Frontend-Check Logik ist jetzt korrekt.Die Integration der zeitgesteuerten Wartung (Zeile 287) und die kombinierte Prüfung von
blockFrontendunddomainInMaintenance(Zeilen 293-296) ist gut gelöst. Der Silent Mode (Zeilen 299-304) mit frühem Exit ist eine saubere Implementierung.Die zuvor gemeldete Issue mit der Frontend-Sperre wurde korrekt behoben.
404-413: Moin! Domain-Indikatoren sind sauber implementiert.Die Anzeige der Domain-Wartungsstatus im Backend-Menü ist gut gelöst. Die Unterscheidung zwischen globaler Sperre (
D:All) und einzelnen gesperrten Domains (D:count) ist intuitiv.package.yml (2)
64-65: Moin! Cronjob-Interval-Platzhalter{i}unklar.In Zeile 65 wird
interval: '{i}'verwendet. Was bedeutet dieser Platzhalter? Ist das eine REDAXO-Konvention für ein variablen Intervall oder ein Tippfehler?Bitte kläre, ob
{i}durch einen konkreten Wert ersetzt werden sollte (z.B.{1}für minütlich) oder ob das so korrekt ist. Falls das ein Template-Platzhalter ist, sollte das im Code oder in einem Kommentar erklärt werden.
70-71: Moin! Legacy-Configallowed_yrewrite_domainsund Authentifizierung.Zeile 70: Der Key
allowed_yrewrite_domainswird noch in der default_config definiert. Lt. PR-Beschreibung wurde doch vonallowed_yrewrite_domainszudomain_statusmigriert. Ist dieser Legacy-Key noch notwendig oder kann er entfernt werden?Zeile 71: Die Schreibweise
authentication_modeist jetzt korrekt (früherauthentification_mode).Prüfe, ob
allowed_yrewrite_domainsnoch benötigt wird oder ob die Migration in update.php diesen komplett durchdomain_statusersetzt.lib/cronjob/scheduled_maintenance.php (1)
22-44: Moin! Cronjob execute() Logik ist korrekt.Die Methode ruft
checkScheduledMaintenance()auf und gibt dann den aktuellen Status zurück. Der Return-Werttrueist korrekt für erfolgreiche Cronjob-Ausführung.lang/de_de.lang (1)
1-176: Moin! Sprachdatei ist umfassend und konsistent.Die Übersetzungen decken alle neuen Features ab (Domain-Verwaltung, zeitgesteuerte Wartung, Silent Mode, erweiterte Einstellungen). Die Terminologie ist einheitlich und die Texte sind verständlich formuliert.
pages/frontend.index.php (7)
1-17: Moin! Saubere Initialisierung und Standard-Pattern.Die Datei-Header und Form-Initialisierung folgen den REDAXO-Konventionen korrekt. Keine Probleme erkennbar.
19-25: Moin! Korrekte Select-Field-Implementierung.Das Feld
block_frontendist sauber implementiert mit i18n-Unterstützung.
41-45: Moin! Korrekte Number-Input-Implementierung.Das Update-Interval-Feld ist sauber implementiert.
53-58: Moin! Rechtschreibung korrekt - vorheriger Hinweis wurde umgesetzt.Das Feld
authentication_modeverwendet die korrekte Schreibweise. Der frühere Hinweis zur Korrektur von "authentification" wurde erfolgreich umgesetzt.
60-66: Moin! Standard-Implementierung ohne Probleme.Das Feld
block_frontend_rex_userist korrekt umgesetzt.
68-72: Moin! Saubere URL-Feld-Implementierung.Das Redirect-URL-Feld mit HTML5-Typ-Validierung ist korrekt implementiert.
108-121: Moin! Sauberes Layout-Rendering mit Fragment-Pattern.Die Fragment-Initialisierung und das zweispaltige Layout sind korrekt implementiert. Die Sidebar-Integration ist sauber gelöst.
fragments/maintenance/frontend.php (5)
1-9: Moin! Multilanguage-Logik ist korrekt implementiert.Die Prüfung in Zeile 8 aktiviert die Sprachauswahl nur, wenn beide Texte vorhanden sind. Das ist die richtige Logik für die Mehrsprachigkeits-Aktivierung.
10-25: Moin! Saubere HTML-Head-Implementierung mit defensiven Checks.Die YRewrite-Existenzprüfungen in Zeile 19 sind korrekt implementiert mit null-safe operator. Die Meta-Tags und der Titel sind gut strukturiert.
360-385: Moin! Language-Switcher korrekt implementiert.Der Sprachschalter wird nur bei aktivierter Mehrsprachigkeit angezeigt (Zeile 362). Die Verwendung von
rex_i18n::msg('maintenance_language')in Zeile 371 ist korrekt – der frühere Hinweis zu hard-codiertem Text wurde umgesetzt. EN ist standardmäßig aktiv (Zeile 374), was der erwarteten Logik entspricht.
407-413: Moin! Saubere Subfragment-Integration.Die Ausgabe der Subfragments für Ankündigung, Login und Reload ist korrekt implementiert.
415-478: Moin! Solide JavaScript-Implementierung mit CSP-Compliance.Das JavaScript für die Sprachauswahl ist gut strukturiert:
- CSP-konform mit Nonce (Zeile 416) ✓
- Keyboard-freundlich und zugänglich ✓
- SessionStorage mit try-catch für Fehlerbehandlung ✓
- Sprach-Persistierung über Seitenaufrufe ✓
| redirect_backend_to_url: '' # `https://example.com/maintenance.html` | ||
| secret: '' | ||
| editor: 'class="form-control redactor-editor--default"' | ||
| editor: 'class="form-control cke5-editor" data-profile="default"' |
There was a problem hiding this comment.
Moin! Editor-Wechsel von Redactor zu CKEditor 5 könnte Nutzer betreffen.
Die Änderung des Standard-Editors von redactor-editor--default zu cke5-editor (Zeile 78) ist ein potenzieller Breaking Change für Installationen, die nur Redactor installiert haben. CKEditor 5 muss als AddOn vorhanden sein, damit der Editor funktioniert.
Empfehlung:
- Im Update-Prozess (update.php) könnte geprüft werden, ob CKEditor 5 verfügbar ist
- Falls nicht, den alten Editor-Wert beibehalten
- Oder: Im README einen Hinweis auf die Editor-Anforderung ergänzen
🤖 Prompt for AI Agents
In package.yml around line 78 the default editor was changed to CKEditor 5 which
can break installs that only have Redactor; update the migration/update logic
(e.g., update.php) to detect whether the CKEditor 5 addon/plugin is installed
and only switch the stored editor value to the CKEditor 5 class when that addon
is present, otherwise preserve the existing Redactor value as the fallback;
alternatively add a clear note to the README/upgrade instructions that CKEditor
5 must be installed before changing the default editor so administrators can
prepare.
pages/frontend.index.php
Outdated
| // Aktuellen Status anzeigen | ||
| $scheduledStart = (string) $addon->getConfig('scheduled_start', ''); | ||
| $scheduledEnd = (string) $addon->getConfig('scheduled_end', ''); | ||
| if ('' !== $scheduledStart || '' !== $scheduledEnd) { | ||
| $statusHtml = '<div class="alert alert-info">'; | ||
| $statusHtml .= '<strong>' . $addon->i18n('maintenance_scheduled_active') . '</strong><br>'; | ||
| if ('' !== $scheduledStart) { | ||
| $statusHtml .= $addon->i18n('maintenance_scheduled_starts_at') . ': <code>' . rex_escape($scheduledStart) . '</code><br>'; | ||
| } | ||
| if ('' !== $scheduledEnd) { | ||
| $statusHtml .= $addon->i18n('maintenance_scheduled_ends_at') . ': <code>' . rex_escape($scheduledEnd) . '</code>'; | ||
| } | ||
| $statusHtml .= '</div>'; | ||
| $field = $form->addRawField($statusHtml); | ||
| } |
There was a problem hiding this comment.
Moin! Status-Anzeige könnte irreführend sein bei alten oder ungültigen Daten.
Die Status-Anzeige wird angezeigt, sobald scheduled_start oder scheduled_end gesetzt sind, ohne zu prüfen, ob die Zeiten gültig oder aktuell sind. Das könnte verwirrend sein, wenn alte oder abgelaufene Wartungszeiten noch angezeigt werden.
Erwäge eine Validierung hinzuzufügen:
$scheduledStart = (string) $addon->getConfig('scheduled_start', '');
$scheduledEnd = (string) $addon->getConfig('scheduled_end', '');
-if ('' !== $scheduledStart || '' !== $scheduledEnd) {
+
+$now = new DateTimeImmutable();
+$isActive = false;
+$startTime = null;
+$endTime = null;
+
+try {
+ if ('' !== $scheduledStart) {
+ $startTime = new DateTimeImmutable($scheduledStart);
+ }
+ if ('' !== $scheduledEnd) {
+ $endTime = new DateTimeImmutable($scheduledEnd);
+ }
+ if ($startTime || $endTime) {
+ $isActive = true;
+ }
+} catch (Exception $e) {
+ // Invalid datetime format
+}
+
+if ($isActive) {
$statusHtml = '<div class="alert alert-info">';
$statusHtml .= '<strong>' . $addon->i18n('maintenance_scheduled_active') . '</strong><br>';
if ('' !== $scheduledStart) {
$statusHtml .= $addon->i18n('maintenance_scheduled_starts_at') . ': <code>' . rex_escape($scheduledStart) . '</code><br>';
}
if ('' !== $scheduledEnd) {
$statusHtml .= $addon->i18n('maintenance_scheduled_ends_at') . ': <code>' . rex_escape($scheduledEnd) . '</code>';
}
$statusHtml .= '</div>';
$field = $form->addRawField($statusHtml);
}Committable suggestion skipped: line range outside the PR's diff.
- package.yml: Cronjob-Definition vereinfacht (war falsch formatiert) - boot.php: Tokenfield JavaScript/CSS entfernt (nicht mehr benötigt) - Cronjob sollte nun im Cronjob-Addon sichtbar sein
- lib/cronjob/scheduled_maintenance.php → lib/cronjob.php (REDAXO-Standard) - package.yml: Cronjob-Deklaration entfernt (automatische Erkennung) - Inline JavaScript nach assets/js/frontend-advanced.js ausgelagert - Inline JavaScript nach assets/js/domains.js ausgelagert - Inline CSS nach assets/css/ip-addresses.css ausgelagert - IP-Adressen als data-Attribute statt PHP-Interpolation - Fragments behalten inline CSS/JS (Sperrseiten)
- Überschrift zeigt 'Maintenance' (EN) / 'Wartung' (DE) je nach Sprachwahl - Domain wird unter der Überschrift angezeigt (YRewrite oder ServerName) - CSS angepasst für inline maintenance-text Spans in Überschrift - Funktioniert nur bei aktivierter Mehrsprachigkeit
- max-width: 450px, width: 100% für Container - padding-top: 4rem (Desktop) / 3.5rem (Mobile) für Platz über Icon - Language-Switcher bleibt in oberer rechter Ecke (auch mobil) - Kompaktere Buttons auf Mobile (120px statt 140px) - Verhindert Überlappung mit Info-Icon
- Überschrift 'Wartung' (DE) wird initial angezeigt - Entspricht dem Verhalten der Texte (DE ist Standard) - Sprachwechsler funktioniert wie bisher
- Language-Option DE initial als 'active' markiert - Überschrift 'Wartung' (DE) mit 'active' Klasse - Konsistent mit den Nachrichtentexten (DE ist Standard) - Sprachwechsler zeigt nun korrekt DE als gewählte Sprache
- Initial 'Deutsch' statt 'Language' - Button-Text wechselt bei Sprachwahl (English/Deutsch) - Extrahiert Sprachname aus Option-Text (ohne EN/DE Prefix) - Konsistent mit aktivem Dropdown-Item
- execute(): bool → execute() - getTypeName(): string → getTypeName() - getParamFields(): array → getParamFields() - Entspricht REDAXO-Standard (wie PHPMailer, Backup) - Cronjob sollte nun in Auswahl erscheinen
- Feldauswahl mit name-Attribut statt ID (rex_config_form Standard) - Event-Delegation mit $(document).on() für dynamische Elemente - Null-Check für data-ip Attribut - Error-Logging wenn Feld nicht gefunden - Entspricht genau der Upkeep-Implementierung
- Exakte Struktur wie phpmailer cronjob - Eigenständige Logik ohne Aufruf von Maintenance::checkScheduledMaintenance() - Direkte Config-Manipulation für aktivieren/deaktivieren - Besseres Logging mit Status-Updates
- rex_cronjob_manager::registerType() im boot.php - Prüfung ob Cronjob-Addon verfügbar ist - Folgt dem Standard von Backup/PHPMailer AddOns
- Schritt-für-Schritt-Anleitung zur Cronjob-Konfiguration - Erklärung aller relevanten Einstellungen - Hinweis auf optionale Nutzung (Request-basiert funktioniert auch)
- checkScheduledMaintenance() aus checkFrontend() entfernt - Cronjob-Status-Warnung in Frontend-Einstellungen - Direkt-Link zum Cronjob erstellen wenn nicht vorhanden - README und Sprachdateien aktualisiert - Klarstellung: Funktion nur über Cronjob, nicht request-basiert
…niert - Neue Unterseite 'Planung' (frontend.scheduled.php) unter Frontend - Zeitgesteuerte Wartung von frontend.index.php entfernt - Wartungsankündigung von frontend.announcement.php integriert - Beide Features jetzt unter Maintenance > Frontend > Planung - package.yml: scheduled als Unterseite von frontend - Icon: fa-calendar-alt für Planungs-Seite - boot.php: OUTPUT_FILTER für frontend/scheduled aktiviert - Editor-Einstellung wird wieder berücksichtigt - Sidebar mit Schnellzugriffen und Code-Beispiel für Ankündigung
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
lib/Maintenance.php (1)
295-364: Moin Silent Mode blockiert Whitelist-ZugriffeDer Silent Mode bricht hier sofort ab, bevor IP-/Host-Whitelist, Secret oder eingeloggte User geprüft werden – damit verlieren bestehende Ausnahmeregeln ihre Wirkung, sobald der Silent Mode aktiv ist. Bitte erst nach den Allow-Checks entscheiden, ob nur der Statuscode ohne HTML gesendet werden soll.
- $silentMode = (bool) self::getConfig('silent_mode', false); - if ($silentMode) { - $responsecode = (int) self::getConfig('http_response_code', 503); - header('HTTP/1.1 ' . $responsecode); - exit; - } + $silentMode = (bool) self::getConfig('silent_mode', false); @@ - $redirect_url = (string) self::getConfig('redirect_frontend_to_url', ''); - $responsecode = (int) self::getConfig('http_response_code', 503); + $redirect_url = (string) self::getConfig('redirect_frontend_to_url', ''); + $responsecode = (int) self::getConfig('http_response_code', 503); + + if ($silentMode) { + header('HTTP/1.1 ' . $responsecode); + exit; + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
README.md(3 hunks)assets/css/ip-addresses.css(1 hunks)assets/js/domains.js(1 hunks)assets/js/frontend-advanced.js(1 hunks)boot.php(2 hunks)fragments/maintenance/frontend.php(1 hunks)lang/de_de.lang(3 hunks)lang/en_gb.lang(1 hunks)lib/Maintenance.php(6 hunks)lib/cronjob.php(1 hunks)package.yml(3 hunks)pages/domains.php(1 hunks)pages/frontend.advanced.php(1 hunks)pages/frontend.index.php(1 hunks)pages/frontend.scheduled.php(1 hunks)pages/frontend.sidebar.php(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- pages/frontend.index.php
- pages/domains.php
🧰 Additional context used
🧬 Code graph analysis (3)
boot.php (2)
lib/cronjob.php (1)
rex_cronjob_scheduled_maintenance(6-59)lib/Maintenance.php (3)
getConfig(446-449)Maintenance(30-458)isDomainInMaintenance(129-153)
pages/frontend.scheduled.php (1)
lib/Maintenance.php (1)
getConfig(446-449)
lib/cronjob.php (1)
lib/Maintenance.php (1)
getConfig(446-449)
🪛 LanguageTool
README.md
[grammar] ~24-~24: Hier könnte ein Fehler sein.
Context: ...rsion 3.5.0) ### Zeitgesteuerte Wartung Die zeitgesteuerte Wartung ermöglich...
(QB_NEW_DE)
[grammar] ~26-~26: Hier könnte ein Fehler sein.
Context: ...punkt zu aktivieren und zu deaktivieren: * Cronjob-basiert: Die Ausführung erfolg...
(QB_NEW_DE)
[grammar] ~28-~28: Ergänze ein Wort
Context: ...zu aktivieren und zu deaktivieren: * Cronjob-basiert: Die Ausführung erfolgt aussc...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_NOUN)
[grammar] ~28-~28: Ersetze das Satzzeichen
Context: ...erfolgt ausschließlich über den Cronjob "Geplante Wartung prüfen" * **Automatische Berein...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~28-~28: Ersetze das Satzzeichen
Context: ...lich über den Cronjob "Geplante Wartung prüfen" * Automatische Bereinigung: Nach erfolgr...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOTPERIOD)
[grammar] ~29-~29: Hier könnte ein Fehler sein.
Context: ...ie geplanten Zeiten automatisch gelöscht Verwendung: 1. Cronjob einrichten...
(QB_NEW_DE)
[grammar] ~31-~31: Hier könnte ein Fehler sein.
Context: ...iten automatisch gelöscht Verwendung: 1. Cronjob einrichten (erforderlich): ...
(QB_NEW_DE)
[grammar] ~33-~33: Ergänze ein Wort
Context: ...matisch gelöscht Verwendung: 1. Cronjob einrichten (erforderlich): - Im RE...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_NOUN)
[grammar] ~35-~35: Ersetze das Satzzeichen
Context: ...stem > Cronjobs** navigieren - Auf "+" klicken, um einen neuen Cronjob zu ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~35-~35: Ersetze das Satzzeichen
Context: ...em > Cronjobs** navigieren - Auf "+" klicken, um einen neuen Cronjob zu er...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~37-~37: Korrigiere die Fehler
Context: ...tellungen vornehmen: - Name: z.B. "Geplante Wartung prüfen" - **Typ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_MULTITOKEN)
[grammar] ~37-~37: Hier könnte ein Fehler sein.
Context: ...lungen vornehmen: - Name: z.B. "Geplante Wartung prüfen" - Typ: `Geplan...
(QB_NEW_DE)
[grammar] ~37-~37: Ersetze das Satzzeichen
Context: ... - Name: z.B. "Geplante Wartung prüfen" - Typ: `Geplante Wartung prüfe...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~39-~39: Korrigiere die Fehler
Context: ...wn wählen) - Ausführungsart: z.B. "Jede Minute" oder "Alle 5 Minuten" ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_MULTITOKEN)
[grammar] ~39-~39: Hier könnte ein Fehler sein.
Context: ...wählen) - Ausführungsart: z.B. "Jede Minute" oder "Alle 5 Minuten" - **...
(QB_NEW_DE)
[grammar] ~39-~39: Ersetze das Satzzeichen
Context: ...) - Ausführungsart: z.B. "Jede Minute" oder "Alle 5 Minuten" - **Umgebung...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~39-~39: Ersetze das Satzzeichen
Context: ...sführungsart**: z.B. "Jede Minute" oder "Alle 5 Minuten" - Umgebung: "Fronte...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~39-~39: Ersetze das Satzzeichen
Context: ...sart**: z.B. "Jede Minute" oder "Alle 5 Minuten" - Umgebung: "Frontend, Backend...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~40-~40: Ersetze das Satzzeichen
Context: ...r "Alle 5 Minuten" - Umgebung: "Frontend, Backend, Skript" - Speichern 2. In...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~40-~40: Ersetze das Satzzeichen
Context: ... - Umgebung: "Frontend, Backend, Skript" - Speichern 2. In den Frontend-Eins...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~41-~41: Hier könnte ein Fehler sein.
Context: ...rontend, Backend, Skript" - Speichern 2. In den Frontend-Einstellungen unter "Zei...
(QB_NEW_DE)
[grammar] ~43-~43: Ersetze das Satzzeichen
Context: ... 2. In den Frontend-Einstellungen unter "Zeitgesteuerte Wartung": - Startzeitpunkt einge...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~43-~43: Ersetze das Satzzeichen
Context: ...end-Einstellungen unter "Zeitgesteuerte Wartung": - Startzeitpunkt eingeben (z.B. ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~44-~44: Ergänze ein Leerzeichen
Context: ...g": - Startzeitpunkt eingeben (z.B. 2025-12-31 02:00:00) - **Endzeitp...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_ORTHOGRAPHY_SPACE)
[grammar] ~45-~45: Ergänze ein Leerzeichen
Context: ...:00) - **Endzeitpunkt** eingeben (z.B. 2025-12-31 06:00:00`) 3. Speichern - ...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_ORTHOGRAPHY_SPACE)
[grammar] ~46-~46: Ersetze das Satzzeichen
Context: ...ingeben (z.B. 2025-12-31 06:00:00) 3. Speichern - der Wartungsmodus wird zur konfiguriert...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_DASH_–)
[grammar] ~46-~46: Hier könnte ein Fehler sein.
Context: ...it automatisch aktiviert und deaktiviert Format: YYYY-MM-DD HH:MM:SS (z.B. `2...
(QB_NEW_DE)
[grammar] ~48-~48: Entferne ein Wort
Context: ...utomatisch aktiviert und deaktiviert Format: YYYY-MM-DD HH:MM:SS (z.B. `2025-12-31...
(QB_NEW_DE_OTHER_ERROR_IDS_UNNECESSARY_NOUN)
[grammar] ~48-~48: Ergänze ein Leerzeichen
Context: ...t Format: YYYY-MM-DD HH:MM:SS (z.B. 2025-12-31 23:59:59) Wichtig: O...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_ORTHOGRAPHY_SPACE)
[grammar] ~48-~48: Hier könnte ein Fehler sein.
Context: ...D HH:MM:SS(z.B.2025-12-31 23:59:59`) Wichtig: Ohne eingerichteten Cronjob f...
(QB_NEW_DE)
[grammar] ~50-~50: Entferne ein Wort
Context: ...:MM:SS(z.B.2025-12-31 23:59:59`) Wichtig: Ohne eingerichteten Cronjob funktionier...
(QB_NEW_DE_OTHER_ERROR_IDS_UNNECESSARY_NOUN)
[grammar] ~50-~50: Hier könnte ein Fehler sein.
Context: ...oniert die zeitgesteuerte Wartung nicht! ### Sperren des REDAXO-Backends * Sperren d...
(QB_NEW_DE)
[grammar] ~79-~79: Ersetze das Satzzeichen
Context: ...staltung erfolgen. ### Silent Mode für Staging/Development-Umgebungen Der **Silent Mo...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_STAGINGSLASHDEVELOPMENTDASHUMGEBUNGEN_STAGINGDASHSLASHDEVELOPMENTDASHUMGEBUNGEN)
[grammar] ~79-~79: Hier könnte ein Fehler sein.
Context: ... Mode für Staging/Development-Umgebungen Der Silent Mode ist ideal für Stagin...
(QB_NEW_DE)
[grammar] ~81-~81: Hier könnte ein Fehler sein.
Context: ...gen, die permanent gesperrt sein sollen: * Sendet nur den HTTP-Status-Code (z.B. 50...
(QB_NEW_DE)
[uncategorized] ~83-~83: Uneinheitliche Verwendung von Bindestrichen. Der Text enthält sowohl ‚HTTP-Status-Code‘ als auch ‚HTTP-Statuscode‘.
Context: ...gesperrt sein sollen: * Sendet nur den HTTP-Status-Code (z.B. 503 oder 403) * Zeigt keine H...
(DE_COMPOUND_COHERENCY)
[grammar] ~83-~83: Ergänze ein Leerzeichen
Context: ...: * Sendet nur den HTTP-Status-Code (z.B. 503 oder 403) * Zeigt keine HTML-W...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_ORTHOGRAPHY_SPACE)
[uncategorized] ~84-~84: Fehlendes Komma: Teilsätze, Einschübe, Aufzählungen und direkte Rede müssen durch ein Komma vom Rest des Satzes getrennt werden.
Context: ...3) * Zeigt keine HTML-Wartungsseite an * Verhindert Rückschlüsse auf das verwe...
(AI_DE_KOMMA_MISSING_COMMA)
[grammar] ~86-~86: Hier könnte ein Fehler sein.
Context: ...ie nur nach Login zugänglich sein sollen Aktivierung: In den erweiterten Einste...
(QB_NEW_DE)
[grammar] ~88-~88: Passe das Symbol an
Context: ...n zugänglich sein sollen Aktivierung: In den erweiterten Einstellungen (Einst...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_OTHER)
[grammar] ~88-~88: Ersetze das Satzzeichen
Context: ...ten Einstellungen (Einstellungen) unter "HTTP-Einstellungen" die Option "Silent Mode"...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~88-~88: Ersetze das Satzzeichen
Context: ...nstellungen (Einstellungen) unter "HTTP-Einstellungen" die Option "Silent Mode" aktivieren. #...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~88-~88: Ersetze das Satzzeichen
Context: ...) unter "HTTP-Einstellungen" die Option "Silent Mode" aktivieren. ## Anzeige des aktue...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_„)
[grammar] ~88-~88: Ersetze das Satzzeichen
Context: ..."HTTP-Einstellungen" die Option "Silent Mode" aktivieren. ## Anzeige des aktuellen S...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_QUOTE_L_DOUBLE_QUOT)
[grammar] ~88-~88: Hier könnte ein Fehler sein.
Context: ...en" die Option "Silent Mode" aktivieren. ## Anzeige des aktuellen Status im REDAXO-H...
(QB_NEW_DE)
[grammar] ~110-~110: Ergänze ein Satzzeichen
Context: ...` wieder crawlen. 🕵🏻 ## Konsole Das Addon bietet verschiedene Konsolen-Befehle zu...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_PUNCTUATION_ADDDASHON)
[grammar] ~110-~110: Wähle ein passenderes Wort
Context: ... Konsole Das Addon bietet verschiedene Konsolen-Befehle zur Verwaltung des Wartungsmodus: ### ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_NOUN)
[grammar] ~110-~110: Hier könnte ein Fehler sein.
Context: ...efehle zur Verwaltung des Wartungsmodus: ### Status anzeigen Zeigt den aktuellen Sta...
(QB_NEW_DE)
[grammar] ~112-~112: Hier könnte ein Fehler sein.
Context: ... des Wartungsmodus: ### Status anzeigen Zeigt den aktuellen Status aller Wartung...
(QB_NEW_DE)
[grammar] ~114-~114: Hier könnte ein Fehler sein.
Context: ... aktuellen Status aller Wartungsmodi an: bash php redaxo/bin/console maintenance:mode status ### Frontend-Wartungsmodus Aktivieren: ```b...
(QB_NEW_DE)
[grammar] ~120-~120: Hier könnte ein Fehler sein.
Context: ...e status ### Frontend-Wartungsmodus Aktivieren:bash php redaxo/bin/conso...
(QB_NEW_DE)
[grammar] ~122-~122: Hier könnte ein Fehler sein.
Context: ... ### Frontend-Wartungsmodus Aktivieren: bash php redaxo/bin/console maintenance:mode frontend on Deaktivieren: ```bash php redaxo/bin/con...
(QB_NEW_DE)
[grammar] ~127-~127: Hier könnte ein Fehler sein.
Context: ...ance:mode frontend on Deaktivieren:bash php redaxo/bin/console maintenance:mode frontend off ### Backend-Wartungsmodus Aktivieren:ba...
(QB_NEW_DE)
[grammar] ~132-~132: Hier könnte ein Fehler sein.
Context: ...ntend off ### Backend-Wartungsmodus Aktivieren:bash php redaxo/bin/conso...
(QB_NEW_DE)
[grammar] ~134-~134: Hier könnte ein Fehler sein.
Context: ... ### Backend-Wartungsmodus Aktivieren: bash php redaxo/bin/console maintenance:mode backend on Deaktivieren: ```bash php redaxo/bin/con...
(QB_NEW_DE)
[grammar] ~139-~139: Hier könnte ein Fehler sein.
Context: ...nance:mode backend on Deaktivieren:bash php redaxo/bin/console maintenance:mode backend off ``` ### Alle Modi gleichzeitig Alle Wartungsmod...
(QB_NEW_DE)
[grammar] ~144-~144: Hier könnte ein Fehler sein.
Context: ...kend off ``` ### Alle Modi gleichzeitig Alle Wartungsmodi (Frontend, Backend und...
(QB_NEW_DE)
[grammar] ~146-~146: Hier könnte ein Fehler sein.
Context: ...d, Backend und alle Domains) aktivieren: bash php redaxo/bin/console maintenance:mode all on Alle Wartungsmodi deaktivieren: ```bash ...
(QB_NEW_DE)
[grammar] ~151-~151: Hier könnte ein Fehler sein.
Context: ... on Alle Wartungsmodi deaktivieren:bash php redaxo/bin/console maintenance:mode all off ``` ### Domain-spezifische Wartung (YRewrite) E...
(QB_NEW_DE)
[grammar] ~156-~156: Hier könnte ein Fehler sein.
Context: ...## Domain-spezifische Wartung (YRewrite) Einzelne Domain sperren: ```bash php red...
(QB_NEW_DE)
[grammar] ~158-~158: Hier könnte ein Fehler sein.
Context: ...ung (YRewrite) Einzelne Domain sperren: bash php redaxo/bin/console maintenance:mode domain example.com --lock Einzelne Domain entsperren: ```bash php ...
(QB_NEW_DE)
[grammar] ~163-~163: Hier könnte ein Fehler sein.
Context: ... --lock Einzelne Domain entsperren:bash php redaxo/bin/console maintenance:mode domain example.com --unlock ``` ### Legacy-Unterstützung Die alten Befehle ...
(QB_NEW_DE)
[grammar] ~168-~168: Hier könnte ein Fehler sein.
Context: ...m --unlock ``` ### Legacy-Unterstützung Die alten Befehle funktionieren weiterhi...
(QB_NEW_DE)
[grammar] ~170-~170: Hier könnte ein Fehler sein.
Context: ...terhin (steuern nur den Frontend-Modus): bash php redaxo/bin/console maintenance:mode on php redaxo/bin/console maintenance:mode off ## Autor Thomas Skerbis – [KLXM Crossm...
(QB_NEW_DE)
[grammar] ~177-~177: Hier könnte ein Fehler sein.
Context: ...nsole maintenance:mode off ``` ## Autor Thomas Skerbis – [KLXM Crossmedia](htt...
(QB_NEW_DE)
[grammar] ~179-~179: Hier könnte ein Fehler sein.
Context: ...r Thomas Skerbis – KLXM Crossmedia ## Projekt-Lead * [Thomas Skerbis](https:/...
(QB_NEW_DE)
[grammar] ~181-~181: Hier könnte ein Fehler sein.
Context: ...media](https://klxm.de) ## Projekt-Lead * [Thomas Skerbis](https://github.com/skerb...
(QB_NEW_DE)
[grammar] ~183-~183: Hier könnte ein Fehler sein.
Context: ....de) ## Projekt-Lead * Thomas Skerbis ## Credits Danke an: * [Christian Gehrke]...
(QB_NEW_DE)
[grammar] ~186-~186: Hier könnte ein Fehler sein.
Context: ...https://github.com/skerbis) ## Credits Danke an: * [Christian Gehrke](https://...
(QB_NEW_DE)
[grammar] ~188-~188: Hier könnte ein Fehler sein.
Context: ...hub.com/skerbis) ## Credits Danke an: * [Christian Gehrke](https://github.com/chr...
(QB_NEW_DE)
[grammar] ~190-~190: Wähle ein passenderes Wort
Context: ... Credits Danke an: * Christian Gehrke // first ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_NOUN)
| $(document).on('rex:ready', function() { | ||
| $('#all-domains-locked').on('change', function() { | ||
| if ($(this).val() == '1') { | ||
| $('#individual-domains').slideUp(); | ||
| } else { | ||
| $('#individual-domains').slideDown(); | ||
| } | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Moin Initialzustand des Domain-Blocks fehlt
Der Handler reagiert nur auf spätere Änderungen. Wenn die Seite mit value="1" geladen wird, bleibt der Bereich sichtbar, bis der Admin manuell toggelt. Bitte beim Laden einmal anwenden:
$(document).on('rex:ready', function() {
- $('#all-domains-locked').on('change', function() {
- if ($(this).val() == '1') {
- $('#individual-domains').slideUp();
- } else {
- $('#individual-domains').slideDown();
- }
- });
+ var $toggle = $('#all-domains-locked');
+ var applyToggle = function() {
+ if ($toggle.val() === '1') {
+ $('#individual-domains').slideUp();
+ } else {
+ $('#individual-domains').slideDown();
+ }
+ };
+ $toggle.on('change', applyToggle);
+ applyToggle();
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| $(document).on('rex:ready', function() { | |
| $('#all-domains-locked').on('change', function() { | |
| if ($(this).val() == '1') { | |
| $('#individual-domains').slideUp(); | |
| } else { | |
| $('#individual-domains').slideDown(); | |
| } | |
| }); | |
| }); | |
| $(document).on('rex:ready', function() { | |
| var $toggle = $('#all-domains-locked'); | |
| var applyToggle = function() { | |
| if ($toggle.val() === '1') { | |
| $('#individual-domains').slideUp(); | |
| } else { | |
| $('#individual-domains').slideDown(); | |
| } | |
| }; | |
| $toggle.on('change', applyToggle); | |
| applyToggle(); | |
| }); |
🤖 Prompt for AI Agents
In assets/js/domains.js around lines 4 to 12, the change handler only runs on
future user interactions so if the page loads with #all-domains-locked value "1"
the #individual-domains block remains visible; invoke the same logic on load by
either triggering the change handler once (e.g. call
.change()/.trigger('change') on #all-domains-locked after binding) or by
immediately checking its value and calling slideUp()/slideDown() accordingly so
the initial state matches the current value.
| maintenance_authentication_mode_label = Authentifizierung | ||
| maintenance_authentication_mode_notice = Authentifizierungsmethode auswählen, um Zugriff zu erhalten. | ||
|
|
||
| maintenance_authentification_mode_none = Keine Authentifizierung | ||
| maintenance_authentification_mode_password = 🔑 Passwort | ||
| maintenance_authentification_mode_url = 🔗 Geheim-URL (Standard) | ||
| maintenance_authentication_mode_none = Keine Authentifizierung | ||
| maintenance_authentication_mode_password = Passwort | ||
| maintenance_authentication_mode_url = Geheim-URL (Standard) | ||
|
|
There was a problem hiding this comment.
Moin Neue Schlüssel ohne passende en-Übersetzung
Mit diesem Rename zu maintenance_authentication_* fehlen in lang/en_gb.lang die korrespondierenden Keys (dort stehen weiterhin maintenance_authentification_*). Im englischen Backend werden damit nur Platzhalter angezeigt. Bitte die en-Übersetzungen anpassen, z. B.:
- maintenance_authentification_mode_label = Authentication
+ maintenance_authentication_mode_label = Authentication
- maintenance_authentification_mode_notice = Choose the authentication method to gain access.
+ maintenance_authentication_mode_notice = Choose the authentication method to gain access.
- maintenance_authentification_mode_none = No Authentication
+ maintenance_authentication_mode_none = No Authentication
- maintenance_authentification_mode_password = 🔑 Password
+ maintenance_authentication_mode_password = 🔑 Password
- maintenance_authentification_mode_url = 🔗 Secret URL (default)
+ maintenance_authentication_mode_url = 🔗 Secret URL (default)Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In lang/de_de.lang around lines 69 to 75 you renamed keys to
maintenance_authentication_*, but the corresponding keys in lang/en_gb.lang
still use maintenance_authentification_*, causing missing placeholders in the
English UI; update lang/en_gb.lang by adding or renaming the matching keys to
maintenance_authentication_mode_label, maintenance_authentication_mode_notice,
maintenance_authentication_mode_none, maintenance_authentication_mode_password
and maintenance_authentication_mode_url with the correct English strings (remove
or deprecate the old maintenance_authentification_* entries to avoid
duplicates).
| $info = '<div class="alert alert-info">'; | ||
| $info .= '<h4><i class="rex-icon fa-info-circle"></i> ' . $addon->i18n('maintenance_announcement_info_title') . '</h4>'; | ||
| $info .= '<p>' . $addon->i18n('maintenance_announcement_info_text') . '</p>'; | ||
| $info .= '<p><strong>' . $addon->i18n('maintenance_announcement_usage') . ':</strong></p>'; | ||
| $info .= '<div style="position: relative;">'; | ||
| $info .= '<pre style="margin-bottom: 0;"><code>' . htmlspecialchars($codeExample) . '</code></pre>'; | ||
| $info .= '<button class="btn btn-xs btn-default" style="position: absolute; top: 5px; right: 5px;" onclick="navigator.clipboard.writeText(' . htmlspecialchars(json_encode($codeExample), ENT_QUOTES) . '); this.innerHTML=\'<i class=\\\'rex-icon fa-check\\\'></i> ' . $addon->i18n('maintenance_copied') . '\'; setTimeout(() => this.innerHTML=\'<i class=\\\'rex-icon fa-copy\\\'></i> ' . $addon->i18n('maintenance_copy') . '\', 2000);"><i class="rex-icon fa-copy"></i> ' . $addon->i18n('maintenance_copy') . '</button>'; | ||
| $info .= '</div>'; | ||
| $info .= '</div>'; |
There was a problem hiding this comment.
Moin JS-Strings für Übersetzungen korrekt escapen
Wird die Oberfläche in einer Sprache mit Apostrophen (z. B. Französisch) übersetzt, brechen maintenance_copied bzw. maintenance_copy das in einfache Anführungszeichen gesetzte onclick-Literal – der Copy-Button reagiert dann gar nicht mehr. Bite die Texte vor dem Einfügen in den JS-String mit der js-Strategie escapen und für den sichtbaren Button-Text HTML-escaping nutzen.
+ $copiedLabelJs = rex_escape($addon->i18n('maintenance_copied'), 'js');
+ $copyLabelJs = rex_escape($addon->i18n('maintenance_copy'), 'js');
+ $copyLabelHtml = rex_escape($addon->i18n('maintenance_copy'));
$info .= '<div style="position: relative;">';
$info .= '<pre style="margin-bottom: 0;"><code>' . htmlspecialchars($codeExample) . '</code></pre>';
- $info .= '<button class="btn btn-xs btn-default" style="position: absolute; top: 5px; right: 5px;" onclick="navigator.clipboard.writeText(' . htmlspecialchars(json_encode($codeExample), ENT_QUOTES) . '); this.innerHTML=\'<i class=\\\'rex-icon fa-check\\\'></i> ' . $addon->i18n('maintenance_copied') . '\'; setTimeout(() => this.innerHTML=\'<i class=\\\'rex-icon fa-copy\\\'></i> ' . $addon->i18n('maintenance_copy') . '\', 2000);"><i class="rex-icon fa-copy"></i> ' . $addon->i18n('maintenance_copy') . '</button>';
+ $info .= '<button class="btn btn-xs btn-default" style="position: absolute; top: 5px; right: 5px;" onclick="navigator.clipboard.writeText(' . htmlspecialchars(json_encode($codeExample), ENT_QUOTES) . '); this.innerHTML=\'<i class=\\\'rex-icon fa-check\\\'></i> ' . $copiedLabelJs . '\'; setTimeout(() => this.innerHTML=\'<i class=\\\'rex-icon fa-copy\\\'></i> ' . $copyLabelJs . '\', 2000);"><i class="rex-icon fa-copy"></i> ' . $copyLabelHtml . '</button>';🤖 Prompt for AI Agents
In pages/frontend.scheduled.php around lines 114 to 122, the translated strings
maintenance_copied and maintenance_copy are injected directly into a
single-quoted onclick JS literal and break when translations contain
apostrophes; escape those translations for inclusion in JS using the js strategy
(e.g. pass through the translator's js escape) and keep the visible button label
HTML-escaped (htmlspecialchars) so the onclick value remains valid while the
button text is safe for HTML; update the concatenation so the onclick uses the
js-escaped variants and the inner visible text uses the HTML-escaped variants.
| if (rex_config::get('maintenance', 'block_frontend') || $allDomainsLocked) { | ||
| $url = '' . rex::getServer() . '?maintenance_secret=' . rex_config::get('maintenance', 'maintenance_secret'); | ||
| $copy .= '<li class="list-group-item">'; | ||
| $copy .= '<label for="maintenance-mode-url">' . $addon->i18n('maintenance_bypass_url_default') . '</label>'; | ||
| $copy .= ' | ||
| <clipboard-copy for="maintenance-mode-url" class="input-group"> | ||
| <input id="maintenance-mode-url" type="text" value="' . $url . '" readonly class="form-control"> | ||
| <span class="input-group-addon"><i class="rex-icon fa-clone"></i></span> | ||
| </clipboard-copy></li>'; | ||
| } | ||
|
|
||
| // YRewrite-Domains nur anzeigen, wenn sie gesperrt sind | ||
| if ($yrewriteAvailable && count(rex_yrewrite::getDomains()) > 1) { | ||
| foreach (rex_yrewrite::getDomains() as $key => $domain) { | ||
| if ('default' == $key) { | ||
| continue; | ||
| } | ||
|
|
||
| // Domain nur anzeigen, wenn: | ||
| // - Alle Domains gesperrt sind ODER | ||
| // - Diese spezifische Domain gesperrt ist | ||
| $isDomainLocked = $allDomainsLocked || (isset($domainStatus[$key]) && 1 == $domainStatus[$key]); | ||
|
|
||
| if ($isDomainLocked) { | ||
| $url = $domain->getUrl() . '?maintenance_secret=' . rex_config::get('maintenance', 'maintenance_secret'); | ||
| $copy .= '<li class="list-group-item">'; | ||
| $copy .= '<label for="maintenance-mode-url-' . $key . '">YRewrite: ' . htmlspecialchars($key) . '</label>'; | ||
| $copy .= ' | ||
| <clipboard-copy for="maintenance-mode-url-' . $key . '" class="input-group"> | ||
| <input id="maintenance-mode-url-' . $key . '" type="text" value="' . $url . '" readonly class="form-control"> | ||
| <span class="input-group-addon"><i class="rex-icon fa-clone"></i></span> | ||
| </clipboard-copy></li>'; | ||
| } |
There was a problem hiding this comment.
Moin Falscher Config-Key für Bypass-Links
Hier wird rex_config::get('maintenance', 'maintenance_secret') verwendet. In package.yml lautet der Default-Key jedoch secret, dadurch bleibt der Parameter leer und alle generierten Bypass-URLs funktionieren nicht. Bitte auf den korrekten Key umstellen.
- $url = '' . rex::getServer() . '?maintenance_secret=' . rex_config::get('maintenance', 'maintenance_secret');
+ $url = rex::getServer() . '?maintenance_secret=' . rex_config::get('maintenance', 'secret');
…
- $url = $domain->getUrl() . '?maintenance_secret=' . rex_config::get('maintenance', 'maintenance_secret');
+ $url = $domain->getUrl() . '?maintenance_secret=' . rex_config::get('maintenance', 'secret');📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (rex_config::get('maintenance', 'block_frontend') || $allDomainsLocked) { | |
| $url = '' . rex::getServer() . '?maintenance_secret=' . rex_config::get('maintenance', 'maintenance_secret'); | |
| $copy .= '<li class="list-group-item">'; | |
| $copy .= '<label for="maintenance-mode-url">' . $addon->i18n('maintenance_bypass_url_default') . '</label>'; | |
| $copy .= ' | |
| <clipboard-copy for="maintenance-mode-url" class="input-group"> | |
| <input id="maintenance-mode-url" type="text" value="' . $url . '" readonly class="form-control"> | |
| <span class="input-group-addon"><i class="rex-icon fa-clone"></i></span> | |
| </clipboard-copy></li>'; | |
| } | |
| // YRewrite-Domains nur anzeigen, wenn sie gesperrt sind | |
| if ($yrewriteAvailable && count(rex_yrewrite::getDomains()) > 1) { | |
| foreach (rex_yrewrite::getDomains() as $key => $domain) { | |
| if ('default' == $key) { | |
| continue; | |
| } | |
| // Domain nur anzeigen, wenn: | |
| // - Alle Domains gesperrt sind ODER | |
| // - Diese spezifische Domain gesperrt ist | |
| $isDomainLocked = $allDomainsLocked || (isset($domainStatus[$key]) && 1 == $domainStatus[$key]); | |
| if ($isDomainLocked) { | |
| $url = $domain->getUrl() . '?maintenance_secret=' . rex_config::get('maintenance', 'maintenance_secret'); | |
| $copy .= '<li class="list-group-item">'; | |
| $copy .= '<label for="maintenance-mode-url-' . $key . '">YRewrite: ' . htmlspecialchars($key) . '</label>'; | |
| $copy .= ' | |
| <clipboard-copy for="maintenance-mode-url-' . $key . '" class="input-group"> | |
| <input id="maintenance-mode-url-' . $key . '" type="text" value="' . $url . '" readonly class="form-control"> | |
| <span class="input-group-addon"><i class="rex-icon fa-clone"></i></span> | |
| </clipboard-copy></li>'; | |
| } | |
| if (rex_config::get('maintenance', 'block_frontend') || $allDomainsLocked) { | |
| $url = rex::getServer() . '?maintenance_secret=' . rex_config::get('maintenance', 'secret'); | |
| $copy .= '<li class="list-group-item">'; | |
| $copy .= '<label for="maintenance-mode-url">' . $addon->i18n('maintenance_bypass_url_default') . '</label>'; | |
| $copy .= ' | |
| <clipboard-copy for="maintenance-mode-url" class="input-group"> | |
| <input id="maintenance-mode-url" type="text" value="' . $url . '" readonly class="form-control"> | |
| <span class="input-group-addon"><i class="rex-icon fa-clone"></i></span> | |
| </clipboard-copy></li>'; | |
| } | |
| // YRewrite-Domains nur anzeigen, wenn sie gesperrt sind | |
| if ($yrewriteAvailable && count(rex_yrewrite::getDomains()) > 1) { | |
| foreach (rex_yrewrite::getDomains() as $key => $domain) { | |
| if ('default' == $key) { | |
| continue; | |
| } | |
| // Domain nur anzeigen, wenn: | |
| // - Alle Domains gesperrt sind ODER | |
| // - Diese spezifische Domain gesperrt ist | |
| $isDomainLocked = $allDomainsLocked || (isset($domainStatus[$key]) && 1 == $domainStatus[$key]); | |
| if ($isDomainLocked) { | |
| $url = $domain->getUrl() . '?maintenance_secret=' . rex_config::get('maintenance', 'secret'); | |
| $copy .= '<li class="list-group-item">'; | |
| $copy .= '<label for="maintenance-mode-url-' . $key . '">YRewrite: ' . htmlspecialchars($key) . '</label>'; | |
| $copy .= ' | |
| <clipboard-copy for="maintenance-mode-url-' . $key . '" class="input-group"> | |
| <input id="maintenance-mode-url-' . $key . '" type="text" value="' . $url . '" readonly class="form-control"> | |
| <span class="input-group-addon"><i class="rex-icon fa-clone"></i></span> | |
| </clipboard-copy></li>'; | |
| } |
🤖 Prompt for AI Agents
pages/frontend.sidebar.php around lines 31 to 63: the code uses
rex_config::get('maintenance', 'maintenance_secret') but the package.yml default
key is named "secret", so the generated bypass URLs are empty; change all uses
of rex_config::get('maintenance', 'maintenance_secret') to
rex_config::get('maintenance', 'secret') (or call rex_config::get('maintenance',
'secret', '<fallback>') if you want a fallback) so the correct config value is
retrieved and the bypass URLs are built properly.
Maintenance AddOn - Umfassende Verbesserungen & Neue Features
📋 Zusammenfassung
Diese PR bringt umfassende Verbesserungen, neue Features und wichtige Bugfixes für das Maintenance AddOn. Die Änderungen umfassen Performance-Optimierungen, neue Funktionen für zeitgesteuerte Wartung, Silent Mode für Staging-Umgebungen, UI-Verbesserungen und zahlreiche Bugfixes.
✨ Neue Features
1. Zeitgesteuerte Wartung (Scheduled Maintenance)
scheduled_start: Startzeitpunkt (Y-m-d H:i:s)scheduled_end: Endzeitpunkt (Y-m-d H:i:s)rex_cronjob_scheduled_maintenancefür minutengenaue AusführungVerwendung:
2. Wartungsankündigung
Maintenance::showAnnouncement()3. Silent Mode für Staging/Development
4. Mehrsprachige Sperrseite mit Language-Switcher
5. Domain-basierte Wartung (nur YRewrite)
🔧 Verbesserungen & Optimierungen
Performance
isDomainInMaintenance()vereinfachtCode-Qualität
assets/js/frontend-advanced.js(IP-Whitelist-Management)assets/js/domains.js(Domain-Toggle-Logik)assets/css/ip-addresses.css(IP-Listen-Styling)lib/cronjob.phpstatt UnterverzeichnisUI/UX
🐛 Bugfixes
Kritische Fixes
Frontend-Sperre funktioniert wieder (feat: Umfassende Verbesserungen des Maintenance AddOns #156)
IP Click-to-Add repariert
rex_i18n aus Frontend-Fragment entfernt
translate:maintenance_languageUndefined Variable $currentPage
Kleinere Fixes
📁 Geänderte Dateien
Neue Dateien
lib/cronjob.php(nach PHPMailer-Vorbild implementiert)pages/frontend.scheduled.php(Planungs-Seite: Zeitgesteuerte Wartung + Ankündigung)assets/js/frontend-advanced.js(IP-Whitelist-Management)assets/js/domains.js(Domain-Toggle-Logik)assets/css/ip-addresses.css(IP-Listen-Styling)Hauptänderungen
lib/Maintenance.php:checkScheduledMaintenance()- Neue Methode (nur für Cronjob)checkFrontend()- Silent Mode Early Exitlib/cronjob.php:pages/frontend.index.php:pages/frontend.scheduled.php:pages/frontend.advanced.php:pages/domains.php:fragments/maintenance/frontend.php:boot.php:package.yml:lang/de_de.lang:Entfernte Dateien
fragments/maintenance/frontend_old.php(temporäres Backup)pages/frontend.announcement.php(in frontend.scheduled.php integriert)🔄 Breaking Changes
Keine Breaking Changes - Alle Änderungen sind abwärtskompatibel.
Bestehende Konfigurationen bleiben erhalten und funktionieren weiterhin.
📦 Migration
Update-Schritte
Neue Config-Werte (automatisch gesetzt)
🧪 Testing
Getestet mit:
📝 Review-Kommentare aus PR #156
Alle Review-Kommentare wurden adressiert:
📸 Screenshots
Planungs-Seite (Maintenance > Frontend > Planung)
Erweiterte Einstellungen
Sperrseite
Summary by CodeRabbit
Release Notes v3.5.0
New Features
Improvements