--- phase: 06-sonarqube-quality plan: 06 type: execute wave: 2 depends_on: [] files_modified: - src/Modules/Settings/ShopproOrdersSyncService.php - src/Modules/Orders/OrdersRepository.php autonomous: true --- ## Goal Skrócić 4 metody przekraczające limit linii — eliminacja naruszeń SonarQube php:S138. Dodatkowo: `OrdersRepository::paginate()` (183 linie) i `findDetails()` (101 linii) jako najdłuższe metody w module Orders. ## Purpose Metody o 87-195 liniach są niereviewowalne w MR i trudne do lokalnego rozumowania. Wydzielenie sub-metod ogranicza zakres zmian przy przyszłych modyfikacjach — edytujesz 30-liniową metodę, nie 200-liniowy monolit. ## Output 6 metod skróconych do ≤50 linii każda przez ekstrakcję sub-metod. SonarQube S138 spada z 4 do 0. **Uwaga na kolejność z planem 06-05:** Ten plan (06-06) modyfikuje ShopproOrdersSyncService. Plan 06-05 podnosi zależność `depends_on: ["06-04"]`. Jeśli 06-05 jest w trakcie, odłóż zmiany w ShopproOrdersSyncService do po zakończeniu 06-05. ## Project Context @.paul/PROJECT.md ## Source Files @src/Modules/Settings/ShopproOrdersSyncService.php @src/Modules/Orders/OrdersRepository.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: ShopproOrdersSyncService — sync() skrócone ```gherkin Given sync() ma 195 linii When wydzielasz procesPage() i processOrderCandidate() (jeśli nie zrobione w 06-04) Then sync() ma ≤60 linii; wydzielone metody mają ≤50 linii każda ``` ## AC-2: ShopproOrdersSyncService — mapAddresses() skrócone ```gherkin Given mapAddresses() ma 166 linii (budowanie customer + delivery address) When wydzielasz buildCustomerAddress(): array i buildDeliveryAddress(): array Then mapAddresses() ma ≤50 linii; każda sub-metoda ≤60 linii ``` ## AC-3: OrdersRepository::paginate() skrócone ```gherkin Given paginate() ma 183 linie (dynamic SQL building + data transformation) When wydzielasz buildFilters(): array i transformRow(array $row): array Then paginate() ma ≤80 linii; sub-metody mają ≤50 linii każda ``` ## AC-4: OrdersRepository::findDetails() skrócone ```gherkin Given findDetails() ma 101 linii (8 kolejnych zapytań DB) When wydzielasz osobne private metody per query group (loadOrderItems, loadOrderShipments, etc.) Then findDetails() ma ≤50 linii; każdy loader ≤30 linii ``` ## AC-5: Brak regresji ```gherkin Given lista zamówień i szczegóły zamówienia działają przed zmianą When zmiany są czysto strukturalne (extract method) Then paginate() i findDetails() zwracają identyczne dane ``` Task 1: Skróć ShopproOrdersSyncService — sync() i mapAddresses() src/Modules/Settings/ShopproOrdersSyncService.php Przeczytaj ShopproOrdersSyncService dokładnie. **Sprawdź najpierw:** czy 06-04 już wydzielił processPageCandidates() z sync(). Jeśli tak, sprawdź czy sync() jest już ≤60 linii. Jeśli nie — wydziel. **sync() (195 linii) — jeśli jeszcze nie zrobione w 06-04:** Wydziel: - private processPageCandidates(array $candidates, array $integration, array $statusMap, array &$results): void → zawiera foreach ($candidates) + try-catch + logikę przetwarzania 1 zamówienia - private fetchOrdersPage(array $integration, int $page, string $startDate): array → zawiera wywołanie API + obsługę błędów odpowiedzi **mapAddresses() (166 linii):** Wydziel: - private buildCustomerAddress(array $payload): array → adres klienta (billing address) - private buildDeliveryAddress(array $payload): array → adres dostawy (shipping address) - private buildPickupPointData(array $payload): array (jeśli dotyczy) mapAddresses() staje się kompozytorem: wywołuje buildCustomerAddress() i buildDeliveryAddress(). NIE zmieniaj logiki — tylko gdzie jest kod. Nowe private metody na końcu klasy (ale przed zamknięciem `}`). php -l src/Modules/Settings/ShopproOrdersSyncService.php Ręcznie: sync() ≤60 linii, mapAddresses() ≤50 linii AC-1, AC-2 satisfied: sync() i mapAddresses() skrócone Task 2: Skróć OrdersRepository — paginate() i findDetails() src/Modules/Orders/OrdersRepository.php Przeczytaj OrdersRepository dokładnie — paginate() i findDetails(). **paginate() (183 linie):** Ma dwie odrębne odpowiedzialności: budowanie SQL z filtrami + transformacja wierszy. Wydziel: - private buildPaginateFilters(array $filters): array → zwraca ['conditions' => [], 'bindings' => []] → zawiera bloki if ($filter['source']), if ($filter['status']), if ($filter['date_from']), etc. - private transformOrderRow(array $row): array → transformuje jeden wiersz z DB → format gotowy dla widoku → jeśli nie ma transformacji per-row, wydziel transformOrderRows(array $rows): array paginate() staje się: build SQL structure → execute → transform → return. WAŻNE: Medoo query syntax — zachowaj dokładnie ten sam format przekazywania warunków do Medoo. NIE zmieniaj sposobu budowania prepared statements. **findDetails() (101 linii):** Metoda wykonuje 8 kolejnych zapytań DB. Wydziel każde lub grupuj logicznie: - private loadOrderAddresses(int $orderId): array - private loadOrderItems(int $orderId): array - private loadOrderShipments(int $orderId): array - private loadOrderHistory(int $orderId): array - (i inne grupy które znajdziesz w metodzie) findDetails() staje się: załaduj dane orderu + złóż w całość + return. NIE zmieniaj logiki SQL, kolumn, tabel, sposobu bindingu. NIE zmieniaj zwracanej struktury danych. php -l src/Modules/Orders/OrdersRepository.php Ręcznie: paginate() ≤80 linii, findDetails() ≤50 linii AC-3, AC-4, AC-5 satisfied: paginate() i findDetails() skrócone; brak zmiany logiki SQL ## DO NOT CHANGE - Logika SQL w OrdersRepository — prepared statements, WHERE conditions, column names - Zwracana struktura danych z paginate() i findDetails() — widoki zależą od tych kluczy - Publiczne sygnatury metod - Inne pliki poza ShopproOrdersSyncService.php i OrdersRepository.php ## SCOPE LIMITS - Tylko extract method refactoring — nie zmieniaj algorytmów - Nie przenoś metod do innych klas (to zakres 06-05) - Nie zmieniaj logiki filtrowania w paginate() — tylko gdzie jest kod - ShopproOrdersSyncService: uważaj na interferencję z 06-05 (jeśli 06-05 już zmienił tę klasę — dostosuj) Przed zamknięciem planu: - [ ] php -l src/Modules/Settings/ShopproOrdersSyncService.php — brak błędów - [ ] php -l src/Modules/Orders/OrdersRepository.php — brak błędów - [ ] sync() w ShopproOrdersSyncService: ≤60 linii (ręczne sprawdzenie) - [ ] mapAddresses(): ≤50 linii - [ ] paginate(): ≤80 linii - [ ] findDetails(): ≤50 linii - [ ] Lista zamówień ładuje się (brak PHP fatal errors) - [ ] sonar-scanner — S138 violations zmalały - Oba pliki bez błędów składniowych - 4 metody skrócone poniżej limitu SonarQube - Nowe private helper metody ≤50 linii każda - SonarQube S138 spada z 4 do 0 Po zakończeniu utwórz `.paul/phases/06-sonarqube-quality/06-06-SUMMARY.md`