fix: dziala aktualizacja systemu i Wyczysc cache na /admin/update/main_view/ (v0.353)

Zdalny changelog z shoppro.project-dc.pl/updates/changelog.php zwracal
niezbalansowany HTML (niezamkniety <script>/<style>/<textarea>/<!--),
ktory "polykal" reszte dokumentu - inline-script z handlerami
#confirm/#confirmUpdateAll i footer-script z main-layout.php
(#clear-cache-btn) nigdy nie parsowaly sie jako JS. Klienci nie mogli
aktualizowac shopPRO.

Fix w admin/templates/update/main-view.php:
1. Blok <script> z handlerami przeniesiony PRZED sekcje Changelog -
   handlery podpinaja sie niezaleznie od zdalnego HTML.
2. Sanityzacja zdalnego changeloga: preg_replace usuwa komentarze HTML,
   strip_tags z whitelista (<p><br><b><strong><i><em><u><ul><ol><li>
   <h1>-<h6><span><div><a><pre><code><hr>) wycina tagi strukturalne i
   wykonywalne (<script>, <style>, <iframe>, <textarea>).

Skutek uboczny: footer-script z main-layout.php (Wyczysc cache + globalne
wyszukiwanie + sprawdzanie aktualizacji) dziala teraz na podstronie update.

Po wgraniu na instancje: hard-reload (Ctrl+F5) + restart PHP-FPM /
wyczyszczenie OPcache.

Suita PHPUnit: 846 testow / 2348 assertions OK.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-13 23:10:08 +02:00
parent 8a89305f29
commit 073069c303
8 changed files with 409 additions and 19 deletions

View File

@@ -0,0 +1,173 @@
---
phase: 21-admin-update-view-js-fix
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- admin/templates/update/main-view.php
autonomous: false
delegation: off
---
<objective>
## Goal
Naprawić niedziałające przyciski na `/admin/update/main_view/`: "Aktualizuj do wyższej wersji" (`#confirm`), "Aktualizuj do najwyższej wersji" (`#confirmUpdateAll`) oraz globalny "Wyczyść cache" (`#clear-cache-btn`) z headera admina.
## Purpose
Na instancjach klientów shopPRO aktualizacja wersji nie była możliwa — zdalny changelog z `shoppro.project-dc.pl/updates/changelog.php` wstrzykiwał niezbalansowany HTML (niezamknięty `<script>`/`<style>`/`<textarea>`/`<!--`), który „połykał" pozostałą część dokumentu jako tekst i blokował parsowanie inline-scriptu z handlerami oraz footer-scriptu z `main-layout.php`. Bez tej naprawy klienci nie mogą aktualizować systemu.
## Output
Zmodyfikowany plik `admin/templates/update/main-view.php`:
1. Blok `<script>` z handlerami przeniesiony PRZED sekcję Changelog.
2. Zdalny changelog sanityzowany przed wyrenderowaniem (usunięcie komentarzy HTML + `strip_tags` z białą listą).
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
## Source Files
@admin/templates/update/main-view.php
@change.md
<clarifications>
- **Scope** — Wystarczy fix zgodny z change.md (jeden plik, dwa kroki)?
→ Odpowiedź: brak pytań — change.md zawiera kompletny opis problemu, przyczyny i konkretne fragmenty kodu do wdrożenia. Plan = mechaniczne wdrożenie change.md.
</clarifications>
</context>
<acceptance_criteria>
## AC-1: Handlery JS działają niezależnie od treści zdalnego changeloga
```gherkin
Given administrator jest na /admin/update/main_view/ z wersją starszą niż najnowsza
And zdalny serwer shoppro.project-dc.pl zwraca dowolny HTML (nawet niezbalansowany)
When admin klika "Aktualizuj do wyższej wersji" lub "Aktualizuj do najwyższej wersji"
Then otwiera się dialog `$.confirm` (potwierdzenie aktualizacji)
And po potwierdzeniu uruchamia się aktualizacja (redirect /admin/update/update/ lub AJAX /admin/update/updateAll/)
```
## AC-2: Globalny przycisk "Wyczyść cache" działa na podstronie update
```gherkin
Given administrator jest na /admin/update/main_view/
When klika "Wyczyść cache" w headerze admina (`#clear-cache-btn`)
Then footer-script z main-layout.php obsługuje kliknięcie (nie jest połknięty" przez nieparzysty tag changeloga)
```
## AC-3: Zdalny changelog nadal się wyświetla, ale nie może popsuć strony
```gherkin
Given zdalny changelog zawiera `<script>`, `<style>`, `<textarea>`, `<iframe>`, `<!--...-->` lub niezamknięte tagi strukturalne
When szablon main-view.php renderuje sekcję Changelog
Then niedozwolone tagi są usunięte przez `strip_tags` (whitelist: <p><br><b><strong><i><em><u><ul><ol><li><h1>-<h6><span><div><a><pre><code><hr>)
And komentarze HTML `<!--...-->` są usuwane
And treść tekstowa changeloga + dozwolone tagi formatujące są widoczne na stronie
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Reorder + sanitize w main-view.php</name>
<files>admin/templates/update/main-view.php</files>
<action>
Wdrożyć zmianę zgodnie z change.md:
1. **Przenieść blok `<script type="text/javascript">...</script>`** (linie 64-140 obecnej wersji) PRZED sekcję Changelog (przed `<div class="panel">` zawierający `<span class="panel-title">Changelog</span>`).
Nowa kolejność w szablonie:
- panel "Aktualizacja systemu" (wersje + przyciski)
- panel "Log ostatniej aktualizacji" (warunkowy)
- **`<script>` z handlerami** ← przeniesiony tutaj
- panel "Changelog" (zdalny `file_get_contents` + sanityzacja)
2. **Zastąpić linię z `file_get_contents`** (obecnie linia 60):
```php
<?= @file_get_contents( 'https://shoppro.project-dc.pl/updates/changelog.php?ver=' . $this->ver ); ?>
```
na blok sanityzacji:
```php
<?php
$changelog = (string) @file_get_contents( 'https://shoppro.project-dc.pl/updates/changelog.php?ver=' . $this->ver );
$changelog = preg_replace( '/<!--.*?-->/s', '', $changelog );
$changelog = strip_tags( $changelog, '<p><br><b><strong><i><em><u><ul><ol><li><h1><h2><h3><h4><h5><h6><span><div><a><pre><code><hr>' );
echo $changelog;
?>
```
Nie zmieniać:
- logiki JS w bloku `<script>` (handlery `#confirm`, `#confirmUpdateAll`, funkcja `updateAll`)
- struktury HTML paneli (klasy CSS, ID, atrybuty)
- tekstów polskich w szablonie
- składni krótkich tagów `<?` (kompatybilność PHP < 8.0 — szablon używa krótkich tagów, zachować konwencję)
Plik zostaje UTF-8 bez BOM.
Unikać: wprowadzania dodatkowych zależności, refaktoringu spoza zakresu change.md, zmiany URL zdalnego changeloga.
</action>
<verify>
1. `php -l admin/templates/update/main-view.php` → "No syntax errors"
2. Grep: `grep -n "strip_tags" admin/templates/update/main-view.php` → linia z whitelistą obecna
3. Grep: blok `<script type="text/javascript">` znajduje się przed `<span class="panel-title">Changelog</span>` w pliku (sprawdzić numery linii)
</verify>
<done>AC-3 satisfied (sanityzacja whitelist + usunięcie komentarzy HTML); strukturalna baza dla AC-1 i AC-2 (reorder przed changelogiem)</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>
Reorder bloku `<script>` przed sekcję Changelog + sanityzacja zdalnego changeloga w `admin/templates/update/main-view.php`.
</what-built>
<how-to-verify>
1. Wgrać zmodyfikowany plik na instancję testową (lub lokalnie, jeśli setup pozwala).
2. Hard-reload (Ctrl+F5) w przeglądarce.
3. Restart PHP-FPM / wyczyścić OPcache (jeśli aktywny).
4. Wejść na `/admin/update/main_view/` jako admin (przy wersji starszej niż najnowsza, żeby przyciski się pokazały).
5. **AC-1:** Kliknąć "Aktualizuj do wyższej wersji" → dialog `$.confirm` musi się otworzyć. To samo dla "Aktualizuj do najwyższej wersji".
6. **AC-2:** Kliknąć "Wyczyść cache" w headerze admina → handler musi zadziałać (komunikat / akcja zgodna z `main-layout.php`).
7. **AC-3:** Sekcja Changelog nadal wyświetla treść ze zdalnego serwera (tekst + formatowanie), ale bez `<script>`/`<style>`/`<iframe>` (View Source).
8. Sprawdzić DevTools console — brak nowych błędów JS związanych z `main-view.php`.
</how-to-verify>
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- Logikę JS handlerów aktualizacji (`#confirm`, `#confirmUpdateAll`, funkcja `updateAll`) — wyłącznie reorder bloku.
- `admin/templates/site/main-layout.php` (footer-script `#clear-cache-btn`) — naprawa jest skutkiem ubocznym reorderu w main-view.
- URL zdalnego changeloga (`https://shoppro.project-dc.pl/updates/changelog.php`).
- Logikę kontrolera `UpdateController` i endpointy `/admin/update/update/`, `/admin/update/updateAll/`.
- Inne szablony w `admin/templates/update/`.
## SCOPE LIMITS
- Tylko jeden plik: `admin/templates/update/main-view.php`.
- Brak testów PHPUnit (zmiana w warstwie szablonu, brak unit-testowalnej logiki).
- Brak zmian w bazie / migracjach.
- Brak release update package — to robi `/koniec-pracy` po UNIFY.
- Brak zmiany sposobu pobierania changeloga (np. cache, timeout, fallback) — to byłby osobny scope.
</boundaries>
<verification>
Before declaring plan complete:
- [ ] `php -l admin/templates/update/main-view.php` passes
- [ ] Blok `<script>` znajduje się przed sekcją Changelog (kolejność w pliku)
- [ ] Sekcja Changelog zawiera `strip_tags` z whitelistą formatowania
- [ ] Human-verify checkpoint approved (3 przyciski działają, changelog renderuje się sanityzowany)
- [ ] All acceptance criteria met
</verification>
<success_criteria>
- AC-1, AC-2, AC-3 spełnione i potwierdzone w human-verify
- Brak regresji innych funkcji panelu admina
- Pełna suita PHPUnit (`./test.ps1`) nadal zielona (846 testów — bez nowych testów w tym planie)
</success_criteria>
<output>
After completion, create `.paul/phases/21-admin-update-view-js-fix/21-01-SUMMARY.md`
</output>

View File

@@ -0,0 +1,124 @@
---
phase: 21-admin-update-view-js-fix
plan: 01
subsystem: admin
tags: [template, js, htmlsanitize, update, admin-panel]
requires:
- phase: none
provides: none
provides:
- Działające przyciski aktualizacji systemu (`#confirm`, `#confirmUpdateAll`) na /admin/update/main_view/
- Działający globalny przycisk "Wyczyść cache" (`#clear-cache-btn`) na tej podstronie
- Sanityzacja zdalnego changeloga (whitelist tagów formatujących + usunięcie komentarzy HTML)
affects: [admin update workflow, future remote-content includes]
tech-stack:
added: []
patterns:
- "Zdalne file_get_contents w szablonie sanityzować przez strip_tags z whitelistą + usunięcie komentarzy HTML; krytyczne <script> renderować PRZED takim includem"
key-files:
created: []
modified:
- admin/templates/update/main-view.php
key-decisions:
- "Reorder: blok <script> z handlerami PRZED sekcję Changelog (nie po) — odporność na uszkodzony zdalny HTML"
- "Whitelist strip_tags ogranicza zdalny changelog do tagów formatujących; <script>/<style>/<textarea>/<iframe> wykluczone"
patterns-established:
- "Sanityzacja zdalnego HTML w szablonach admina: preg_replace('/<!--.*?-->/s', '', $html) + strip_tags(whitelist)"
duration: ~15min
started: 2026-05-13T00:00:00Z
completed: 2026-05-13T00:00:00Z
---
# Phase 21 Plan 01: Admin update view JS fix — Summary
**Naprawiono niedziałające przyciski aktualizacji systemu i globalny "Wyczyść cache" na `/admin/update/main_view/` przez reorder bloku `<script>` przed sekcję Changelog + sanityzację zdalnego changeloga w `admin/templates/update/main-view.php`.**
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~15min |
| Tasks | 1 auto + 1 checkpoint:human-verify |
| Files modified | 1 |
| Tests | 846 / 2348 asercji — OK |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Handlery JS działają niezależnie od treści zdalnego changeloga | Pass | Blok `<script>` w linii 55, przed sekcją Changelog w linii 135 — handlery `#confirm`/`#confirmUpdateAll` podpinają się przed parsowaniem zdalnego HTML |
| AC-2: Globalny "Wyczyść cache" działa na podstronie update | Pass | Footer-script z `main-layout.php` (#clear-cache-btn) nie jest już „połykany" przez niezbalansowany tag changeloga — potwierdzone human-verify |
| AC-3: Zdalny changelog renderuje się sanityzowany | Pass | `preg_replace('/<!--.*?-->/s', '', ...)` usuwa komentarze HTML, `strip_tags` z whitelistą `<p><br><b><strong><i><em><u><ul><ol><li><h1>-<h6><span><div><a><pre><code><hr>` wycina niedozwolone tagi strukturalne i wykonywalne |
## Accomplishments
- Klient może aktualizować shopPRO na instancjach — root cause (niezbalansowany zdalny HTML „połykający" inline-script handlerów i footer-script `main-layout.php`) wyeliminowany przez reorder + sanityzację.
- Globalny "Wyczyść cache" w headerze admina działa nie tylko na podstronie update, ale i pośrednio wszędzie indziej (footer-script się teraz parsuje).
- Dodatkowy zysk bezpieczeństwa: zdalny `shoppro.project-dc.pl/updates/changelog.php` nie może już wstrzyknąć `<script>`/`<style>`/`<iframe>` w panel admina.
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `admin/templates/update/main-view.php` | Modified | Reorder bloku `<script>` przed sekcję Changelog + sanityzacja zdalnego changeloga (strip_tags whitelist + usunięcie komentarzy HTML) |
## Decisions Made
| Decision | Rationale | Impact |
|----------|-----------|--------|
| Reorder zamiast np. wyłączenia zdalnego changeloga | Zachowuje istniejącą funkcjonalność (admin widzi nowości), eliminuje root cause | Minimalna zmiana, ten sam UX |
| `strip_tags` z białą listą zamiast np. iframe sandbox | Najprostszy, zerowy narzut, działa na PHP 7.4, brak dodatkowych zależności | Zdalny content może być tylko tekstem z formatowaniem — wystarczy do changeloga |
| Whitelist obejmuje tagi formatujące + `<div>`/`<span>`/`<a>` | Zachowuje typową strukturę changeloga | Zdalny serwer nie może już strukturalnie popsuć strony |
## Deviations from Plan
### Summary
| Type | Count | Impact |
|------|-------|--------|
| Auto-fixed | 0 | — |
| Scope additions | 0 | — |
| Deferred | 0 | — |
**Total impact:** Plan wykonany dokładnie według change.md, bez odstępstw.
### Deferred Items
None.
## Issues Encountered
| Issue | Resolution |
|-------|------------|
| `./test.ps1` z CLAUDE.md nie istnieje w repo (zmiana w lokalnej konfiguracji) | Uruchomiono `php phpunit.phar` bezpośrednio — 846 testów zielonych |
## Skill Audit (Phase 21)
| Expected | Invoked | Notes |
|----------|---------|-------|
| /feature-dev | ○ | Hotfix template-only z konkretną instrukcją w change.md — override per pattern poprzednich faz |
| /koniec-pracy | ○ | Pending — uruchomić przy release update package |
Skill audit: not blocking (warning only).
## Next Phase Readiness
**Ready:**
- Repo gotowe do `/koniec-pracy` (release update package z nową wersją zawierającą fix `admin/templates/update/main-view.php`)
- Brak regresji testowej — 846 testów zielonych
**Concerns:**
- Po wgraniu update package na instancje klientów konieczny: hard-reload (Ctrl+F5) + restart PHP-FPM / wyczyszczenie OPcache (zgodnie z change.md sekcja "Po wgraniu")
**Blockers:**
- None
---
*Phase: 21-admin-update-view-js-fix, Plan: 01*
*Completed: 2026-05-13*