Files
shopPRO/.paul/phases/06-integrations-refactoring/06-01-PLAN.md
2026-03-12 13:36:06 +01:00

7.6 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous
phase plan type wave depends_on files_modified autonomous
06-integrations-refactoring 01 execute 1
autoload/Domain/Integrations/ApiloRepository.php
tests/Unit/Domain/Integrations/ApiloRepositoryTest.php
true
## Goal Wyekstrahować wszystkie metody Apilo z `IntegrationsRepository` do nowej klasy `ApiloRepository` — non-breaking (IntegrationsRepository pozostaje bez zmian do planu 06-02).

Purpose

IntegrationsRepository ma 875 linii z czego ~650 to logika Apilo (OAuth, keepalive, fetchList, produkty). Po ekstrakcji każda klasa będzie mieć jedną odpowiedzialność, zgodnie z zasadami projektu (jedna klasa = jedna odpowiedzialność, max ~50 linii na metodę).

Output

  • Nowy plik: autoload/Domain/Integrations/ApiloRepository.php (~650 linii)
  • Nowy plik testów: tests/Unit/Domain/Integrations/ApiloRepositoryTest.php
  • IntegrationsRepository bez zmian (backward compatible)
## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md

Source Files

@autoload/Domain/Integrations/IntegrationsRepository.php @tests/Unit/Domain/Integrations/IntegrationsRepositoryTest.php

<acceptance_criteria>

AC-1: ApiloRepository zawiera wszystkie metody Apilo

Given plik autoload/Domain/Integrations/ApiloRepository.php istnieje
When przeglądamy jego publiczne metody
Then klasa ma: apiloAuthorize, apiloGetAccessToken, apiloKeepalive,
     apiloIntegrationStatus, apiloFetchList, apiloFetchListResult,
     apiloProductSearch, apiloCreateProduct

AC-2: ApiloRepository ma własny dostęp do DB (DI przez konstruktor)

Given ApiloRepository(db: $mdb) jest tworzona
When wywoływana jest dowolna metoda apilo*
Then używa $db do zapytań bez zależności od IntegrationsRepository

AC-3: IntegrationsRepository nie zmieniona (backward compatible)

Given istniejące testy IntegrationsRepositoryTest przechodzą
When uruchamiane jest ./test.ps1
Then wszystkie 817+ testów green, brak nowych błędów

AC-4: Testy ApiloRepository pokrywają kluczowe metody

Given nowy plik ApiloRepositoryTest.php
When uruchamiane jest ./test.ps1
Then testy dla: apiloGetAccessToken, apiloKeepalive, apiloIntegrationStatus,
     apiloFetchListResult, apiloFetchList (invalid type), prywatnych helperów przechodzą

</acceptance_criteria>

Task 1: Utwórz ApiloRepository — ekstrakcja metod Apilo autoload/Domain/Integrations/ApiloRepository.php Utwórz nowy plik `autoload/Domain/Integrations/ApiloRepository.php`.
Namespace: `Domain\Integrations`

Klasa ma:
- `private $db;`
- `private const SETTINGS_TABLE = 'pp_shop_apilo_settings';`
- Konstruktor: `public function __construct($db)`

Przenieś (skopiuj) z IntegrationsRepository **bez modyfikacji logiki**:
- Metody publiczne: `apiloAuthorize`, `apiloGetAccessToken`, `apiloKeepalive`,
  `apiloIntegrationStatus`, `apiloFetchList`, `apiloFetchListResult`,
  `apiloProductSearch`, `apiloCreateProduct`
- Metody prywatne: `refreshApiloAccessToken`, `shouldRefreshAccessToken`,
  `isFutureDate`, `normalizeApiloMapList`, `isMapListShape`, `extractApiloErrorMessage`

Dostosowania niezbędne po przeniesieniu:
- Wszędzie gdzie metody apilo* wewnętrznie wołają `$this->getSettings('apilo')` —
  zamień na `$this->db->select(self::SETTINGS_TABLE, ['name', 'value'])` i mapuj
  na `[$row['name'] => $row['value']]` (ta sama logika co w IntegrationsRepository::getSettings)
- Wszędzie gdzie wołają `$this->saveSetting('apilo', ...)` — zamień na bezpośrednie
  `$this->db->update(self::SETTINGS_TABLE, ['value' => $value], ['name' => $name])`
  i `$this->db->insert(self::SETTINGS_TABLE, ['name' => $name, 'value' => $value])`
  z `count()` przed jak w saveSetting (dokładna kopia logiki)

