Files
orderPRO/.paul/phases/02-bug-fixes/02-04-PLAN.md
Jacek Pyziak 880ab5933f feat(02-bug-fixes): extract CronHandlerFactory, complete Phase 2
Phase 2 complete (4/4 plans):
- Plan 02-01: Fix dead ZPL page size condition in AllegroShipmentService
- Plan 02-02: Add time-based cursor to AllegroStatusSyncService
- Plan 02-03: Fix ShopproOrdersSyncService using wrong state repository
- Plan 02-04: Extract CronHandlerFactory as single cron composition point

Plan 02-04 specifics:
- New CronHandlerFactory builds complete cron object graph
- Application::maybeRunCronOnWeb() reduced from 80+ to ~20 lines
- bin/cron.php reduced from 123 to 26 lines
- Fixed 2 bugs: AllegroOAuthClient→AllegroTokenManager,
  AllegroOrderSyncStateRepository→ShopproOrderSyncStateRepository

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-13 00:43:04 +01:00

11 KiB
Raw Blame History

phase, plan, type, wave, depends_on, files_modified, autonomous
phase plan type wave depends_on files_modified autonomous
02-bug-fixes 04 execute 1
src/Modules/Cron/CronHandlerFactory.php
src/Core/Application.php
bin/cron.php
true
## Cel Wydzielić `CronHandlerFactory` — jedyne miejsce, które buduje graf obiektów dla crona. Zastąpić nią ręczną konstrukcję w `Application::maybeRunCronOnWeb()` oraz `bin/cron.php`.

Powód

Application.php (linie 274353) zawiera 80+ linii ręcznego new X($this->db) powielających okablowanie z bin/cron.php. Oba miejsca mogą się rozjechać — już teraz bin/cron.php przekazuje AllegroOAuthClient tam, gdzie powinien być AllegroTokenManager, oraz używa AllegroOrderSyncStateRepository zamiast ShopproOrderSyncStateRepository dla shopPRO.

Output

  • Nowy plik src/Modules/Cron/CronHandlerFactory.php
  • Application.php::maybeRunCronOnWeb() skrócona do ~10 linii
  • bin/cron.php skrócone do ~15 linii
  • Oba błędy w bin/cron.php naprawione przy okazji
## Kontekst projektu @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md

Pliki źródłowe

@src/Core/Application.php @bin/cron.php @routes/web.php

## Required Skills (from SPECIAL-FLOWS.md)
Skill Priority When to Invoke Loaded?
/code-review required Po implementacji, przed UNIFY
sonar-scanner required Po APPLY, przed UNIFY

BLOCKING: Required skills MUST be loaded before APPLY proceeds.

Skill Invocation Checklist

  • /code-review loaded
  • sonar-scanner run po zakończeniu implementacji

<acceptance_criteria>

AC-1: Jeden punkt definicji handlerow crona

Given codebase z trzema miejscami budującymi graf obiektów crona
When plik CronHandlerFactory.php istnieje
Then Application.php i bin/cron.php nie zawierają już new AllegroIntegrationRepository / new ShopproIntegrationsRepository / new AllegroOrderImportService w kontekście crona — wszystkie obiekty buduje fabryka

AC-2: Web cron działa identycznie jak przed zmianą

Given ustawienie cron_run_on_web = true w bazie
When użytkownik odwiedza dowolną stronę aplikacji
Then maybeRunCronOnWeb() uruchamia CronRunner z tymi samymi handlerami co wcześniej — brak regresji funkcjonalnej

AC-3: bin/cron.php używa poprawnych zależności

