---
phase: 05-tech-debt-3
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - src/Modules/Orders/OrdersController.php
  - src/Modules/Shipments/ShipmentController.php
autonomous: true
---

<objective>
## Goal
Zastąpić bezpośrednie zapisy do `$_SESSION['order_flash_*']` i `$_SESSION['shipment_flash_*']` wywołaniami `Flash::set()` / `Flash::get()` w `OrdersController` i `ShipmentController`.

## Purpose
Ujednolicenie wzorca flash messages w całej aplikacji — obecnie `OrdersController` i `ShipmentController` omijają warstwę abstrakcji `Flash`, co tworzy dwa niekompatybilne mechanizmy. Pozostałe kontrolery (Settings) używają już `Flash::set()`/`Flash::get()`.

## Output
Dwa zmodyfikowane pliki PHP z usuniętymi bezpośrednimi odwołaniami do `$_SESSION['*_flash_*']`. Concern `[MEDIUM] Direct $_SESSION Writes` zamknięty.
</objective>

<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md

## Source Files
@src/Core/Support/Flash.php
@src/Modules/Orders/OrdersController.php
@src/Modules/Shipments/ShipmentController.php
</context>

<skills>
## Required Skills (from SPECIAL-FLOWS.md)

| Skill | Priority | When to Invoke | Loaded? |
|-------|----------|----------------|---------|
| sonar-scanner | required | Po APPLY, przed UNIFY | ○ |
| /code-review | optional | Po implementacji, przed UNIFY | ○ |

**BLOCKING:** `sonar-scanner` musi być uruchomiony przed UNIFY.

## Skill Invocation Checklist
- [ ] sonar-scanner uruchomiony (CLI w katalogu projektu)
- [ ] /code-review opcjonalnie przed UNIFY

</skills>

<acceptance_criteria>

## AC-1: OrdersController używa Flash
```gherkin
Given OrdersController.php nie zawiera żadnych odwołań do $_SESSION['order_flash_*']
When przeglądamy kod OrdersController
Then wszystkie odczyty flash używają Flash::get('order.success') i Flash::get('order.error')
  And wszystkie zapisy flash używają Flash::set('order.success', ...) i Flash::set('order.error', ...)
  And Flash jest zaimportowany przez use App\Core\Support\Flash
```

## AC-2: ShipmentController używa Flash
```gherkin
Given ShipmentController.php nie zawiera żadnych odwołań do $_SESSION['shipment_flash_*']
When przeglądamy kod ShipmentController
Then wszystkie odczyty flash używają Flash::get('shipment.success') i Flash::get('shipment.error')
  And wszystkie zapisy flash używają Flash::set('shipment.success', ...) i Flash::set('shipment.error', ...)
  And Flash jest zaimportowany przez use App\Core\Support\Flash
```

## AC-3: Brak regresji — widoki nadal otrzymują flashSuccess/flashError
```gherkin
Given widok orders/show.php oczekuje zmiennych $flashSuccess i $flashError
  And widok shipments/prepare.php oczekuje zmiennych $flashSuccess i $flashError
When kontrolery renderują widoki po migracji
Then zmienne flashSuccess i flashError nadal są przekazywane do template->render()
  And ich wartości pochodzą z Flash::get() zamiast z $_SESSION bezpośrednio
```

</acceptance_criteria>

<tasks>

<task type="auto">
  <name>Task 1: Migracja flash messages w OrdersController</name>
  <files>src/Modules/Orders/OrdersController.php</files>
  <action>
    1. Dodaj import `use App\Core\Support\Flash;` do sekcji use (po pozostałych use w pliku).

    2. W metodzie `show()` (linie ~163–165) zastąp:
       ```php
       $flashSuccess = (string) ($_SESSION['order_flash_success'] ?? '');
       $flashError = (string) ($_SESSION['order_flash_error'] ?? '');
       unset($_SESSION['order_flash_success'], $_SESSION['order_flash_error']);
       ```
       przez:
       ```php
       $flashSuccess = (string) Flash::get('order.success', '');
       $flashError = (string) Flash::get('order.error', '');
       ```
       (Flash::get() usuwa klucz automatycznie — unset zbędny)

    3. W metodzie `updateStatus()` zastąp wszystkie zapisy `$_SESSION['order_flash_*']`:
       - `$_SESSION['order_flash_error'] = ...` → `Flash::set('order.error', ...)`
       - `$_SESSION['order_flash_success'] = ...` → `Flash::set('order.success', ...)`

    Dotyczy 4 miejsc (linie ~204, ~210, ~219, ~221).
    Nie zmieniaj nazw zmiennych przekazywanych do template->render() ('flashSuccess', 'flashError').
  </action>
  <verify>grep -n "_SESSION\['order_flash" src/Modules/Orders/OrdersController.php — zwraca 0 wyników</verify>
  <done>AC-1 satisfied: brak bezpośrednich odwołań do $_SESSION['order_flash_*']</done>