Unikaj: dziedziczenia z IntegrationsRepository, jakichkolwiek zależności poza $db.
PHP < 8.0: brak match, named args, union types, str_contains.
php -l autoload/Domain/Integrations/ApiloRepository.php zwraca "No syntax errors" Klasa ma dokładnie 8 publicznych metod apilo* + 6 prywatnych helperów. AC-1 i AC-2 spełnione Task 2: Utwórz ApiloRepositoryTest tests/Unit/Domain/Integrations/ApiloRepositoryTest.php Utwórz `tests/Unit/Domain/Integrations/ApiloRepositoryTest.php`.
Namespace: `Tests\Unit\Domain\Integrations`
Klasa extends `PHPUnit\Framework\TestCase`

Przenieś (skopiuj) z IntegrationsRepositoryTest wszystkie testy dotyczące metod Apilo:
- `testApiloGetAccessTokenReturnsNullWithoutSettings`
- `testShouldRefreshAccessTokenReturnsFalseForFarFutureDate`
- `testShouldRefreshAccessTokenReturnsTrueForNearExpiryDate`
- `testApiloFetchListThrowsForInvalidType`
- `testApiloFetchListResultReturnsDetailedErrorWhenConfigMissing`
- `testApiloIntegrationStatusReturnsMissingConfigMessage`
- `testNormalizeApiloMapListRejectsErrorPayload`
- `testNormalizeApiloMapListAcceptsIdNameList`

Dostosuj w skopiowanych testach:
- Zmień `new IntegrationsRepository($this->mockDb)` → `new ApiloRepository($this->mockDb)`
- Use statement: `use Domain\Integrations\ApiloRepository;`
- setUp: `$this->repository = new ApiloRepository($this->mockDb);`

Uwaga: w testach mockujących `select` z `pp_shop_apilo_settings` — sprawdź czy
ApiloRepository używa dokładnie tej samej tabeli i struktury zapytania co IntegrationsRepository.
Jeśli zmieniło się wywołanie (np. bezpośrednie select zamiast przez getSettings),
dostosuj expect() w testach.

Nie usuwaj tych testów z IntegrationsRepositoryTest — zostają tam do planu 06-02.
./test.ps1 tests/Unit/Domain/Integrations/ApiloRepositoryTest.php — wszystkie testy green ./test.ps1 — pełna suite green (817+ testów, brak regresji) AC-3 i AC-4 spełnione

DO NOT CHANGE

  • autoload/Domain/Integrations/IntegrationsRepository.php — bez żadnych zmian w tym planie
  • tests/Unit/Domain/Integrations/IntegrationsRepositoryTest.php — tylko dodajemy, nie usuwamy
  • Żadne kontrolery, App.php, cron.php — migracja konsumentów to plan 06-02
  • Żadne zmiany logiki biznesowej — czysta ekstrakcja, zero refaktoringu logiki

SCOPE LIMITS

  • Ten plan tworzy tylko nową klasę + testy. Konsumenci nadal używają IntegrationsRepository.
  • Nie zmieniamy nazw metod, sygnatur, zachowania.
  • Nie optymalizujemy kodu Apilo podczas przenoszenia.
Before declaring plan complete: - [ ] php -l autoload/Domain/Integrations/ApiloRepository.php — no syntax errors - [ ] ApiloRepository ma 8 publicznych metod: apiloAuthorize, apiloGetAccessToken, apiloKeepalive, apiloIntegrationStatus, apiloFetchList, apiloFetchListResult, apiloProductSearch, apiloCreateProduct - [ ] ./test.ps1 tests/Unit/Domain/Integrations/ApiloRepositoryTest.php — all green - [ ] ./test.ps1 — full suite green, żadna regresja w IntegrationsRepositoryTest - [ ] IntegrationsRepository.php nie został zmodyfikowany

<success_criteria>

  • ApiloRepository.php istnieje z pełnym zestawem metod Apilo
  • ApiloRepositoryTest.php istnieje z testami dla kluczowych metod
  • Pełna suite testów green (817+ testów)
  • IntegrationsRepository niezmieniony (backward compatible) </success_criteria>
After completion, create `.paul/phases/06-integrations-refactoring/06-01-SUMMARY.md`