wip(06-sonarqube-quality): 6 planów SonarQube Quality utworzonych
Plany dla php:S112, S1142, S1192, S3776, S1448, S138 — gotowe do APPLY. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
251
.paul/phases/06-sonarqube-quality/06-01-PLAN.md
Normal file
251
.paul/phases/06-sonarqube-quality/06-01-PLAN.md
Normal file
@@ -0,0 +1,251 @@
|
||||
---
|
||||
phase: 06-sonarqube-quality
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- src/Core/Exceptions/OrderProException.php
|
||||
- src/Core/Exceptions/AllegroApiException.php
|
||||
- src/Core/Exceptions/AllegroOAuthException.php
|
||||
- src/Core/Exceptions/ApaczkaApiException.php
|
||||
- src/Core/Exceptions/ShipmentException.php
|
||||
- src/Core/Exceptions/IntegrationConfigException.php
|
||||
- src/Modules/Settings/AllegroApiClient.php
|
||||
- src/Modules/Settings/AllegroOAuthClient.php
|
||||
- src/Modules/Settings/AllegroTokenManager.php
|
||||
- src/Modules/Settings/AllegroIntegrationRepository.php
|
||||
- src/Modules/Settings/AllegroIntegrationController.php
|
||||
- src/Modules/Settings/AllegroOrderImportService.php
|
||||
- src/Modules/Settings/AllegroOrdersSyncService.php
|
||||
- src/Modules/Settings/ApaczkaApiClient.php
|
||||
- src/Modules/Settings/ApaczkaIntegrationRepository.php
|
||||
- src/Modules/Shipments/ApaczkaShipmentService.php
|
||||
- src/Modules/Shipments/AllegroShipmentService.php
|
||||
- src/Modules/Shipments/ShipmentController.php
|
||||
- src/Modules/Settings/IntegrationSecretCipher.php
|
||||
- src/Modules/Settings/InpostIntegrationRepository.php
|
||||
- src/Modules/Settings/ShopproIntegrationsRepository.php
|
||||
- src/Modules/Settings/ShopproOrdersSyncService.php
|
||||
- src/Modules/Settings/ShopproPaymentStatusSyncService.php
|
||||
autonomous: true
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Zastąpić 86+ wywołań `throw new RuntimeException()` dedykowanymi klasami wyjątków per moduł — eliminacja naruszeń SonarQube php:S112.
|
||||
|
||||
## Purpose
|
||||
SonarQube flaguje `RuntimeException` jako zbyt ogólny — łapanie `catch (RuntimeException)` nie mówi nic o tym, jaki błąd nastąpił. Typowane wyjątki umożliwiają precyzyjny catch w wywołującym kodzie i poprawiają czytelność stacktrace.
|
||||
|
||||
## Output
|
||||
Hierarchia klas wyjątków w `src/Core/Exceptions/` + podmienione throw w 13 plikach. Liczba S112 w SonarQube spada z 95 do ~5 (pozostałości w Core).
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
## Project Context
|
||||
@.paul/PROJECT.md
|
||||
@.paul/STATE.md
|
||||
|
||||
## Source Files
|
||||
@src/Modules/Settings/AllegroApiClient.php
|
||||
@src/Modules/Settings/AllegroOAuthClient.php
|
||||
@src/Modules/Settings/AllegroTokenManager.php
|
||||
@src/Modules/Shipments/ApaczkaShipmentService.php
|
||||
@src/Modules/Shipments/AllegroShipmentService.php
|
||||
@src/Modules/Settings/ApaczkaApiClient.php
|
||||
@src/Modules/Settings/IntegrationSecretCipher.php
|
||||
</context>
|
||||
|
||||
<skills>
|
||||
## Required Skills (from SPECIAL-FLOWS.md)
|
||||
|
||||
| Skill | Priority | When to Invoke | Loaded? |
|
||||
|-------|----------|----------------|---------|
|
||||
| sonar-scanner | required | Po APPLY, przed UNIFY | ○ |
|
||||
|
||||
## Skill Invocation Checklist
|
||||
- [ ] sonar-scanner uruchomiony po zakończeniu APPLY (CLI w katalogu projektu)
|
||||
</skills>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Hierarchia wyjątków istnieje
|
||||
```gherkin
|
||||
Given brak folderu src/Core/Exceptions/
|
||||
When plan zostaje wykonany
|
||||
Then folder src/Core/Exceptions/ istnieje z klasami: OrderProException, AllegroApiException, AllegroOAuthException, ApaczkaApiException, ShipmentException, IntegrationConfigException
|
||||
```
|
||||
|
||||
## AC-2: Allegro-specific throws podmienione
|
||||
```gherkin
|
||||
Given AllegroApiClient, AllegroOAuthClient, AllegroTokenManager rzucają RuntimeException
|
||||
When plan zostaje wykonany
|
||||
Then wszystkie throw w tych plikach używają AllegroApiException lub AllegroOAuthException
|
||||
```
|
||||
|
||||
## AC-3: Apaczka-specific throws podmienione
|
||||
```gherkin
|
||||
Given ApaczkaApiClient, ApaczkaShipmentService, ApaczkaIntegrationRepository rzucają RuntimeException
|
||||
When plan zostaje wykonany
|
||||
Then wszystkie throw w tych plikach używają ApaczkaApiException
|
||||
```
|
||||
|
||||
## AC-4: Shipment throws podmienione
|
||||
```gherkin
|
||||
Given AllegroShipmentService, ShipmentController rzucają RuntimeException
|
||||
When plan zostaje wykonany
|
||||
Then wszystkie throw używają ShipmentException
|
||||
```
|
||||
|
||||
## AC-5: Brak regresji
|
||||
```gherkin
|
||||
Given aplikacja działa przed zmianą
|
||||
When klasy wyjątków rozszerzają RuntimeException (łańcuch dziedziczenia zachowany)
|
||||
Then istniejące catch (RuntimeException) w kodzie wywołującym nadal działają
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Utwórz hierarchię klas wyjątków</name>
|
||||
<files>
|
||||
src/Core/Exceptions/OrderProException.php,
|
||||
src/Core/Exceptions/AllegroApiException.php,
|
||||
src/Core/Exceptions/AllegroOAuthException.php,
|
||||
src/Core/Exceptions/ApaczkaApiException.php,
|
||||
src/Core/Exceptions/ShipmentException.php,
|
||||
src/Core/Exceptions/IntegrationConfigException.php
|
||||
</files>
|
||||
<action>
|
||||
Utwórz folder src/Core/Exceptions/ i pliki klas z namespace App\Core\Exceptions.
|
||||
|
||||
Hierarchia:
|
||||
- OrderProException extends \RuntimeException — baza dla wszystkich własnych wyjątków
|
||||
- AllegroApiException extends OrderProException — błędy HTTP/JSON Allegro API i OAuth
|
||||
- AllegroOAuthException extends AllegroApiException — specyficznie błędy OAuth (token refresh, brak tokenów)
|
||||
- ApaczkaApiException extends OrderProException — błędy API Apaczka (HTTP, curl, payload)
|
||||
- ShipmentException extends OrderProException — błędy tworzenia/pobierania przesyłek (brak zamówienia, brak providera, brak paczki)
|
||||
- IntegrationConfigException extends OrderProException — błędy konfiguracji integracji (brak rekordu w DB, brak klucza API, brak sekretu)
|
||||
|
||||
Każda klasa: minimalna (tylko class declaration + extends). Brak dodatkowych metod — nie powielać logiki.
|
||||
Nie dodawaj konstruktorów ani innych metod — klasy wyjątków mają być tylko markerami.
|
||||
</action>
|
||||
<verify>php -l src/Core/Exceptions/OrderProException.php (i pozostałe 5 plików) — każdy zwraca "No syntax errors"</verify>
|
||||
<done>AC-1 satisfied: folder src/Core/Exceptions/ z 6 klasami istnieje i jest poprawny składniowo</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Podmień RuntimeException w plikach Allegro</name>
|
||||
<files>
|
||||
src/Modules/Settings/AllegroApiClient.php,
|
||||
src/Modules/Settings/AllegroOAuthClient.php,
|
||||
src/Modules/Settings/AllegroTokenManager.php,
|
||||
src/Modules/Settings/AllegroIntegrationRepository.php,
|
||||
src/Modules/Settings/AllegroIntegrationController.php,
|
||||
src/Modules/Settings/AllegroOrderImportService.php,
|
||||
src/Modules/Settings/AllegroOrdersSyncService.php
|
||||
</files>
|
||||
<action>
|
||||
W każdym pliku:
|
||||
1. Dodaj use App\Core\Exceptions\AllegroApiException; (i AllegroOAuthException tam gdzie dotyczy OAuth)
|
||||
2. Zastąp throw new RuntimeException(...) odpowiednią klasą:
|
||||
- AllegroApiClient.php (18x): HTTP/JSON/curl błędy → AllegroApiException; błędy OAuth (ALLEGRO_HTTP_401) → AllegroApiException
|
||||
- AllegroOAuthClient.php (6x): wszystkie → AllegroOAuthException
|
||||
- AllegroTokenManager.php (3x): brak połączenia OAuth, brak danych, niepowodzenie refresh → AllegroOAuthException
|
||||
- AllegroIntegrationRepository.php (1x): brak rekordu → IntegrationConfigException (użyj use App\Core\Exceptions\IntegrationConfigException)
|
||||
- AllegroIntegrationController.php (1x): brak credentials → IntegrationConfigException
|
||||
- AllegroOrderImportService.php (2x): błędy importu → AllegroApiException
|
||||
- AllegroOrdersSyncService.php (1x): brak aktywnej integracji → IntegrationConfigException
|
||||
|
||||
Uwaga: NIE zmieniaj logiki catch bloków — tylko throw. NIE zmieniaj komunikatów błędów.
|
||||
Uwaga: \RuntimeException w AllegroIntegrationController (jeśli catch) — NIE ruszać.
|
||||
</action>
|
||||
<verify>
|
||||
php -l src/Modules/Settings/AllegroApiClient.php
|
||||
php -l src/Modules/Settings/AllegroOAuthClient.php
|
||||
php -l src/Modules/Settings/AllegroTokenManager.php
|
||||
grep -r "new RuntimeException" src/Modules/Settings/Allegro*.php — powinno zwrócić 0 wyników
|
||||
</verify>
|
||||
<done>AC-2 satisfied: pliki Allegro nie zawierają throw new RuntimeException</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: Podmień RuntimeException w plikach Apaczka, Shipment i pozostałych</name>
|
||||
<files>
|
||||
src/Modules/Settings/ApaczkaApiClient.php,
|
||||
src/Modules/Settings/ApaczkaIntegrationRepository.php,
|
||||
src/Modules/Shipments/ApaczkaShipmentService.php,
|
||||
src/Modules/Shipments/AllegroShipmentService.php,
|
||||
src/Modules/Shipments/ShipmentController.php,
|
||||
src/Modules/Settings/IntegrationSecretCipher.php,
|
||||
src/Modules/Settings/InpostIntegrationRepository.php,
|
||||
src/Modules/Settings/ShopproIntegrationsRepository.php,
|
||||
src/Modules/Settings/ShopproOrdersSyncService.php,
|
||||
src/Modules/Settings/ShopproPaymentStatusSyncService.php
|
||||
</files>
|
||||
<action>
|
||||
Podmień RuntimeException:
|
||||
- ApaczkaApiClient.php (9x): curl/HTTP/JSON błędy → ApaczkaApiException
|
||||
- ApaczkaIntegrationRepository.php (4x): brak rekordu/klucza → IntegrationConfigException
|
||||
- ApaczkaShipmentService.php (15x): brak zamówienia/paczki/etykiety → ShipmentException; brak konfiguracji (brak app_id) → IntegrationConfigException; brak danych nadawcy → IntegrationConfigException
|
||||
- AllegroShipmentService.php (8x): brak zamówienia/paczki/przesyłki → ShipmentException; brak danych nadawcy → IntegrationConfigException
|
||||
- ShipmentController.php (3x): nieznany provider, brak paczki, brak providera → ShipmentException
|
||||
- IntegrationSecretCipher.php (3x): brak sekretu, błąd szyfrowania → IntegrationConfigException
|
||||
- InpostIntegrationRepository.php (1x): brak rekordu → IntegrationConfigException
|
||||
- ShopproIntegrationsRepository.php (1x): INTEGRATION_NOT_FOUND → IntegrationConfigException
|
||||
- ShopproOrdersSyncService.php (2x): brak danych API, błąd pobierania zamówień → \RuntimeException (zostawić — są wewnątrz try-catch i message pochodzi z zewnętrznego API)
|
||||
- ShopproPaymentStatusSyncService.php (1x): zostawić jako \RuntimeException (message z zewnętrznego API)
|
||||
|
||||
W każdym pliku dodaj odpowiednie use statements na górze.
|
||||
NIE zmieniaj logiki catch — tylko throw.
|
||||
</action>
|
||||
<verify>
|
||||
php -l src/Modules/Shipments/ApaczkaShipmentService.php
|
||||
php -l src/Modules/Shipments/AllegroShipmentService.php
|
||||
php -l src/Modules/Settings/ApaczkaApiClient.php
|
||||
grep -rn "new RuntimeException" src/ — powinno zwrócić maks. 5 wyników (ShopproOrdersSyncService, ShopproPaymentStatusSyncService, CronRunner, AllegroTokenRefreshHandler — intentional pozostałości)
|
||||
</verify>
|
||||
<done>AC-3, AC-4, AC-5 satisfied: Apaczka i Shipment pliki używają typowanych wyjątków; łańcuch dziedziczenia od RuntimeException zachowany</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- Bloki catch (RuntimeException) w controllers/handlers — łańcuch dziedziczenia zachowuje kompatybilność, ale NIE ruszaj istniejących catch
|
||||
- Komunikaty błędów w throw — tylko typ wyjątku się zmienia
|
||||
- src/Core/Exceptions/ — nie tworzyć tu nic poza 6 klasami z tego planu
|
||||
- routes/web.php
|
||||
- Pliki widoków (resources/views/)
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Nie refaktoryzuj logiki poza podmianą throw
|
||||
- Nie dodawaj konstruktorów ani metod do klas wyjątków
|
||||
- Nie zmieniaj sposobu obsługi błędów w UI (flash messages, HTTP redirecty)
|
||||
- Core wyjątki (Router.php, Template.php, Translator.php, ConnectionFactory.php, Migrator.php) — zostawić jako RuntimeException (mają sens jako generyczne)
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Przed zamknięciem planu:
|
||||
- [ ] php -l na wszystkich zmodyfikowanych plikach PHP — zero błędów składniowych
|
||||
- [ ] grep -rn "new RuntimeException" src/ — max 5 wyników (tylko Core + 2 Shoppro intentional)
|
||||
- [ ] ls src/Core/Exceptions/ — 6 plików: OrderProException, AllegroApiException, AllegroOAuthException, ApaczkaApiException, ShipmentException, IntegrationConfigException
|
||||
- [ ] Aplikacja startuje bez błędów (wejście na stronę główną, brak PHP fatal errors w logach)
|
||||
- [ ] sonar-scanner uruchomiony — sprawdź czy S112 violations zmalały
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Wszystkie 3 taski ukończone
|
||||
- Zero błędów składniowych PHP
|
||||
- grep "new RuntimeException" src/ zwraca ≤5 wyników
|
||||
- SonarQube S112 spada z 95 do ≤10
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Po zakończeniu utwórz `.paul/phases/06-sonarqube-quality/06-01-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user