</task>

<task type="auto">
  <name>Task 2: Migracja flash messages w ShipmentController</name>
  <files>src/Modules/Shipments/ShipmentController.php</files>
  <action>
    1. Dodaj import `use App\Core\Support\Flash;` do sekcji use (po pozostałych use w pliku).

    2. W metodzie `prepare()` (linie ~93–95) zastąp:
       ```php
       $flashSuccess = (string) ($_SESSION['shipment_flash_success'] ?? '');
       $flashError = (string) ($_SESSION['shipment_flash_error'] ?? '');
       unset($_SESSION['shipment_flash_success'], $_SESSION['shipment_flash_error']);
       ```
       przez:
       ```php
       $flashSuccess = (string) Flash::get('shipment.success', '');
       $flashError = (string) Flash::get('shipment.error', '');
       ```

    3. W metodach `create()` i `label()` zastąp wszystkie zapisy `$_SESSION['shipment_flash_*']`:
       - `$_SESSION['shipment_flash_error'] = ...` → `Flash::set('shipment.error', ...)`
       - `$_SESSION['shipment_flash_success'] = ...` → `Flash::set('shipment.success', ...)`

    Dotyczy 6 miejsc (linie ~155, ~209, ~220, ~272, ~318, ~328).
    Nie zmieniaj nazw zmiennych przekazywanych do template->render() ('flashSuccess', 'flashError').
  </action>
  <verify>grep -n "_SESSION\['shipment_flash" src/Modules/Shipments/ShipmentController.php — zwraca 0 wyników</verify>
  <done>AC-2 i AC-3 satisfied: brak bezpośrednich odwołań do $_SESSION['shipment_flash_*'], zmienne flashSuccess/flashError nadal przekazywane do widoku</done>
</task>

</tasks>

<boundaries>

## DO NOT CHANGE
- src/Core/Support/Flash.php (klasa Flash — działa poprawnie, nie modyfikować)
- resources/views/orders/show.php (widok — oczekuje 'flashSuccess'/'flashError', nie zmieniać nazw kluczy w render())
- resources/views/shipments/prepare.php (widok — analogicznie)
- Żadne inne pliki poza dwoma kontrolerami

## SCOPE LIMITS
- Nie refaktoryzuj innych fragmentów kontrolerów — tylko flash messages
- Nie zmieniaj nazw kluczy flash przekazywanych do widoków ('flashSuccess', 'flashError')
- Nie dotykaj metody checkStatus() w ShipmentController — nie używa flash
- Nie dodawaj nowych zależności

</boundaries>

<verification>
Before declaring plan complete:
- [ ] grep -rn "_SESSION\['order_flash" src/ — zero wyników
- [ ] grep -rn "_SESSION\['shipment_flash" src/ — zero wyników
- [ ] grep -n "use App\\Core\\Support\\Flash" src/Modules/Orders/OrdersController.php — jeden wynik
- [ ] grep -n "use App\\Core\\Support\\Flash" src/Modules/Shipments/ShipmentController.php — jeden wynik
- [ ] PHP lint: php -l src/Modules/Orders/OrdersController.php — No syntax errors
- [ ] PHP lint: php -l src/Modules/Shipments/ShipmentController.php — No syntax errors
</verification>

<success_criteria>
- Oba kontrolery używają Flash::set()/Flash::get() zamiast bezpośrednich $_SESSION writes
- Zero odwołań do $_SESSION['order_flash_*'] i $_SESSION['shipment_flash_*'] w całej bazie kodu
- PHP lint przechodzi bez błędów
- Widoki nadal otrzymują flashSuccess i flashError (brak regresji w renderowaniu)
</success_criteria>

<output>
After completion, create `.paul/phases/05-tech-debt-3/05-01-SUMMARY.md`
</output>
