--- 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 --- ## 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. ## Project Context @.paul/PROJECT.md ## Source Files @src/Modules/Settings/AllegroIntegrationController.php @src/Modules/Settings/ShopproIntegrationsController.php @src/Modules/Settings/ShopproOrdersSyncService.php ## 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 ## 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ą ``` Task 1: Uproszczenie AllegroIntegrationController — oauthCallback() i loadDeliveryServices() src/Modules/Settings/AllegroIntegrationController.php 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 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 AC-1, AC-2 satisfied: obie metody uproszczone, składnia poprawna Task 2: Uproszczenie ShopproIntegrationsController — saveStatusMappings() src/Modules/Settings/ShopproIntegrationsController.php 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. php -l src/Modules/Settings/ShopproIntegrationsController.php Ręczne sprawdzenie saveStatusMappings(): max 2 poziomy zagnieżdżenia AC-3 satisfied: saveStatusMappings() uproszczone Task 3: Uproszczenie ShopproOrdersSyncService::sync() src/Modules/Settings/ShopproOrdersSyncService.php 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. php -l src/Modules/Settings/ShopproOrdersSyncService.php Ręczne sprawdzenie sync(): max 3 poziomy zagnieżdżenia (foreach integrations > for pages > processPageCandidates) AC-4, AC-5 satisfied: sync() uproszczone, ShopproOrdersSyncService poprawna składniowo ## 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 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 - Wszystkie 3 pliki bez błędów składniowych - 5 wskazanych metod z zredukowanym zagnieżdżeniem - SonarQube S3776 spada z 31 do ≤18 Po zakończeniu utwórz `.paul/phases/06-sonarqube-quality/06-04-SUMMARY.md`