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:
246
.paul/phases/06-sonarqube-quality/06-04-PLAN.md
Normal file
246
.paul/phases/06-sonarqube-quality/06-04-PLAN.md
Normal file
@@ -0,0 +1,246 @@
|
||||
---
|
||||
phase: 06-sonarqube-quality
|
||||
plan: 04
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- src/Modules/Settings/AllegroIntegrationController.php
|
||||
- src/Modules/Settings/ShopproIntegrationsController.php
|
||||
- src/Modules/Settings/ShopproOrdersSyncService.php
|
||||
autonomous: true
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Obniżyć złożoność kognitywną (cognitive complexity) w 5 najbardziej skomplikowanych metodach — eliminacja naruszeń SonarQube php:S3776 (31 wystąpień).
|
||||
|
||||
## Purpose
|
||||
Metody z zagnieżdżonymi if/foreach/switch na 4+ poziomach są trudne do testowania i modyfikacji. Wydzielenie fragmentów do private helper methods upraszcza główny przepływ i obniża wynik SonarQube poniżej progu 15.
|
||||
|
||||
## Output
|
||||
Zmniejszona złożoność w 5 kluczowych metodach w 3 plikach. SonarQube S3776 spada z 31 do ~15.
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
## Project Context
|
||||
@.paul/PROJECT.md
|
||||
|
||||
## Source Files
|
||||
@src/Modules/Settings/AllegroIntegrationController.php
|
||||
@src/Modules/Settings/ShopproIntegrationsController.php
|
||||
@src/Modules/Settings/ShopproOrdersSyncService.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
|
||||
</skills>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: AllegroIntegrationController::oauthCallback() uproszczone
|
||||
```gherkin
|
||||
Given oauthCallback() ma 6 zagnieżdżonych if (validation chain)
|
||||
When wydzielasz każdy blok walidacji do osobnej private metody
|
||||
Then oauthCallback() ma max 2 poziomy zagnieżdżenia
|
||||
```
|
||||
|
||||
## AC-2: AllegroIntegrationController::loadDeliveryServices() uproszczone
|
||||
```gherkin
|
||||
Given loadDeliveryServices() ma try-catch z 4 poziomami zagnieżdżenia
|
||||
When wydzielasz ładowanie Allegro services i Apaczka services do osobnych private metod
|
||||
Then loadDeliveryServices() ma max 2 poziomy zagnieżdżenia
|
||||
```
|
||||
|
||||
## AC-3: ShopproIntegrationsController::saveStatusMappings() uproszczone
|
||||
```gherkin
|
||||
Given saveStatusMappings() ma 3 zagnieżdżone pętle (foreach w foreach z if)
|
||||
When wydzielasz przetwarzanie pojedynczego mappingu do private metody
|
||||
Then saveStatusMappings() ma max 2 poziomy zagnieżdżenia
|
||||
```
|
||||
|
||||
## AC-4: ShopproOrdersSyncService::sync() uproszczone
|
||||
```gherkin
|
||||
Given sync() (195 linii) ma triple nested loop (for pages > foreach candidates > try-catch > if)
|
||||
When wydzielasz przetwarzanie pojedynczej strony do private processPage() i pojedynczego zamówienia do processCandidate()
|
||||
Then sync() ma max 3 poziomy zagnieżdżenia; główna pętla jest czytelna
|
||||
```
|
||||
|
||||
## AC-5: Brak regresji
|
||||
```gherkin
|
||||
Given funkcjonalność działa przed refaktoryzacją
|
||||
When zmiany są czysto strukturalne (extract method, nie zmiana logiki)
|
||||
Then zachowanie identyczne — OAuth flow, status mappings, sync działają
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Uproszczenie AllegroIntegrationController — oauthCallback() i loadDeliveryServices()</name>
|
||||
<files>src/Modules/Settings/AllegroIntegrationController.php</files>
|
||||
<action>
|
||||
Przeczytaj oauthCallback() i loadDeliveryServices() dokładnie.
|
||||
|
||||
**oauthCallback() — wzorzec uproszczenia:**
|
||||
Każdy blok `if (warunek) { flash error; return; }` to kandydat do wydzielenia.
|
||||
Stwórz private validateOAuthState(array $params): bool — sprawdza state parameter
|
||||
Stwórz private validateOAuthCode(array $params): bool — sprawdza code parameter
|
||||
Główna metoda: series of guard checks bez zagnieżdżenia.
|
||||
Docelowy kształt:
|
||||
```php
|
||||
public function oauthCallback(): void {
|
||||
if (!$this->validateOAuthState($params)) { [flash + redirect]; return; }
|
||||
if (!$this->validateOAuthCode($params)) { [flash + redirect]; return; }
|
||||
// logika bez zagnieżdżenia
|
||||
}
|
||||
```
|
||||
|
||||
**loadDeliveryServices() — wzorzec uproszczenia:**
|
||||
Wydziel ładowanie Allegro delivery services do private loadAllegroDeliveryServices(): array
|
||||
Wydziel ładowanie Apaczka services do private loadApaczkaServices(): array
|
||||
Główna metoda wywołuje oba i buduje odpowiedź — bez zagnieżdżonych try-catch.
|
||||
Każda z wydzielonych metod ma swój własny try-catch wewnętrznie.
|
||||
|
||||
Zasady:
|
||||
- NIE zmieniaj logiki — tylko gdzie jest kod
|
||||
- NIE zmieniaj komunikatów, flash keys, redirect paths
|
||||
- Nowe private metody na końcu klasy
|
||||
</action>
|
||||
<verify>
|
||||
php -l src/Modules/Settings/AllegroIntegrationController.php
|
||||
Ręczne sprawdzenie oauthCallback(): max 2 poziomy zagnieżdżenia w ciele metody
|
||||
Ręczne sprawdzenie loadDeliveryServices(): max 2 poziomy zagnieżdżenia
|
||||
</verify>
|
||||
<done>AC-1, AC-2 satisfied: obie metody uproszczone, składnia poprawna</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Uproszczenie ShopproIntegrationsController — saveStatusMappings()</name>
|
||||
<files>src/Modules/Settings/ShopproIntegrationsController.php</files>
|
||||
<action>
|
||||
Przeczytaj saveStatusMappings() i loadDeliveryServices().
|
||||
|
||||
**saveStatusMappings() — wzorzec uproszczenia:**
|
||||
Jeśli metoda zawiera zagnieżdżone foreach z logiką wewnątrz:
|
||||
```php
|
||||
foreach ($mappings as $mapping) {
|
||||
foreach ($mapping['items'] as $item) {
|
||||
if (...) {
|
||||
// logika
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Wydziel wewnętrzny foreach+if do private processMappingItem(array $item, ...): void
|
||||
lub private processSingleStatusMapping(array $mapping): void
|
||||
|
||||
**loadDeliveryServices() (jeśli jest w Shoppro):**
|
||||
Ten sam wzorzec co Allegro — wydziel ładowanie per-provider.
|
||||
|
||||
Główna zasada: metoda po refaktoryzacji powinna być "czytalna jak lista kroków" — bez zagłębiania się w szczegóły.
|
||||
|
||||
NIE zmieniaj logiki biznesowej.
|
||||
Nowe private metody na końcu klasy.
|
||||
</action>
|
||||
<verify>
|
||||
php -l src/Modules/Settings/ShopproIntegrationsController.php
|
||||
Ręczne sprawdzenie saveStatusMappings(): max 2 poziomy zagnieżdżenia
|
||||
</verify>
|
||||
<done>AC-3 satisfied: saveStatusMappings() uproszczone</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: Uproszczenie ShopproOrdersSyncService::sync()</name>
|
||||
<files>src/Modules/Settings/ShopproOrdersSyncService.php</files>
|
||||
<action>
|
||||
Przeczytaj metodę sync() (ok. 195 linii).
|
||||
|
||||
**sync() — wzorzec uproszczenia:**
|
||||
Obecna struktura (schemat):
|
||||
```
|
||||
foreach ($integrations) {
|
||||
for ($page = 1; ...) {
|
||||
foreach ($candidates) {
|
||||
try {
|
||||
if (...) {
|
||||
// przetwarzanie zamówienia
|
||||
}
|
||||
} catch (...) { ... }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Wydziel:
|
||||
1. private processOrderCandidate(array $candidate, array $integration, array $statusMap, ...): void
|
||||
- zawiera: try-catch + logikę przetwarzania jednego zamówienia
|
||||
2. private processPageCandidates(array $candidates, array $integration, array $statusMap, array &$results): void
|
||||
- zawiera: foreach ($candidates) + wywołanie processOrderCandidate()
|
||||
|
||||
Po wydzieleniu sync() powinna wyglądać jak:
|
||||
```
|
||||
foreach ($integrations) {
|
||||
for ($page = 1; ...) {
|
||||
$candidates = $this->buildCandidates($orders);
|
||||
$this->processPageCandidates($candidates, $integration, $statusMap, $results);
|
||||
if (brak kolejnej strony) break;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Zachowaj wszystkie parametry które są potrzebne (przekaż przez argumenty lub &$results).
|
||||
NIE zmieniaj logiki przetwarzania — tylko gdzie jest kod.
|
||||
</action>
|
||||
<verify>
|
||||
php -l src/Modules/Settings/ShopproOrdersSyncService.php
|
||||
Ręczne sprawdzenie sync(): max 3 poziomy zagnieżdżenia (foreach integrations > for pages > processPageCandidates)
|
||||
</verify>
|
||||
<done>AC-4, AC-5 satisfied: sync() uproszczone, ShopproOrdersSyncService poprawna składniowo</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- Logika biznesowa — warunkowa, obliczeniowa, API calls
|
||||
- Komunikaty błędów, flash keys, redirect paths
|
||||
- Publiczne sygnatury metod (public function names + parameters)
|
||||
- Inne metody poza wymienionymi w AC
|
||||
- Pliki poza files_modified
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Wydzielanie metod tylko wewnątrz istniejącej klasy (nie tworzyć nowych klas — to zakres 06-05)
|
||||
- Nowe metody: private, na końcu klasy, jasna nazwa opisująca co robią
|
||||
- Nie optymalizuj algorytmicznie — tylko strukturalnie
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Przed zamknięciem planu:
|
||||
- [ ] php -l na wszystkich 3 plikach — zero błędów
|
||||
- [ ] oauthCallback() — max 2 poziomy zagnieżdżenia (ręczne sprawdzenie)
|
||||
- [ ] loadDeliveryServices() (Allegro) — max 2 poziomy zagnieżdżenia
|
||||
- [ ] saveStatusMappings() (Shoppro) — max 2 poziomy zagnieżdżenia
|
||||
- [ ] sync() (ShopproOrdersSyncService) — max 3 poziomy zagnieżdżenia
|
||||
- [ ] sonar-scanner — S3776 violations zmalały
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Wszystkie 3 pliki bez błędów składniowych
|
||||
- 5 wskazanych metod z zredukowanym zagnieżdżeniem
|
||||
- SonarQube S3776 spada z 31 do ≤18
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Po zakończeniu utwórz `.paul/phases/06-sonarqube-quality/06-04-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user