--- phase: 68-code-deduplication-refactor plan: 01 type: execute wave: 1 depends_on: [] files_modified: - src/Core/Http/SslCertificateResolver.php (new) - src/Modules/Settings/AllegroApiClient.php - src/Modules/Settings/ApaczkaApiClient.php - src/Modules/Settings/ShopproApiClient.php - src/Modules/Settings/AllegroOAuthClient.php - src/Modules/Shipments/AllegroTrackingService.php - src/Modules/Shipments/InpostShipmentService.php - src/Modules/Shipments/InpostTrackingService.php - src/Core/Http/ToggleableRepositoryTrait.php (new) - src/Modules/Automation/AutomationController.php - src/Modules/Settings/EmailMailboxRepository.php - src/Modules/Settings/EmailTemplateRepository.php - src/Modules/Settings/ReceiptConfigRepository.php - src/Modules/Settings/EmailMailboxController.php - src/Modules/Settings/EmailTemplateController.php - src/Modules/Settings/ReceiptConfigController.php - src/Core/Http/RedirectPathResolver.php (new) - src/Modules/Settings/AllegroIntegrationController.php - src/Modules/Settings/ApaczkaIntegrationController.php - src/Modules/Settings/InpostIntegrationController.php autonomous: true delegation: auto --- ## Goal Wyeliminowac zduplikowana logike biznesowa i infrastrukturalna z codebase — 7x getCaBundlePath, 7x toggleStatus, 3x resolveRedirectPath — przez ekstrakcje do wspolnych klas/traitow. ## Purpose Duplikacja kodu powoduje realne bugi (jak dzisiejszy brak godzin na paragonach — ta sama logika w 2 miejscach, poprawiona tylko w 1). Konsolidacja zmniejsza ryzyko rozsynchronizowania i ulatwia utrzymanie. ## Output - `Core/Http/SslCertificateResolver.php` — statyczna metoda zastepujaca 7 kopii getCaBundlePath - `Core/Http/ToggleableRepositoryTrait.php` — trait z metoda toggleActive() dla repozytoriow - `Core/Http/RedirectPathResolver.php` — statyczna metoda zastepujaca 3 kopie resolveRedirectPath - 13 zrefaktoryzowanych plikow zrodlowych ## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md ## Source Files @src/Modules/Settings/AllegroApiClient.php @src/Modules/Settings/ApaczkaApiClient.php @src/Modules/Settings/ShopproApiClient.php @src/Modules/Settings/AllegroOAuthClient.php @src/Modules/Shipments/AllegroTrackingService.php @src/Modules/Shipments/InpostShipmentService.php @src/Modules/Shipments/InpostTrackingService.php @src/Modules/Automation/AutomationController.php @src/Modules/Settings/EmailMailboxRepository.php @src/Modules/Settings/EmailTemplateRepository.php @src/Modules/Settings/ReceiptConfigRepository.php @src/Modules/Settings/AllegroIntegrationController.php @src/Modules/Settings/ApaczkaIntegrationController.php @src/Modules/Settings/InpostIntegrationController.php ## AC-1: getCaBundlePath wyeliminowane z 7 klas ```gherkin Given 7 klas posiada identyczna prywatna metode getCaBundlePath() When refaktor zostanie zastosowany Then istnieje jedna klasa SslCertificateResolver ze statyczna metoda resolve() And zadna z 7 klas nie posiada juz metody getCaBundlePath And wszystkie wywolania uzywaja SslCertificateResolver::resolve() And PHP lint przechodzi bez bledow ``` ## AC-2: toggleStatus skonsolidowane w trait ```gherkin Given 4+ repozytoriow posiada podobna metode toggleActive/toggleStatus When refaktor zostanie zastosowany Then istnieje trait ToggleableRepositoryTrait z metoda toggleActive() And repozytoria uzywaja traita zamiast wlasnej implementacji And kontrolery toggleStatus wywoluja repozytorium bez zmian w zachowaniu And PHP lint przechodzi bez bledow ``` ## AC-3: resolveRedirectPath skonsolidowane ```gherkin Given 3 kontrolery integracji posiadaja identyczna metode resolveRedirectPath When refaktor zostanie zastosowany Then istnieje jedna klasa/metoda RedirectPathResolver And 3 kontrolery uzywaja wspolnej implementacji And PHP lint przechodzi bez bledow ``` Task 1: Ekstrakcja SslCertificateResolver z 7 kopii getCaBundlePath src/Core/Http/SslCertificateResolver.php (new), src/Modules/Settings/AllegroApiClient.php, src/Modules/Settings/ApaczkaApiClient.php, src/Modules/Settings/ShopproApiClient.php, src/Modules/Settings/AllegroOAuthClient.php, src/Modules/Shipments/AllegroTrackingService.php, src/Modules/Shipments/InpostShipmentService.php, src/Modules/Shipments/InpostTrackingService.php 1. Przeczytaj getCaBundlePath() z jednej z 7 klas (identyczne) 2. Utworz src/Core/Http/SslCertificateResolver.php: - final class, namespace App\Core\Http - public static function resolve(): string — logika z getCaBundlePath 3. W kazdej z 7 klas: - Dodaj use App\Core\Http\SslCertificateResolver - Zamien wywolania $this->getCaBundlePath() na SslCertificateResolver::resolve() - Usun prywatna metode getCaBundlePath() 4. Uruchom PHP lint na wszystkich 8 plikach Unikaj: zmieniania jakiejkolwiek innej logiki w tych klasach PHP lint: php -l na wszystkich 8 plikach + grep -r "getCaBundlePath" src/ zwraca 0 wynikow AC-1 satisfied: getCaBundlePath nie istnieje w zadnej z 7 klas, SslCertificateResolver jest jedynym zrodlem Task 2: Ekstrakcja ToggleableRepositoryTrait z powtorzonej logiki toggleActive src/Core/Http/ToggleableRepositoryTrait.php (new), src/Modules/Settings/EmailMailboxRepository.php, src/Modules/Settings/EmailTemplateRepository.php, src/Modules/Settings/ReceiptConfigRepository.php, src/Modules/Automation/AutomationController.php, src/Modules/Settings/EmailMailboxController.php, src/Modules/Settings/EmailTemplateController.php, src/Modules/Settings/ReceiptConfigController.php 1. Przeczytaj metody toggleActive/toggleStatus z repozytoriow — zidentyfikuj wspolny wzorzec 2. Utworz src/Core/Http/ToggleableRepositoryTrait.php: - trait ToggleableRepositoryTrait, namespace App\Core\Http - Metoda toggleActive(string $table, int $id, string $column = 'is_active'): bool - Wymaga aby klasa uzywajaca traita miala property $db (Medoo) 3. W kazdym repozytorium z toggleActive: - Dodaj use ToggleableRepositoryTrait - Usun lokalna metode toggleActive/toggleStatus - Jesli sygnatura sie rozni, dostosuj wywolania w kontrolerach 4. PHP lint na wszystkich zmienionych plikach Unikaj: zmieniania logiki kontrolerow poza dostosowaniem wywolan toggle PHP lint na wszystkich zmienionych plikach + metody toggleActive/toggleStatus nie istnieja lokalnie w repozytoriach AC-2 satisfied: trait ToggleableRepositoryTrait jest jedynym zrodlem logiki toggle Task 3: Ekstrakcja RedirectPathResolver z 3 kontrolerow integracji src/Core/Http/RedirectPathResolver.php (new), src/Modules/Settings/AllegroIntegrationController.php, src/Modules/Settings/ApaczkaIntegrationController.php, src/Modules/Settings/InpostIntegrationController.php 1. Przeczytaj resolveRedirectPath() z 3 kontrolerow — potwierdz identycznosc 2. Utworz src/Core/Http/RedirectPathResolver.php: - final class, namespace App\Core\Http - public static function resolve(string $requestedPath, array $allowedPaths, string $default): string 3. W kazdym z 3 kontrolerow: - Dodaj use App\Core\Http\RedirectPathResolver - Zamien wywolania $this->resolveRedirectPath(...) na RedirectPathResolver::resolve(...) - Usun prywatna metode resolveRedirectPath() 4. PHP lint na 4 plikach Unikaj: zmieniania logiki walidacji/przekierowan poza ekstrakcja PHP lint na 4 plikach + grep -r "function resolveRedirectPath" src/ zwraca 0 wynikow AC-3 satisfied: resolveRedirectPath nie istnieje w zadnym z 3 kontrolerow ## DO NOT CHANGE - database/migrations/* — brak zmian schematu - resources/views/* — brak zmian widokow - routes/web.php — brak zmian routingu (chyba ze wymagane przez nowe zależności DI) - Logika biznesowa w zmienianych klasach — refaktor dotyczy TYLKO duplikacji ## SCOPE LIMITS - Ten plan obejmuje tylko getCaBundlePath, toggleStatus i resolveRedirectPath - Duplikacje apiRequest, downloadLabel, buildReceiverAddress, resolveColumns — osobny plan (68-02) - Nie refaktoryzowac validateCsrf (wymaga analizy middleware — osobny plan) Before declaring plan complete: - [ ] PHP lint przechodzi na wszystkich zmienionych plikach - [ ] grep -r "getCaBundlePath" src/ — 0 wynikow - [ ] grep -r "function resolveRedirectPath" src/ — 0 wynikow - [ ] Ponowna analiza duplikacji w codebase — potwierdzenie eliminacji - [ ] Wszystkie acceptance criteria spelnione - 7 kopii getCaBundlePath → 1 klasa SslCertificateResolver - 7 kopii toggleStatus → 1 trait ToggleableRepositoryTrait - 3 kopie resolveRedirectPath → 1 klasa RedirectPathResolver - ~170 linii zduplikowanego kodu wyeliminowane - Zero regresji (PHP lint clean) - Ponowna analiza duplikacji potwierdza eliminacje After completion, create `.paul/phases/68-code-deduplication-refactor/68-01-SUMMARY.md`