--- phase: 05-domain-seoadditional-cron-releases plan: 01 type: execute wave: 1 depends_on: [] files_modified: - autoload/Domain/SeoAdditional/SeoAdditionalRepository.php - autoload/Domain/Cron/CronRepository.php - autoload/Domain/Releases/ReleasesRepository.php - autoload/Domain/Releases/UpdateRepository.php - autoload/admin/factory/class.SeoAdditional.php - autoload/class.Cron.php - autoload/admin/factory/class.Releases.php - autoload/admin/factory/class.Update.php autonomous: true delegation: auto --- ## Goal Utworzyć Domain repositories dla SeoAdditional, Cron i Releases/Update, oraz zaktualizować legacy klasy do wzorca wrapper delegation. ## Purpose Kompletuje Domain layer (wszystkie 13 repozytoriów). Po tej fazie cała logika biznesowa domenowa jest w namespace Domain\ — gotowe pod Admin\ controllers (Fazy 6-13). ## Output - autoload/Domain/SeoAdditional/SeoAdditionalRepository.php - autoload/Domain/Cron/CronRepository.php - autoload/Domain/Releases/ReleasesRepository.php - autoload/Domain/Releases/UpdateRepository.php - Wrappery w 4 legacy klasach (SeoAdditional, Cron, Releases, Update) ## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md ## Prior Work @.paul/phases/04-domain-authors-newsletter/04-01-SUMMARY.md ## Source Files @autoload/admin/factory/class.SeoAdditional.php @autoload/class.Cron.php @autoload/admin/factory/class.Releases.php @autoload/admin/factory/class.Update.php @autoload/Domain/Authors/AuthorsRepository.php @autoload/admin/factory/class.Authors.php ## AC-1: SeoAdditional Repository ```gherkin Given klasa admin\factory\SeoAdditional używa global $mdb bezpośrednio When migrujemy logikę do Domain\SeoAdditional\SeoAdditionalRepository Then repo przyjmuje $db w konstruktorze, nie używa globals And factory wrapper deleguje do nowego repo (new repo per call) And wszystkie 3 metody: elementDelete, elementSave, elementDetails ``` ## AC-2: Cron Repository ```gherkin Given legacy class Cron (bez namespace) w autoload/class.Cron.php używa global $mdb When migrujemy logikę do Domain\Cron\CronRepository Then repo przyjmuje $db w konstruktorze And legacy class Cron deleguje do Domain\Cron\CronRepository (new repo per call z global $mdb) And wszystkie metody zachowane: automaticUpdateSites, getSiteMainLinks, getSiteOtherLinks + metody prywatne helper ``` ## AC-3: Releases Repository ```gherkin Given klasa admin\factory\Releases używa global $mdb bezpośrednio When migrujemy logikę do Domain\Releases\ReleasesRepository Then repo przyjmuje $db w konstruktorze And factory wrapper deleguje do nowego repo And wszystkie metody zachowane: getVersions, promote, demote, discoverVersions, getLicenses, getLicense, saveLicense, deleteLicense, toggleBeta ``` ## AC-4: Update Repository ```gherkin Given klasa admin\factory\Update używa global $mdb i $settings bezpośrednio When migrujemy logikę do Domain\Releases\UpdateRepository Then repo przyjmuje $db i $settings w konstruktorze And factory wrapper deleguje do nowego repo (przekazując globals przez konstruktor) And metoda update() zachowana w pełni ``` Task 1: SeoAdditional — Domain repo + wrapper autoload/Domain/SeoAdditional/SeoAdditionalRepository.php, autoload/admin/factory/class.SeoAdditional.php Utwórz autoload/Domain/SeoAdditional/SeoAdditionalRepository.php: - namespace Domain\SeoAdditional; - konstruktor: __construct($db) — przechowuje $db jako private property - Metody (camelCase, z logiki class.SeoAdditional.php): * elementDelete($elementId) — delete z pp_seo_additional * elementSave($id, $url, $status, $title, $keywords, $description, $text) — insert lub update + \S::delete_cache() * elementDetails($elementId) — get z pp_seo_additional - PHP < 8.0: bez typed params, bez named args, bez match Zaktualizuj autoload/admin/factory/class.SeoAdditional.php: - Zastąp każdą metodę wrapperem delegującym: new \Domain\SeoAdditional\SeoAdditionalRepository($mdb)->metoda() - Pattern z class.Authors.php: global $mdb; $repo = new \Domain\...\Repository($mdb); return $repo->method(...) - Zachowaj dokładnie te same sygnatury metod (snake_case w factory, camelCase w repo) Grep: Domain\SeoAdditional istnieje w autoload/Domain/SeoAdditional/SeoAdditionalRepository.php Grep: new \Domain\SeoAdditional\SeoAdditionalRepository istnieje w class.SeoAdditional.php Brak global $mdb bezpośrednio w repo (tylko w factory wrapper) AC-1 satisfied: SeoAdditional repo + wrapper delegation Task 2: Cron — Domain repo + wrapper autoload/Domain/Cron/CronRepository.php, autoload/class.Cron.php Utwórz autoload/Domain/Cron/CronRepository.php: - namespace Domain\Cron; - konstruktor: __construct($db) - Przenieś CAŁĄ logikę z class.Cron.php do repo jako metody camelCase: * automaticUpdateSites() — odpowiednik automatic_update_sites() * getSiteMainLinks() — odpowiednik get_site_main_links() * getSiteOtherLinks() — odpowiednik get_site_other_links() * Wszystkie metody prywatne helper (getSiteMetaTitle, getSiteMetaKeywords, itd.) — przenieś jako private methods - PHP < 8.0: bez typed params - $mdb zastąp przez $this->db we wszystkich zapytaniach Zaktualizuj autoload/class.Cron.php: - Zachowaj oryginalny namespace (brak namespace — klasa globalna Cron) - Zastąp każdą public static metodę wrapperem: global $mdb; $repo = new \Domain\Cron\CronRepository($mdb); return $repo->camelCaseMethod(); - Usuń ciała helper methods (prywatne) — logika jest teraz w repo Grep: Domain\Cron istnieje w autoload/Domain/Cron/CronRepository.php Grep: new \Domain\Cron\CronRepository istnieje w autoload/class.Cron.php Brak bezpośrednich zapytań $mdb-> w class.Cron.php (tylko delegacja) AC-2 satisfied: Cron repo + wrapper delegation Task 3: Releases + Update — Domain repos + wrappers autoload/Domain/Releases/ReleasesRepository.php, autoload/Domain/Releases/UpdateRepository.php, autoload/admin/factory/class.Releases.php, autoload/admin/factory/class.Update.php Utwórz autoload/Domain/Releases/ReleasesRepository.php: - namespace Domain\Releases; - konstruktor: __construct($db) - Przenieś logikę z class.Releases.php: getVersions, promote, demote, discoverVersions, getLicenses, getLicense, saveLicense, deleteLicense, toggleBeta - Prywatna metoda zipDir() jako private helper - PHP < 8.0: bez ": array", bez ": void", bez ": int", bez ": string" type hints (PHP < 8.0, ale PHP 7.x obsługuje return types — ZACHOWAJ return type hints jeśli były w oryginale, bo PHP 7+ je obsługuje) - Uwaga: PHP < 8.0 znaczy brak PHP8 features. PHP 7.x return types działają. Sprawdź oryginał — miał ": array", ": void", ": int", ": string" — zachowaj je. Utwórz autoload/Domain/Releases/UpdateRepository.php: - namespace Domain\Releases; - konstruktor: __construct($db, $settings) — settings potrzebne do update_key i wersji - Przenieś logikę z class.Update.php: metoda update() - Zastąp global $mdb → $this->db, global $settings → $this->settings - Wywołania \S::* zachowaj (klasa S jest dostępna globalnie) Zaktualizuj autoload/admin/factory/class.Releases.php: - Zastąp każdą metodę wrapperem: global $mdb; $repo = new \Domain\Releases\ReleasesRepository($mdb); return $repo->method(...) - Zachowaj dokładnie te same sygnatury Zaktualizuj autoload/admin/factory/class.Update.php: - Zastąp metodę update() wrapperem: global $mdb, $settings; $repo = new \Domain\Releases\UpdateRepository($mdb, $settings); return $repo->update(); Grep: Domain\Releases istnieje w obu nowych plikach repo Grep: new \Domain\Releases\ReleasesRepository istnieje w class.Releases.php Grep: new \Domain\Releases\UpdateRepository istnieje w class.Update.php Brak bezpośrednich zapytań $mdb-> w factory wrapperach AC-3 i AC-4 satisfied: Releases + Update repos + wrapper delegation ## DO NOT CHANGE - autoload/autoloader.php (PSR-4 mapowanie już obejmuje Domain\) - autoload/Domain/Authors/, autoload/Domain/Newsletter/ (ukończone w Phase 4) - autoload/Domain/Scontainers/, autoload/Domain/Banners/ (ukończone w Phase 3) - Żadne inne pliki poza listą files_modified - cron.php entry point — nie modyfikuj (klasa Cron nadal globalna) ## SCOPE LIMITS - Tylko Domain repositories i factory wrappers — bez Admin\ controllers - Bez zmian w tabelach bazy danych ani SQL schema - Bez refaktoryzacji metod — 1:1 przeniesienie logiki Przed deklaracją ukończenia: - [ ] Grep: autoload/Domain/SeoAdditional/SeoAdditionalRepository.php istnieje - [ ] Grep: autoload/Domain/Cron/CronRepository.php istnieje - [ ] Grep: autoload/Domain/Releases/ReleasesRepository.php istnieje - [ ] Grep: autoload/Domain/Releases/UpdateRepository.php istnieje - [ ] Grep: class.SeoAdditional.php zawiera "new \Domain\SeoAdditional" - [ ] Grep: class.Cron.php zawiera "new \Domain\Cron" - [ ] Grep: class.Releases.php zawiera "new \Domain\Releases" - [ ] Grep: class.Update.php zawiera "new \Domain\Releases" - [ ] Brak syntax errors (php -l na każdym nowym pliku) - 4 nowe Domain repository pliki utworzone - 4 legacy klasy zaktualizowane do wrapper delegation - Zero zmian w logice biznesowej (1:1 migracja) - PHP < 8.0 kompatybilność zachowana - Brak globals w repozytoriach Po ukończeniu utwórz: .paul/phases/05-domain-seoadditional-cron-releases/05-01-SUMMARY.md