Given bin/cron.php przed zmianą używał AllegroOAuthClient zamiast AllegroTokenManager (arg #2 AllegroOrderImportService i AllegroOrdersSyncService) oraz AllegroOrderSyncStateRepository zamiast ShopproOrderSyncStateRepository dla ShopproOrdersSyncService
When bin/cron.php zostanie zaktualizowany do użycia CronHandlerFactory
Then oba błędy są naprawione — fabryka przekazuje AllegroTokenManager i ShopproOrderSyncStateRepository

</acceptance_criteria>

Task 1: Utwórz CronHandlerFactory src/Modules/Cron/CronHandlerFactory.php Utwórz klasę `App\Modules\Cron\CronHandlerFactory` w nowym pliku.
Konstruktor: `__construct(private readonly \PDO $db, private readonly string $integrationSecret)`.

Metoda publiczna: `build(CronRepository $cronRepository, \App\Core\Support\Logger $logger): CronRunner`.

Wewnątrz `build()` skonstruuj dokładnie te same obiekty co w `Application::maybeRunCronOnWeb()` (stan po naprawie z planu 02-03, czyli wersja z `Application.php` — NIE z `bin/cron.php`):

```
$integrationRepository = new AllegroIntegrationRepository($this->db, $this->integrationSecret)
$oauthClient = new AllegroOAuthClient()
$tokenManager = new AllegroTokenManager($integrationRepository, $oauthClient)
$apiClient = new AllegroApiClient()
$statusMappingRepository = new AllegroStatusMappingRepository($this->db)
$orderImportService = new AllegroOrderImportService(
    $integrationRepository, $tokenManager, $apiClient,
    new OrderImportRepository($this->db), $statusMappingRepository, new OrdersRepository($this->db)
)
$ordersSyncService = new AllegroOrdersSyncService(
    $integrationRepository, new AllegroOrderSyncStateRepository($this->db),
    $tokenManager, $apiClient, $orderImportService
)
$shopproIntegrationsRepo = new ShopproIntegrationsRepository($this->db, $this->integrationSecret)
$shopproSyncService = new ShopproOrdersSyncService(
    $shopproIntegrationsRepo, new ShopproOrderSyncStateRepository($this->db),
    new ShopproApiClient(), new OrderImportRepository($this->db),
    new ShopproStatusMappingRepository($this->db), new OrdersRepository($this->db)
)
$shopproStatusSyncService = new ShopproStatusSyncService($shopproIntegrationsRepo, $shopproSyncService)
$shopproPaymentSyncService = new ShopproPaymentStatusSyncService(
    $shopproIntegrationsRepo, new ShopproApiClient(), new OrdersRepository($this->db), $this->db
)
```

Zwróć `new CronRunner($cronRepository, $logger, [ handlers array ])` — lista handlerów identyczna jak w `Application.php` (allegro_token_refresh, allegro_orders_import, allegro_status_sync, shoppro_orders_import, shoppro_order_status_sync, shoppro_payment_status_sync).

Dodaj wszystkie potrzebne `use` na górze pliku. Klasa powinna być `final`.

UNIKAJ: przyjmowania całego `Application` lub tablicy konfiguracji jako parametru — tylko `$db` i `$integrationSecret` są potrzebne.
Plik istnieje: `src/Modules/Cron/CronHandlerFactory.php`. Składnia PHP poprawna: `php -l src/Modules/Cron/CronHandlerFactory.php` zwraca "No syntax errors detected". AC-1 częściowo — fabryka istnieje i buduje kompletny graf obiektów Task 2: Uproszczenie Application::maybeRunCronOnWeb() src/Core/Application.php W metodzie `maybeRunCronOnWeb()` zastąp blok `try { ... $runner = new CronRunner(...) ... }` wywołaniem fabryki:
```php
$factory = new CronHandlerFactory(
    $this->db,
    (string) $this->config('app.integrations.secret', '')
);
$runner = $factory->build($repository, $this->logger);
$runner->run($webLimit);
```

Zachowaj blok `finally { $this->releaseWebCronLock(); }`.

Dodaj `use App\Modules\Cron\CronHandlerFactory;` do importów na górze pliku.

Usuń z `Application.php` wszystkie `use` instrukcje które były potrzebne wyłącznie dla ręcznej konstrukcji grafu crona (AllegroIntegrationRepository, AllegroOAuthClient, AllegroTokenManager, AllegroApiClient, AllegroStatusMappingRepository, AllegroOrderImportService, AllegroOrdersSyncService, AllegroOrderSyncStateRepository, AllegroStatusSyncService, ShopproApiClient, ShopproIntegrationsRepository, ShopproOrdersSyncService, ShopproOrderSyncStateRepository, ShopproPaymentStatusSyncService, ShopproStatusSyncService, ShopproStatusMappingRepository, OrderImportRepository, OrdersRepository) — TYLKO jeśli nie są używane nigdzie indziej w Application.php.

UNIKAJ usuwania `use` dla CronRunner, CronRepository, AllegroOrdersImportHandler i innych klas Cron, bo mogą być używane.
SPRAWDŹ przed usunięciem każdego `use` czy nie pojawia się w innych metodach lub właściwościach klasy.
`php -l src/Core/Application.php` — brak błędów składni. Metoda `maybeRunCronOnWeb()` liczy ≤25 linii (było 80+). Grep na "new AllegroIntegrationRepository" w Application.php — brak wystąpień w metodzie maybeRunCronOnWeb. AC-1 spełnione — Application.php nie buduje już własnego grafu crona; AC-2 spełnione — ta sama fabryka, te same handlery Task 3: Uproszczenie bin/cron.php z naprawą błędów bin/cron.php Zastąp całą sekcję od `$cronRepository = new CronRepository(...)` do `$runner = new CronRunner(...)` wywołaniem fabryki:
```php
$cronRepository = new CronRepository($app->db());
$factory = new CronHandlerFactory(
    $app->db(),
    (string) $app->config('app.integrations.secret', '')
);
$runner = $factory->build($cronRepository, $app->logger());
```

Zachowaj blok `$result = $runner->run($limit)` i `fwrite(...)`.

Zachowaj blok parsowania `--limit` z `$argv`.

Usuń wszystkie `use` instrukcje które nie są już potrzebne — zastąp je jednym `use App\Modules\Cron\CronHandlerFactory;` (obok `use App\Core\Application;` i `use App\Modules\Cron\CronRepository;`).

To NAPRAWIA dwa istniejące błędy w bin/cron.php:
- AllegroOAuthClient zamiast AllegroTokenManager w AllegroOrderImportService i AllegroOrdersSyncService
- AllegroOrderSyncStateRepository zamiast ShopproOrderSyncStateRepository dla ShopproOrdersSyncService
`php -l bin/cron.php` — brak błędów składni. bin/cron.php liczy ≤25 linii łącznie (było 123). Grep "AllegroOAuthClient" w bin/cron.php — brak (usunięto nieprawidłowe użycie). Grep "AllegroOrderSyncStateRepository" w bin/cron.php — brak (usunięto nieprawidłowe użycie). AC-3 spełnione — bin/cron.php używa poprawnych zależności przez fabrykę

DO NOT CHANGE

  • Logika wewnątrz handlerów (AllegroOrdersImportHandler, AllegroStatusSyncHandler, itp.)
  • Klasa CronRunner — interfejs publiczny pozostaje niezmieniony
  • Metody Application poza maybeRunCronOnWeb() i blokiem use
  • routes/web.php — nie dotykamy, nie buduje handlerow crona
  • Migracje i schemat bazy danych

SCOPE LIMITS

  • Nie wprowadzamy DI container — to osobny temat (CONCERNS.md [MEDIUM] No DI Container)
  • Nie naprawiamy innych bugów z CONCERNS.md w tym planie
  • Nie przenosimy crona do routes/web.php — fabryka jest prostszym i bardziej przenośnym rozwiązaniem
  • Nie zmieniamy publicznego API CronHandlerFactory po jego stworzeniu bez potrzeby
Przed deklaracją planu jako zakończonego: - [ ] `php -l src/Modules/Cron/CronHandlerFactory.php` — No syntax errors - [ ] `php -l src/Core/Application.php` — No syntax errors - [ ] `php -l bin/cron.php` — No syntax errors - [ ] Grep "new AllegroIntegrationRepository" w Application.php — 0 wyników w maybeRunCronOnWeb - [ ] Grep "new ShopproIntegrationsRepository" w Application.php — 0 wyników w maybeRunCronOnWeb - [ ] Grep "AllegroOrderSyncStateRepository" w bin/cron.php — 0 wyników - [ ] Grep "AllegroOAuthClient" w bin/cron.php — 0 wyników - [ ] Wszystkie kryteria akceptacji AC-1, AC-2, AC-3 spełnione

<success_criteria>

  • CronHandlerFactory istnieje i buduje kompletny, poprawny graf obiektów crona
  • Application::maybeRunCronOnWeb() liczy ≤25 linii (skrócone z 80+)
  • bin/cron.php liczy ≤25 linii (skrócone ze 123)
  • Dwa błędy w bin/cron.php naprawione (AllegroOAuthClient → AllegroTokenManager, AllegroOrderSyncStateRepository → ShopproOrderSyncStateRepository)
  • Brak błędów składni PHP we wszystkich zmienionych plikach
  • Brak duplikacji okablowania crona między Application.php a bin/cron.php </success_criteria>
Po zakończeniu utwórz `.paul/phases/02-bug-fixes/02-04-SUMMARY.md`