From 21efe28464889b8bda8096e88ca1232dbd1a0b95 Mon Sep 17 00:00:00 2001 From: Jacek Pyziak Date: Thu, 19 Feb 2026 19:30:38 +0100 Subject: [PATCH] =?UTF-8?q?ver.=200.295:=20Admin=20order=20product=20editi?= =?UTF-8?q?ng=20=E2=80=94=20add/remove/modify=20products,=20AJAX=20search,?= =?UTF-8?q?=20stock=20adjustment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Order product CRUD in admin panel (add, delete, edit quantity/prices) - AJAX product search endpoint for order edit form - Automatic stock adjustment when editing order products - Transport cost recalculation based on free delivery threshold - Fix: promo price = 0 when equal to base price (no real promotion) - Clean up stale temp/ build artifacts Co-Authored-By: Claude Opus 4.6 --- .phpunit.result.cache | 2 +- CLAUDE.md | 2 +- .../shop-order/order-edit-custom-script.php | 206 +++ admin/templates/shop-order/order-edit.php | 91 +- autoload/Domain/Order/OrderAdminService.php | 223 ++- autoload/Domain/Order/OrderRepository.php | 94 +- autoload/admin/App.php | 9 +- .../admin/Controllers/ShopOrderController.php | 49 +- docs/CHANGELOG.md | 17 + docs/TESTING.md | 4 +- docs/UPDATE_INSTRUCTIONS.md | 10 +- temp/build_294.sh | 70 - temp/update_build/delete_files_0.273.txt | 9 - temp/update_build/delete_files_0.274.txt | 1 - temp/update_build/delete_files_0.275.txt | 3 - .../tmp_0.275/admin/ajax/shop-category.php | 15 - .../tmp_0.275/admin/ajax/shop.php | 60 - .../categories-list-custom-script.php | 153 -- .../shop-category/categories-list.php | 61 - .../category-browse-custom-script.php | 106 -- .../shop-category/category-browse-list.php | 59 - .../category-edit-custom-script.php | 53 - .../templates/shop-category/category-edit.php | 209 --- .../category-products-custom-script.php | 62 - .../shop-category/category-products.php | 37 - .../shop-category/subcategories-list.php | 36 - .../shop-category/subcategory-browse-list.php | 25 - .../templates/shop-product/mass-edit.php | 114 -- .../templates/shop-product/product-edit.php | 1348 -------------- .../shop-product/subcategories-list.php | 24 - .../admin/templates/site/main-layout.php | 273 --- .../Controllers/ShopCategoryController.php | 163 -- .../Controllers/ShopProductController.php | 73 - .../tmp_0.275/autoload/admin/class.Site.php | 493 ----- .../admin/controls/class.ShopProduct.php | 373 ---- .../admin/factory/class.ShopProduct.php | 1578 ----------------- temp/update_build/tmp_0.275/docs/CHANGELOG.md | 458 ----- .../tmp_0.275/docs/DATABASE_STRUCTURE.md | 630 ------- .../tmp_0.275/docs/PROJECT_STRUCTURE.md | 338 ---- .../tmp_0.275/docs/REFACTORING_PLAN.md | 297 ---- temp/update_build/tmp_0.275/docs/TESTING.md | 456 ----- .../tmp_0.275/libraries/grid/config.php | 48 - .../ShopCategoryControllerTest.php | 80 - temp/update_build/update_0.273.zip | Bin 45279 -> 0 bytes temp/update_build/update_0.274.zip | Bin 32069 -> 0 bytes temp/update_build/update_0.275.zip | Bin 77819 -> 0 bytes .../banners/banners-list-custom-script.php | 100 -- .../admin/templates/banners/banners-list.php | 5 - .../templates/filemanager/filemanager.php | 4 - .../products-list-custom-script.php | 100 -- .../product-archive/products-list.php | 5 - .../Domain/Product/ProductRepository.php | 247 --- .../admin/Controllers/BannerController.php | 337 ---- .../Controllers/FilemanagerController.php | 46 - .../Controllers/ProductArchiveController.php | 165 -- .../autoload/admin/class.Site.php | 356 ---- .../admin/controls/class.ShopProduct.php | 414 ----- temp/update_build/ver_0.290.zip | Bin 36607 -> 0 bytes temp/update_build/ver_0.290_files.txt | 5 - temp/update_build/ver_0.291.zip | Bin 9105 -> 0 bytes temp/update_build/ver_0.291_files.txt | 2 - temp/update_build/ver_0.292.zip | Bin 80982 -> 0 bytes temp/update_build/ver_0.292_files.txt | 9 - temp/update_build/ver_0.293.zip | Bin 10732 -> 0 bytes temp/update_build/ver_0.293_files.txt | 2 - temp/ver_0.294.zip | Bin 154376 -> 0 bytes temp/ver_0.294_files.txt | 12 - .../Domain/Order/OrderAdminServiceTest.php | 230 +++ .../Unit/Domain/Order/OrderRepositoryTest.php | 132 ++ .../Controllers/ShopOrderControllerTest.php | 6 +- updates/0.20/ver_0.295.zip | Bin 0 -> 25124 bytes updates/changelog.php | 6 + updates/versions.php | 2 +- 73 files changed, 1037 insertions(+), 9560 deletions(-) delete mode 100644 temp/build_294.sh delete mode 100644 temp/update_build/delete_files_0.273.txt delete mode 100644 temp/update_build/delete_files_0.274.txt delete mode 100644 temp/update_build/delete_files_0.275.txt delete mode 100644 temp/update_build/tmp_0.275/admin/ajax/shop-category.php delete mode 100644 temp/update_build/tmp_0.275/admin/ajax/shop.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-category/categories-list-custom-script.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-category/categories-list.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-category/category-browse-custom-script.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-category/category-browse-list.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-category/category-edit-custom-script.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-category/category-edit.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-category/category-products-custom-script.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-category/category-products.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-category/subcategories-list.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-category/subcategory-browse-list.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-product/mass-edit.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-product/product-edit.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/shop-product/subcategories-list.php delete mode 100644 temp/update_build/tmp_0.275/admin/templates/site/main-layout.php delete mode 100644 temp/update_build/tmp_0.275/autoload/admin/Controllers/ShopCategoryController.php delete mode 100644 temp/update_build/tmp_0.275/autoload/admin/Controllers/ShopProductController.php delete mode 100644 temp/update_build/tmp_0.275/autoload/admin/class.Site.php delete mode 100644 temp/update_build/tmp_0.275/autoload/admin/controls/class.ShopProduct.php delete mode 100644 temp/update_build/tmp_0.275/autoload/admin/factory/class.ShopProduct.php delete mode 100644 temp/update_build/tmp_0.275/docs/CHANGELOG.md delete mode 100644 temp/update_build/tmp_0.275/docs/DATABASE_STRUCTURE.md delete mode 100644 temp/update_build/tmp_0.275/docs/PROJECT_STRUCTURE.md delete mode 100644 temp/update_build/tmp_0.275/docs/REFACTORING_PLAN.md delete mode 100644 temp/update_build/tmp_0.275/docs/TESTING.md delete mode 100644 temp/update_build/tmp_0.275/libraries/grid/config.php delete mode 100644 temp/update_build/tmp_0.275/tests/Unit/admin/Controllers/ShopCategoryControllerTest.php delete mode 100644 temp/update_build/update_0.273.zip delete mode 100644 temp/update_build/update_0.274.zip delete mode 100644 temp/update_build/update_0.275.zip delete mode 100644 temp/update_build/ver_0.200_20260211_000158/admin/templates/banners/banners-list-custom-script.php delete mode 100644 temp/update_build/ver_0.200_20260211_000158/admin/templates/banners/banners-list.php delete mode 100644 temp/update_build/ver_0.200_20260211_000158/admin/templates/filemanager/filemanager.php delete mode 100644 temp/update_build/ver_0.200_20260211_000158/admin/templates/product-archive/products-list-custom-script.php delete mode 100644 temp/update_build/ver_0.200_20260211_000158/admin/templates/product-archive/products-list.php delete mode 100644 temp/update_build/ver_0.200_20260211_000158/autoload/Domain/Product/ProductRepository.php delete mode 100644 temp/update_build/ver_0.200_20260211_000158/autoload/admin/Controllers/BannerController.php delete mode 100644 temp/update_build/ver_0.200_20260211_000158/autoload/admin/Controllers/FilemanagerController.php delete mode 100644 temp/update_build/ver_0.200_20260211_000158/autoload/admin/Controllers/ProductArchiveController.php delete mode 100644 temp/update_build/ver_0.200_20260211_000158/autoload/admin/class.Site.php delete mode 100644 temp/update_build/ver_0.200_20260211_000158/autoload/admin/controls/class.ShopProduct.php delete mode 100644 temp/update_build/ver_0.290.zip delete mode 100644 temp/update_build/ver_0.290_files.txt delete mode 100644 temp/update_build/ver_0.291.zip delete mode 100644 temp/update_build/ver_0.291_files.txt delete mode 100644 temp/update_build/ver_0.292.zip delete mode 100644 temp/update_build/ver_0.292_files.txt delete mode 100644 temp/update_build/ver_0.293.zip delete mode 100644 temp/update_build/ver_0.293_files.txt delete mode 100644 temp/ver_0.294.zip delete mode 100644 temp/ver_0.294_files.txt create mode 100644 tests/Unit/Domain/Order/OrderAdminServiceTest.php create mode 100644 updates/0.20/ver_0.295.zip diff --git a/.phpunit.result.cache b/.phpunit.result.cache index c367db5..78b8078 100644 --- a/.phpunit.result.cache +++ b/.phpunit.result.cache @@ -1 +1 @@ -{"version":1,"defects":{"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveCreatesNewArticle":3,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveUpdatesExistingArticle":3,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsInsertsForNewArticle":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsUpsertsForExistingArticle":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSavePagesForNewArticle":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveDeletesMarkedImagesOnUpdate":4,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFrontScontainerDetailsReturnsContainerWithLanguage":3,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorAcceptsRepository":4,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testHasMainActionMethods":4,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorRequiresCouponRepository":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendReturnsArticleWithRelations":3,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendCopyFromFallback":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testTopArticlesOrderByViews":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testNewsListArticlesOrderByDateDesc":4},"times":{"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetQuantityReturnsCorrectValue":0.005,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetQuantityReturnsNullWhenProductNotFound":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindReturnsProductData":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateQuantitySuccess":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsRegularPrice":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsPromoPrice":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsRegularWhenPromoIsHigher":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetNameReturnsProductName":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetNameReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetQuantityReturnsInteger":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUnarchiveUpdatesProductAndChildren":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testArchiveUpdatesProductAndChildren":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUnarchiveReturnsBool":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testArchiveReturnsBool":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testConstructorAcceptsRepository":0.004,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testHasListMethod":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testHasUnarchiveMethod":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testListMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testUnarchiveMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testConstructorRequiresProductRepository":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testFindReturnsBannerWithTranslations":0.001,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testDeleteReturnsTrue":0.001,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testSaveInsertsNewBanner":0,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheWithRedis":0.001,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheRedisUnavailable":0,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheWithoutRedis":0,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheReturnStructure":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testCanBeInstantiated":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testHasSaveSettingsMethod":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testHasGetSettingsMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasClearCacheMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasClearCacheAjaxMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasViewMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testIsNotAbstract":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testCanCreateController":0.004,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasListMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testListMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasEditMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testEditMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testConstructorAcceptsRepository":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testConstructorRequiresArticleRepository":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testFindReturnsArticleWithRelations":0.004,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testFindReturnsNullWhenArticleDoesNotExist":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeleteNonassignedFilesDeletesDbRows":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeleteNonassignedImagesDeletesDbRows":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveCreatesNewArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveReturnsZeroWhenInsertFails":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveUpdatesExistingArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsInsertsForNewArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsUpsertsForExistingArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSavePagesForNewArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveDeletesMarkedImagesOnUpdate":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArchiveSetsStatusToMinusOne":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArchiveReturnsFalseWhenUpdateFails":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveGalleryOrderUpdatesImageOrder":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveGalleryOrderSkipsEmptyValues":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasBrowseListMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasGalleryOrderSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testBrowseListMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testGalleryOrderSaveMethodReturnType":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testListForAdminUsesBoundParamsForTitleFilter":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testSaveWithLegacyFormat":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testSaveUpdatesExistingTranslationsByBannerAndLang":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testListForAdminIncludesThumbnailSrc":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testRestoreSetsStatusToZero":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeletePermanentlyRemovesArticleAndRelations":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testListArchivedForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testFindReturnsUnitWithTranslations":0.001,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testFindReturnsNullWhenUnitNotFound":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testSaveInsertsNewUnitAndTranslationsForStringLanguageId":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testDeleteRemovesUnitAndTranslations":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testGetUnitNameByIdReturnsTextFromDatabase":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testGetUnitNameByIdSupportsStringLanguageId":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testAllUnitsReturnsArrayIndexedById":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testLanguageDetailsReturnsArrayOrNull":0.001,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testLanguagesListReturnsArray":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testSaveLanguageRejectsInvalidLanguageId":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testSaveTranslationInsertsNewTranslationAndReturnsId":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDeleteTranslationReturnsBoolean":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testListForAdminReturnsItemsAndTotal":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageIdReturnsLanguageWithStartFlag":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageIdFallsBackToFirstLanguageOrPl":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testFindReturnsLayoutWithRelations":0.001,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testDeleteReturnsFalseWhenOnlyOneLayoutExists":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testFindReturnsDefaultLayoutWhenRecordDoesNotExist":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testSaveInsertsNewLayoutAndReturnsId":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testListAllReturnsArray":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testTemplateDetailsReturnsNullForInvalidId":0.002,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testTemplateDetailsReturnsArray":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testSaveSettingsUpdatesHeaderAndFooter":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testDeleteTemplateReturnsFalseForAdminTemplate":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testTemplateByNameReturnsText":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFindReturnsDefaultContainerForInvalidId":0.001,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFindReturnsContainerWithTranslations":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testDetailsForLanguageReturnsNullForInvalidData":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testFindReturnsUserWhenExists":0.001,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testCheckLoginReturnsErrorWhenLoginIsTaken":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testCheckLoginReturnsOkWhenAvailable":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForTooShortPasswordOnCreate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForMismatchedPasswordsOnCreate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveCreatesUserWithNormalizedSwitches":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveUpdatesExistingUserWithPassword":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveUpdatesExistingUserWithoutPassword":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForTooShortPasswordOnUpdate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForMismatchedPasswordsOnUpdate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDeleteReturnsTrue":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDeleteReturnsFalseOnFailure":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDetailsReturnsUserByLogin":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDetailsReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testLogonReturnsSuccessForValidCredentials":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testLogonReturnsZeroForNonexistentUser":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testLogonReturnsNegativeOneForBlockedUser":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsFalseForNonexistentUser":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsFalseAfterMaxAttempts":0.075,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsFalseForExpiredCode":0.076,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsTrueForValidCode":0.151,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSendTwofaCodeReturnsFalseWhen2FADisabled":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSendTwofaCodeReturnsFalseForInvalidEmail":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testUpdateByIdCallsDbUpdate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testListForAdminReturnsItemsAndTotal":0,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testConstructorRequiresArticleRepository":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasListMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasEditMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testConstructorRequiresDictionariesRepository":0,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testConstructorRequiresLanguagesRepository":0,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testConstructorRequiresLayoutsRepository":0,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testConstructorAcceptsDependencies":0.002,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testConstructorRequiresRepositoryAndRenderer":0,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testConstructorAcceptsDependencies":0.001,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testConstructorRequiresRepositoryAndLanguagesRepository":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasViewListMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasUserEditMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasUserSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasUserDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasTwofaMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasLoginFormMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testConstructorRequiresUserRepository":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testNormalizeUserReturnsDefaultsForNull":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testNormalizeUserCastsTypes":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testNormalizeUserHandlesPartialData":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveFilesOrderUpdatesFilesOrder":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveFilesOrderSkipsEmptyValues":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPagesSummaryForArticlesBuildsLabels":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testUpdateImageAltDelegatesToDatabase":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testMarkFileToDeleteDelegatesToDatabase":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindReturnsDefaultCouponForInvalidId":0.001,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindNormalizesCouponData":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testSaveInsertsCouponAndReturnsId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testSaveUpdatesCouponAndReturnsId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testDeleteReturnsTrueWhenDatabaseDeleteSucceeds":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testCategoriesTreeReturnsHierarchy":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetSettingsReturnsArray":0.002,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetSettingReturnsValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetSettingReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testSaveSettingUpdatesExistingValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testSaveSettingInsertsNewValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testInvalidProviderThrowsException":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testLinkProductUpdatesDatabase":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testUnlinkProductClearsFields":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetProductSkuReturnsValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetProductSkuReturnsNullForMissing":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloGetAccessTokenReturnsNullWithoutSettings":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloFetchListThrowsForInvalidType":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testAllPublicMethodsExist":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testSettingsTableMapping":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testShopproProviderWorks":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testMenusListReturnsArray":0.002,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testMenuDeleteReturnsFalseWhenMenuHasPages":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testGenerateSeoLinkAddsSuffixWhenBaseSlugExists":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testPageUrlPreviewBuildsLanguagePrefixedUrlForNonDefaultLanguage":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testFindReturnsDefaultPromotionForInvalidId":0.002,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testSaveInsertsPromotionAndReturnsId":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testDeleteReturnsTrueWhenDatabaseDeleteSucceeds":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testCategoriesTreeReturnsHierarchy":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasImageAltChangeMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasFileNameChangeMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasImageDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasFileDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testImageAltChangeMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testFileNameChangeMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testImageDeleteMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testFileDeleteMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testConstructorAcceptsDependencies":0.002,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testConstructorRequiresRepository":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllApiloSettingsMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllApiloDataFetchMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllApiloProductMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllShopproMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testApiloSettingsReturnsString":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testShopproSettingsReturnsString":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testVoidReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testDoesNotHaveSellasistMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testDoesNotHaveBaselinkerMethods":0,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testConstructorAcceptsRepositories":0.001,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testConstructorRequiresPagesLanguagesAndLayoutsRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testConstructorRequiresCouponRepository":0,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testConstructorRequiresPromotionRepository":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindReturnsNullForNegativeId":0.001,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindReturnsStatusWithIdZero":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindNormalizesNullApiloStatusId":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveUpdatesColorAndApiloStatusId":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveWithIdZeroWorks":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveWithEmptyApiloStatusIdSetsNull":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveRejectsNegativeId":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetApiloStatusIdReturnsValue":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetApiloStatusIdReturnsNullWhenNotSet":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetByIntegrationStatusIdForApilo":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetByIntegrationStatusIdReturnsNullForUnknownIntegration":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testAllStatusesReturnsOrderedList":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testConstructorRequiresShopStatusRepository":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testShouldRefreshAccessTokenReturnsFalseForFarFutureDate":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testShouldRefreshAccessTokenReturnsTrueForNearExpiryDate":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloFetchListResultReturnsDetailedErrorWhenConfigMissing":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloIntegrationStatusReturnsMissingConfigMessage":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testNormalizeApiloMapListRejectsErrorPayload":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testNormalizeApiloMapListAcceptsIdNameList":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindReturnsNullForInvalidId":0.001,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindNormalizesData":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSaveUpdatesRowAndReturnsId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSavePreservesNonNumericApiloPaymentTypeId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSaveReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testAllActiveReturnsNormalizedRows":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testAllForAdminReturnsRowsIncludingInactive":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindActiveByIdReturnsNullForNotFound":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindKeepsNonNumericApiloPaymentTypeId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testIsActiveNormalizesStatusValue":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testGetApiloPaymentTypeIdHandlesNullAndInt":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testGetApiloPaymentTypeIdReturnsStringForNonNumericValue":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testForTransportReturnsRows":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindReturnsNullForInvalidId":0.001,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindNormalizesDataAndIncludesPaymentMethods":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindHandlesNullMaxWpAndApiloId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveInsertReturnsNewId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveUpdateReturnsExistingId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveInsertReturnsNullOnFailure":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveResetsDefaultWhenSettingNew":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveSwitchValuesNormalization":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testListForAdminWhitelistsSortColumn":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testAllActiveReturnsNormalizedRows":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testGetApiloCarrierAccountIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testGetApiloCarrierAccountIdReturnsIntOrNull":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testGetTransportCostReturnsFloatOrNull":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testAllForAdminReturnsAllTransports":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testConstructorRequiresPaymentMethodRepository":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testConstructorAcceptsRepositories":0.002,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testConstructorRequiresBothRepositories":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFindAttributeReturnsDefaultAttributeForInvalidId":0.002,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testListForAdminWhitelistsSortDirectionAndPerPage":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testSaveValuesRemovesObsoleteRowsAndSetsDefault":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testSaveValuesDeletesTranslationWhenNameIsEmpty":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testGetAttributeValueByIdUsesDefaultLanguageWhenNotProvided":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSortTypesReturnsExpectedKeys":0.002,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDetailsReturnsDefaultForInvalidId":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDetailsLoadsTranslations":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveCategoriesOrderReturnsFalseForNonArray":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveCategoriesOrderUpdatesOrderAndParent":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveProductOrderReturnsFalseForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveProductOrderUpdatesCategoryProductOrder":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDeleteReturnsFalseWhenHasChildren":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDeleteReturnsTrueWhenDeleted":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryTitleReturnsEmptyWhenNotFound":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryTitleReturnsFirstAvailableTitle":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testListForAdminWhitelistsSortAndPagination":0.001,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testOrdersForClientReturnsEmptyOnMissingInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testOrdersForClientNormalizesRows":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testTotalsForClientReturnsZeroForMissingInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testTotalsForClientReturnsAggregatedValues":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testConstructorAcceptsDb":0.001,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testHasAllPublicMethods":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testSalesGridReturnsArray":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testLastOrdersReturnsArray":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testMostViewedProductsReturnsArray":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testBestSalesProductsReturnsArray":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageReturnsId":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageReturnsFallbackWhenEmpty":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testActiveLanguagesReturnsList":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testActiveLanguagesReturnsEmptyArrayWhenNone":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testTranslationsReturnsArray":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testTranslationsDefaultsToPl":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testTranslationsForDifferentLanguage":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testUnsubscribeReturnsFalseForInvalidHash":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testUnsubscribeDeletesSubscriber":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testConfirmSubscriptionReturnsFalseForInvalidHash":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testConfirmSubscriptionUpdatesStatus":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testGetHashByEmailReturnsHash":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testGetHashByEmailReturnsNullForMissing":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testRemoveByEmailDeletesSubscriber":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testRemoveByEmailReturnsFalseForMissing":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testSignupReturnsFalseForExistingEmail":0.001,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testConstructorAcceptsOptionalDependencies":0.002,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderStatusesReturnsMappedArray":0.001,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testNextAndPrevOrderIdReturnNullForInvalidInput":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testListForAdminReturnsItemsAndTotal":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindReturnsDefaultProducerForInvalidId":0.001,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindNormalizesProducerData":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testSaveInsertsNewProducer":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testSaveUpdatesExistingProducer":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testDeleteReturnsTrueOnSuccess":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testListForAdminWhitelistsSortAndPagination":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testAllProducersReturnsFormattedList":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testProducerProductsReturnsPaginatedResults":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testFindReturnsDefaultSetForInvalidId":0.001,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testFindNormalizesSetData":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testSaveInsertsNewSetAndSyncsProducts":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testSaveUpdatesExistingSet":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testListForAdminWhitelistsSortAndPagination":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testAllSetsReturnsFormattedList":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testAllProductsForMassEditReturnsMap":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testAllProductsForMassEditEmptyWhenNoProducts":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetProductsByCategoryReturnsList":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetProductsByCategoryReturnsEmptyArray":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testApplyDiscountPercentReturnsNullForInvalidProduct":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testApplyDiscountPercentReturnsCorrectPrices":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testApplyDiscountPercentZeroPercentNullsPromo":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testAllSettingsReturnsAssociativeArray":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testAllSettingsReturnsEmptyArrayWhenNoSettings":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testAllSettingsHandlesNullFromDb":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testGetSingleValueReturnsCorrectParam":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testGetSingleValueUsesParamNotHardcoded":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testGetSingleValueReturnsEmptyStringWhenNotFound":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testConstructorAcceptsDb":0.001,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testHasUpdateMethod":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testUpdateReturnsArray":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testHasRunPendingMigrationsMethod":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testRunPendingMigrationsWithNoResults":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testHasPrivateHelperMethods":0,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testConstructorAcceptsRepositories":0.001,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testHasMainViewMethod":0,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testMainViewReturnsString":0,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testConstructorRequiresRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testConstructorAcceptsRepositories":0.002,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testConstructorRequiresBothRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testValidateValuesRowsReturnsErrorsForMissingDefaultLanguageAndDefaultSelection":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testValidateValuesRowsReturnsEmptyArrayForValidRows":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testConstructorAcceptsDependencies":0.001,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testHasExpectedActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testViewActionsReturnString":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testMutationActionsReturnVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testConstructorRequiresCategoryAndLanguagesRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testConstructorRequiresClientRepository":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testConstructorAcceptsService":0.003,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testHasExpectedActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testViewActionsReturnString":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testMutationActionsReturnVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testConstructorRequiresOrderAdminService":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testConstructorAcceptsRepositories":0.002,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testConstructorRequiresBothRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testConstructorAcceptsRepositories":0.002,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasMassEditActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasViewListMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasEditAndSaveMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasOperationMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasCombinationMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasImageAndFileMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testMassEditReturnsString":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testMassEditSaveReturnsVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testGetProductsByCategoryReturnsVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testConstructorRequiresRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasFormBuildingHelpers":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testSaveMethodReturnsVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testConstructorRequiresProductSetRepository":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasMainViewMethod":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testMainViewReturnsString":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasUpdateMethod":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasUpdateAllMethod":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testConstructorRequiresRepository":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendReturnsArticleWithRelations":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendReturnsNullForMissing":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendCopyFromFallback":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticlesIdsReturnsSortedIds":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticlesIdsReturnsNullForEmpty":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPageArticlesCountReturnsInt":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPageArticlesCountReturnsZeroForEmpty":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPageArticlesPagination":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleNoindexReturnsBool":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleNoindexReturnsFalseForNonNoindex":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testNewsReturnsArticlesArray":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testTopArticlesOrderByViews":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testNewsListArticlesOrderByDateDesc":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testBannersReturnsActiveBannersWithFlatLanguages":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testBannersReturnsNullWhenNoBanners":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testMainBannerReturnsActiveBannerWithFlatLanguages":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testMainBannerReturnsNullWhenNoBanner":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testCategoryDefaultLayoutIdReturnsId":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testCategoryDefaultLayoutIdReturnsNullWhenNone":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetDefaultLayoutReturnsLayoutFromDb":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetDefaultLayoutReturnsNullWhenNoLayout":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetArticleLayoutReturnsLayoutFromDb":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetArticleLayoutReturnsNullWhenNoLayout":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetActiveLayoutFallsBackToDefault":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetActiveLayoutReturnsNullWhenNothingFound":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontPageDetailsReturnsPageWithLanguage":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontPageDetailsReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMainPageIdReturnsStartPage":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMainPageIdFallsBackToFirstActive":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontPageSortReturnsValue":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMenuDetailsReturnsMenuWithPages":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMenuDetailsReturnsNullForInvalidMenu":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMenuPagesReturnsEmptyForNoPages":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFrontScontainerDetailsReturnsContainerWithLanguage":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFrontScontainerDetailsReturnsFallbackForNotFound":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontAttributeDetailsReturnsAttributeWithLanguage":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontAttributeDetailsReturnsFallbackForNotFound":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontValueDetailsReturnsValueWithLanguage":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontValueDetailsReturnsFallbackForNotFound":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testSummaryWpCalculatesTotal":0.001,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testSummaryWpReturnsZeroForEmptyBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsSumsQuantities":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsReturnsZeroForEmptyBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextSingular":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextPlural2to4":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextPlural5Plus":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextCastsToInt":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testGetCategorySortReturnsZeroForInvalidId":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testGetCategorySortReturnsSortType":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryNameReturnsEmptyForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryNameReturnsTitle":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryNameReturnsEmptyWhenNotFound":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testFrontCategoryDetailsReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testFrontCategoryDetailsReturnsCategoryWithLanguage":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testFrontCategoryDetailsReturnsEmptyWhenCategoryNotFound":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoriesTreeReturnsEmptyWhenNoCategories":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryProductsCountReturnsZeroForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryProductsCountReturnsCount":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testProductsIdReturnsEmptyForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testProductsIdReturnsProductIds":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testBlogCategoryProductsReturnsEmptyForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testBlogCategoryProductsReturnsIds":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testPaginatedCategoryProductsReturnsEmptyWhenNoProducts":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testPaginatedCategoryProductsClampsPage":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientDetailsReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientDetailsReturnsRowOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientDetailsReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientEmailReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientEmailReturnsStringOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientEmailReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientAddressesReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientAddressesReturnsRows":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientAddressesHandlesFalseFromDb":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDetailsReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDetailsReturnsRow":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDeleteReturnsTrueOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressSaveReturnsFalseForInvalidClientId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressSaveInsertsNewAddress":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressSaveUpdatesExistingAddress":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testMarkAddressAsCurrentReturnsFalseForInvalidIds":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testMarkAddressAsCurrentResetsAndSets":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsErrorOnEmptyInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsErrorWhenClientNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsInactiveForUnconfirmedAccount":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsErrorOnWrongPassword":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsOkOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testCreateClientReturnsNullOnEmptyInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testCreateClientReturnsNullWhenEmailTaken":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testCreateClientReturnsIdAndHashOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testConfirmRegistrationReturnsNullOnEmptyHash":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testConfirmRegistrationReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testConfirmRegistrationActivatesAndReturnsEmail":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testGenerateNewPasswordReturnsNullOnEmptyHash":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testGenerateNewPasswordReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testGenerateNewPasswordReturnsEmailAndPassword":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testInitiatePasswordRecoveryReturnsNullOnEmptyEmail":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testInitiatePasswordRecoveryReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testInitiatePasswordRecoverySetsRecoveryFlagAndReturnsHash":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientOrdersReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindByNameReturnsObjectWhenFound":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindByNameReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindByNameReturnsNullForEmptyName":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsTrueForActiveCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsFalseForUsedCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsFalseForInactiveCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsFalseForNullCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableWorksWithArray":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testMarkAsUsedCallsUpdate":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testMarkAsUsedSkipsInvalidId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIncrementUsedCountCallsUpdate":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIncrementUsedCountSkipsInvalidId":0,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorAcceptsRepository":0,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorRequiresCouponRepository":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindIdByHashReturnsIdWhenFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindIdByHashReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindIdByHashReturnsNullForEmptyHash":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindHashByIdReturnsHashWhenFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindHashByIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderDetailsFrontendByIdReturnsArrayWithProducts":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderDetailsFrontendByHashReturnsArrayWithProducts":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderDetailsFrontendReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGenerateOrderNumberFormatsCorrectly":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGenerateOrderNumberStartsAt001":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testAllActiveProducersReturnsFullData":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testAllActiveProducersReturnsEmptyOnNull":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindForFrontendReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindForFrontendReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindForFrontendReturnsProducerWithLanguage":0,"Tests\\Unit\\front\\Controllers\\ShopOrderControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\front\\Controllers\\ShopOrderControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\front\\Controllers\\ShopOrderControllerTest::testConstructorRequiresOrderRepository":0,"Tests\\Unit\\front\\Controllers\\ShopProducerControllerTest::testConstructorAcceptsRepository":0,"Tests\\Unit\\front\\Controllers\\ShopProducerControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\front\\Controllers\\ShopProducerControllerTest::testConstructorRequiresProducerRepository":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testIsActiveReturnsOneForActivePayment":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testIsActiveReturnsZeroForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindActiveByIdReturnsNormalizedData":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindActiveByIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testAllActiveReturnsEmptyOnNull":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testGetApiloPaymentTypeIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testForTransportReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetSkuWithFallbackReturnsSku":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetSkuWithFallbackFromParent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetSkuWithFallbackReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetEanWithFallbackReturnsEan":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetEanWithFallbackFromParent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testIsProductActiveCachedReturnsOneForActive":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testIsProductActiveCachedReturnsZeroForInactive":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testIsProductActiveCachedReturnsZeroForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testProductCategoriesFrontReturnsCategories":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testProductCategoriesFrontUsesParentId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testProductCategoriesFrontReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageZeroReturnsMessage":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageZeroReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageNonzeroReturnsMessage":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageNonzeroReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testTopProductIdsReturnsActiveProducts":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testNewProductIdsReturnsProductIds":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testNewProductIdsReturnsEmptyWhenNoProducts":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testPromotedProductIdsCachedReturnsIds":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testPromotedProductIdsCachedReturnsEmptyWhenNone":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeWholeBasketAppliesDiscountToAll":0.001,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoriesOrAppliesDiscountToMatchingCategories":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoryConditionAppliesWhenConditionMet":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoryConditionNoDiscountWhenConditionNotMet":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoriesAndAppliesWhenBothConditionsMet":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportCostCachedReturnsCost":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindActiveByIdCachedReturnsTransport":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindActiveByIdCachedReturnsNullForInvalid":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testForPaymentMethodReturnsTransports":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testForPaymentMethodReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCheckProductQuantityInStockReturnsFalseOnNullBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCheckProductQuantityInStockReturnsFalseOnEmptyBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testValidateBasketReturnsEmptyArrayOnNull":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testValidateBasketReturnsBasketArrayAsIs":0}} \ No newline at end of file +{"version":1,"defects":{"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveCreatesNewArticle":3,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveUpdatesExistingArticle":3,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsInsertsForNewArticle":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsUpsertsForExistingArticle":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSavePagesForNewArticle":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveDeletesMarkedImagesOnUpdate":4,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFrontScontainerDetailsReturnsContainerWithLanguage":3,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorAcceptsRepository":4,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testHasMainActionMethods":4,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorRequiresCouponRepository":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendReturnsArticleWithRelations":3,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendCopyFromFallback":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testTopArticlesOrderByViews":4,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testNewsListArticlesOrderByDateDesc":4},"times":{"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetQuantityReturnsCorrectValue":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetQuantityReturnsNullWhenProductNotFound":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testFindReturnsProductData":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUpdateQuantitySuccess":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsRegularPrice":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsPromoPrice":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsRegularWhenPromoIsHigher":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetPriceReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetNameReturnsProductName":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetNameReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetQuantityReturnsInteger":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUnarchiveUpdatesProductAndChildren":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testArchiveUpdatesProductAndChildren":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testUnarchiveReturnsBool":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testArchiveReturnsBool":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testHasListMethod":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testHasUnarchiveMethod":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testListMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testUnarchiveMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ProductArchiveControllerTest::testConstructorRequiresProductRepository":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testFindReturnsBannerWithTranslations":0.001,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testDeleteReturnsTrue":0.002,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testSaveInsertsNewBanner":0,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheWithRedis":0.001,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheRedisUnavailable":0,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheWithoutRedis":0,"Tests\\Unit\\Domain\\Cache\\CacheRepositoryTest::testClearCacheReturnStructure":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testCanBeInstantiated":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testHasSaveSettingsMethod":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testHasGetSettingsMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasClearCacheMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasClearCacheAjaxMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testHasViewMethod":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testIsNotAbstract":0,"Tests\\Unit\\admin\\Controllers\\SettingsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testCanCreateController":0.005,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasListMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testListMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasEditMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testEditMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testConstructorAcceptsRepository":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testConstructorRequiresArticleRepository":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testFindReturnsArticleWithRelations":0.005,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testFindReturnsNullWhenArticleDoesNotExist":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeleteNonassignedFilesDeletesDbRows":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeleteNonassignedImagesDeletesDbRows":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveCreatesNewArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveReturnsZeroWhenInsertFails":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveUpdatesExistingArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsInsertsForNewArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveTranslationsUpsertsForExistingArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSavePagesForNewArticle":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveDeletesMarkedImagesOnUpdate":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArchiveSetsStatusToMinusOne":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArchiveReturnsFalseWhenUpdateFails":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveGalleryOrderUpdatesImageOrder":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveGalleryOrderSkipsEmptyValues":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasBrowseListMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasGalleryOrderSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testBrowseListMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testGalleryOrderSaveMethodReturnType":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testListForAdminUsesBoundParamsForTitleFilter":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testSaveWithLegacyFormat":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testSaveUpdatesExistingTranslationsByBannerAndLang":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testListForAdminIncludesThumbnailSrc":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testRestoreSetsStatusToZero":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testDeletePermanentlyRemovesArticleAndRelations":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testListArchivedForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testFindReturnsUnitWithTranslations":0.001,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testFindReturnsNullWhenUnitNotFound":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testSaveInsertsNewUnitAndTranslationsForStringLanguageId":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testDeleteRemovesUnitAndTranslations":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testGetUnitNameByIdReturnsTextFromDatabase":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testGetUnitNameByIdSupportsStringLanguageId":0,"Tests\\Unit\\Domain\\Dictionaries\\DictionariesRepositoryTest::testAllUnitsReturnsArrayIndexedById":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testLanguageDetailsReturnsArrayOrNull":0.001,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testLanguagesListReturnsArray":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testSaveLanguageRejectsInvalidLanguageId":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testSaveTranslationInsertsNewTranslationAndReturnsId":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDeleteTranslationReturnsBoolean":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testListForAdminReturnsItemsAndTotal":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageIdReturnsLanguageWithStartFlag":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageIdFallsBackToFirstLanguageOrPl":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testFindReturnsLayoutWithRelations":0.002,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testDeleteReturnsFalseWhenOnlyOneLayoutExists":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testFindReturnsDefaultLayoutWhenRecordDoesNotExist":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testSaveInsertsNewLayoutAndReturnsId":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testListAllReturnsArray":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testTemplateDetailsReturnsNullForInvalidId":0.002,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testTemplateDetailsReturnsArray":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testSaveSettingsUpdatesHeaderAndFooter":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testDeleteTemplateReturnsFalseForAdminTemplate":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testTemplateByNameReturnsText":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFindReturnsDefaultContainerForInvalidId":0.001,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFindReturnsContainerWithTranslations":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testDetailsForLanguageReturnsNullForInvalidData":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testFindReturnsUserWhenExists":0.001,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testCheckLoginReturnsErrorWhenLoginIsTaken":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testCheckLoginReturnsOkWhenAvailable":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForTooShortPasswordOnCreate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForMismatchedPasswordsOnCreate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveCreatesUserWithNormalizedSwitches":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveUpdatesExistingUserWithPassword":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveUpdatesExistingUserWithoutPassword":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForTooShortPasswordOnUpdate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSaveReturnsErrorForMismatchedPasswordsOnUpdate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDeleteReturnsTrue":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDeleteReturnsFalseOnFailure":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDetailsReturnsUserByLogin":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testDetailsReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testLogonReturnsSuccessForValidCredentials":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testLogonReturnsZeroForNonexistentUser":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testLogonReturnsNegativeOneForBlockedUser":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsFalseForNonexistentUser":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsFalseAfterMaxAttempts":0.078,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsFalseForExpiredCode":0.079,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testVerifyTwofaCodeReturnsTrueForValidCode":0.157,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSendTwofaCodeReturnsFalseWhen2FADisabled":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testSendTwofaCodeReturnsFalseForInvalidEmail":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testUpdateByIdCallsDbUpdate":0,"Tests\\Unit\\Domain\\User\\UserRepositoryTest::testListForAdminReturnsItemsAndTotal":0,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ArticlesArchiveControllerTest::testConstructorRequiresArticleRepository":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testConstructorAcceptsRepository":0.003,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasListMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasEditMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testHasDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\DictionariesControllerTest::testConstructorRequiresDictionariesRepository":0,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\LanguagesControllerTest::testConstructorRequiresLanguagesRepository":0,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\LayoutsControllerTest::testConstructorRequiresLayoutsRepository":0,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testConstructorAcceptsDependencies":0.003,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\NewsletterControllerTest::testConstructorRequiresRepositoryAndRenderer":0,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testConstructorAcceptsDependencies":0.002,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ScontainersControllerTest::testConstructorRequiresRepositoryAndLanguagesRepository":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasViewListMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasUserEditMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasUserSaveMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasUserDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasTwofaMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testHasLoginFormMethod":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testConstructorRequiresUserRepository":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testNormalizeUserReturnsDefaultsForNull":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testNormalizeUserCastsTypes":0,"Tests\\Unit\\admin\\Controllers\\UsersControllerTest::testNormalizeUserHandlesPartialData":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveFilesOrderUpdatesFilesOrder":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testSaveFilesOrderSkipsEmptyValues":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPagesSummaryForArticlesBuildsLabels":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testUpdateImageAltDelegatesToDatabase":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testMarkFileToDeleteDelegatesToDatabase":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindReturnsDefaultCouponForInvalidId":0.001,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindNormalizesCouponData":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testSaveInsertsCouponAndReturnsId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testSaveUpdatesCouponAndReturnsId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testDeleteReturnsTrueWhenDatabaseDeleteSucceeds":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testCategoriesTreeReturnsHierarchy":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetSettingsReturnsArray":0.002,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetSettingReturnsValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetSettingReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testSaveSettingUpdatesExistingValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testSaveSettingInsertsNewValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testInvalidProviderThrowsException":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testLinkProductUpdatesDatabase":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testUnlinkProductClearsFields":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetProductSkuReturnsValue":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testGetProductSkuReturnsNullForMissing":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloGetAccessTokenReturnsNullWithoutSettings":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloFetchListThrowsForInvalidType":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testAllPublicMethodsExist":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testSettingsTableMapping":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testShopproProviderWorks":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testMenusListReturnsArray":0.002,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testMenuDeleteReturnsFalseWhenMenuHasPages":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testGenerateSeoLinkAddsSuffixWhenBaseSlugExists":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testPageUrlPreviewBuildsLanguagePrefixedUrlForNonDefaultLanguage":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testFindReturnsDefaultPromotionForInvalidId":0.001,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testSaveInsertsPromotionAndReturnsId":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testDeleteReturnsTrueWhenDatabaseDeleteSucceeds":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testCategoriesTreeReturnsHierarchy":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasImageAltChangeMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasFileNameChangeMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasImageDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testHasFileDeleteMethod":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testImageAltChangeMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testFileNameChangeMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testImageDeleteMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\ArticlesControllerTest::testFileDeleteMethodReturnType":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testConstructorAcceptsDependencies":0.002,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testConstructorRequiresRepository":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllApiloSettingsMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllApiloDataFetchMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllApiloProductMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testHasAllShopproMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testApiloSettingsReturnsString":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testShopproSettingsReturnsString":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testVoidReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testDoesNotHaveSellasistMethods":0,"Tests\\Unit\\admin\\Controllers\\IntegrationsControllerTest::testDoesNotHaveBaselinkerMethods":0,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testConstructorAcceptsRepositories":0.002,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\PagesControllerTest::testConstructorRequiresPagesLanguagesAndLayoutsRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopCouponControllerTest::testConstructorRequiresCouponRepository":0,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopPromotionControllerTest::testConstructorRequiresPromotionRepository":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindReturnsNullForNegativeId":0.001,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindReturnsStatusWithIdZero":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testFindNormalizesNullApiloStatusId":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveUpdatesColorAndApiloStatusId":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveWithIdZeroWorks":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveWithEmptyApiloStatusIdSetsNull":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testSaveRejectsNegativeId":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetApiloStatusIdReturnsValue":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetApiloStatusIdReturnsNullWhenNotSet":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetByIntegrationStatusIdForApilo":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testGetByIntegrationStatusIdReturnsNullForUnknownIntegration":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testAllStatusesReturnsOrderedList":0,"Tests\\Unit\\Domain\\ShopStatus\\ShopStatusRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopStatusesControllerTest::testConstructorRequiresShopStatusRepository":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testShouldRefreshAccessTokenReturnsFalseForFarFutureDate":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testShouldRefreshAccessTokenReturnsTrueForNearExpiryDate":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloFetchListResultReturnsDetailedErrorWhenConfigMissing":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testApiloIntegrationStatusReturnsMissingConfigMessage":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testNormalizeApiloMapListRejectsErrorPayload":0,"Tests\\Unit\\Domain\\Integrations\\IntegrationsRepositoryTest::testNormalizeApiloMapListAcceptsIdNameList":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindReturnsNullForInvalidId":0.001,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindNormalizesData":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSaveUpdatesRowAndReturnsId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSavePreservesNonNumericApiloPaymentTypeId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testSaveReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testListForAdminWhitelistsSortAndDirection":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testAllActiveReturnsNormalizedRows":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testAllForAdminReturnsRowsIncludingInactive":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindActiveByIdReturnsNullForNotFound":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindKeepsNonNumericApiloPaymentTypeId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testIsActiveNormalizesStatusValue":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testGetApiloPaymentTypeIdHandlesNullAndInt":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testGetApiloPaymentTypeIdReturnsStringForNonNumericValue":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testForTransportReturnsRows":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindNormalizesDataAndIncludesPaymentMethods":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindHandlesNullMaxWpAndApiloId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveInsertReturnsNewId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveUpdateReturnsExistingId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveInsertReturnsNullOnFailure":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveResetsDefaultWhenSettingNew":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testSaveSwitchValuesNormalization":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testListForAdminWhitelistsSortColumn":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testAllActiveReturnsNormalizedRows":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testGetApiloCarrierAccountIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testGetApiloCarrierAccountIdReturnsIntOrNull":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testGetTransportCostReturnsFloatOrNull":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testAllForAdminReturnsAllTransports":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopPaymentMethodControllerTest::testConstructorRequiresPaymentMethodRepository":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testConstructorAcceptsRepositories":0.001,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopTransportControllerTest::testConstructorRequiresBothRepositories":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFindAttributeReturnsDefaultAttributeForInvalidId":0.002,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testListForAdminWhitelistsSortDirectionAndPerPage":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testSaveValuesRemovesObsoleteRowsAndSetsDefault":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testSaveValuesDeletesTranslationWhenNameIsEmpty":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testGetAttributeValueByIdUsesDefaultLanguageWhenNotProvided":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSortTypesReturnsExpectedKeys":0.002,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDetailsReturnsDefaultForInvalidId":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDetailsLoadsTranslations":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveCategoriesOrderReturnsFalseForNonArray":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveCategoriesOrderUpdatesOrderAndParent":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveProductOrderReturnsFalseForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testSaveProductOrderUpdatesCategoryProductOrder":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDeleteReturnsFalseWhenHasChildren":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryDeleteReturnsTrueWhenDeleted":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryTitleReturnsEmptyWhenNotFound":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryTitleReturnsFirstAvailableTitle":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testListForAdminWhitelistsSortAndPagination":0.001,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testOrdersForClientReturnsEmptyOnMissingInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testOrdersForClientNormalizesRows":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testTotalsForClientReturnsZeroForMissingInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testTotalsForClientReturnsAggregatedValues":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testConstructorAcceptsDb":0.001,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testHasAllPublicMethods":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testSalesGridReturnsArray":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testLastOrdersReturnsArray":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testMostViewedProductsReturnsArray":0,"Tests\\Unit\\Domain\\Dashboard\\DashboardRepositoryTest::testBestSalesProductsReturnsArray":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageReturnsId":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testDefaultLanguageReturnsFallbackWhenEmpty":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testActiveLanguagesReturnsList":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testActiveLanguagesReturnsEmptyArrayWhenNone":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testTranslationsReturnsArray":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testTranslationsDefaultsToPl":0,"Tests\\Unit\\Domain\\Languages\\LanguagesRepositoryTest::testTranslationsForDifferentLanguage":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testUnsubscribeReturnsFalseForInvalidHash":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testUnsubscribeDeletesSubscriber":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testConfirmSubscriptionReturnsFalseForInvalidHash":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testConfirmSubscriptionUpdatesStatus":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testGetHashByEmailReturnsHash":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testGetHashByEmailReturnsNullForMissing":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testRemoveByEmailDeletesSubscriber":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testRemoveByEmailReturnsFalseForMissing":0,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testSignupReturnsFalseForExistingEmail":0.001,"Tests\\Unit\\Domain\\Newsletter\\NewsletterRepositoryTest::testConstructorAcceptsOptionalDependencies":0.003,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderStatusesReturnsMappedArray":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testNextAndPrevOrderIdReturnNullForInvalidInput":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testListForAdminReturnsItemsAndTotal":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindReturnsDefaultProducerForInvalidId":0.001,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindNormalizesProducerData":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testSaveInsertsNewProducer":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testSaveUpdatesExistingProducer":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testDeleteReturnsTrueOnSuccess":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testListForAdminWhitelistsSortAndPagination":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testAllProducersReturnsFormattedList":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testProducerProductsReturnsPaginatedResults":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testFindReturnsDefaultSetForInvalidId":0.001,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testFindNormalizesSetData":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testSaveInsertsNewSetAndSyncsProducts":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testSaveUpdatesExistingSet":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testListForAdminWhitelistsSortAndPagination":0,"Tests\\Unit\\Domain\\ProductSet\\ProductSetRepositoryTest::testAllSetsReturnsFormattedList":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testAllProductsForMassEditReturnsMap":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testAllProductsForMassEditEmptyWhenNoProducts":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetProductsByCategoryReturnsList":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetProductsByCategoryReturnsEmptyArray":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testApplyDiscountPercentReturnsNullForInvalidProduct":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testApplyDiscountPercentReturnsCorrectPrices":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testApplyDiscountPercentZeroPercentNullsPromo":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testAllSettingsReturnsAssociativeArray":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testAllSettingsReturnsEmptyArrayWhenNoSettings":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testAllSettingsHandlesNullFromDb":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testGetSingleValueReturnsCorrectParam":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testGetSingleValueUsesParamNotHardcoded":0,"Tests\\Unit\\Domain\\Settings\\SettingsRepositoryTest::testGetSingleValueReturnsEmptyStringWhenNotFound":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testConstructorAcceptsDb":0.001,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testHasUpdateMethod":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testUpdateReturnsArray":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testHasRunPendingMigrationsMethod":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testRunPendingMigrationsWithNoResults":0,"Tests\\Unit\\Domain\\Update\\UpdateRepositoryTest::testHasPrivateHelperMethods":0,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testConstructorAcceptsRepositories":0.001,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testHasMainViewMethod":0,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testMainViewReturnsString":0,"Tests\\Unit\\admin\\Controllers\\DashboardControllerTest::testConstructorRequiresRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testConstructorAcceptsRepositories":0.002,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testHasNoLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testConstructorRequiresBothRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testValidateValuesRowsReturnsErrorsForMissingDefaultLanguageAndDefaultSelection":0,"Tests\\Unit\\admin\\Controllers\\ShopAttributeControllerTest::testValidateValuesRowsReturnsEmptyArrayForValidRows":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testConstructorAcceptsDependencies":0.002,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testHasExpectedActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testViewActionsReturnString":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testMutationActionsReturnVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopCategoryControllerTest::testConstructorRequiresCategoryAndLanguagesRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testConstructorAcceptsRepository":0.002,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopClientsControllerTest::testConstructorRequiresClientRepository":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testConstructorAcceptsService":0.002,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testHasExpectedActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testViewActionsReturnString":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testMutationActionsReturnVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopOrderControllerTest::testConstructorRequiresOrderAdminService":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testConstructorAcceptsRepositories":0.002,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopProducerControllerTest::testConstructorRequiresBothRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testConstructorAcceptsRepositories":0.002,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasMassEditActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasViewListMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasEditAndSaveMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasOperationMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasCombinationMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasImageAndFileMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testMassEditReturnsString":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testMassEditSaveReturnsVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testGetProductsByCategoryReturnsVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testConstructorRequiresRepositories":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testHasFormBuildingHelpers":0,"Tests\\Unit\\admin\\Controllers\\ShopProductControllerTest::testSaveMethodReturnsVoid":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testHasLegacyAliasMethods":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testActionMethodReturnTypes":0,"Tests\\Unit\\admin\\Controllers\\ShopProductSetsControllerTest::testConstructorRequiresProductSetRepository":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasMainViewMethod":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testMainViewReturnsString":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasUpdateMethod":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testHasUpdateAllMethod":0,"Tests\\Unit\\admin\\Controllers\\UpdateControllerTest::testConstructorRequiresRepository":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendReturnsArticleWithRelations":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendReturnsNullForMissing":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleDetailsFrontendCopyFromFallback":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticlesIdsReturnsSortedIds":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticlesIdsReturnsNullForEmpty":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPageArticlesCountReturnsInt":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPageArticlesCountReturnsZeroForEmpty":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testPageArticlesPagination":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleNoindexReturnsBool":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testArticleNoindexReturnsFalseForNonNoindex":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testNewsReturnsArticlesArray":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testTopArticlesOrderByViews":0,"Tests\\Unit\\Domain\\Article\\ArticleRepositoryTest::testNewsListArticlesOrderByDateDesc":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testBannersReturnsActiveBannersWithFlatLanguages":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testBannersReturnsNullWhenNoBanners":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testMainBannerReturnsActiveBannerWithFlatLanguages":0,"Tests\\Unit\\Domain\\Banner\\BannerRepositoryTest::testMainBannerReturnsNullWhenNoBanner":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testCategoryDefaultLayoutIdReturnsId":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testCategoryDefaultLayoutIdReturnsNullWhenNone":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetDefaultLayoutReturnsLayoutFromDb":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetDefaultLayoutReturnsNullWhenNoLayout":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetArticleLayoutReturnsLayoutFromDb":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetArticleLayoutReturnsNullWhenNoLayout":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetActiveLayoutFallsBackToDefault":0,"Tests\\Unit\\Domain\\Layouts\\LayoutsRepositoryTest::testGetActiveLayoutReturnsNullWhenNothingFound":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontPageDetailsReturnsPageWithLanguage":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontPageDetailsReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMainPageIdReturnsStartPage":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMainPageIdFallsBackToFirstActive":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontPageSortReturnsValue":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMenuDetailsReturnsMenuWithPages":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMenuDetailsReturnsNullForInvalidMenu":0,"Tests\\Unit\\Domain\\Pages\\PagesRepositoryTest::testFrontMenuPagesReturnsEmptyForNoPages":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFrontScontainerDetailsReturnsContainerWithLanguage":0,"Tests\\Unit\\Domain\\Scontainers\\ScontainersRepositoryTest::testFrontScontainerDetailsReturnsFallbackForNotFound":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontAttributeDetailsReturnsAttributeWithLanguage":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontAttributeDetailsReturnsFallbackForNotFound":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontValueDetailsReturnsValueWithLanguage":0,"Tests\\Unit\\Domain\\Attribute\\AttributeRepositoryTest::testFrontValueDetailsReturnsFallbackForNotFound":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testSummaryWpCalculatesTotal":0.001,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testSummaryWpReturnsZeroForEmptyBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsSumsQuantities":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsReturnsZeroForEmptyBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextSingular":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextPlural2to4":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextPlural5Plus":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCountProductsTextCastsToInt":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testGetCategorySortReturnsZeroForInvalidId":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testGetCategorySortReturnsSortType":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryNameReturnsEmptyForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryNameReturnsTitle":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryNameReturnsEmptyWhenNotFound":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testFrontCategoryDetailsReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testFrontCategoryDetailsReturnsCategoryWithLanguage":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testFrontCategoryDetailsReturnsEmptyWhenCategoryNotFound":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoriesTreeReturnsEmptyWhenNoCategories":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryProductsCountReturnsZeroForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testCategoryProductsCountReturnsCount":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testProductsIdReturnsEmptyForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testProductsIdReturnsProductIds":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testBlogCategoryProductsReturnsEmptyForInvalidInput":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testBlogCategoryProductsReturnsIds":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testPaginatedCategoryProductsReturnsEmptyWhenNoProducts":0,"Tests\\Unit\\Domain\\Category\\CategoryRepositoryTest::testPaginatedCategoryProductsClampsPage":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientDetailsReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientDetailsReturnsRowOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientDetailsReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientEmailReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientEmailReturnsStringOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientEmailReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientAddressesReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientAddressesReturnsRows":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientAddressesHandlesFalseFromDb":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDetailsReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDetailsReturnsRow":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDeleteReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressDeleteReturnsTrueOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressSaveReturnsFalseForInvalidClientId":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressSaveInsertsNewAddress":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAddressSaveUpdatesExistingAddress":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testMarkAddressAsCurrentReturnsFalseForInvalidIds":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testMarkAddressAsCurrentResetsAndSets":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsErrorOnEmptyInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsErrorWhenClientNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsInactiveForUnconfirmedAccount":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsErrorOnWrongPassword":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testAuthenticateReturnsOkOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testCreateClientReturnsNullOnEmptyInput":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testCreateClientReturnsNullWhenEmailTaken":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testCreateClientReturnsIdAndHashOnSuccess":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testConfirmRegistrationReturnsNullOnEmptyHash":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testConfirmRegistrationReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testConfirmRegistrationActivatesAndReturnsEmail":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testGenerateNewPasswordReturnsNullOnEmptyHash":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testGenerateNewPasswordReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testGenerateNewPasswordReturnsEmailAndPassword":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testInitiatePasswordRecoveryReturnsNullOnEmptyEmail":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testInitiatePasswordRecoveryReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testInitiatePasswordRecoverySetsRecoveryFlagAndReturnsHash":0,"Tests\\Unit\\Domain\\Client\\ClientRepositoryTest::testClientOrdersReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindByNameReturnsObjectWhenFound":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindByNameReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testFindByNameReturnsNullForEmptyName":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsTrueForActiveCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsFalseForUsedCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsFalseForInactiveCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableReturnsFalseForNullCoupon":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIsAvailableWorksWithArray":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testMarkAsUsedCallsUpdate":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testMarkAsUsedSkipsInvalidId":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIncrementUsedCountCallsUpdate":0,"Tests\\Unit\\Domain\\Coupon\\CouponRepositoryTest::testIncrementUsedCountSkipsInvalidId":0,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\front\\Controllers\\ShopCouponControllerTest::testConstructorRequiresCouponRepository":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindIdByHashReturnsIdWhenFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindIdByHashReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindIdByHashReturnsNullForEmptyHash":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindHashByIdReturnsHashWhenFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testFindHashByIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderDetailsFrontendByIdReturnsArrayWithProducts":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderDetailsFrontendByHashReturnsArrayWithProducts":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testOrderDetailsFrontendReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGenerateOrderNumberFormatsCorrectly":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGenerateOrderNumberStartsAt001":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testAllActiveProducersReturnsFullData":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testAllActiveProducersReturnsEmptyOnNull":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindForFrontendReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindForFrontendReturnsNullWhenNotFound":0,"Tests\\Unit\\Domain\\Producer\\ProducerRepositoryTest::testFindForFrontendReturnsProducerWithLanguage":0,"Tests\\Unit\\front\\Controllers\\ShopOrderControllerTest::testConstructorAcceptsRepository":0.001,"Tests\\Unit\\front\\Controllers\\ShopOrderControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\front\\Controllers\\ShopOrderControllerTest::testConstructorRequiresOrderRepository":0,"Tests\\Unit\\front\\Controllers\\ShopProducerControllerTest::testConstructorAcceptsRepository":0,"Tests\\Unit\\front\\Controllers\\ShopProducerControllerTest::testHasMainActionMethods":0,"Tests\\Unit\\front\\Controllers\\ShopProducerControllerTest::testConstructorRequiresProducerRepository":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testIsActiveReturnsOneForActivePayment":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testIsActiveReturnsZeroForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindActiveByIdReturnsNormalizedData":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testFindActiveByIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testAllActiveReturnsEmptyOnNull":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testGetApiloPaymentTypeIdReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\PaymentMethod\\PaymentMethodRepositoryTest::testForTransportReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetSkuWithFallbackReturnsSku":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetSkuWithFallbackFromParent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetSkuWithFallbackReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetEanWithFallbackReturnsEan":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetEanWithFallbackFromParent":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testIsProductActiveCachedReturnsOneForActive":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testIsProductActiveCachedReturnsZeroForInactive":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testIsProductActiveCachedReturnsZeroForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testProductCategoriesFrontReturnsCategories":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testProductCategoriesFrontUsesParentId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testProductCategoriesFrontReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageZeroReturnsMessage":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageZeroReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageNonzeroReturnsMessage":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testGetWarehouseMessageNonzeroReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testTopProductIdsReturnsActiveProducts":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testNewProductIdsReturnsProductIds":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testNewProductIdsReturnsEmptyWhenNoProducts":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testPromotedProductIdsCachedReturnsIds":0,"Tests\\Unit\\Domain\\Product\\ProductRepositoryTest::testPromotedProductIdsCachedReturnsEmptyWhenNone":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeWholeBasketAppliesDiscountToAll":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoriesOrAppliesDiscountToMatchingCategories":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoryConditionAppliesWhenConditionMet":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoryConditionNoDiscountWhenConditionNotMet":0,"Tests\\Unit\\Domain\\Promotion\\PromotionRepositoryTest::testApplyTypeCategoriesAndAppliesWhenBothConditionsMet":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testTransportCostCachedReturnsCost":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindActiveByIdCachedReturnsTransport":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testFindActiveByIdCachedReturnsNullForInvalid":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testForPaymentMethodReturnsTransports":0,"Tests\\Unit\\Domain\\Transport\\TransportRepositoryTest::testForPaymentMethodReturnsEmptyForInvalidId":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCheckProductQuantityInStockReturnsFalseOnNullBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testCheckProductQuantityInStockReturnsFalseOnEmptyBasket":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testValidateBasketReturnsEmptyArrayOnNull":0,"Tests\\Unit\\Domain\\Basket\\BasketCalculatorTest::testValidateBasketReturnsBasketArrayAsIs":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testConstructorAcceptsOnlyOrderRepository":0.006,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testConstructorAcceptsAllDependencies":0.013,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSearchProductsReturnsEmptyForEmptyQuery":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSearchProductsReturnsEmptyWithoutProductRepo":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSearchProductsReturnsFormattedResults":0.001,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSaveOrderProductsReturnsFalseForInvalidOrderId":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSaveOrderProductsDeletesRemovedProducts":0.001,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSaveOrderProductsUpdatesQuantityAndAdjustsStock":0.001,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testSaveOrderProductsAddsNewProductAndDecreasesStock":0.001,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testGetFreeDeliveryThresholdReturnsZeroWithoutSettingsRepo":0,"Tests\\Unit\\Domain\\Order\\OrderAdminServiceTest::testGetFreeDeliveryThresholdReturnsValue":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGetOrderProductReturnsNullForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testGetOrderProductReturnsArray":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testAddOrderProductReturnsNullForInvalidOrderId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testAddOrderProductInsertsAndReturnsId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateOrderProductReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateOrderProductUpdatesFields":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateOrderProductReturnsFalseForEmptyData":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testDeleteOrderProductReturnsFalseForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testDeleteOrderProductCallsDelete":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateTransportCostDoesNothingForInvalidId":0,"Tests\\Unit\\Domain\\Order\\OrderRepositoryTest::testUpdateTransportCostUpdatesOrder":0}} \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 15cd384..976fc21 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -36,7 +36,7 @@ composer test PHPUnit 9.6 via `phpunit.phar`. Bootstrap: `tests/bootstrap.php`. Config: `phpunit.xml`. -Current suite: **610 tests, 1817 assertions**. +Current suite: **636 tests, 1868 assertions**. ### Creating Updates See `docs/UPDATE_INSTRUCTIONS.md` for the full procedure. Updates are ZIP packages in `updates/0.XX/`. Never include `*.md` files, `updates/changelog.php`, or root `.htaccess` in update ZIPs. diff --git a/admin/templates/shop-order/order-edit-custom-script.php b/admin/templates/shop-order/order-edit-custom-script.php index 0f2e99a..bea0136 100644 --- a/admin/templates/shop-order/order-edit-custom-script.php +++ b/admin/templates/shop-order/order-edit-custom-script.php @@ -1,5 +1,10 @@ diff --git a/admin/templates/shop-order/order-edit.php b/admin/templates/shop-order/order-edit.php index d478d43..46b6fec 100644 --- a/admin/templates/shop-order/order-edit.php +++ b/admin/templates/shop-order/order-edit.php @@ -84,7 +84,12 @@ $orderId = (int)($this -> order['id'] ?? 0);
-
Kwota zamówienia order[ 'summary' ];?> zł
+
Kwota zamówienia order[ 'summary' ];?> zł
+
+ Produkty: 0,00 +  |  + Dostawa: order['transport_cost'] ?? 0), 2, ',', '');?> +

@@ -160,46 +165,75 @@ $orderId = (int)($this -> order['id'] ?? 0);
+
Produkty zamówienia:
- +
- + - - - - + + + + + - - order[ 'products' ] ) ): foreach ( $this -> order[ 'products' ] as $product ):?> - + + + order[ 'products' ] ) ): foreach ( $this -> order[ 'products' ] as $i => $product ):?> + + + + + + + + + + + - - - -
ZdjęcieZdjęcie NazwaIlośćCena / szt:Cena / szt (po rabacie):Suma (po rabacie):IlośćCena / szt:Cena promo:Suma:
- + - -
-
- -
-
-
- Wiadomość: ' . $product['message'] : '';?> -
+ + +
+ + +
Wiadomość:
+ +
+ + + + + + + 0 ? (float)$product['price_brutto_promo'] : (float)$product['price_brutto']) * (int)$product['quantity'], 2, ',', '');?> zł + +
-
+
+ +
+
Dodaj produkt:
+
+
+
+ + +
+
+
+
@@ -222,4 +256,11 @@ $orderId = (int)($this -> order['id'] ?? 0);
+ \ No newline at end of file diff --git a/autoload/Domain/Order/OrderAdminService.php b/autoload/Domain/Order/OrderAdminService.php index 350db31..c6ac433 100644 --- a/autoload/Domain/Order/OrderAdminService.php +++ b/autoload/Domain/Order/OrderAdminService.php @@ -4,10 +4,20 @@ namespace Domain\Order; class OrderAdminService { private OrderRepository $orders; + private $productRepo; + private $settingsRepo; + private $transportRepo; - public function __construct(OrderRepository $orders) - { + public function __construct( + OrderRepository $orders, + $productRepo = null, + $settingsRepo = null, + $transportRepo = null + ) { $this->orders = $orders; + $this->productRepo = $productRepo; + $this->settingsRepo = $settingsRepo; + $this->transportRepo = $transportRepo; } public function details(int $orderId): array @@ -71,6 +81,215 @@ class OrderAdminService return $saved; } + // ========================================================================= + // Order products management (admin) + // ========================================================================= + + public function searchProducts(string $query, string $langId): array + { + if (!$this->productRepo || trim($query) === '') { + return []; + } + + $rows = $this->productRepo->searchProductByNameAjax($query, $langId); + $results = []; + + foreach ($rows as $row) { + $productId = (int)($row['product_id'] ?? 0); + if ($productId <= 0) { + continue; + } + + $product = $this->productRepo->findCached($productId, $langId); + if (!is_array($product)) { + continue; + } + + $name = isset($product['language']['name']) ? (string)$product['language']['name'] : ''; + $img = $this->productRepo->getProductImg($productId); + + $results[] = [ + 'product_id' => $productId, + 'parent_product_id' => (int)($product['parent_id'] ?? 0), + 'name' => $name, + 'sku' => (string)($product['sku'] ?? ''), + 'ean' => (string)($product['ean'] ?? ''), + 'price_brutto' => (float)($product['price_brutto'] ?? 0), + 'price_brutto_promo' => (float)($product['price_brutto_promo'] ?? 0), + 'vat' => (float)($product['vat'] ?? 0), + 'quantity' => (int)($product['quantity'] ?? 0), + 'image' => $img, + ]; + } + + return $results; + } + + public function saveOrderProducts(int $orderId, array $productsData): bool + { + if ($orderId <= 0) { + return false; + } + + $currentProducts = $this->orders->orderProducts($orderId); + $currentById = []; + foreach ($currentProducts as $cp) { + $currentById[(int)$cp['id']] = $cp; + } + + $submittedIds = []; + + foreach ($productsData as $item) { + $orderProductId = (int)($item['order_product_id'] ?? 0); + $deleted = !empty($item['delete']); + + if ($deleted && $orderProductId > 0) { + // Usunięcie — zwrot na stan + $existing = isset($currentById[$orderProductId]) ? $currentById[$orderProductId] : null; + if ($existing) { + $this->adjustStock((int)$existing['product_id'], (int)$existing['quantity']); + } + $this->orders->deleteOrderProduct($orderProductId); + $submittedIds[] = $orderProductId; + continue; + } + + if ($deleted) { + continue; + } + + if ($orderProductId > 0 && isset($currentById[$orderProductId])) { + // Istniejący produkt — aktualizacja + $existing = $currentById[$orderProductId]; + $newQty = max(1, (int)($item['quantity'] ?? 1)); + $oldQty = (int)$existing['quantity']; + $qtyDiff = $oldQty - $newQty; + + $update = [ + 'quantity' => $newQty, + 'price_brutto' => (float)($item['price_brutto'] ?? $existing['price_brutto']), + 'price_brutto_promo' => (float)($item['price_brutto_promo'] ?? $existing['price_brutto_promo']), + ]; + + $this->orders->updateOrderProduct($orderProductId, $update); + + // Korekta stanu: qtyDiff > 0 = zmniejszono ilość = zwrot na stan + if ($qtyDiff !== 0) { + $this->adjustStock((int)$existing['product_id'], $qtyDiff); + } + + $submittedIds[] = $orderProductId; + } elseif ($orderProductId === 0) { + // Nowy produkt + $productId = (int)($item['product_id'] ?? 0); + $qty = max(1, (int)($item['quantity'] ?? 1)); + + $this->orders->addOrderProduct($orderId, [ + 'product_id' => $productId, + 'parent_product_id' => (int)($item['parent_product_id'] ?? $productId), + 'name' => (string)($item['name'] ?? ''), + 'attributes' => '', + 'vat' => (float)($item['vat'] ?? 0), + 'price_brutto' => (float)($item['price_brutto'] ?? 0), + 'price_brutto_promo' => (float)($item['price_brutto_promo'] ?? 0), + 'quantity' => $qty, + 'message' => '', + 'custom_fields' => '', + ]); + + // Zmniejsz stan magazynowy + $this->adjustStock($productId, -$qty); + } + } + + // Usunięte z formularza (nie przesłane) — zwrot na stan + foreach ($currentById as $cpId => $cp) { + if (!in_array($cpId, $submittedIds)) { + $this->adjustStock((int)$cp['product_id'], (int)$cp['quantity']); + $this->orders->deleteOrderProduct($cpId); + } + } + + // Przelicz koszt dostawy (próg darmowej dostawy) + $this->recalculateTransportCost($orderId); + + return true; + } + + public function getFreeDeliveryThreshold(): float + { + if (!$this->settingsRepo) { + return 0.0; + } + + return (float)$this->settingsRepo->getSingleValue('free_delivery'); + } + + private function adjustStock(int $productId, int $delta): void + { + if (!$this->productRepo || $productId <= 0 || $delta === 0) { + return; + } + + $currentQty = $this->productRepo->getQuantity($productId); + if ($currentQty === null) { + return; + } + + $newQty = max(0, $currentQty + $delta); + $this->productRepo->updateQuantity($productId, $newQty); + } + + private function recalculateTransportCost(int $orderId): void + { + $order = $this->orders->findRawById($orderId); + if (!$order) { + return; + } + + $transportId = (int)($order['transport_id'] ?? 0); + if ($transportId <= 0 || !$this->transportRepo || !$this->settingsRepo) { + return; + } + + $transport = $this->transportRepo->findActiveById($transportId); + if (!is_array($transport)) { + return; + } + + // Oblicz sumę produktów (bez dostawy) + $productsSummary = $this->calculateProductsTotal($orderId); + $freeDelivery = (float)$this->settingsRepo->getSingleValue('free_delivery'); + + if ((int)($transport['delivery_free'] ?? 0) === 1 && $freeDelivery > 0 && $productsSummary >= $freeDelivery) { + $transportCost = 0.0; + } else { + $transportCost = (float)($transport['cost'] ?? 0); + } + + $this->orders->updateTransportCost($orderId, $transportCost); + } + + private function calculateProductsTotal(int $orderId): float + { + $products = $this->orders->orderProducts($orderId); + $summary = 0.0; + + foreach ($products as $row) { + $pricePromo = (float)($row['price_brutto_promo'] ?? 0); + $price = (float)($row['price_brutto'] ?? 0); + $quantity = (float)($row['quantity'] ?? 0); + + if ($pricePromo > 0) { + $summary += $pricePromo * $quantity; + } else { + $summary += $price * $quantity; + } + } + + return $summary; + } + public function changeStatus(int $orderId, int $status, bool $sendEmail): array { $order = $this->orders->findRawById($orderId); diff --git a/autoload/Domain/Order/OrderRepository.php b/autoload/Domain/Order/OrderRepository.php index 63dc4ca..3c8c2a8 100644 --- a/autoload/Domain/Order/OrderRepository.php +++ b/autoload/Domain/Order/OrderRepository.php @@ -435,6 +435,91 @@ class OrderRepository return true; } + // --- Order product CRUD (admin) --- + + public function getOrderProduct(int $orderProductId): ?array + { + if ($orderProductId <= 0) { + return null; + } + + $row = $this->db->get('pp_shop_order_products', '*', ['id' => $orderProductId]); + + return is_array($row) ? $row : null; + } + + public function addOrderProduct(int $orderId, array $data): ?int + { + if ($orderId <= 0) { + return null; + } + + $this->db->insert('pp_shop_order_products', [ + 'order_id' => $orderId, + 'product_id' => (int)($data['product_id'] ?? 0), + 'parent_product_id' => (int)($data['parent_product_id'] ?? 0), + 'name' => (string)($data['name'] ?? ''), + 'attributes' => (string)($data['attributes'] ?? ''), + 'vat' => (float)($data['vat'] ?? 0), + 'price_brutto' => (float)($data['price_brutto'] ?? 0), + 'price_brutto_promo' => (float)($data['price_brutto_promo'] ?? 0), + 'quantity' => max(1, (int)($data['quantity'] ?? 1)), + 'message' => (string)($data['message'] ?? ''), + 'custom_fields' => (string)($data['custom_fields'] ?? ''), + ]); + + $id = $this->db->id(); + + return $id ? (int)$id : null; + } + + public function updateOrderProduct(int $orderProductId, array $data): bool + { + if ($orderProductId <= 0) { + return false; + } + + $update = []; + + if (array_key_exists('quantity', $data)) { + $update['quantity'] = max(1, (int)$data['quantity']); + } + if (array_key_exists('price_brutto', $data)) { + $update['price_brutto'] = (float)$data['price_brutto']; + } + if (array_key_exists('price_brutto_promo', $data)) { + $update['price_brutto_promo'] = (float)$data['price_brutto_promo']; + } + + if (empty($update)) { + return false; + } + + $this->db->update('pp_shop_order_products', $update, ['id' => $orderProductId]); + + return true; + } + + public function deleteOrderProduct(int $orderProductId): bool + { + if ($orderProductId <= 0) { + return false; + } + + $this->db->delete('pp_shop_order_products', ['id' => $orderProductId]); + + return true; + } + + public function updateTransportCost(int $orderId, float $cost): void + { + if ($orderId <= 0) { + return; + } + + $this->db->update('pp_shop_orders', ['transport_cost' => $cost], ['id' => $orderId]); + } + // --- Frontend methods --- public function findIdByHash(string $hash) @@ -652,6 +737,11 @@ class OrderRepository $product_price_tmp = \Domain\Basket\BasketCalculator::calculateBasketProductPrice((float)$product['price_brutto_promo'], (float)$product['price_brutto'], $coupon, $basket_position, $productRepo); + // Cena promo = 0 gdy taka sama jak cena bazowa (brak realnej promocji/kuponu) + $effectivePromoPrice = (float)$product_price_tmp['price_new']; + $effectiveBasePrice = (float)$product_price_tmp['price']; + $promoPrice = ($effectivePromoPrice != $effectiveBasePrice) ? $effectivePromoPrice : 0; + $this->db->insert('pp_shop_order_products', [ 'order_id' => $order_id, 'product_id' => $basket_position['product-id'], @@ -659,8 +749,8 @@ class OrderRepository 'name' => $product['language']['name'], 'attributes' => $attributes, 'vat' => $product['vat'], - 'price_brutto' => $product_price_tmp['price'], - 'price_brutto_promo' => $product_price_tmp['price_new'], + 'price_brutto' => $effectiveBasePrice, + 'price_brutto_promo' => $promoPrice, 'quantity' => $basket_position['quantity'], 'message' => $basket_position['message'], 'custom_fields' => $product_custom_fields, diff --git a/autoload/admin/App.php b/autoload/admin/App.php index 29e7e5f..a89b6ca 100644 --- a/autoload/admin/App.php +++ b/autoload/admin/App.php @@ -417,10 +417,15 @@ class App }, 'ShopOrder' => function() { global $mdb; + $productRepo = new \Domain\Product\ProductRepository( $mdb ); return new \admin\Controllers\ShopOrderController( new \Domain\Order\OrderAdminService( - new \Domain\Order\OrderRepository( $mdb ) - ) + new \Domain\Order\OrderRepository( $mdb ), + $productRepo, + new \Domain\Settings\SettingsRepository( $mdb ), + new \Domain\Transport\TransportRepository( $mdb ) + ), + $productRepo ); }, 'Update' => function() { diff --git a/autoload/admin/Controllers/ShopOrderController.php b/autoload/admin/Controllers/ShopOrderController.php index 015c35a..0f0bdc0 100644 --- a/autoload/admin/Controllers/ShopOrderController.php +++ b/autoload/admin/Controllers/ShopOrderController.php @@ -2,15 +2,18 @@ namespace admin\Controllers; use Domain\Order\OrderAdminService; +use Domain\Product\ProductRepository; use admin\ViewModels\Common\PaginatedTableViewModel; class ShopOrderController { private OrderAdminService $service; + private $productRepo; - public function __construct(OrderAdminService $service) + public function __construct(OrderAdminService $service, ProductRepository $productRepo = null) { $this->service = $service; + $this->productRepo = $productRepo; } public function list(): string @@ -187,12 +190,27 @@ class ShopOrderController public function order_edit(): string { $orderId = (int)\Shared\Helpers\Helpers::get('order_id'); + $transports = ( new \Domain\Transport\TransportRepository( $GLOBALS['mdb'] ) )->allActive(); + + // Dane transportów do JS (id, cost, delivery_free) + $transportsJson = []; + if (is_array($transports)) { + foreach ($transports as $t) { + $transportsJson[] = [ + 'id' => (int)$t['id'], + 'cost' => (float)$t['cost'], + 'delivery_free' => (int)($t['delivery_free'] ?? 0), + ]; + } + } return \Shared\Tpl\Tpl::view('shop-order/order-edit', [ 'order' => $this->service->details($orderId), 'order_statuses' => $this->service->statuses(), - 'transport' => ( new \Domain\Transport\TransportRepository( $GLOBALS['mdb'] ) )->allActive(), + 'transport' => $transports, 'payment_methods' => ( new \Domain\PaymentMethod\PaymentMethodRepository( $GLOBALS['mdb'] ) )->allActive(), + 'free_delivery' => $this->service->getFreeDeliveryThreshold(), + 'transports_json' => json_encode($transportsJson), ]); } @@ -203,8 +221,16 @@ class ShopOrderController public function order_save(): void { + $orderId = (int)\Shared\Helpers\Helpers::get('order_id'); + + // Zapisz produkty PRZED zapisem zamówienia (bo saveOrderByAdmin przelicza summary) + $productsData = \Shared\Helpers\Helpers::get('products'); + if (is_array($productsData)) { + $this->service->saveOrderProducts($orderId, $productsData); + } + $saved = $this->service->saveOrderByAdmin([ - 'order_id' => (int)\Shared\Helpers\Helpers::get('order_id'), + 'order_id' => $orderId, 'client_name' => (string)\Shared\Helpers\Helpers::get('client_name'), 'client_surname' => (string)\Shared\Helpers\Helpers::get('client_surname'), 'client_street' => (string)\Shared\Helpers\Helpers::get('client_street'), @@ -225,7 +251,22 @@ class ShopOrderController \Shared\Helpers\Helpers::alert('Zamówienie zostało zapisane.'); } - header('Location: /admin/shop_order/order_details/order_id=' . (int)\Shared\Helpers\Helpers::get('order_id')); + header('Location: /admin/shop_order/order_details/order_id=' . $orderId); + exit; + } + + public function search_products_ajax(): void + { + $query = trim((string)\Shared\Helpers\Helpers::get('query')); + $langId = trim((string)\Shared\Helpers\Helpers::get('lang_id')); + if ($langId === '') { + $langId = isset($_SESSION['lang_id']) ? (string)$_SESSION['lang_id'] : 'pl'; + } + + $results = $this->service->searchProducts($query, $langId); + + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(['status' => 'ok', 'products' => $results]); exit; } diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 223149c..ab41816 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,23 @@ Logi zmian z migracji na Domain-Driven Architecture. Najnowsze na gorze. --- +## ver. 0.295 (2026-02-19) - Admin: edycja produktów w zamówieniu + wyszukiwanie AJAX + korekta stanów magazynowych + +- **NEW**: Edycja produktów w zamówieniu z panelu admina (dodawanie, usuwanie, zmiana ilości/cen) +- **NEW**: Wyszukiwarka produktów AJAX w formularzu edycji zamówienia (`search_products_ajax`) +- **NEW**: Automatyczna korekta stanów magazynowych przy edycji produktów zamówienia +- **NEW**: Automatyczne przeliczanie kosztu dostawy (próg darmowej dostawy) po zmianie produktów +- **NEW**: `OrderRepository` — CRUD: `addOrderProduct()`, `updateOrderProduct()`, `deleteOrderProduct()`, `getOrderProduct()`, `updateTransportCost()` +- **NEW**: `OrderAdminService` — `searchProducts()`, `saveOrderProducts()`, `getFreeDeliveryThreshold()`, `adjustStock()`, `recalculateTransportCost()` +- **NEW**: `ShopOrderController` — endpoint `search_products_ajax`, rozszerzony `order_save` o zapis produktów +- **UPDATE**: `admin\App` — rozszerzone DI wiring (ProductRepository, SettingsRepository, TransportRepository) +- **FIX**: `OrderRepository::createOrder()` — promo price = 0 gdy taka sama jak cena bazowa (brak realnej promocji) +- **NEW**: Template `order-edit-custom-script.php` — interaktywny JS do zarządzania produktami zamówienia +- **UPDATE**: Template `order-edit.php` — sekcja edycji produktów z dynamicznym formularzem +- **Tests**: `OrderAdminServiceTest` (nowy), rozszerzony `OrderRepositoryTest` (+132 linii), zaktualizowany `ShopOrderControllerTest` + +--- + ## ver. 0.294 (2026-02-19) - Code review: full codebase review complete (96/96 classes), 27 fixes across all layers **Code review zakończony — 96 klas, ~1144 metody przejrzane.** diff --git a/docs/TESTING.md b/docs/TESTING.md index cb519ce..5313b49 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -23,10 +23,10 @@ composer test # standard ## Aktualny stan ```text -OK (614 tests, 1821 assertions) +OK (636 tests, 1868 assertions) ``` -Zweryfikowano: 2026-02-19 (ver. 0.293) +Zweryfikowano: 2026-02-19 (ver. 0.295) ## Konfiguracja diff --git a/docs/UPDATE_INSTRUCTIONS.md b/docs/UPDATE_INSTRUCTIONS.md index 2c0eefd..1e6abe3 100644 --- a/docs/UPDATE_INSTRUCTIONS.md +++ b/docs/UPDATE_INSTRUCTIONS.md @@ -18,16 +18,16 @@ Aktualizacje znajdują się w folderze `updates/0.XX/` gdzie XX oznacza dziesią ## Procedura tworzenia nowej aktualizacji -## Status biezacej aktualizacji (ver. 0.294) +## Status biezacej aktualizacji (ver. 0.295) -- Wersja udostepniona: `0.294` (data: 2026-02-19). +- Wersja udostepniona: `0.295` (data: 2026-02-19). - Pliki publikacyjne: - - `updates/0.20/ver_0.294.zip` + - `updates/0.20/ver_0.295.zip` - Pliki metadanych aktualizacji: - `updates/changelog.php` - - `updates/versions.php` (`$current_ver = 294`) + - `updates/versions.php` (`$current_ver = 295`) - Weryfikacja testow przed publikacja: - - `OK (614 tests, 1821 assertions)` + - `OK (636 tests, 1868 assertions)` ### 1. Określ numer wersji Sprawdź ostatnią wersję w `updates/` i zwiększ o 1. diff --git a/temp/build_294.sh b/temp/build_294.sh deleted file mode 100644 index e8af1d9..0000000 --- a/temp/build_294.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/bash -set -e -cd "c:/visual studio code/projekty/shopPRO" - -# Files to include in update package (modified, excluding .md, tests, .phpunit) -FILES=( - admin/templates/dashboard/main-view.php - admin/templates/shop-order/order-details.php - admin/templates/shop-order/order-edit.php - admin/templates/shop-product/product-combination.php - autoload/Domain/Attribute/AttributeRepository.php - autoload/Domain/Basket/BasketCalculator.php - autoload/Domain/Category/CategoryRepository.php - autoload/Domain/Integrations/IntegrationsRepository.php - autoload/Domain/Order/OrderAdminService.php - autoload/Domain/Order/OrderRepository.php - autoload/Domain/Product/ProductRepository.php - autoload/Domain/Promotion/PromotionRepository.php - autoload/Shared/Helpers/Helpers.php - autoload/admin/Controllers/ShopOrderController.php - autoload/admin/Controllers/ShopProductController.php - autoload/admin/Controllers/ShopPromotionController.php - autoload/front/App.php - autoload/front/Controllers/ShopBasketController.php - autoload/front/Controllers/ShopClientController.php - autoload/front/Controllers/ShopOrderController.php - autoload/front/Controllers/ShopProductController.php - autoload/front/LayoutEngine.php - autoload/front/Controllers/SearchController.php - autoload/front/Views/ShopSearch.php - cron-turstmate.php - cron.php - index.php - templates/controls/alert-product-sets.php - templates/shop-basket/_partials/product-custom-fields.php - templates/shop-basket/alert-product-sets.php - templates/shop-basket/basket-details.php - templates/shop-basket/summary-view.php - templates/shop-category/blog-category-products.php - templates/shop-category/category-infinitescroll.php - templates/shop-category/category.php - templates/shop-category/products.php - templates/shop-client/client-orders.php - templates/shop-order/mail-summary.php - templates/shop-order/order-details.php - templates/shop-order/order-simple.php - templates/shop-producer/products.php - templates/shop-product/_partial/product-attribute.php - templates/shop-product/_partial/product-meta.php - templates/shop-product/_partial/product-warehouse-message.php - templates/shop-product/product-mini.php - templates/shop-product/product.php - templates/shop-product/products-box.php - templates/shop-product/products-new.php - templates/shop-product/products-top.php - templates/shop-product/promoted-products.php - templates/shop-search/product-search.php - templates/shop-search/products.php - updates/changelog.php - updates/versions.php -) - -# Create directory structure and copy files -for f in "${FILES[@]}"; do - dir=$(dirname "$f") - mkdir -p "temp/temp_294/$dir" - cp "$f" "temp/temp_294/$f" -done - -echo "Copied ${#FILES[@]} files to temp/temp_294/" diff --git a/temp/update_build/delete_files_0.273.txt b/temp/update_build/delete_files_0.273.txt deleted file mode 100644 index 2f1a8af..0000000 --- a/temp/update_build/delete_files_0.273.txt +++ /dev/null @@ -1,9 +0,0 @@ -admin/templates/shop-producer/edit.php -admin/templates/shop-producer/list.php -autoload/admin/controls/class.ShopProducer.php -autoload/admin/factory/class.Languages.php -autoload/admin/factory/class.Layouts.php -autoload/admin/factory/class.Newsletter.php -autoload/admin/factory/class.Scontainers.php -autoload/admin/factory/class.ShopProducer.php -autoload/admin/factory/class.ShopTransport.php diff --git a/temp/update_build/delete_files_0.274.txt b/temp/update_build/delete_files_0.274.txt deleted file mode 100644 index cac62ca..0000000 --- a/temp/update_build/delete_files_0.274.txt +++ /dev/null @@ -1 +0,0 @@ -# brak plikow do usuniecia w ver. 0.274 diff --git a/temp/update_build/delete_files_0.275.txt b/temp/update_build/delete_files_0.275.txt deleted file mode 100644 index 98ab009..0000000 --- a/temp/update_build/delete_files_0.275.txt +++ /dev/null @@ -1,3 +0,0 @@ -autoload/admin/controls/class.ShopCategory.php -autoload/admin/factory/class.ShopCategory.php -autoload/admin/view/class.ShopCategory.php diff --git a/temp/update_build/tmp_0.275/admin/ajax/shop-category.php b/temp/update_build/tmp_0.275/admin/ajax/shop-category.php deleted file mode 100644 index a16c6b6..0000000 --- a/temp/update_build/tmp_0.275/admin/ajax/shop-category.php +++ /dev/null @@ -1,15 +0,0 @@ - 'error', 'msg' => 'Podczas zapisywania kolejności wyświetlania produktów wystąpił błąd. Proszę spróbować ponownie.' ]; - - $categoryRepository = new \Domain\Category\CategoryRepository( $mdb ); - - if ( $categoryRepository->saveProductOrder( \S::get( 'category_id' ), \S::get( 'products' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; -} diff --git a/temp/update_build/tmp_0.275/admin/ajax/shop.php b/temp/update_build/tmp_0.275/admin/ajax/shop.php deleted file mode 100644 index 48af10e..0000000 --- a/temp/update_build/tmp_0.275/admin/ajax/shop.php +++ /dev/null @@ -1,60 +0,0 @@ - 'error', 'msg' => 'Podczas zapisywania kolejności kategorii wystąpił błąd. Proszę spróbować ponownie.' ]; - - $categoryRepository = new \Domain\Category\CategoryRepository( $mdb ); - - if ( $categoryRepository->saveCategoriesOrder( \S::get( 'categories' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; -} - -if ( $a == 'product_file_delete' ) -{ - $response = [ 'status' => 'error', 'msg' => 'Podczas usuwania załącznika wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::delete_file( \S::get( 'file_id' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; -} - -if ( $a == 'product_file_name_change' ) -{ - $response = [ 'status' => 'error', 'msg' => 'Podczas zmiany nazwy załącznika wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::file_name_change( \S::get( 'file_id' ), \S::get( 'file_name' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; -} - -if ( $a == 'product_image_delete' ) -{ - $response = [ 'status' => 'error', 'msg' => 'Podczas usuwania zdjecia wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::delete_img( \S::get( 'image_id' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; -} diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-category/categories-list-custom-script.php b/temp/update_build/tmp_0.275/admin/templates/shop-category/categories-list-custom-script.php deleted file mode 100644 index 16b4953..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-category/categories-list-custom-script.php +++ /dev/null @@ -1,153 +0,0 @@ - - - diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-category/categories-list.php b/temp/update_build/tmp_0.275/admin/templates/shop-category/categories-list.php deleted file mode 100644 index 3a4ef4c..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-category/categories-list.php +++ /dev/null @@ -1,61 +0,0 @@ - - - id = 'pages-list'; -$grid -> gdb_opt = $gdb; -$grid -> include_plugins = true; -$grid -> title = 'Lista kategorii'; -$grid -> default_buttons = false; -$grid -> buttons = [ - [ - 'label' => 'Dodaj kategorię', - 'url' => '/admin/shop_category/category_edit/', - 'icon' => 'fa-plus-circle', - 'class' => 'btn-success' - ] - ]; -$grid -> external_code = $out; - -echo $grid -> draw(); -?> - \ No newline at end of file diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-category/category-browse-custom-script.php b/temp/update_build/tmp_0.275/admin/templates/shop-category/category-browse-custom-script.php deleted file mode 100644 index a27a2e0..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-category/category-browse-custom-script.php +++ /dev/null @@ -1,106 +0,0 @@ - - - diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-category/category-browse-list.php b/temp/update_build/tmp_0.275/admin/templates/shop-category/category-browse-list.php deleted file mode 100644 index 0ad148f..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-category/category-browse-list.php +++ /dev/null @@ -1,59 +0,0 @@ - - - id = 'pages-list'; -$grid -> gdb_opt = $gdb; -$grid -> include_plugins = false; -$grid -> title = 'Lista kategorii'; -$grid -> default_buttons = false; -$grid -> external_code = $out; - -echo $grid -> draw(); -?> - - \ No newline at end of file diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-category/category-edit-custom-script.php b/temp/update_build/tmp_0.275/admin/templates/shop-category/category-edit-custom-script.php deleted file mode 100644 index bd2a72d..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-category/category-edit-custom-script.php +++ /dev/null @@ -1,53 +0,0 @@ - diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-category/category-edit.php b/temp/update_build/tmp_0.275/admin/templates/shop-category/category-edit.php deleted file mode 100644 index 9053b6c..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-category/category-edit.php +++ /dev/null @@ -1,209 +0,0 @@ - - - -
-
    -
  • Treść
  • -
  • Ustawienia
  • -
  • SEO
  • -
-
-
-
-
    - languages ) ): foreach ( $this -> languages as $lg ):?> - -
  • ';?>
  • - - -
-
- languages ) ): foreach ( $this -> languages as $lg ):?> - -
- 'Nazwa kategorii', - 'name' => 'title[' . $lg['id'] . ']', - 'id' => 'title_' . $lg['id'], - 'value' => $this -> category[ 'languages' ][ $lg['id'] ]['title'], - 'inline' => true - ) - );?> - 'Opis kategorii', - 'name' => 'text[' . $lg['id'] . ']', - 'id' => 'text_' . $lg['id'], - 'value' => $this -> category['languages'][ $lg['id'] ]['text'], - 'inline' => true - ) - );?> - 'Opis kategorii (rozwinięcie)', - 'name' => 'text_hidden[' . $lg['id'] . ']', - 'id' => 'text_hidden_' . $lg['id'], - 'value' => $this -> category['languages'][ $lg['id'] ]['text_hidden'], - 'inline' => true - ) - );?> - 'Dodatkowy tekst (nad produktami)', - 'name' => 'additional_text[' . $lg['id'] . ']', - 'id' => 'additional_text_' . $lg['id'], - 'value' => $this -> category['languages'][ $lg['id'] ]['additional_text'], - 'inline' => true - ] );?> - -
- - -
-
-
-
-
- 'Aktywna', - 'name' => 'status', - 'checked' => $this -> category['status'] == 1 or !$this -> category['id'] ? true : false - ) - );?> - 'Sortowanie produktów', - 'name' => 'sort_type', - 'id' => 'sort_type', - 'values' => is_array( $this -> sort_types ) ? $this -> sort_types : [], - 'value' => $this -> category['sort_type'] - ] - );?> - 'Wyświetlić podkategorie', - 'name' => 'view_subcategories', - 'checked' => $this -> category['view_subcategories'] == 1 ? true : false - ) - );?> -
-
-
-
    - languages ) ): foreach ( $this -> languages as $lg ):?> - -
  • ';?>
  • - - -
-
- languages ) ): foreach ( $this -> languages as $lg ):?> - -
- 'Link SEO', - 'name' => 'seo_link[' . $lg['id'] . ']', - 'id' => 'seo_link_' . $lg['id'], - 'value' => $this -> category['languages' ][ $lg['id'] ]['seo_link'], - 'icon_content' => 'generuj', - 'icon_js' => 'generate_seo_links( "' . $lg['id'] . '", $( "#title_' . $lg['id'] . '" ).val(), ' . (int)$this -> category['id'] . ' );' - ) - );?> - 'Tytuł kategorii (h1)', - 'name' => 'category_title[' . $lg['id'] . ']', - 'id' => 'category_title_' . $lg['id'], - 'value' => $this -> category['languages' ][ $lg['id'] ]['category_title'] - ) - );?> - 'Meta title', - 'name' => 'meta_title[' . $lg['id'] . ']', - 'id' => 'meta_title_' . $lg['id'], - 'value' => $this -> category['languages'][ $lg['id'] ]['meta_title'] - ) - );?> - 'Meta description', - 'name' => 'meta_description[' . $lg['id'] . ']', - 'id' => 'meta_description_' . $lg['id'], - 'value' => $this -> category['languages'][ $lg['id'] ]['meta_description'] - ) - );?> - 'Meta keywords', - 'name' => 'meta_keywords[' . $lg['id'] . ']', - 'id' => 'meta_keywords_' . $lg['id'], - 'value' => $this -> category['languages'][ $lg['id'] ]['meta_keywords'] - ) - );?> - 'Blokuj indeksację', - 'name' => 'noindex[' . $lg['id'] . ']', - 'id' => 'noindex_' . $lg['id'], - 'values' => array( - 0 => 'nie', 1 => 'tak' - ), - 'value' => $this -> category['languages'][ $lg['id'] ]['noindex'] == 1 ? 1 : 0 - ) - );?> -
- - -
-
-
-
-
-
- id = 'category-edit'; -$grid -> gdb_opt = $gdb; -$grid -> include_plugins = true; -$grid -> title = 'Edycja kategorii'; -$grid -> fields = [ - [ - 'db' => 'id', - 'type' => 'hidden', - 'value' => $this -> category['id'] - ], - [ - 'db' => 'parent_id', - 'type' => 'hidden', - 'value' => $this -> category['id'] ? $this -> category['parent_id'] : $this -> pid - ] - ]; -$grid -> actions = [ - 'save' => [ 'url' => '/admin/shop_category/save/', 'back_url' => '/admin/shop_category/view_list/' ], - 'cancel' => [ 'url' => '/admin/shop_category/view_list/' ] - ]; -$grid -> external_code = $out; -$grid -> persist_edit = true; -$grid -> id_param = 'id'; - -echo $grid -> draw(); -?> - - - diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-category/category-products-custom-script.php b/temp/update_build/tmp_0.275/admin/templates/shop-category/category-products-custom-script.php deleted file mode 100644 index 3a43fa0..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-category/category-products-custom-script.php +++ /dev/null @@ -1,62 +0,0 @@ - - - diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-category/category-products.php b/temp/update_build/tmp_0.275/admin/templates/shop-category/category-products.php deleted file mode 100644 index 7885fd8..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-category/category-products.php +++ /dev/null @@ -1,37 +0,0 @@ - -
    - products ) ) foreach ( $this -> products as $product ) - { - ?> -
  1. -
    -
  2. - -
- gdb_opt = $gdb; -$grid -> include_plugins = true; -$grid -> default_buttons = false; -$grid -> external_code = $out; -$grid -> title = 'Lista produktów'; -$grid -> buttons = [ - [ - 'label' => 'Wstecz', - 'url' => '/admin/shop_category/view_list/', - 'icon' => 'fa-reply', - 'class' => 'btn-dark' - ] - ]; -echo $grid -> draw(); -?> - $this -> category_id ] ); ?> \ No newline at end of file diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-category/subcategories-list.php b/temp/update_build/tmp_0.275/admin/templates/shop-category/subcategories-list.php deleted file mode 100644 index 739fe25..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-category/subcategories-list.php +++ /dev/null @@ -1,36 +0,0 @@ - categories ) ):?> -
    - categories as $category ):?> -
  1. -
    - - ';?> - dlang]['title'];?> - -
    - ( new \Domain\Category\CategoryRepository( $GLOBALS['mdb'] ) )->subcategories( $category['id'] ), - 'level' => $this -> level + 1, - 'dlang' => $this -> dlang - ] );?> -
  2. - -
- \ No newline at end of file diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-category/subcategory-browse-list.php b/temp/update_build/tmp_0.275/admin/templates/shop-category/subcategory-browse-list.php deleted file mode 100644 index 1fafb54..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-category/subcategory-browse-list.php +++ /dev/null @@ -1,25 +0,0 @@ - categories ) ):?> -
    - categories as $category ):?> -
  1. -
    - - ';?> - dlang]['title'];?> - -
    - ( new \Domain\Category\CategoryRepository( $GLOBALS['mdb'] ) )->subcategories( $category['id'] ), - 'level' => $this -> level + 1, - 'dlang' => $this -> dlang - ] );?> -
  2. - -
- \ No newline at end of file diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-product/mass-edit.php b/temp/update_build/tmp_0.275/admin/templates/shop-product/mass-edit.php deleted file mode 100644 index 0823132..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-product/mass-edit.php +++ /dev/null @@ -1,114 +0,0 @@ - - - - - -
-
- Masowa edycja produktów -
-
- - -
-
-
- -
-
-
- - - - -
-
-
-
-
-
-
-
- products ) ): foreach ( $this->products as $key => $product ): ?> -
- - -
- -
-
- -
-
-
-
- - diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-product/product-edit.php b/temp/update_build/tmp_0.275/admin/templates/shop-product/product-edit.php deleted file mode 100644 index 8d1519c..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-product/product-edit.php +++ /dev/null @@ -1,1348 +0,0 @@ - - - - $this -> user['id'], - 'expires' => time() + 60*20 -]; - -$_SESSION['rfm_akey'] = bin2hex(random_bytes(16)); -$_SESSION['rfm_akey_expires'] = time() + 20*60; -$_SESSION['can_use_rfm'] = true; -$rfmAkeyJS = $_SESSION['rfm_akey']; - -ob_start(); -?> - -
-
    -
  • Opis
  • -
  • Zakładki
  • -
  • Cena
  • -
  • Magazyn
  • -
  • Ustawienia
  • -
  • SEO
  • -
  • Wyświetlanie
  • -
  • Galeria
  • -
  • Załączniki
  • -
  • Produkty powiązane
  • -
  • XML
  • -
  • Dodatkowe pola
  • -
  • GPSR
  • -
-
-
-
-
    - languages)) : foreach ($this->languages as $lg) : ?> - -
  • '; ?>
  • - - -
-
- languages)) : foreach ($this->languages as $lg) : ?> - languages)) - foreach ($this->languages as $lg_tmp) - { - if ($lg_tmp['id'] != $lg['id']) - $languages[$lg_tmp['id']] = $lg_tmp['name']; - } - ?> - -
- 'Wyświetlaj treść z wersji', - 'name' => 'copy_from[' . $lg['id'] . ']', - 'values' => $languages, - 'value' => $this->product['languages'][$lg['id']]['copy_from'], - ) - ); - ?> - 'Nazwa', - 'name' => 'name[' . $lg['id'] . ']', - 'id' => 'name_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['name'], - 'inline' => true - ) - ); - ?> - 'Komunikat gdy stan magazynowy równy 0', - 'name' => 'warehouse_message_zero[' . $lg['id'] . ']', - 'id' => 'warehouse_message_zero_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['warehouse_message_zero'], - 'inline' => true - ) - ); - ?> - 'Komunikat gdy stan magazynowy większy niż 0', - 'name' => 'warehouse_message_nonzero[' . $lg['id'] . ']', - 'id' => 'warehouse_message_nonzero_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['warehouse_message_nonzero'], - 'inline' => true - ) - ); - ?> - 'Krótki opis', - 'name' => 'short_description[' . $lg['id'] . ']', - 'id' => 'short_description_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['short_description'], - 'inline' => true - ) - ); - ?> - 'Opis', - 'name' => 'description[' . $lg['id'] . ']', - 'id' => 'description_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['description'], - 'inline' => true - ) - ); - ?> - -
- - -
-
-
-
-
-
-
    - languages)) : foreach ($this->languages as $lg) : ?> - -
  • '; ?>
  • - - -
-
- languages)) : foreach ($this->languages as $lg) : ?> - languages)) - foreach ($this->languages as $lg_tmp) - { - if ($lg_tmp['id'] != $lg['id']) - $languages[$lg_tmp['id']] = $lg_tmp['name']; - } - ?> - -
- 'Nazwa zakładki (1)', - 'name' => 'tab_name_1[' . $lg['id'] . ']', - 'id' => 'tab_name_1_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['tab_name_1'], - 'inline' => true - ) - ); - ?> - 'Zawartość zakładki (1)', - 'name' => 'tab_description_1[' . $lg['id'] . ']', - 'id' => 'tab_description_1_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['tab_description_1'], - 'inline' => true - ) - ); - ?> - 'Nazwa zakładki (2)', - 'name' => 'tab_name_2[' . $lg['id'] . ']', - 'id' => 'tab_name_2_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['tab_name_2'], - 'inline' => true - ) - ); - ?> - 'Zawartość zakładki (2)', - 'name' => 'tab_description_2[' . $lg['id'] . ']', - 'id' => 'tab_description_2_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['tab_description_2'], - 'inline' => true - ) - ); - ?> - -
- - -
-
-
-
-
- 'VAT (%)', - 'name' => 'vat', - 'id' => 'vat', - 'class' => 'int-format', - 'value' => $this->product['id'] ? $this->product['vat'] : 23, - 'onchange' => 'calculate_price_brutto(); return false;' - ) - ); - ?> - 'Cena netto (PLN)', - 'name' => 'price_netto', - 'id' => 'price_netto', - 'class' => 'number-format', - 'value' => $this->product['price_netto'], - 'onchange' => 'calculate_price_brutto(); return false;' - ) - ); - ?> - 'Cena brutto (PLN)', - 'name' => 'price_brutto', - 'id' => 'price_brutto', - 'class' => 'number-format', - 'value' => $this->product['price_brutto'], - 'onchange' => 'calculate_price_netto(); return false;' - ) - ); - ?> - 'Promocyjna cena netto (PLN)', - 'name' => 'price_netto_promo', - 'id' => 'price_netto_promo', - 'class' => 'number-format', - 'value' => $this->product['price_netto_promo'], - 'onchange' => 'calculate_price_brutto_promo(); return false;' - ) - ); - ?> - 'Promocyjna cena brutto (PLN)', - 'name' => 'price_brutto_promo', - 'id' => 'price_brutto_promo', - 'class' => 'number-format', - 'value' => $this->product['price_brutto_promo'], - 'onchange' => 'calculate_price_netto_promo(); return false;' - ) - ); - ?> - - units as $unit) - $units[$unit['id']] = $unit['text']; - ?> - 'Jednostka miary', - 'name' => 'product_unit', - 'id' => 'product_unit', - 'values' => $units, - 'value' => $this->product['product_unit_id'] - ]); ?> - 'Waga/pojemność', - 'name' => 'weight', - 'id' => 'weight', - 'class' => 'number-format', - 'value' => $this->product['weight'] - ]); ?> -
-
- 'Stan magazynowy', - 'name' => 'quantity', - 'id' => 'quantity', - 'class' => 'int-format', - 'value' => $this->product['quantity'] - ]); - ?> - 'Pozwól zamawiać gdy stan 0', - 'name' => 'stock_0_buy', - 'checked' => $this->product['stock_0_buy'] == 1 ? true : false - ]); - ?> - 'Współczynnik WP', - 'name' => 'wp', - 'id' => 'wp', - 'class' => 'number-format', - 'value' => $this->product['wp'] - ]); - ?> - 'Kod SKU', - 'name' => 'sku', - 'id' => 'sku', - 'value' => $this->product['sku'], - 'icon_content' => 'generuj', - 'icon_js' => 'generate_sku_code( ' . (int)$this->product['id'] . ' );' - ]); ?> - 'EAN', - 'name' => 'ean', - 'id' => 'ean', - 'value' => $this->product['ean'] - ]); ?> -
-
- 'Widoczny', - 'name' => 'status', - 'checked' => $this->product['status'] == 1 or !$this->product['id'] ? true : false - ]); - ?> - 'Promowany', - 'name' => 'promoted', - 'checked' => $this->product['promoted'] == 1 ? true : false - ]); - ?> - 'Nowość do dnia', - 'name' => 'new_to_date', - 'id' => 'new_to_date', - 'class' => 'date', - 'value' => $this->product['new_to_date'] - ]); - ?> - 'Wyświetlaj pole na dodatkową wiadomość', - 'name' => 'additional_message', - 'checked' => $this->product['additional_message'] == 1 ? true : false - ]); - ?> - 'Dodatkowa wiadomość jest wymagana', - 'name' => 'additional_message_required', - 'checked' => $this->product['additional_message_required'] == 1 ? true : false - ]); - ?> - 'Dodatkowa wiadomość (treść komunikatu)', - 'name' => 'additional_message_text', - 'id' => 'additional_message_text', - 'value' => $this->product['additional_message_text'] - ]); - ?> -
-
-
-
    - languages)) : foreach ($this->languages as $lg) : ?> - -
  • '; ?>
  • - - -
-
- languages)) : foreach ($this->languages as $lg) : ?> - -
- 'Link SEO', - 'name' => 'seo_link[' . $lg['id'] . ']', - 'id' => 'seo_link_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['seo_link'], - 'icon_content' => 'generuj', - 'icon_js' => 'generate_seo_links( "' . $lg['id'] . '", $( "#name_' . $lg['id'] . '" ).val(), ' . (int)$this->product['id'] . ' );' - ) - ); - ?> - 'Meta title', - 'name' => 'meta_title[' . $lg['id'] . ']', - 'id' => 'meta_title_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['meta_title'] - ]); ?> - 'Meta description', - 'name' => 'meta_description[' . $lg['id'] . ']', - 'id' => 'meta_description_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['meta_description'] - ) - ); - ?> - 'Meta keywords', - 'name' => 'meta_keywords[' . $lg['id'] . ']', - 'id' => 'meta_keywords_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['meta_keywords'] - ) - ); - ?> - 'Canonical', - 'name' => 'canonical[' . $lg['id'] . ']', - 'id' => 'canonical_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['canonical'] - ]); ?> -
- - -
-
-
-
-
- layouts)) : foreach ($this->layouts as $layout) : - $layouts[$layout['id']] = $layout['name']; - endforeach; - endif; - ?> - 'Szablon', - 'name' => 'layout_id', - 'id' => 'layout_id', - 'values' => $layouts, - 'value' => $this->product['layout_id'] - ]); - ?> -
- -
- -
-
-
-
-
-
    - product['images'])) : foreach ($this->product['images'] as $img) : - ?> -
  • - - - - - -
  • - -
-
You browser doesn't have Flash installed.
-
-
-
    - product['files'])) : foreach ($this->product['files'] as $file) : - - if ($file['name']) - $name = $file['name']; - else - { - $name = explode('/', $file['src']); - $name = $name[count($name) - 1]; - } - ?> -
  • -
    - - - - -
    -
  • - -
-
You browser doesn't have Flash installed.
-
-
-
- -
- -
-
-
- -
- -
-
-
-
-
- -
- - languages)) : foreach ($this->languages as $lg) : ?> - -
- -
- -
-
- - -
-
- 'Custom label 0', - 'name' => 'custom_label_0', - 'id' => 'custom_label_0', - 'value' => $this->product['custom_label_0'] - ]); - ?> - 'Custom label 1', - 'name' => 'custom_label_1', - 'id' => 'custom_label_1', - 'value' => $this->product['custom_label_1'] - ]); - ?> - 'Custom label 2', - 'name' => 'custom_label_2', - 'id' => 'custom_label_2', - 'value' => $this->product['custom_label_2'] - ]); - ?> - 'Custom label 3', - 'name' => 'custom_label_3', - 'id' => 'custom_label_3', - 'value' => $this->product['custom_label_3'] - ]); - ?> - 'Custom label 4', - 'name' => 'custom_label_4', - 'id' => 'custom_label_4', - 'value' => $this->product['custom_label_4'] - ]); - ?> -
-
- dodaj niestandardowe pole -
- product['custom_fields'] ) ) : foreach ( $this->product['custom_fields'] as $field ):?> - -
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
- usuń -
-
-
- -
-
-
- producers as $producer) - $producers[$producer['id']] = $producer['name']; - ?> - 'Producent', - 'name' => 'producer_id', - 'id' => 'producer_id', - 'values' => $producers, - 'value' => $this->product['producer_id'] - ]); ?> -
-
    - languages ) ): foreach ( $this -> languages as $lg ):?> - -
  • '; ?>
  • - - -
-
- languages ) ): foreach ( $this -> languages as $lg ):?> - -
- 'Informacje o bezpieczeństwie ('.$lg['name'].')', - 'name' => 'security_information[' . $lg['id'] . ']', - 'id' => 'security_information_' . $lg['id'], - 'value' => $this->product['languages'][$lg['id']]['security_information'] - ] );?> -
- - - -
-
-
-
-
-
-id = 'product-edit'; -$grid->gdb_opt = $gdb; -$grid->include_plugins = true; -$grid->title = $this->product['id'] ? 'Edycja produktu: ' . $this->product['languages'][\front\factory\Languages::default_language()]['name'] . '' : 'Edycja produktu'; -$grid->fields = [ - [ - 'db' => 'id', - 'type' => 'hidden', - 'value' => $this->product['id'] - ] -]; -$grid->actions = [ - 'save' => ['url' => '/admin/shop_product/save/', 'back_url' => '/admin/shop_product/view_list/'], - 'cancel' => ['url' => '/admin/shop_product/view_list/'] -]; -$grid->buttons = [ - [ - 'label' => 'Podgląd', - 'id' => 'product-preview', - 'url' => '#', - 'icon' => 'fa-search', - 'class' => 'btn-primary' - ] -]; -$grid->external_code = $out; -$grid->persist_edit = true; -$grid->id_param = 'id'; - -echo $grid->draw(); -?> - - - - - - - - - - - - - - - - - - diff --git a/temp/update_build/tmp_0.275/admin/templates/shop-product/subcategories-list.php b/temp/update_build/tmp_0.275/admin/templates/shop-product/subcategories-list.php deleted file mode 100644 index 5c7f796..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/shop-product/subcategories-list.php +++ /dev/null @@ -1,24 +0,0 @@ - categories ) ):?> -
    - categories as $category ):?> -
  1. -
    - - ';?> - product_categories ) and in_array( $category[ 'id' ], $this -> product_categories ) ):?>checked="checked" /> - dlang ][ 'title' ];?> -
    - ( new \Domain\Category\CategoryRepository( $GLOBALS['mdb'] ) )->subcategories( $category[ 'id' ] ), - 'product_categories' => $this -> product_categories, - 'dlang' => $this -> dlang, - 'name' => $this -> name - ] ); - ?> -
  2. - -
- \ No newline at end of file diff --git a/temp/update_build/tmp_0.275/admin/templates/site/main-layout.php b/temp/update_build/tmp_0.275/admin/templates/site/main-layout.php deleted file mode 100644 index e090e08..0000000 --- a/temp/update_build/tmp_0.275/admin/templates/site/main-layout.php +++ /dev/null @@ -1,273 +0,0 @@ - - - - - shopPro - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- -
-
-
-
-
- -
-
- -
-
- -
-
-
- - - -
-
-
- -
-
- content;?> -
-
-
-
-
- - - diff --git a/temp/update_build/tmp_0.275/autoload/admin/Controllers/ShopCategoryController.php b/temp/update_build/tmp_0.275/autoload/admin/Controllers/ShopCategoryController.php deleted file mode 100644 index 61d70b5..0000000 --- a/temp/update_build/tmp_0.275/autoload/admin/Controllers/ShopCategoryController.php +++ /dev/null @@ -1,163 +0,0 @@ -repository = $repository; - $this->languagesRepository = $languagesRepository; - } - - public function view_list(): string - { - return \Tpl::view('shop-category/categories-list', [ - 'categories' => $this->repository->subcategories(null), - 'level' => 0, - 'dlang' => \front\factory\Languages::default_language(), - ]); - } - - public function list(): string - { - return $this->view_list(); - } - - public function category_edit(): string - { - return \Tpl::view('shop-category/category-edit', [ - 'category' => $this->repository->categoryDetails(\S::get('id')), - 'pid' => \S::get('pid'), - 'languages' => $this->languagesRepository->languagesList(), - 'sort_types' => $this->repository->sortTypes(), - ]); - } - - public function edit(): string - { - return $this->category_edit(); - } - - public function save(): void - { - $response = [ - 'status' => 'error', - 'msg' => 'Podczas zapisywania kategorii wystąpił błąd. Proszę spróbować ponownie.', - ]; - - $values = json_decode((string)\S::get('values'), true); - if (is_array($values)) { - $savedId = $this->repository->save($values); - if (!empty($savedId)) { - $response = [ - 'status' => 'ok', - 'msg' => 'Kategoria została zapisana.', - 'id' => (int)$savedId, - ]; - } - } - - echo json_encode($response); - exit; - } - - public function category_delete(): void - { - if ($this->repository->categoryDelete(\S::get('id'))) { - \S::set_message('Kategoria została usunięta.'); - } else { - \S::alert('Podczas usuwania kategorii wystąpił błąd. Aby usunąć kategorię nie może ona posiadać przypiętych podkategorii.'); - } - - header('Location: /admin/shop_category/view_list/'); - exit; - } - - public function delete(): void - { - $this->category_delete(); - } - - public function category_products(): string - { - return \Tpl::view('shop-category/category-products', [ - 'category_id' => \S::get('id'), - 'products' => $this->repository->categoryProducts((int)\S::get('id')), - ]); - } - - public function products(): string - { - return $this->category_products(); - } - - public function category_url_browser(): void - { - echo \Tpl::view('shop-category/category-browse-list', [ - 'categories' => $this->repository->subcategories(null), - 'level' => 0, - 'dlang' => \front\factory\Languages::default_language(), - ]); - exit; - } - - public function save_categories_order(): void - { - $response = [ - 'status' => 'error', - 'msg' => 'Podczas zapisywania kolejności kategorii wystąpił błąd. Proszę spróbować ponownie.', - ]; - - if ( $this->repository->saveCategoriesOrder( \S::get( 'categories' ) ) ) { - $response = [ 'status' => 'ok' ]; - } - - echo json_encode( $response ); - exit; - } - - public function save_products_order(): void - { - $response = [ - 'status' => 'error', - 'msg' => 'Podczas zapisywania kolejności wyświetlania produktów wystąpił błąd. Proszę spróbować ponownie.', - ]; - - if ( $this->repository->saveProductOrder( \S::get( 'category_id' ), \S::get( 'products' ) ) ) { - $response = [ 'status' => 'ok' ]; - } - - echo json_encode( $response ); - exit; - } - - public function cookie_categories(): void - { - $categoryId = (string) \S::get( 'category_id' ); - if ( $categoryId === '' ) { - echo json_encode( [ 'status' => 'error' ] ); - exit; - } - - $array = []; - if ( isset( $_COOKIE['cookie_categories'] ) ) { - $tmp = @unserialize( (string) $_COOKIE['cookie_categories'] ); - if ( is_array( $tmp ) ) { - $array = $tmp; - } - } - - $array[$categoryId] = isset( $array[$categoryId] ) && (int) $array[$categoryId] === 1 ? 0 : 1; - - setcookie( 'cookie_categories', serialize( $array ), time() + 3600 * 24 * 365, '/' ); - - echo json_encode( [ 'status' => 'ok' ] ); - exit; - } -} diff --git a/temp/update_build/tmp_0.275/autoload/admin/Controllers/ShopProductController.php b/temp/update_build/tmp_0.275/autoload/admin/Controllers/ShopProductController.php deleted file mode 100644 index 3cb3372..0000000 --- a/temp/update_build/tmp_0.275/autoload/admin/Controllers/ShopProductController.php +++ /dev/null @@ -1,73 +0,0 @@ -repository = $repository; - } - - /** - * Widok masowej edycji produktów. - */ - public function mass_edit(): string - { - $categoryRepository = new CategoryRepository( $GLOBALS['mdb'] ); - - return \Tpl::view( 'shop-product/mass-edit', [ - 'products' => $this->repository->allProductsForMassEdit(), - 'categories' => $categoryRepository->subcategories( null ), - 'dlang' => \front\factory\Languages::default_language() - ] ); - } - - /** - * AJAX: zastosowanie rabatu procentowego na zaznaczonych produktach. - */ - public function mass_edit_save(): void - { - $discountPercent = \S::get( 'discount_percent' ); - $products = \S::get( 'products' ); - - if ( $discountPercent != '' && $products && is_array( $products ) && count( $products ) > 0 ) { - $productId = (int) $products[0]; - $result = $this->repository->applyDiscountPercent( $productId, (float) $discountPercent ); - - if ( $result !== null ) { - echo json_encode( [ - 'status' => 'ok', - 'price_brutto_promo' => $result['price_brutto_promo'], - 'price_brutto' => $result['price_brutto'] - ] ); - exit; - } - } - - echo json_encode( [ 'status' => 'error' ] ); - exit; - } - - /** - * AJAX: pobranie ID produktów z danej kategorii. - */ - public function get_products_by_category(): void - { - $categoryId = (int) \S::get( 'category_id' ); - $products = $this->repository->getProductsByCategory( $categoryId ); - - echo json_encode( [ 'status' => 'ok', 'products' => $products ] ); - exit; - } -} diff --git a/temp/update_build/tmp_0.275/autoload/admin/class.Site.php b/temp/update_build/tmp_0.275/autoload/admin/class.Site.php deleted file mode 100644 index 2d6c1ad..0000000 --- a/temp/update_build/tmp_0.275/autoload/admin/class.Site.php +++ /dev/null @@ -1,493 +0,0 @@ - $user['login'], - 'ts' => time() - ]; - - $json = json_encode($payloadArr, JSON_UNESCAPED_SLASHES); - $sig = hash_hmac('sha256', $json, self::APP_SECRET_KEY); - $payload = base64_encode($json . '.' . $sig); - - setcookie( $cookie_name, $payload, [ - 'expires' => time() + (86400 * 14), - 'path' => '/', - 'domain' => $domain, - 'secure' => true, - 'httponly' => true, - 'samesite' => 'Lax', - ]); - } - } - - public static function special_actions() - { - global $mdb; - - $sa = \S::get('s-action'); - $domain = preg_replace('/^www\./', '', $_SERVER['SERVER_NAME']); - $cookie_name = 'admin_remember_' . str_replace( '.', '-', $domain ); - $users = new \Domain\User\UserRepository($mdb); - - switch ($sa) - { - case 'user-logon': - { - $login = \S::get('login'); - $pass = \S::get('password'); - - $result = $users->logon($login, $pass); - - if ( $result == 1 ) - { - $user = $users->details($login); - - if ( $user['twofa_enabled'] == 1 ) - { - \S::set_session( 'twofa_pending', [ - 'uid' => (int)$user['id'], - 'login' => $login, - 'remember' => (bool)\S::get('remember'), - 'started' => time(), - ] ); - - if ( !$users->sendTwofaCode( (int)$user['id'] ) ) - { - \S::alert('Nie udało się wysłać kodu 2FA. Spróbuj ponownie.'); - \S::delete_session('twofa_pending'); - header('Location: /admin/'); - exit; - } - - header('Location: /admin/user/twofa/'); - exit; - } - else - { - $user = $users->details($login); - - self::finalize_admin_login( - $user, - $domain, - $cookie_name, - (bool)\S::get('remember') - ); - - header('Location: /admin/articles/list/'); - exit; - } - } - else - { - if ($result == -1) - { - \S::alert('Z powodu 5 nieudanych prób Twoje konto zostało zablokowane.'); - } - else - { - \S::alert('Podane hasło jest nieprawidłowe lub użytkownik nie istnieje.'); - } - header('Location: /admin/'); - exit; - } - } - break; - - case 'user-2fa-verify': - { - $pending = \S::get_session('twofa_pending'); - if ( !$pending || empty( $pending['uid'] ) ) { - \S::alert('Sesja 2FA wygasła. Zaloguj się ponownie.'); - header('Location: /admin/'); - exit; - } - - $code = trim((string)\S::get('twofa')); - if (!preg_match('/^\d{6}$/', $code)) - { - \S::alert('Nieprawidłowy format kodu.'); - header('Location: /admin/user/twofa/'); - exit; - } - - $ok = $users->verifyTwofaCode((int)$pending['uid'], $code); - if (!$ok) - { - \S::alert('Błędny lub wygasły kod.'); - header('Location: /admin/user/twofa/'); - exit; - } - - // 2FA OK - finalna sesja - $user = $users->details($pending['login']); - - self::finalize_admin_login( - $user, - $domain, - $cookie_name, - $pending['remember'] ? true : false - ); - - header('Location: /admin/articles/list/'); - exit; - } - break; - - case 'user-2fa-resend': - { - $pending = \S::get_session('twofa_pending'); - if (!$pending || empty($pending['uid'])) - { - \S::alert('Sesja 2FA wygasła. Zaloguj się ponownie.'); - header('Location: /admin/'); - exit; - } - - if (!$users->sendTwofaCode((int)$pending['uid'], true)) - { - \S::alert('Kod można wysłać ponownie po krótkiej przerwie.'); - } - else - { - \S::alert('Nowy kod został wysłany.'); - } - header('Location: /admin/user/twofa/'); - exit; - } - break; - - case 'user-logout': - { - setcookie($cookie_name, "", [ - 'expires' => time() - 86400, - 'path' => '/', - 'domain' => $domain, - 'secure' => true, - 'httponly' => true, - 'samesite' => 'Lax', - ]); - \S::delete_session('twofa_pending'); - session_destroy(); - header('Location: /admin/'); - exit; - } - break; - } - } - - /** - * Mapa nowych kontrolerów: module => fabryka kontrolera (DI) - * Przy migracji kolejnego kontrolera - dodaj wpis tutaj - */ - private static $newControllers = []; - - /** - * Zwraca mapę fabryk kontrolerów (inicjalizacja runtime) - */ - private static function getControllerFactories(): array - { - if ( !empty( self::$newControllers ) ) - return self::$newControllers; - - self::$newControllers = [ - 'Articles' => function() { - global $mdb; - - return new \admin\Controllers\ArticlesController( - new \Domain\Article\ArticleRepository( $mdb ), - new \Domain\Languages\LanguagesRepository( $mdb ), - new \Domain\Layouts\LayoutsRepository( $mdb ), - new \Domain\Pages\PagesRepository( $mdb ) - ); - }, - 'ArticlesArchive' => function() { - global $mdb; - - return new \admin\Controllers\ArticlesArchiveController( - new \Domain\Article\ArticleRepository( $mdb ) - ); - }, - 'Banners' => function() { - global $mdb; - - return new \admin\Controllers\BannerController( - new \Domain\Banner\BannerRepository( $mdb ), - new \Domain\Languages\LanguagesRepository( $mdb ) - ); - }, - 'Settings' => function() { - global $mdb; - - return new \admin\Controllers\SettingsController( - new \Domain\Settings\SettingsRepository( $mdb ), - new \Domain\Languages\LanguagesRepository( $mdb ) - ); - }, - 'ProductArchive' => function() { - global $mdb; - - return new \admin\Controllers\ProductArchiveController( - new \Domain\Product\ProductRepository( $mdb ) - ); - }, - // Alias dla starego modułu /admin/archive/list/ - 'Archive' => function() { - global $mdb; - - return new \admin\Controllers\ProductArchiveController( - new \Domain\Product\ProductRepository( $mdb ) - ); - }, - 'Dictionaries' => function() { - global $mdb; - - return new \admin\Controllers\DictionariesController( - new \Domain\Dictionaries\DictionariesRepository( $mdb ), - new \Domain\Languages\LanguagesRepository( $mdb ) - ); - }, - 'Filemanager' => function() { - return new \admin\Controllers\FilemanagerController(); - }, - 'Users' => function() { - global $mdb; - - return new \admin\Controllers\UsersController( - new \Domain\User\UserRepository( $mdb ) - ); - }, - 'Languages' => function() { - global $mdb; - - return new \admin\Controllers\LanguagesController( - new \Domain\Languages\LanguagesRepository( $mdb ) - ); - }, - 'Layouts' => function() { - global $mdb; - - return new \admin\Controllers\LayoutsController( - new \Domain\Layouts\LayoutsRepository( $mdb ), - new \Domain\Languages\LanguagesRepository( $mdb ) - ); - }, - 'Newsletter' => function() { - global $mdb; - - return new \admin\Controllers\NewsletterController( - new \Domain\Newsletter\NewsletterRepository( - $mdb, - new \Domain\Settings\SettingsRepository( $mdb ) - ), - new \Domain\Newsletter\NewsletterPreviewRenderer() - ); - }, - 'Scontainers' => function() { - global $mdb; - - return new \admin\Controllers\ScontainersController( - new \Domain\Scontainers\ScontainersRepository( $mdb ), - new \Domain\Languages\LanguagesRepository( $mdb ) - ); - }, - 'ShopPromotion' => function() { - global $mdb; - - return new \admin\Controllers\ShopPromotionController( - new \Domain\Promotion\PromotionRepository( $mdb ) - ); - }, - 'ShopCoupon' => function() { - global $mdb; - - return new \admin\Controllers\ShopCouponController( - new \Domain\Coupon\CouponRepository( $mdb ) - ); - }, - 'ShopAttribute' => function() { - global $mdb; - - return new \admin\Controllers\ShopAttributeController( - new \Domain\Attribute\AttributeRepository( $mdb ), - new \Domain\Languages\LanguagesRepository( $mdb ) - ); - }, - 'ShopPaymentMethod' => function() { - global $mdb; - - return new \admin\Controllers\ShopPaymentMethodController( - new \Domain\PaymentMethod\PaymentMethodRepository( $mdb ) - ); - }, - 'ShopTransport' => function() { - global $mdb; - - return new \admin\Controllers\ShopTransportController( - new \Domain\Transport\TransportRepository( $mdb ), - new \Domain\PaymentMethod\PaymentMethodRepository( $mdb ) - ); - }, - 'Pages' => function() { - global $mdb; - - return new \admin\Controllers\PagesController( - new \Domain\Pages\PagesRepository( $mdb ), - new \Domain\Languages\LanguagesRepository( $mdb ), - new \Domain\Layouts\LayoutsRepository( $mdb ) - ); - }, - 'Integrations' => function() { - global $mdb; - - return new \admin\Controllers\IntegrationsController( - new \Domain\Integrations\IntegrationsRepository( $mdb ) - ); - }, - 'ShopStatuses' => function() { - global $mdb; - - return new \admin\Controllers\ShopStatusesController( - new \Domain\ShopStatus\ShopStatusRepository( $mdb ) - ); - }, - 'ShopProductSets' => function() { - global $mdb; - - return new \admin\Controllers\ShopProductSetsController( - new \Domain\ProductSet\ProductSetRepository( $mdb ) - ); - }, - 'ShopProducer' => function() { - global $mdb; - - return new \admin\Controllers\ShopProducerController( - new \Domain\Producer\ProducerRepository( $mdb ), - new \Domain\Languages\LanguagesRepository( $mdb ) - ); - }, - 'ShopCategory' => function() { - global $mdb; - - return new \admin\Controllers\ShopCategoryController( - new \Domain\Category\CategoryRepository( $mdb ), - new \Domain\Languages\LanguagesRepository( $mdb ) - ); - }, - 'ShopProduct' => function() { - global $mdb; - - return new \admin\Controllers\ShopProductController( - new \Domain\Product\ProductRepository( $mdb ) - ); - }, - 'ShopClients' => function() { - global $mdb; - - return new \admin\Controllers\ShopClientsController( - new \Domain\Client\ClientRepository( $mdb ) - ); - }, - ]; - - return self::$newControllers; - } - - /** - * Tworzy instancję nowego kontrolera z Dependency Injection - */ - private static function createController( string $moduleName ) - { - global $mdb; - - $factories = self::getControllerFactories(); - if ( !isset( $factories[$moduleName] ) ) - return null; - - $factory = $factories[$moduleName]; - if ( !is_callable( $factory ) ) - return null; - - return $factory(); - } - - - public static function route() - { - $_SESSION['admin'] = true; - - if ( \S::get( 'p' ) ) - \S::set_session( 'p' , \S::get( 'p' ) ); - - $page = \S::get_session( 'p' ); - - // Budowanie nazwy modułu - $moduleName = ''; - $results = explode( '_', \S::get( 'module' ) ); - if ( is_array( $results ) ) foreach ( $results as $row ) - $moduleName .= ucfirst( $row ); - - $action = \S::get( 'action' ); - - // 1. Sprawdź czy istnieje nowy kontroler - $factories = self::getControllerFactories(); - if ( isset( $factories[$moduleName] ) ) - { - $controller = self::createController( $moduleName ); - if ( $controller ) - { - if ( method_exists( $controller, $action ) ) - { - return $controller->$action(); - } - - if ( $moduleName === 'ShopAttribute' ) - { - \S::alert( 'Nieprawidłowy adres url.' ); - return false; - } - } - - } - - // 2. Fallback na stary kontroler - $class = '\admin\controls\\' . $moduleName; - - if ( class_exists( $class ) and method_exists( new $class, $action ) ) - return call_user_func_array( array( $class, $action ), array() ); - else - { - \S::alert( 'Nieprawidłowy adres url.' ); - return false; - } - } - - static public function update() - { - global $mdb; - - if ( $results = $mdb -> select( 'pp_updates', [ 'name' ], [ 'done' => 0 ] ) ) - { - foreach ( $results as $row ) - { - $class = '\admin\factory\Update'; - $method = $row['name']; - - if ( class_exists( $class ) and method_exists( new $class, $method ) ) - call_user_func_array( array( $class, $method ), array() ); - } - } - } -} - diff --git a/temp/update_build/tmp_0.275/autoload/admin/controls/class.ShopProduct.php b/temp/update_build/tmp_0.275/autoload/admin/controls/class.ShopProduct.php deleted file mode 100644 index c7113d4..0000000 --- a/temp/update_build/tmp_0.275/autoload/admin/controls/class.ShopProduct.php +++ /dev/null @@ -1,373 +0,0 @@ - $val ) - { - if ( strpos( $key, 'attribute_' ) !== false ) - { - $attribute = explode( 'attribute_', $key ); - $attributes[ $attribute[1] ] = $val; - } - } - - if ( \admin\factory\ShopProduct::generate_permutation( (int) \S::get( 'product_id' ), $attributes ) ) - \S::alert( 'Kombinacje produktu zostały wygenerowane.' ); - - header( 'Location: /admin/shop_product/product_combination/product_id=' . (int) \S::get( 'product_id' ) ); - exit; - } - - //usunięcie kombinacji produktu - static public function delete_combination() - { - if ( \admin\factory\ShopProduct::delete_combination( (int)\S::get( 'combination_id' ) ) ) - \S::alert( 'Kombinacja produktu została usunięta' ); - else - \S::alert( 'Podczas usuwania kombinacji produktu wystąpił błąd. Proszę spróbować ponownie' ); - - header( 'Location: /admin/shop_product/product_combination/product_id=' . \S::get( 'product_id' ) ); - exit; - } - - static public function duplicate_product() - { - if ( \admin\factory\ShopProduct::duplicate_product( (int)\S::get( 'product-id' ), (int)\S::get( 'combination' ) ) ) - \S::set_message( 'Produkt został zduplikowany.' ); - else - \S::alert( 'Podczas duplikowania produktu wystąpił błąd. Proszę spróbować ponownie' ); - - header( 'Location: /admin/shop_product/view_list/' ); - exit; - } - - public static function image_delete() - { - $response = [ 'status' => 'error', 'msg' => 'Podczas usuwania zdjecia wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::delete_img( \S::get( 'image_id' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } - - public static function images_order_save() - { - if ( \admin\factory\ShopProduct::images_order_save( \S::get( 'product_id' ), \S::get( 'order' ) ) ) - echo json_encode( [ 'status' => 'ok', 'msg' => 'Produkt został zapisany.' ] ); - - exit; - } - - public static function image_alt_change() - { - $response = [ 'status' => 'error', 'msg' => 'Podczas zmiany atrybutu alt zdjęcia wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::image_alt_change( \S::get( 'image_id' ), \S::get( 'image_alt' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } - - // szybka zmiana statusu produktu - static public function change_product_status() { - - if ( \admin\factory\ShopProduct::change_product_status( (int)\S::get( 'product-id' ) ) ) - \S::set_message( 'Status produktu został zmieniony' ); - - header( 'Location: ' . $_SERVER['HTTP_REFERER'] ); - exit; - } - - // szybka zmiana google xml label - static public function product_change_custom_label() - { - $response = [ 'status' => 'error', 'msg' => 'Podczas zmiany google xml label wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::product_change_custom_label( (int) \S::get( 'product_id' ), \S::get( 'custom_label' ), \S::get( 'value' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } - - // szybka zmiana ceny promocyjnej - static public function product_change_price_brutto_promo() - { - $response = [ 'status' => 'error', 'msg' => 'Podczas zmiany ceny wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::product_change_price_brutto_promo( (int) \S::get( 'product_id' ), \S::get( 'price' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } - - // szybka zmiana ceny - static public function product_change_price_brutto() - { - $response = [ 'status' => 'error', 'msg' => 'Podczas zmiany ceny wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::product_change_price_brutto( (int) \S::get( 'product_id' ), \S::get( 'price' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } - - // pobierz bezpośredni url produktu - static public function ajax_product_url() - { - echo json_encode( [ 'url' => \shop\Product::getProductUrl( \S::get( 'product_id' ) ) ] ); - exit; - } - - // zapisanie produktu - public static function save() - { - $response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania produktu wystąpił błąd. Proszę spróbować ponownie.' ]; - $values = json_decode( \S::get( 'values' ), true ); - - if ( $id = \admin\factory\ShopProduct::save( - $values['id'], $values['name'], $values['short_description'], $values['description'], $values['status'], $values['meta_description'], $values['meta_keywords'], $values['seo_link'], - $values['copy_from'], $values['categories'], $values['price_netto'], $values['price_brutto'], $values['vat'], $values['promoted'], $values['warehouse_message_zero'], $values['warehouse_message_nonzero'], $values['tab_name_1'], - $values['tab_description_1'], $values['tab_name_2'], $values['tab_description_2'], $values['layout_id'], $values['products_related'], (int) $values['set'], $values['price_netto_promo'], $values['price_brutto_promo'], - $values['new_to_date'], $values['stock_0_buy'], $values['wp'], $values['custom_label_0'], $values['custom_label_1'], $values['custom_label_2'], $values['custom_label_3'], $values['custom_label_4'], $values['additional_message'], (int)$values['quantity'], $values['additional_message_text'], $values['additional_message_required'] == 'on' ? 1 : 0, $values['canonical'], $values['meta_title'], $values['producer_id'], $values['sku'], $values['ean'], $values['product_unit'], $values['weight'], $values['xml_name'], $values['custom_field_name'], $values['custom_field_required'], $values['security_information'], $values['custom_field_type'] - ) ) { - $response = [ 'status' => 'ok', 'msg' => 'Produkt został zapisany.', 'id' => $id ]; - } - - echo json_encode( $response ); - exit; - } - - // product_unarchive - static public function product_unarchive() - { - if ( \admin\factory\ShopProduct::product_unarchive( (int) \S::get( 'product_id' ) ) ) - \S::alert( 'Produkt został przywrócony z archiwum.' ); - else - \S::alert( 'Podczas przywracania produktu z archiwum wystąpił błąd. Proszę spróbować ponownie' ); - - header( 'Location: /admin/product_archive/list/' ); - exit; - } - - static public function product_archive() - { - if ( \admin\factory\ShopProduct::product_archive( (int) \S::get( 'product_id' ) ) ) - \S::alert( 'Produkt został przeniesiony do archiwum.' ); - else - \S::alert( 'Podczas przenoszenia produktu do archiwum wystąpił błąd. Proszę spróbować ponownie' ); - - header( 'Location: /admin/shop_product/view_list/' ); - exit; - } - - public static function product_delete() - { - if ( \admin\factory\ShopProduct::product_delete( (int) \S::get( 'id' ) ) ) - \S::set_message( 'Produkt został usunięty.' ); - else - \S::alert( 'Podczas usuwania produktu wystąpił błąd. Proszę spróbować ponownie' ); - header( 'Location: /admin/shop_product/view_list/' ); - exit; - } - - // edycja produktu - public static function product_edit() { - global $user, $mdb; - - if ( !$user ) { - header( 'Location: /admin/' ); - exit; - } - - \admin\factory\ShopProduct::delete_nonassigned_images(); - \admin\factory\ShopProduct::delete_nonassigned_files(); - - return \Tpl::view( 'shop-product/product-edit', [ - 'product' => \admin\factory\ShopProduct::product_details( (int) \S::get( 'id' ) ), - 'languages' => ( new \Domain\Languages\LanguagesRepository( $GLOBALS['mdb'] ) )->languagesList(), - 'categories' => ( new \Domain\Category\CategoryRepository( $GLOBALS['mdb'] ) )->subcategories( null ), - 'layouts' => self::layouts_for_product_edit( $mdb ), - 'products' => \admin\factory\ShopProduct::products_list(), - 'dlang' => \front\factory\Languages::default_language(), - 'sets' => \shop\ProductSet::sets_list(), - 'producers' => ( new \Domain\Producer\ProducerRepository( $mdb ) )->allProducers(), - 'units' => ( new \Domain\Dictionaries\DictionariesRepository( $mdb ) ) -> allUnits(), - 'user' => $user - ] ); - } - - private static function layouts_for_product_edit( $db ) - { - if ( class_exists( '\Domain\Layouts\LayoutsRepository' ) ) - { - $rows = ( new \Domain\Layouts\LayoutsRepository( $db ) ) -> listAll(); - return is_array( $rows ) ? $rows : []; - } - - return []; - } - - // ajax_load_products ARCHIVE - static public function ajax_load_products_archive() - { - echo json_encode( [ - 'status' => 'deprecated', - 'msg' => 'Endpoint nie jest juz wspierany. Uzyj /admin/product_archive/list/.', - 'redirect_url' => '/admin/product_archive/list/' - ] ); - exit; - } - - // ajax_load_products - static public function ajax_load_products() { - - $response = [ 'status' => 'error', 'msg' => 'Podczas ładowania produktów wystąpił błąd. Proszę spróbować ponownie.' ]; - - \S::set_session( 'products_list_current_page', \S::get( 'current_page' ) ); - \S::set_session( 'products_list_query', \S::get( 'query' ) ); - - if ( $products = \admin\factory\ShopProduct::ajax_products_list( \S::get_session( 'products_list_current_page' ), \S::get_session( 'products_list_query' ) ) ) { - $response = [ - 'status' => 'ok', - 'pagination_max' => ceil( $products['products_count'] / 10 ), - 'html' => \Tpl::view( 'shop-product/products-list-table', [ - 'products' => $products['products'], - 'current_page' => \S::get( 'current_page' ), - 'apilo_enabled' => \admin\factory\Integrations::apilo_settings( 'enabled' ), - 'show_xml_data' => \S::get_session( 'show_xml_data' ) - ] ) - ]; - } - - echo json_encode( $response ); - exit; - } - - static public function view_list() - { - $current_page = \S::get_session( 'products_list_current_page' ); - - if ( !$current_page ) { - $current_page = 1; - \S::set_session( 'products_list_current_page', $current_page ); - } - - $query = \S::get_session( 'products_list_query' ); - if ( $query ) { - $query_array = []; - parse_str( $query, $query_array ); - } - - if ( \S::get( 'show_xml_data' ) === 'true' ) { - \S::set_session( 'show_xml_data', true ); - } else if ( \S::get( 'show_xml_data' ) === 'false' ) { - \S::set_session( 'show_xml_data', false ); - } - - return \Tpl::view( 'shop-product/products-list', [ - 'current_page' => $current_page, - 'query_array' => $query_array, - 'pagination_max' => ceil( \admin\factory\ShopProduct::count_product() / 10 ), - 'apilo_enabled' => \admin\factory\Integrations::apilo_settings( 'enabled' ), - 'show_xml_data' => \S::get_session( 'show_xml_data' ), - 'shoppro_enabled' => \admin\factory\Integrations::shoppro_settings( 'enabled' ) - ] ); - } - - // - // KOMBINACJE PRODUKTU - // - - // zapisanie możliwości zakupu przy stanie 0 w kombinacji produktu - static public function product_combination_stock_0_buy_save() - { - \admin\factory\ShopProduct::product_combination_stock_0_buy_save( (int)\S::get( 'product_id' ), \S::get( 'stock_0_buy' ) ); - exit; - } - - // zapisanie sku w kombinacji produktu - static public function product_combination_sku_save() - { - \admin\factory\ShopProduct::product_combination_sku_save( (int)\S::get( 'product_id' ), \S::get( 'sku' ) ); - exit; - } - - // zapisanie ilości w kombinacji produktu - static public function product_combination_quantity_save() - { - \admin\factory\ShopProduct::product_combination_quantity_save( (int)\S::get( 'product_id' ), \S::get( 'quantity' ) ); - exit; - } - - // zapisanie ceny w kombinacji produktu - static public function product_combination_price_save() - { - \admin\factory\ShopProduct::product_combination_price_save( (int)\S::get( 'product_id' ), \S::get( 'price' ) ); - exit; - } - - //wyświetlenie kombinacji produktu - static public function product_combination() - { - global $mdb; - - return \Tpl::view( 'shop-product/product-combination', [ - 'product' => \admin\factory\ShopProduct::product_details( (int) \S::get( 'product_id' ) ), - 'attributes' => ( new \Domain\Attribute\AttributeRepository( $mdb ) ) -> getAttributesListForCombinations(), - 'default_language' => \front\factory\Languages::default_language(), - 'product_permutations' => \admin\factory\ShopProduct::get_product_permutations( (int) \S::get( 'product_id' ) ) - ] ); - } - - // generate_sku_code - static public function generate_sku_code() { - $response = [ 'status' => 'error', 'msg' => 'Podczas generowania kodu sku wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( $sku = \shop\Product::generate_sku_code( \S::get( 'product_id' ) ) ) - $response = [ 'status' => 'ok', 'sku' => $sku ]; - - echo json_encode( $response ); - exit; - } - - // product_xml_name_save - static public function product_xml_name_save() { - $response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania nazwy produktu wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \shop\Product::product_xml_name_save( \S::get( 'product_id' ), \S::get( 'product_xml_name' ), \S::get( 'lang_id' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } - - // product_custom_label_suggestions - static public function product_custom_label_suggestions() { - $response = [ 'status' => 'error', 'msg' => 'Podczas pobierania sugestii dla custom label wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( $suggestions = \shop\Product::product_custom_label_suggestions( \S::get( 'custom_label' ), \S::get( 'label_type' ) ) ) - $response = [ 'status' => 'ok', 'suggestions' => $suggestions ]; - - echo json_encode( $response ); - exit; - } - - // product_custom_label_save - static public function product_custom_label_save() { - $response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania custom label wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \shop\Product::product_custom_label_save( \S::get( 'product_id' ), \S::get( 'custom_label' ), \S::get( 'label_type' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } -} diff --git a/temp/update_build/tmp_0.275/autoload/admin/factory/class.ShopProduct.php b/temp/update_build/tmp_0.275/autoload/admin/factory/class.ShopProduct.php deleted file mode 100644 index 633cf32..0000000 --- a/temp/update_build/tmp_0.275/autoload/admin/factory/class.ShopProduct.php +++ /dev/null @@ -1,1578 +0,0 @@ - count( 'pp_shop_products_langs', [ - 'AND' => [ - 'lang_id' => $lang_id, - 'seo_link' => $seo_link, - 'product_id[!]' => $product_id, - ], - ] ); - } - - private static function removeConflictingRedirectSources( int $product_id, string $lang_id, string $from ): void - { - global $mdb; - - if ( !$from ) - return; - - $mdb -> delete( 'pp_redirects', [ - 'AND' => [ - 'from' => $from, - 'lang_id' => $lang_id, - 'product_id[!]' => $product_id, - ], - ] ); - } - - // count_product - static public function count_product( $where = null ) - { - global $mdb; - - if ( $where ) - return $mdb -> count( 'pp_shop_products', $where ); - else - return $mdb -> count( 'pp_shop_products', [ 'archive' => 0 ] ); - } - - static public function update_product_combinations_prices( int $product_id, $price_brutto, $vat, $price_brutto_promo ) - { - global $mdb; - - $products = $mdb -> query( 'SELECT psp.id, parent_id ' - . 'FROM pp_shop_products AS psp ' - . 'INNER JOIN pp_shop_products_attributes AS pspa ON psp.id = pspa.product_id ' - . 'INNER JOIN pp_shop_attributes_values AS psav ON pspa.value_id = psav.id ' - . 'WHERE psav.impact_on_the_price > 0 AND psp.parent_id = :product_id', [ ':product_id' => $product_id ] ) -> fetchAll( \PDO::FETCH_ASSOC ); - foreach ( $products as $product ) - { - $price_brutto_combination = $price_brutto; - $price_brutto_promo_combination = $price_brutto_promo; - - $values = $mdb -> query( 'SELECT impact_on_the_price FROM pp_shop_attributes_values AS psav INNER JOIN pp_shop_products_attributes AS pspa ON pspa.value_id = psav.id WHERE impact_on_the_price IS NOT NULL AND product_id = :product_id', [ ':product_id' => $product['id'] ] ) -> fetchAll( \PDO::FETCH_ASSOC ); - foreach ( $values as $value ) - { - $price_brutto_combination += $value['impact_on_the_price']; - if ( $price_brutto_promo ) - $price_brutto_promo_combination += $value['impact_on_the_price']; - else - $price_brutto_promo_combination = null; - } - - $price_netto_combination = \S::normalize_decimal( $price_brutto_combination / ( 100 + $vat ) * 100, 2 ); - if ( $price_brutto_promo_combination ) - $price_netto_promo_combination = \S::normalize_decimal( $price_brutto_promo_combination / ( 100 + $vat ) * 100, 2 ); - else - $price_netto_promo_combination = null; - - $mdb -> update( 'pp_shop_products', [ 'price_netto' => $price_netto_combination, 'price_brutto' => $price_brutto_combination, 'price_netto_promo' => $price_netto_promo_combination, 'price_brutto_promo' => $price_brutto_promo_combination ], [ 'id' => $product['id'] ] ); - } - } - - // szybka zmiana statusu produktu - static public function change_product_status( int $product_id ) { - global $mdb; - - $status = $mdb -> get( 'pp_shop_products', 'status', [ 'id' => $product_id ] ); - $status = $status == 1 ? 0 : 1; - return $mdb -> update( 'pp_shop_products', [ 'status' => $status ], [ 'id' => $product_id ] ); - } - - // domyślna nazwa produktu - static public function product_default_name( int $product_id ) { - global $mdb; - - $default_lang = $mdb -> get( 'pp_langs', 'id', [ 'start' => 1 ] ); - return $mdb -> get( 'pp_shop_products_langs', 'name', [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => $default_lang ] ] ); - } - - // szybka zmiana google xml label - static public function product_change_custom_label( int $product_id, $custom_label, $value ) - { - global $mdb; - return $mdb -> update( 'pp_shop_products', [ 'custom_label_' . $custom_label => $value ? $value : null ], [ 'id' => $product_id ] ); - } - - // szybka zmiana ceny promocyjnej - static public function product_change_price_brutto_promo( int $product_id, $price ) - { - global $mdb; - - $vat = $mdb -> get( 'pp_shop_products', 'vat', [ 'id' => $product_id ] ); - $price_netto = \S::normalize_decimal( (float)$price / ( 100 + (float)$vat ) * 100, 2 ); - - return $mdb -> update( 'pp_shop_products', [ 'price_brutto_promo' => $price != 0.00 ? $price : null, 'price_netto_promo' => $price_netto != 0.00 ? $price : null ], [ 'id' => $product_id ] ); - } - - // szybka zmiana ceny - static public function product_change_price_brutto( int $product_id, $price ) - { - global $mdb; - - $vat = $mdb -> get( 'pp_shop_products', 'vat', [ 'id' => $product_id ] ); - $price_netto = \S::normalize_decimal( (float)$price / ( 100 + (float)$vat ) * 100, 2 ); - - return $mdb -> update( 'pp_shop_products', [ 'price_brutto' => $price != 0.00 ? $price : null, 'price_netto' => $price_netto != 0.00 ? $price : null ], [ 'id' => $product_id ] ); - } - - // pobierz id produktu głównego - static public function get_product_parent_id( int $product_id ) - { - global $mdb; - return $mdb -> get( 'pp_shop_products', 'parent_id', [ 'id' => $product_id ] ); - } - - // usunięcie kombinacji produktu - static public function delete_combination( int $combination_id ) - { - global $mdb; - - $mdb -> delete( 'pp_shop_products', [ 'id' => $combination_id ] ); - $mdb -> delete( 'pp_shop_products_attributes', [ 'product_id' => $combination_id ] ); - - return true; - } - - // pobranie permutacji produktu - static public function get_product_permutations( int $product_id ) - { - global $mdb; - - $results = $mdb -> select( 'pp_shop_products', 'id', [ 'parent_id' => $product_id ] ); - if ( \S::is_array_fix( $results ) ) foreach ( $results as $row ) - $products[] = \admin\factory\ShopProduct::product_details( $row ); - - return $products; - } - - // generowanie kombinacji produktu - static public function generate_permutation( int $product_id, $attributes ) - { - global $mdb; - - $vat = $mdb -> get( 'pp_shop_products', 'vat', [ 'id' => $product_id ] ); - $attributeRepository = new \Domain\Attribute\AttributeRepository( $mdb ); - - $permutations = \shop\Product::array_cartesian( $attributes ); - if ( \S::is_array_fix( $permutations ) ) foreach ( $permutations as $permutation ) - { - $product = null; - ksort( $permutation ); - - $permutation_hash = ''; - - if ( \S::is_array_fix( $permutation ) ) foreach ( $permutation as $key => $val ) - { - if ( $permutation_hash ) - $permutation_hash .= '|'; - - $permutation_hash .= $key . '-' . $val; - - // sprawdzenie czy atrybut ma wpływ na cenę - $value_details = $attributeRepository -> valueDetails( (int)$val ); - $impact_on_the_price = $value_details[ 'impact_on_the_price' ]; - - if ( $impact_on_the_price > 0 ) - { - if ( !$product ) - $product = \admin\factory\ShopProduct::product_details( $product_id ); - - $product_price_brutto = $product['price_brutto'] + $impact_on_the_price; - $product_price_netto = $product_price_brutto / ( 1 + ( $product['vat'] / 100 ) ); - - if ( $product['price_brutto_promo'] ) - { - $product_price_brutto_promo = $product['price_brutto_promo'] + $impact_on_the_price; - $product_price_netto_promo = $product_price_brutto_promo / ( 1 + ( $product['vat'] / 100 ) ); - } - else - { - $product_price_brutto_promo = null; - $product_price_netto_promo = null; - } - } - - if ( $permutation_hash and !$mdb -> count( 'pp_shop_products', [ 'AND' => [ 'parent_id' => $product_id, 'permutation_hash' => $permutation_hash ] ] ) ) - { - if ( $mdb -> insert( 'pp_shop_products', [ 'parent_id' => $product_id, 'permutation_hash' => $permutation_hash, 'vat' => $vat ] ) ) - { - $combination_id = $mdb -> id(); - if ( $product ) - { - $mdb -> update( 'pp_shop_products', [ 'price_netto' => $product_price_netto, 'vat' => $product['vat'], 'price_brutto' => $product_price_brutto, 'price_netto_promo' => $product_price_netto_promo, 'price_brutto_promo' => $product_price_brutto_promo ], [ 'id' => $combination_id ] ); - } - - $permutation_hash_rev_rows = explode( '|', $permutation_hash ); - foreach ( $permutation_hash_rev_rows as $permutation_hash_rev ) - { - $attribute_rev = explode( '-', $permutation_hash_rev ); - $mdb -> insert( 'pp_shop_products_attributes', [ 'product_id' => $combination_id, 'attribute_id' => $attribute_rev[0], 'value_id' => $attribute_rev[1] ] ); - } - } - } - } - } - return true; - } - - public static function product_name($product_id) - { - global $mdb; - - $results = $mdb -> query("SELECT pspl.name FROM pp_shop_products_langs AS pspl, pp_langs AS pl WHERE lang_id = pl.id AND product_id = :product_id AND pspl.name != '' ORDER BY o ASC LIMIT 1", [':product_id' => $product_id]) -> fetchAll(); - - return $results[0]['name']; - } - - public static function get_product_images($product_id) - { - global $mdb; - - return $mdb -> select('pp_shop_products_images', 'src', ['product_id' => (int) $product_id, 'ORDER' => ['o' => 'ASC', 'id' => 'ASC']]); - } - - static public function generate_EAN( $number ) - { - $code = '200' . str_pad($number, 9, '0'); - $weightflag = true; - $sum = 0; - - for ($i = strlen($code) - 1; $i >= 0; $i--) - { - $sum += (int)$code[$i] * ($weightflag?3:1); - $weightflag = !$weightflag; - } - - $code .= (10 - ($sum % 10)) % 10; - return $code; - } - - static public function generate_google_feed_xml() - { - global $mdb, $lang_id; - - $settings = \front\factory\Settings::settings_details(true); - - $domain_prefix = 'https'; - $url = preg_replace('#^(http(s)?://)?w{3}\.#', '$1', $_SERVER['SERVER_NAME']); - - $main_language = \front\factory\Languages::default_language(); - - $doc = new \DOMDocument('1.0', 'UTF-8'); - $xmlRoot = $doc -> createElement('rss'); - $xmlRoot = $doc -> appendChild($xmlRoot); - $xmlRoot -> setAttribute('version', '2.0'); - $xmlRoot -> setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:g', 'http://base.google.com/ns/1.0'); - $channelNode = $xmlRoot -> appendChild($doc -> createElement('channel')); - $channelNode -> appendChild( $doc -> createElement( 'title', $settings['firm_name'])); - $channelNode -> appendChild( $doc -> createElement( 'link', $domain_prefix . '://' . $url ) ); - - $rows = $mdb -> select( 'pp_shop_products', 'id', [ 'AND' => [ 'status' => '1', 'archive' => 0, 'parent_id' => null ] ] ); - if ( \S::is_array_fix( $rows ) ) foreach ( $rows as $product_id ) - { - $product = \shop\Product::getFromCache( $product_id, $lang_id ); - - if ( is_array( $product -> product_combinations ) and count( $product -> product_combinations ) ) - { - foreach ( $product -> product_combinations as $product_combination ) - { - if ( $product_combination -> quantity !== null or $product_combination -> stock_0_buy ) - { - $itemNode = $channelNode -> appendChild( $doc -> createElement( 'item' ) ); - $p_gid = $itemNode -> appendChild( $doc -> createElement('g:id', $product_combination -> id ) ); - $p_groupid = $itemNode -> appendChild( $doc -> createElement( 'g:item_group_id', $product -> id ) ); - - if ( $product -> custom_label_0 ) - $p_label = $itemNode -> appendChild( $doc -> createElement('g:custom_label_0', $product -> custom_label_0 ) ); - - if ( $product -> custom_label_1 ) - $p_label = $itemNode -> appendChild( $doc -> createElement('g:custom_label_1', $product -> custom_label_1 ) ); - - if ( $product -> custom_label_2 ) - $p_label = $itemNode -> appendChild( $doc -> createElement('g:custom_label_2', $product -> custom_label_2 ) ); - - if ( $product -> custom_label_3 ) - $p_label = $itemNode -> appendChild( $doc -> createElement('g:custom_label_3', $product -> custom_label_3 ) ); - - if ( $product -> custom_label_4 ) - $p_label = $itemNode -> appendChild( $doc -> createElement('g:custom_label_4', $product -> custom_label_4 ) ); - - if ( $product -> language['xml_name'] ) - $p_title = $itemNode -> appendChild( $doc -> createElement( 'title', str_replace( '&', '&', $product -> language['xml_name'] ) . ' - ' . $product -> generateSubtitleFromAttributes( $product_combination -> permutation_hash ) ) ); - else - $p_title = $itemNode -> appendChild( $doc -> createElement( 'title', str_replace( '&', '&', $product -> language['name'] ) . ' - ' . $product -> generateSubtitleFromAttributes( $product_combination -> permutation_hash ) ) ); - - if ( $product -> ean ) - $p_gtin = $itemNode -> appendChild( $doc -> createElement( 'g:gtin', $product -> ean ) ); - else - $p_gtin = $itemNode -> appendChild( $doc -> createElement( 'g:gtin', self::generate_EAN( $product -> id ) ) ); - - // opis produktu - if ( $product -> language['short_description'] ) - $p_description = $itemNode -> appendChild( $doc -> createElement( 'g:description', html_entity_decode( strip_tags( $product -> language['short_description'] ) ) ) ); - else - $p_description = $itemNode -> appendChild( $doc -> createElement( 'g:description', html_entity_decode( strip_tags( $product -> language['name'] ) ) ) ); - - if ( $product -> language['seo_link'] ) - $link = $domain_prefix . '://' . $url . '/' . \S::seo( $product -> language['seo_link'] ) . '/' . str_replace( '|', '/', $product_combination -> permutation_hash ); - else - $link = $domain_prefix . '://' . $url . '/' . 'p-' . $product -> id . '-' . \S::seo( $product -> language['name'] ) . '/' . str_replace( '|', '/', $product_combination -> permutation_hash ); - - $p_link = $itemNode -> appendChild( $doc -> createElement( 'link', $link ) ); - - if ( $product -> images[0] ) - $p_gimage_link = $itemNode -> appendChild( $doc -> createElement( 'g:image_link', $domain_prefix . '://' . $url . $product -> images[0]['src'] ) ); - - if ( count( $product -> images ) > 1 ) - { - for ( $i = 1; $i < count( $product -> images ); ++$i ) - $p_gimage_link = $itemNode -> appendChild( $doc -> createElement( 'g:additional_image_link', $domain_prefix . '://' . $url . $product -> images[$i]['src'] ) ); - } - - $p_gcondition = $itemNode -> appendChild( $doc -> createElement( 'g:condition', 'new' ) ); - - if ( $product_combination -> quantity !== null ) - { - if ( $product_combination -> quantity > 0 ) - { - $p_gavailability = $itemNode -> appendChild( $doc -> createElement( 'g:availability', 'in stock' ) ); - $p_gquantity = $itemNode -> appendChild( $doc -> createElement( 'g:quantity', $product_combination -> quantity ) ); - } - else - { - if ( $product_combination -> stock_0_buy ) - $p_availability = $itemNode -> appendChild( $doc -> createElement( 'g:availability', 'in stock' ) ); - else - $p_availability = $itemNode -> appendChild( $doc -> createElement( 'g:availability', 'out of stock' ) ); - } - } - else - { - if ( $product -> quantity > 0 ) - { - $p_gavailability = $itemNode -> appendChild( $doc -> createElement( 'g:availability', 'in stock' ) ); - $p_gquantity = $itemNode -> appendChild( $doc -> createElement( 'g:quantity', $product -> quantity ) ); - } - else - { - if ( $product -> stock_0_buy ) - { - $p_availability = $itemNode -> appendChild( $doc -> createElement( 'g:availability', 'in stock' ) ); - $p_gquantity = $itemNode -> appendChild( $doc -> createElement( 'g:quantity', 999 ) ); - } - else - { - $p_availability = $itemNode -> appendChild( $doc -> createElement( 'g:availability', 'out of stock' ) ); - $p_gquantity = $itemNode -> appendChild( $doc -> createElement( 'g:quantity', 0 ) ); - } - } - } - - if ( $product_combination -> price_brutto ) - { - $p_gprice = $itemNode -> appendChild( $doc -> createElement( 'g:price', $product_combination -> price_brutto . ' PLN' ) ); - - if ( $product_combination -> price_brutto_promo ) - $p_gsale_price = $itemNode -> appendChild( $doc -> createElement( 'g:sale_price', $product_combination -> price_brutto_promo . ' PLN' ) ); - } - else - { - $p_gprice = $itemNode -> appendChild( $doc -> createElement( 'g:price', $product -> price_brutto . ' PLN' ) ); - - if ( $product -> price_brutto_promo ) - $p_gsale_price = $itemNode -> appendChild( $doc -> createElement( 'g:sale_price', $product -> price_brutto_promo . ' PLN' ) ); - } - - $p_gshipping = $itemNode -> appendChild( $doc -> createElement( 'g:shipping' ) ); - $p_gcountry = $p_gshipping -> appendChild( $doc -> createElement( 'g:country', 'PL' ) ); - $p_gservice = $p_gshipping -> appendChild( $doc -> createElement( 'g:service', '1 dzień roboczy' ) ); - $p_gprice = $p_gshipping -> appendChild( $doc -> createElement( 'g:price', ( new \Domain\Transport\TransportRepository( $mdb ) )->lowestTransportPrice( (int) $product -> wp ) . ' PLN' ) ); - } - } - } - else - { - $itemNode = $channelNode -> appendChild( $doc -> createElement( 'item' ) ); - $p_gid = $itemNode -> appendChild( $doc -> createElement('g:id', $product -> id ) ); - $p_groupid = $itemNode -> appendChild( $doc -> createElement( 'g:item_group_id', $product -> id ) ); - - if ( $product -> google_xml_label ) - $p_label = $itemNode -> appendChild($doc -> createElement('g:custom_label_0', $product -> google_xml_label ) ); - - if ( $product -> language['xml_name'] ) - $p_title = $itemNode -> appendChild( $doc -> createElement( 'title', str_replace( '&', '&', $product -> language['xml_name'] ) ) ); - else - $p_title = $itemNode -> appendChild( $doc -> createElement( 'title', str_replace( '&', '&', $product -> language['name'] ) ) ); - - if ( $product -> ean ) - $p_gtin = $itemNode -> appendChild( $doc -> createElement( 'g:gtin', $product -> ean ) ); - else - $p_gtin = $itemNode -> appendChild( $doc -> createElement( 'g:gtin', self::generate_EAN( $product -> id ) ) ); - - // opis produktu - if ( $product -> language['short_description'] ) - $p_description = $itemNode -> appendChild( $doc -> createElement( 'g:description', html_entity_decode( strip_tags( $product -> language['short_description'] ) ) ) ); - else - $p_description = $itemNode -> appendChild( $doc -> createElement( 'g:description', html_entity_decode( strip_tags( $product -> language['name'] ) ) ) ); - - if ( $product -> language['seo_link'] ) - $link = $domain_prefix . '://' . $url . '/' . \S::seo( $product -> language['seo_link'] ); - else - $link = $domain_prefix . '://' . $url . '/' . 'p-' . $product -> id . '-' . \S::seo( $product -> language['name'] ); - - $p_link = $itemNode -> appendChild( $doc -> createElement( 'link', $link ) ); - - if ( $product -> custom_label_0 ) - $p_label = $itemNode -> appendChild( $doc -> createElement('g:custom_label_0', $product -> custom_label_0 ) ); - - if ( $product -> custom_label_1 ) - $p_label = $itemNode -> appendChild( $doc -> createElement('g:custom_label_1', $product -> custom_label_1 ) ); - - if ( $product -> custom_label_2 ) - $p_label = $itemNode -> appendChild( $doc -> createElement('g:custom_label_2', $product -> custom_label_2 ) ); - - if ( $product -> custom_label_3 ) - $p_label = $itemNode -> appendChild( $doc -> createElement('g:custom_label_3', $product -> custom_label_3 ) ); - - if ( $product -> custom_label_4 ) - $p_label = $itemNode -> appendChild( $doc -> createElement('g:custom_label_4', $product -> custom_label_4 ) ); - - if ( $product -> images[0] ) - $p_gimage_link = $itemNode -> appendChild( $doc -> createElement( 'g:image_link', $domain_prefix . '://' . $url . $product -> images[0]['src'] ) ); - - if ( count( $product -> images ) > 1 ) - { - for ( $i = 1; $i < count( $product -> images ); ++$i ) - $p_gimage_link = $itemNode -> appendChild( $doc -> createElement( 'g:additional_image_link', $domain_prefix . '://' . $url . $product -> images[$i]['src'] ) ); - } - - $p_gcondition = $itemNode -> appendChild( $doc -> createElement( 'g:condition', 'new' ) ); - - if ( $product -> quantity ) - { - $p_gavailability = $itemNode -> appendChild( $doc -> createElement( 'g:availability', 'in stock' ) ); - $p_gquantity = $itemNode -> appendChild( $doc -> createElement( 'g:quantity', $product -> quantity ) ); - } - else - { - if ( $product -> stock_0_buy ) { - $p_availability = $itemNode -> appendChild( $doc -> createElement( 'g:availability', 'in stock' ) ); - $p_gquantity = $itemNode -> appendChild( $doc -> createElement( 'g:quantity', 999 ) ); - } - else { - $p_availability = $itemNode -> appendChild( $doc -> createElement( 'g:availability', 'out of stock' ) ); - $p_gquantity = $itemNode -> appendChild( $doc -> createElement( 'g:quantity', 0 ) ); - } - } - - $p_gprice = $itemNode -> appendChild( $doc -> createElement( 'g:price', $product -> price_brutto . ' PLN' ) ); - - if ( $product -> price_brutto_promo ) - $p_gsale_price = $itemNode -> appendChild( $doc -> createElement( 'g:sale_price', $product -> price_brutto_promo . ' PLN' ) ); - - $p_gshipping = $itemNode -> appendChild( $doc -> createElement( 'g:shipping' ) ); - $p_gcountry = $p_gshipping -> appendChild( $doc -> createElement( 'g:country', 'PL' ) ); - $p_gservice = $p_gshipping -> appendChild( $doc -> createElement( 'g:service', '1 dzień roboczy' ) ); - $p_gprice = $p_gshipping -> appendChild( $doc -> createElement( 'g:price', ( new \Domain\Transport\TransportRepository( $mdb ) )->lowestTransportPrice( (int) $product -> wp ) . ' PLN' ) ); - } - } - file_put_contents('../google-feed.xml', $doc -> saveXML()); - } - - static public function count_product_combinations( int $product_id ) - { - global $mdb; - - return $mdb -> count( 'pp_shop_products', [ 'parent_id' => $product_id ] ); - } - - // ajax_products_list - static public function ajax_products_list_archive( $current_page = null, $query = null ) - { - global $mdb; - - $search = ''; - - if ( $query ) - { - $query_array = []; - parse_str( $query, $query_array ); - - foreach ( $query_array as $key => $val ) { - if ( $val !== '' ) - $search .= ' AND ' . $key . ' LIKE \'%' . $val . '%\''; - } - } - - $results = $mdb -> query( 'SELECT ' - . 'DISTINCT( psp.id )' - . 'FROM ' - . 'pp_shop_products AS psp ' - . 'INNER JOIN pp_shop_products_langs AS pspl ON pspl.product_id = psp.id ' - . 'WHERE archive = 1 AND parent_id IS NULL ' . $search . ' ORDER BY id DESC LIMIT ' . ( $current_page - 1 ) * 10 . ', 10' ) -> fetchAll( \PDO::FETCH_ASSOC ); - $results2 = $mdb -> query( 'SELECT ' - . 'COUNT( DISTINCT( psp.id ) ) AS products_count ' - . 'FROM ' - . 'pp_shop_products AS psp ' - . 'INNER JOIN pp_shop_products_langs AS pspl ON pspl.product_id = psp.id ' - . 'WHERE archive = 1 AND parent_id IS NULL ' . $search ) -> fetchAll( \PDO::FETCH_ASSOC ); - - if ( is_array( $results ) ) foreach ( $results as $row ) { - $products[] = \admin\factory\ShopProduct::product_details( $row['id'] ); - } - - return [ 'products' => $products, 'products_count' => $results2[0]['products_count'] ]; - } - - // ajax_products_list - static public function ajax_products_list( $current_page = null, $query = null ) - { - global $mdb; - - if ( $query ) - { - $search = ''; - $query_array = []; - - parse_str( $query, $query_array ); - - foreach ( $query_array as $key => $val ) { - if ( strpos( $key, '|' ) !== false ) - { - $keys_tmp = explode( '|', $key ); - $search .= ' AND ( '; - foreach ( $keys_tmp as $key_tmp ) - { - if ( $key_tmp != reset( $keys_tmp ) ) - $search .= ' OR ' . $key_tmp . ' LIKE \'%' . $val . '%\''; - else - $search .= ' ' . $key_tmp . ' LIKE \'%' . $val . '%\''; - } - $search .= ' )'; - } - else - { - $search .= ' AND ' . $key . ' LIKE \'%' . $val . '%\''; - } - } - - $results = $mdb -> query( 'SELECT ' - . 'DISTINCT( psp.id )' - . 'FROM ' - . 'pp_shop_products AS psp ' - . 'INNER JOIN pp_shop_products_langs AS pspl ON pspl.product_id = psp.id ' - . 'WHERE archive = 0 AND parent_id IS NULL ' . $search . ' ORDER BY id DESC LIMIT ' . ( $current_page - 1 ) * 10 . ', 10' ) -> fetchAll( \PDO::FETCH_ASSOC ); - $results2 = $mdb -> query( 'SELECT ' - . 'COUNT( DISTINCT( psp.id ) ) AS products_count ' - . 'FROM ' - . 'pp_shop_products AS psp ' - . 'INNER JOIN pp_shop_products_langs AS pspl ON pspl.product_id = psp.id ' - . 'WHERE archive = 0 AND parent_id IS NULL ' . $search ) -> fetchAll( \PDO::FETCH_ASSOC ); - } else { - $results = $mdb -> query( 'SELECT id FROM pp_shop_products WHERE parent_id IS NULL ORDER BY id DESC LIMIT ' . ( $current_page - 1 ) * 10 . ', 10' ) -> fetchAll( \PDO::FETCH_ASSOC ); - $results2 = $mdb -> query( 'SELECT COUNT( id ) AS products_count FROM pp_shop_products WHERE parent_id IS NULL' ) -> fetchAll( \PDO::FETCH_ASSOC ); - } - - if ( is_array( $results ) ) foreach ( $results as $row ) { - $products[] = \admin\factory\ShopProduct::product_details( $row['id'] ); - } - - return [ 'products' => $products, 'products_count' => $results2[0]['products_count'] ]; - } - - public static function products_list() - { - global $mdb; - - $results = $mdb -> select( 'pp_shop_products', 'id', [ 'parent_id' => null ] ); - if ( is_array( $results ) ) foreach ( $results as $row ) - { - $products[ $row ] = $mdb -> get ('pp_shop_products_langs', 'name', ['AND' => [ 'product_id' => $row, 'lang_id' => 'pl' ] ] ); - } - - return $products; - } - - public static function images_order_save($product_id, $order) - { - global $mdb; - - $order = explode(';', $order); - if (\is_array($order) && !empty($order)) - { - foreach ($order as $image_id) - { - $mdb -> update('pp_shop_products_images', [ - 'o' => $i++, - ], [ - 'AND' => [ - 'product_id' => $product_id, - 'id' => $image_id, - ], - ]); - } - } - - return true; - } - - public static function image_alt_change($image_id, $image_alt) - { - global $mdb; - $result = $mdb -> update('pp_shop_products_images', [ - 'alt' => $image_alt, - ], [ - 'id' => $image_id, - ]); - \S::delete_cache(); - - return $result; - } - - // product_unarchive - static public function product_unarchive( int $product_id ) - { - global $mdb; - - $mdb -> update( 'pp_shop_products', [ 'status' => 1, 'archive' => 0 ], [ 'id' => $product_id ] ); - $mdb -> update( 'pp_shop_products', [ 'status' => 1, 'archive' => 0 ], [ 'parent_id' => $product_id ] ); - - return true; - } - - static public function product_archive( int $product_id ) - { - global $mdb; - - $mdb -> update( 'pp_shop_products', [ 'status' => 0, 'archive' => 1 ], [ 'id' => $product_id ] ); - $mdb -> update( 'pp_shop_products', [ 'status' => 0, 'archive' => 1 ], [ 'parent_id' => $product_id ] ); - - return true; - } - - public static function product_delete( int $product_id) - { - global $mdb; - - $mdb -> delete( 'pp_shop_products_categories', ['product_id' => $product_id ] ); - $mdb -> delete( 'pp_shop_products_langs', ['product_id' => $product_id ] ); - $mdb -> delete( 'pp_shop_products_images', ['product_id' => $product_id ] ); - $mdb -> delete( 'pp_shop_products_files', ['product_id' => $product_id ] ); - $mdb -> delete( 'pp_shop_products_attributes', ['product_id' => $product_id ] ); - $mdb -> delete( 'pp_shop_products', ['id' => $product_id ] ); - $mdb -> delete( 'pp_shop_product_sets_products', [ 'product_id' => $product_id ] ); - // pp_routes - $mdb -> delete( 'pp_routes', [ 'product_id' => $product_id ] ); - // pp_redirects - $mdb -> delete( 'pp_redirects', [ 'product_id' => $product_id ] ); - - \S::delete_dir( '../upload/product_images/product_' . $product_id . '/' ); - \S::delete_dir( '../upload/product_files/product_' . $product_id . '/' ); - - return true; - } - - public static function product_categories($product_id) - { - global $mdb; - - $results = $mdb -> query('SELECT category_id FROM pp_shop_products_categories WHERE product_id = '.(int) $product_id) -> fetchAll(); - if (\is_array($results) && !empty($results)) - { - foreach ($results as $row) - { - if ('' === $out) - { - $out .= ' - '; - } - - $out .= ( new \Domain\Category\CategoryRepository( $mdb ) )->categoryTitle( (int) $row['category_id'] ); - - if (end($results) !== $row) - { - $out .= ' / '; - } - } - } - - return $out; - } - - public static function max_order() - { - global $mdb; - - return $mdb -> max('pp_shop_products_categories', 'o'); - } - - public static function delete_img($image_id) - { - global $mdb; - $mdb -> update('pp_shop_products_images', ['to_delete' => 1], ['id' => (int) $image_id]); - - return true; - } - - public static function delete_nonassigned_images() - { - global $mdb; - - $results = $mdb -> select('pp_shop_products_images', '*', ['product_id' => null]); - if (\is_array($results)) - { - foreach ($results as $row) - { - if (file_exists('../'.$row['src'])) - { - unlink('../'.$row['src']); - } - } - } - - $mdb -> delete('pp_shop_products_images', ['product_id' => null]); - } - - public static function file_name_change($file_id, $file_name) - { - global $mdb; - $mdb -> update('pp_shop_products_files', ['name' => $file_name], ['id' => (int) $file_id]); - - return true; - } - - public static function delete_file($file_id) - { - global $mdb; - $mdb -> update('pp_shop_products_files', ['to_delete' => 1], ['id' => (int) $file_id]); - - return true; - } - - public static function delete_nonassigned_files() - { - global $mdb; - - $results = $mdb -> select('pp_shop_products_files', '*', ['product_id' => null]); - if (\is_array($results)) - { - foreach ($results as $row) - { - if (file_exists('../'.$row['src'])) - { - unlink('../'.$row['src']); - } - } - } - - $mdb -> delete('pp_shop_products_files', ['product_id' => null]); - } - - public static function save( - $product_id, $name, $short_description, $description, $status, $meta_description, $meta_keywords, $seo_link, $copy_from, $categories, $price_netto, $price_brutto, $vat, $promoted, $warehouse_message_zero, $warehouse_message_nonzero, $tab_name_1, $tab_description_1, $tab_name_2, $tab_description_2, $layout_id, $products_related, int $set_id, $price_netto_promo, $price_brutto_promo, $new_to_date, $stock_0_buy, $wp, $custom_label_0, $custom_label_1, $custom_label_2, $custom_label_3, $custom_label_4, $additional_message, int $quantity, $additional_message_text, int $additional_message_required, $canonical, $meta_title, $producer_id, $sku, $ean, $product_unit, $weight, $xml_name, $custom_field_name, $custom_field_required, $security_information, $custom_field_type - ) - { - global $mdb, $user; - - if ( !$product_id ) - { - $mdb -> insert('pp_shop_products', [ - 'date_add' => date('Y-m-d H:i:s'), - 'date_modify' => date('Y-m-d H:i:s'), - 'modify_by' => $user['id'], - 'status' => 'on' === $status ? 1 : 0, - 'price_netto' => ($price_netto && 0.00 !== $price_netto) ? $price_netto : null, - 'price_brutto' => ($price_brutto && 0.00 !== $price_brutto) ? $price_brutto : null, - 'vat' => $vat, - 'promoted' => 'on' === $promoted ? 1 : 0, - 'layout_id' => $layout_id ? $layout_id : null, - 'price_netto_promo' => ($price_netto_promo && 0.00 !== $price_netto_promo) ? $price_netto_promo : null, - 'price_brutto_promo' => ($price_brutto_promo && 0.00 !== $price_brutto_promo) ? $price_brutto_promo : null, - 'new_to_date' => $new_to_date ? $new_to_date : null, - 'stock_0_buy' => 'on' === $stock_0_buy ? 1 : 0, - 'wp' => $wp ? $wp : null, - 'sku' => $sku ? $sku : null, - 'ean' => $ean ? $ean : null, - 'custom_label_0' => $custom_label_0 ? $custom_label_0 : null, - 'custom_label_1' => $custom_label_1 ? $custom_label_1 : null, - 'custom_label_2' => $custom_label_2 ? $custom_label_2 : null, - 'custom_label_3' => $custom_label_3 ? $custom_label_3 : null, - 'custom_label_4' => $custom_label_4 ? $custom_label_4 : null, - 'additional_message' => $additional_message == 'on' ? 1 : 0, - 'set_id' => $set_id ? $set_id : null, - 'quantity' => $quantity, - 'additional_message_text' => $additional_message_text ? $additional_message_text : null, - 'additional_message_required' => $additional_message_required, - 'producer_id' => !empty( $producer_id ) ? $producer_id : null, - 'product_unit_id' => !empty( $product_unit ) ? $product_unit : null, - 'weight' => !empty( $weight ) ? $weight : null, - ] ); - - $id = $mdb -> id(); - - if ( $id ) - { - $langs = ( new \Domain\Languages\LanguagesRepository( $mdb ) )->languagesList( true ); - foreach ( $langs as $lg ) - { - $mdb -> insert( 'pp_shop_products_langs', [ - 'product_id' => (int) $id, - 'lang_id' => $lg['id'], - 'name' => $name[$lg['id']] ? $name[$lg['id']] : null, - 'short_description' => $short_description[$lg['id']] ? $short_description[$lg['id']] : null, - 'description' => $description[$lg['id']] ? $description[$lg['id']] : null, - 'meta_description' => $meta_description[$lg['id']] ? $meta_description[$lg['id']] : null, - 'meta_keywords' => $meta_keywords[$lg['id']] ? $meta_keywords[$lg['id']] : null, - 'seo_link' => $seo_link[$lg['id']] ? \S::seo($seo_link[$lg['id']]) : null, - 'copy_from' => $copy_from[$lg['id']] ? $copy_from[$lg['id']] : null, - 'warehouse_message_zero' => $warehouse_message_zero[$lg['id']] ? $warehouse_message_zero[$lg['id']] : null, - 'warehouse_message_nonzero' => $warehouse_message_nonzero[$lg['id']] ? $warehouse_message_nonzero[$lg['id']] : null, - 'tab_name_1' => $tab_name_1[$lg['id']] ? $tab_name_1[$lg['id']] : null, - 'tab_description_1' => $tab_description_1[$lg['id']] ? $tab_description_1[$lg['id']] : null, - 'tab_name_2' => $tab_name_2[$lg['id']] ? $tab_name_2[$lg['id']] : null, - 'tab_description_2' => $tab_description_2[$lg['id']] ? $tab_description_2[$lg['id']] : null, - 'canonical' => $canonical[$lg['id']] ? $canonical[$lg['id']] : null, - 'meta_title' => $meta_title[$lg['id']] ? $meta_title[$lg['id']] : null, - 'xml_name' => $xml_name[$lg['id']] ? $xml_name[$lg['id']] : null, - 'security_information' => $security_information[$lg['id']] ? $security_information[$lg['id']] : null, - ] ); - } - - if ( is_array($categories)) - { - foreach ($categories as $category) - { - $order = self::max_order() + 1; - - $mdb -> insert('pp_shop_products_categories', [ - 'product_id' => (int) $id, - 'category_id' => (int) $category, - 'o' => (int) $order, - ]); - } - } - elseif ($categories) - { - $order = self::max_order() + 1; - - $mdb -> insert('pp_shop_products_categories', [ - 'product_id' => (int) $id, - 'category_id' => (int) $categories, - 'o' => (int) $order, - ]); - } - - if (\is_array($products_related)) - { - foreach ($products_related as $product_related ) - { - $mdb -> insert('pp_shop_products_related', [ - 'product_id' => (int) $id, - 'product_related_id' => (int) $product_related, - ]); - } - } - elseif ( $products_related ) - { - $mdb -> insert('pp_shop_products_related', [ - 'product_id' => (int) $id, - 'product_related_id' => (int) $products_related, - ]); - } - - $created = false; - - $results = $mdb -> select('pp_shop_products_files', '*', ['product_id' => null]); - if (\is_array($results)) - { - foreach ($results as $row) - { - $dir = '/upload/product_files/product_'.$id; - - $new_file_name = str_replace('/upload/product_files/tmp', $dir, $row['src']); - - if (file_exists('..'.$row['src'])) - { - if (!is_dir('../'.$dir) && true !== $created) - { - if (mkdir('../'.$dir, 0755, true)) - { - $created = true; - } - } - rename('..'.$row['src'], '..'.$new_file_name); - } - - $mdb -> update('pp_shop_products_files', ['src' => $new_file_name, 'product_id' => $id], ['id' => $row['id']]); - } - } - - $created = false; - - $results = $mdb -> select('pp_shop_products_images', '*', ['product_id' => null]); - if (\is_array($results)) - { - foreach ($results as $row) - { - $dir = '/upload/product_images/product_'.$id; - - $new_file_name = str_replace('/upload/product_images/tmp', $dir, $row['src']); - - if (file_exists('../'.$new_file_name)) - { - $ext = strrpos($new_file_name, '.'); - $fileName_a = substr($new_file_name, 0, $ext); - $fileName_b = substr($new_file_name, $ext); - - $count = 1; - - while (file_exists('../'.$fileName_a.'_'.$count.$fileName_b)) - { - ++$count; - } - - $new_file_name = $fileName_a.'_'.$count.$fileName_b; - } - - if (file_exists('..'.$row['src'])) - { - if (!is_dir('../'.$dir) && true !== $created) - { - if (mkdir('../'.$dir, 0755, true)) - { - $created = true; - } - } - rename('..'.$row['src'], '..'.$new_file_name); - } - - $mdb -> update('pp_shop_products_images', ['src' => $new_file_name, 'product_id' => (int) $id], ['id' => $row['id']]); - } - } - - // dodatkowe pola - for ( $i = 0; $i < count( $custom_field_name ); ++$i ) - { - if ( !empty( $custom_field_name[$i] ) ) - { - $custom_field = $custom_field_name[$i]; - $custom_field_type_data = $custom_field_type[$i]; - $custom_field_required = isset( $custom_field_required[$i] ) ? 1 : 0; - - $mdb -> insert( 'pp_shop_products_custom_fields', [ - 'id_product' => (int) $id, - 'name' => $custom_field, - 'type' => $custom_field_type_data, - 'is_required' => $custom_field_required, - ] ); - } - } - - \S::htacces(); - - \S::delete_dir('../temp/'); - \S::delete_dir('../thumbs/'); - - return $id; - } - } - else - { - $mdb -> update( 'pp_shop_products', [ - 'date_modify' => date('Y-m-d H:i:s'), - 'modify_by' => $user['id'], - 'status' => 'on' === $status ? 1 : 0, - 'price_netto' => ($price_netto && 0.00 !== $price_netto) ? $price_netto : null, - 'price_brutto' => ($price_brutto && 0.00 !== $price_brutto) ? $price_brutto : null, - 'vat' => $vat, - 'promoted' => 'on' === $promoted ? 1 : 0, - 'layout_id' => $layout_id ? $layout_id : null, - 'price_netto_promo' => ($price_netto_promo && 0.00 !== $price_netto_promo) ? $price_netto_promo : null, - 'price_brutto_promo' => ($price_brutto_promo && 0.00 !== $price_brutto_promo) ? $price_brutto_promo : null, - 'new_to_date' => $new_to_date ? $new_to_date : null, - 'stock_0_buy' => 'on' === $stock_0_buy ? 1 : 0, - 'wp' => $wp ? $wp : null, - 'sku' => $sku ? $sku : null, - 'ean' => $ean ? $ean : null, - 'custom_label_0' => $custom_label_0 ? $custom_label_0 : null, - 'custom_label_1' => $custom_label_1 ? $custom_label_1 : null, - 'custom_label_2' => $custom_label_2 ? $custom_label_2 : null, - 'custom_label_3' => $custom_label_3 ? $custom_label_3 : null, - 'custom_label_4' => $custom_label_4 ? $custom_label_4 : null, - 'additional_message' => $additional_message == 'on' ? 1 : 0, - 'set_id' => $set_id ? $set_id : null, - 'quantity' => $quantity, - 'additional_message_text' => $additional_message_text ? $additional_message_text : null, - 'additional_message_required' => $additional_message_required, - 'producer_id' => !empty( $producer_id ) ? $producer_id : null, - 'product_unit_id' => !empty( $product_unit ) ? $product_unit : null, - 'weight' => !empty( $weight ) ? $weight : null, - ], [ - 'id' => (int) $product_id, - ] ); - - $mdb -> update( 'pp_shop_products', [ - 'additional_message' => $additional_message == 'on' ? 1 : 0, - ], [ - 'parent_id' => (int) $product_id, - ] ); - - \admin\factory\ShopProduct::update_product_combinations_prices( $product_id, $price_brutto, $vat, $price_brutto_promo ); - - $langs = ( new \Domain\Languages\LanguagesRepository( $mdb ) )->languagesList( true ); - foreach ( $langs as $lg ) - { - if ( $translation_id = $mdb -> get( 'pp_shop_products_langs', 'id', [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => $lg['id'] ] ] ) ) - { - $current_seo_link = $mdb -> get( 'pp_shop_products_langs', 'seo_link', [ 'id' => $translation_id ] ); - - if ( $seo_link[$lg['id']] ) - $new_seo_link = \S::seo( $seo_link[$lg['id']] ); - else - $new_seo_link = \S::seo( 'p-' . $product_id . '-' . $name[$lg['id']] ); - - if ( $new_seo_link !== $current_seo_link and $current_seo_link != '' ) - { - if ( $mdb -> count( 'pp_redirects', [ 'from' => $new_seo_link, 'to' => $current_seo_link, 'lang_id' => $lg['id'], 'product_id' => $product_id ] ) ) - $mdb -> delete( 'pp_redirects', [ 'from' => $new_seo_link, 'to' => $current_seo_link, 'lang_id' => $lg['id'], 'product_id' => $product_id ] ); - - $mdb -> delete( 'pp_redirects', [ - 'AND' => [ - 'product_id' => $product_id, - 'lang_id' => $lg['id'], - 'from' => $current_seo_link, - 'to[!]' => $new_seo_link, - ], - ] ); - - if ( !self::seoLinkUsedByOtherProduct( (int) $product_id, (string) $lg['id'], (string) $current_seo_link ) ) - { - self::removeConflictingRedirectSources( (int) $product_id, (string) $lg['id'], (string) $current_seo_link ); - - if ( !$mdb -> count( 'pp_redirects', [ 'from' => $current_seo_link, 'to' => $new_seo_link, 'lang_id' => $lg['id'], 'product_id' => $product_id ] ) ) - { - if ( \S::canAddRedirect( $current_seo_link, $new_seo_link, $lg['id'] ) ) - $mdb -> insert( 'pp_redirects', [ 'from' => $current_seo_link, 'to' => $new_seo_link, 'lang_id' => $lg['id'], 'product_id' => $product_id ] ); - } - } - else - $mdb -> delete( 'pp_redirects', [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => $lg['id'], 'from' => $current_seo_link ] ] ); - } - - $mdb -> update( 'pp_shop_products_langs', [ - 'name' => $name[$lg['id']] ? $name[$lg['id']] : null, - 'short_description' => $short_description[$lg['id']] ? $short_description[$lg['id']] : null, - 'description' => $description[$lg['id']] ? $description[$lg['id']] : null, - 'meta_description' => $meta_description[$lg['id']] ? $meta_description[$lg['id']] : null, - 'meta_keywords' => $meta_keywords[$lg['id']] ? $meta_keywords[$lg['id']] : null, - 'seo_link' => $seo_link[$lg['id']] ? \S::seo($seo_link[$lg['id']]) : null, - 'copy_from' => $copy_from[$lg['id']] ? $copy_from[$lg['id']] : null, - 'warehouse_message_zero' => $warehouse_message_zero[$lg['id']] ? $warehouse_message_zero[$lg['id']] : null, - 'warehouse_message_nonzero' => $warehouse_message_nonzero[$lg['id']] ? $warehouse_message_nonzero[$lg['id']] : null, - 'tab_name_1' => $tab_name_1[$lg['id']] ? $tab_name_1[$lg['id']] : null, - 'tab_description_1' => $tab_description_1[$lg['id']] ? $tab_description_1[$lg['id']] : null, - 'tab_name_2' => $tab_name_2[$lg['id']] ? $tab_name_2[$lg['id']] : null, - 'tab_description_2' => $tab_description_2[$lg['id']] ? $tab_description_2[$lg['id']] : null, - 'canonical' => $canonical[$lg['id']] ? $canonical[$lg['id']] : null, - 'meta_title' => $meta_title[$lg['id']] ? $meta_title[$lg['id']] : null, - 'xml_name' => $xml_name[$lg['id']] ? $xml_name[$lg['id']] : null, - 'security_information' => $security_information[$lg['id']] ? $security_information[$lg['id']] : null, - ], [ - 'id' => $translation_id - ] ); - } - else - { - $mdb -> insert( 'pp_shop_products_langs', [ - 'product_id' => (int) $product_id, - 'lang_id' => $lg['id'], - 'name' => $name[$lg['id']] ? $name[$lg['id']] : null, - 'short_description' => $short_description[$lg['id']] ? $short_description[$lg['id']] : null, - 'description' => $description[$lg['id']] ? $description[$lg['id']] : null, - 'meta_description' => $meta_description[$lg['id']] ? $meta_description[$lg['id']] : null, - 'meta_keywords' => $meta_keywords[$lg['id']] ? $meta_keywords[$lg['id']] : null, - 'seo_link' => $seo_link[$lg['id']] ? \S::seo($seo_link[$lg['id']]) : null, - 'copy_from' => $copy_from[$lg['id']] ? $copy_from[$lg['id']] : null, - 'warehouse_message_zero' => $warehouse_message_zero[$lg['id']] ? $warehouse_message_zero[$lg['id']] : null, - 'warehouse_message_nonzero' => $warehouse_message_nonzero[$lg['id']] ? $warehouse_message_nonzero[$lg['id']] : null, - 'tab_name_1' => $tab_name_1[$lg['id']] ? $tab_name_1[$lg['id']] : null, - 'tab_description_1' => $tab_description_1[$lg['id']] ? $tab_description_1[$lg['id']] : null, - 'tab_name_2' => $tab_name_2[$lg['id']] ? $tab_name_2[$lg['id']] : null, - 'tab_description_2' => $tab_description_2[$lg['id']] ? $tab_description_2[$lg['id']] : null, - 'canonical' => $canonical[$lg['id']] ? $canonical[$lg['id']] : null, - 'meta_title' => $meta_title[$lg['id']] ? $meta_title[$lg['id']] : null, - 'xml_name' => $xml_name[$lg['id']] ? $xml_name[$lg['id']] : null, - 'security_information' => $security_information[$lg['id']] ? $security_information[$lg['id']] : null, - ] ); - } - } - - $not_in = [0]; - - if (\is_array($categories)) - { - foreach ($categories as $category) - { - $not_in[] = $category; - } - } - elseif ($categories) - { - $not_in[] = $categories; - } - - $mdb -> delete('pp_shop_products_categories', ['AND' => ['product_id' => (int) $product_id, 'category_id[!]' => $not_in]]); - - $categories_tmp = $mdb -> select('pp_shop_products_categories', 'category_id', ['product_id' => (int) $product_id]); - - if (!\is_array($categories)) - { - $categories = [$categories]; - } - - $categories = array_diff($categories, $categories_tmp); - - if (\is_array($categories)) - { - foreach ($categories as $category) - { - $order = self::max_order() + 1; - - if ( $product_id and $category ) - $mdb -> insert( 'pp_shop_products_categories', [ - 'product_id' => (int)$product_id, - 'category_id' => (int)$category, - 'o' => (int) $order, - ] ); - } - } - - // produkty powiązane - $not_in = [0]; - - if (\is_array($products_related)) - { - foreach ($products_related as $product_related) - { - $not_in[] = $product_related; - } - } - elseif ($products_related) - { - $not_in[] = $products_related; - } - - $mdb -> delete('pp_shop_products_related', ['AND' => ['product_id' => (int) $product_id, 'product_related_id[!]' => $not_in]]); - - $products_related_tmp = $mdb -> select('pp_shop_products_related', 'product_related_id', ['product_id' => (int) $product_id]); - - if (!\is_array($products_related)) - { - $products_related = [$products_related]; - } - - $products_related = array_diff($products_related, $products_related_tmp); - - if (\is_array($products_related)) - { - foreach ($products_related as $product_related) - { - if ($product_id && $product_related) - { - $mdb -> insert('pp_shop_products_related', [ - 'product_id' => (int) $product_id, - 'product_related_id' => (int) $product_related, - ]); - } - } - } - - $created = false; - - $results = $mdb -> select('pp_shop_products_files', '*', ['product_id' => null]); - if (\is_array($results)) - { - foreach ($results as $row) - { - $dir = '/upload/product_files/product_'.$product_id; - - $new_file_name = str_replace('/upload/product_files/tmp', $dir, $row['src']); - - if (file_exists('..'.$row['src'])) - { - if (!is_dir('../'.$dir) && true !== $created) - { - if (mkdir('../'.$dir, 0755, true)) - { - $created = true; - } - } - rename('..'.$row['src'], '..'.$new_file_name); - } - - $mdb -> update('pp_shop_products_files', ['src' => $new_file_name, 'product_id' => (int) $product_id], ['id' => $row['id']]); - } - } - - $results = $mdb -> select('pp_shop_products_files', '*', ['AND' => ['product_id' => (int) $product_id, 'to_delete' => 1]]); - if (\is_array($results)) - { - foreach ($results as $row) - { - if (file_exists('../'.$row['src'])) - { - unlink('../'.$row['src']); - } - } - } - - $mdb -> delete('pp_shop_products_files', ['AND' => ['product_id' => (int) $product_id, 'to_delete' => 1]]); - - $created = false; - - // zdjęcia - $results = $mdb -> select('pp_shop_products_images', '*', ['product_id' => null]); - if (\is_array($results)) - { - foreach ($results as $row) - { - $dir = '/upload/product_images/product_'.$product_id; - - $new_file_name = str_replace('/upload/product_images/tmp', $dir, $row['src']); - - if (file_exists('../'.$new_file_name)) - { - $ext = strrpos($new_file_name, '.'); - $fileName_a = substr($new_file_name, 0, $ext); - $fileName_b = substr($new_file_name, $ext); - - $count = 1; - - while (file_exists('../'.$fileName_a.'_'.$count.$fileName_b)) - { - ++$count; - } - - $new_file_name = $fileName_a.'_'.$count.$fileName_b; - } - - if (file_exists('..'.$row['src'])) - { - if (!is_dir('../'.$dir) && true !== $created) - { - if (mkdir('../'.$dir, 0755, true)) - { - $created = true; - } - } - rename('..'.$row['src'], '..'.$new_file_name); - } - - $mdb -> update('pp_shop_products_images', ['src' => $new_file_name, 'product_id' => (int) $product_id], ['id' => $row['id']]); - } - } - - $results = $mdb -> select('pp_shop_products_images', '*', ['AND' => ['product_id' => (int) $product_id, 'to_delete' => 1]]); - if (\is_array($results)) - { - foreach ($results as $row) - { - if (file_exists('../'.$row['src'])) - { - unlink('../'.$row['src']); - } - } - } - - $mdb -> delete('pp_shop_products_images', ['AND' => ['product_id' => (int) $product_id, 'to_delete' => 1]]); - - // dodatkowe pola - // delete only custom fields that are not in the new list - foreach ( $custom_field_name as $custom_field ) - { - if ( !empty( $custom_field ) ) - { - $exits_custom_ids[] = (int)$mdb -> get( 'pp_shop_products_custom_fields', 'id_additional_field', [ 'AND' => [ 'id_product' => $product_id, 'name' => $custom_field ] ] ); - } - } - - $mdb -> delete( 'pp_shop_products_custom_fields', [ 'AND' => [ 'id_product' => $product_id, 'id_additional_field[!]' => $exits_custom_ids ] ] ); - - // $custom_field_name i $custom_field_required - foreach ( $custom_field_name as $i => $custom_field ) - { - if ( !empty( $custom_field ) ) - { - $custom_field_type_data = $custom_field_type[$i]; - $is_required = !empty( $custom_field_required[$i] ) ? 1 : 0; - - if ( !$mdb -> count( 'pp_shop_products_custom_fields', [ 'AND' => [ 'id_product' => $product_id, 'name' => $custom_field ] ] ) ) - { - $mdb -> insert( 'pp_shop_products_custom_fields', [ - 'id_product' => $product_id, - 'name' => $custom_field, - 'type' => $custom_field_type_data, - 'is_required' => $is_required - ]); - } - else - { - $mdb -> update( 'pp_shop_products_custom_fields', - [ - 'type' => $custom_field_type_data, - 'is_required' => $is_required - ], - [ 'AND' => [ 'id_product' => $product_id, 'name' => $custom_field ] ]); - } - } - } - - \S::htacces(); - - \S::delete_dir( '../temp/' ); - \S::delete_dir( '../thumbs/' ); - - $redis = \RedisConnection::getInstance() -> getConnection(); - if ( $redis ) - $redis -> flushAll(); - - return $product_id; - } - } - - // pobierz prostą listę z ilościami produktu - static public function get_product_quantity_list( int $product_id ) - { - global $mdb; - - return $mdb -> get( 'pp_shop_products', 'quantity', [ 'id' => $product_id ] ); - } - - // ADMIN - szczególy produktu - static public function product_details( int $product_id ) - { - global $mdb; - - if ( $product = $mdb -> get( 'pp_shop_products', '*', [ 'id' => $product_id ] ) ) - { - $results = $mdb -> select( 'pp_shop_products_langs', '*', [ 'product_id' => $product_id ] ); - if ( is_array( $results ) ) foreach ($results as $row) - $product['languages'][ $row['lang_id'] ] = $row; - - $product['images'] = $mdb -> select( 'pp_shop_products_images', '*', [ 'product_id' => $product_id, 'ORDER' => [ 'o' => 'ASC', 'id' => 'ASC' ] ] ); - $product['files'] = $mdb -> select( 'pp_shop_products_files', '*', [ 'product_id' => $product_id ] ); - $product['categories'] = $mdb -> select( 'pp_shop_products_categories', 'category_id', [ 'product_id' => $product_id ] ); - $product['attributes'] = $mdb -> select( 'pp_shop_products_attributes', [ 'attribute_id', 'value_id' ], [ 'product_id' => $product_id ] ); - $product['products_related'] = $mdb -> select( 'pp_shop_products_related', 'product_related_id', [ 'product_id' => $product_id ] ); - $product['custom_fields'] = $mdb -> select( 'pp_shop_products_custom_fields', '*', [ 'id_product' => $product_id ] ); - } - - return $product; - } - - // duplikowanie produktu w panelu administratora - static public function duplicate_product( int $product_id, int $with_combinations = 0 ) - { - global $mdb; - - $product = $mdb -> get( 'pp_shop_products', '*', [ 'id' => $product_id ] ); - if ( $product ) - { - $mdb -> insert( 'pp_shop_products', [ - 'price_netto' => $product['price_netto'], - 'price_brutto' => $product['price_brutto'], - 'price_netto_promo' => $product['price_netto_promo'], - 'price_brutto_promo' => $product['price_brutto_promo'], - 'vat' => $product['vat'], - 'promoted' => $product['promoted'], - 'layout_id' => $product['layout_id'], - 'new_to_date' => $product['new_to_date'], - 'stock_0_buy' => $product['stock_0_buy'], - 'wp' => $product['wp'], - 'custom_label_0' => $product['custom_label_0'], - 'custom_label_1' => $product['custom_label_1'], - 'custom_label_2' => $product['custom_label_2'], - 'custom_label_3' => $product['custom_label_3'], - 'custom_label_4' => $product['custom_label_4'], - 'additional_message' => $product['additional_message'] - ] ); - - $new_product_id = $mdb -> id(); - if ( $new_product_id ) - { - $attributes = $mdb -> select( 'pp_shop_products_attributes', '*', [ 'product_id' => $product_id ] ); - if ( \S::is_array_fix( $attributes ) ) foreach ( $attributes as $row ) - { - $mdb -> insert( 'pp_shop_products_attributes', [ - 'product_id' => $new_product_id, - 'attribute_id' => $row['attribute_id'], - 'value_id' => $row['value_id'] - ] ); - } - - $categories = $mdb -> select( 'pp_shop_products_categories', '*', [ 'product_id' => $product_id ] ); - if ( \S::is_array_fix( $categories ) ) foreach ( $categories as $row ) - { - $mdb -> insert( 'pp_shop_products_categories', [ - 'product_id' => $new_product_id, - 'category_id' => $row['category_id'], - 'o' => $row['o'] - ] ); - } - - $langs = $mdb -> select( 'pp_shop_products_langs', '*', [ 'product_id' => $product_id ] ); - if ( \S::is_array_fix( $langs ) ) foreach ( $langs as $row ) - { - $mdb -> insert( 'pp_shop_products_langs', [ - 'product_id' => $new_product_id, - 'lang_id' => $row['lang_id'], - 'name' => $row['name'] . ' - kopia', - 'short_description' => $row['short_description'], - 'description' => $row['description'], - 'tab_name_1' => $row['tab_name_1'], - 'tab_description_1' => $row['tab_description_1'], - 'tab_name_2' => $row['tab_name_2'], - 'tab_description_2' => $row['tab_description_2'], - 'meta_description' => $row['meta_description'], - 'meta_keywords' => $row['meta_keywords'], - 'copy_from' => $row['copy_from'], - 'warehouse_message_zero' => $row['warehouse_message_zero'], - 'warehouse_message_nonzero' => $row['warehouse_message_nonzero'] - ] ); - } - - // custom fields - $custom_fields = $mdb -> select( 'pp_shop_products_custom_fields', '*', [ 'id_product' => $product_id ] ); - if ( \S::is_array_fix( $custom_fields ) ) foreach ( $custom_fields as $row ) - { - $mdb -> insert( 'pp_shop_products_custom_fields', [ - 'id_product' => $new_product_id, - 'name' => $row['name'] - ] ); - } - } - - // duplikowanie kombinacji produktu - if ( $with_combinations ) - { - $product_combinations = $mdb -> select( 'pp_shop_products', '*', [ 'parent_id' => $product_id ] ); - foreach ( $product_combinations as $product_combination ) - { - $mdb -> insert( 'pp_shop_products', [ - 'parent_id' => $new_product_id, - 'permutation_hash' => $product_combination['permutation_hash'], - 'price_netto' => $product_combination['price_netto'], - 'price_brutto' => $product_combination['price_brutto'], - 'price_netto_promo' => $product_combination['price_netto_promo'], - 'price_brutto_promo' => $product_combination['price_brutto_promo'], - 'vat' => $product_combination['vat'], - 'stock_0_buy' => $product_combination['stock_0_buy'], - 'quantity' => $product_combination['quantity'], - 'wp' => $product_combination['wp'], - 'additional_message' => $product_combination['additional_message'], - 'additional_message_text' => $product_combination['additional_message_text'], - 'additional_message_required' => $product_combination['additional_message_required'] - ] ); - - $combination_id = $mdb -> id(); - if ( $combination_id ) - { - $pp_shop_products_attributes = $mdb -> select( 'pp_shop_products_attributes', '*', [ 'product_id' => $product_combination['id'] ] ); - foreach ( $pp_shop_products_attributes as $pp_shop_products_attribute ) - { - $mdb -> insert( 'pp_shop_products_attributes', [ - 'product_id' => $combination_id, - 'attribute_id' => $pp_shop_products_attribute['attribute_id'], - 'value_id' => $pp_shop_products_attribute['value_id'] - ] ); - } - } - } - } - - return true; - } - return false; - } - - // - // KOMBINACJE PRODUKTU - // - - static public function product_combination_stock_0_buy_save( int $product_id, $stock_0_buy ) - { - global $mdb; - return $mdb -> update( 'pp_shop_products', [ 'stock_0_buy' => $stock_0_buy == 'true' ? 1 : 0 ], [ 'id' => $product_id ] ); - } - - static public function product_combination_sku_save( int $product_id, $sku ) - { - global $mdb; - return $mdb -> update( 'pp_shop_products', [ 'sku' => $sku ], [ 'id' => $product_id ] ); - } - - static public function product_combination_quantity_save( int $product_id, $quantity ) - { - global $mdb; - return $mdb -> update( 'pp_shop_products', [ 'quantity' => $quantity == '' ? $quantity = null : $quantity = (int) $quantity ], [ 'id' => $product_id ] ); - } - - static public function product_combination_price_save( int $product_id, $price_netto ) - { - global $mdb; - - $vat = $mdb -> get( 'pp_shop_products', 'vat', [ 'id' => $product_id ] ); - - $price_brutto = $price_netto * ( 1 + ( $vat / 100 ) ); - - return $mdb -> update( 'pp_shop_products', [ 'price_netto' => $price_netto == '' ? $price_netto = null : $price_netto = (float) $price_netto, 'price_brutto' => $price_brutto == '' ? $price_brutto = null : $price_brutto = (float) $price_brutto ], [ 'id' => $product_id ] ); - } - - // aktualizacja ceny produktu pod wpływem zmiany ceny wartości atrybutu - static public function update_product_price_by_attribute_value_impact( $value_id, $impact_on_the_price ) - { - global $mdb; - - $products = $mdb -> select( 'pp_shop_products_attributes', [ 'product_id' ], [ 'value_id' => $value_id ] ); - if ( is_array( $products ) ) foreach ( $products as $row ) - { - $parent_id = $mdb -> get( 'pp_shop_products', 'parent_id', [ 'id' => $row['product_id'] ] ); - $product = $mdb -> get( 'pp_shop_products', '*', [ 'id' => $parent_id ] ); - if ( $product ) - { - $price_brutto = $product['price_brutto'] + \S::normalize_decimal( $impact_on_the_price ); - $price_netto = \S::normalize_decimal( $price_brutto / ( 1 + ( $product['vat'] / 100 ) ) ); - - if ( $product['price_netto_promo'] ) - { - $price_brutto_promo = $product['price_brutto_promo'] + \S::normalize_decimal( $impact_on_the_price ); - $price_netto_promo = \S::normalize_decimal( $price_brutto_promo / ( 1 + ( $product['vat'] / 100 ) ) ); - } - else - { - $price_netto_promo = null; - $price_brutto_promo = null; - } - - if ( $impact_on_the_price > 0 ) - { - $mdb -> update( 'pp_shop_products', [ 'price_netto' => $price_netto, 'price_brutto' => $price_brutto, 'price_netto_promo' => $price_netto_promo, 'price_brutto_promo' => $price_brutto_promo, 'date_modify' => date( 'Y-m-d H:i:s' ) ], [ 'id' => $row['product_id'] ] ); - } - else if ( isset( $impact_on_the_price ) && $impact_on_the_price == 0 && $impact_on_the_price != '' ) - { - $mdb -> update( 'pp_shop_products', [ 'price_netto' => null, 'price_brutto' => null, 'price_netto_promo' => null, 'price_brutto_promo' => null, 'quantity' => null, 'stock_0_buy' => null, 'date_modify' => date( 'Y-m-d H:i:s' ) ], [ 'id' => $row['product_id'] ] ); - } - } - } - } -} diff --git a/temp/update_build/tmp_0.275/docs/CHANGELOG.md b/temp/update_build/tmp_0.275/docs/CHANGELOG.md deleted file mode 100644 index 2bc9e81..0000000 --- a/temp/update_build/tmp_0.275/docs/CHANGELOG.md +++ /dev/null @@ -1,458 +0,0 @@ -# Changelog shopPRO - -Logi zmian z migracji na Domain-Driven Architecture. Najnowsze na gorze. - ---- - -## ver. 0.275 (2026-02-15) - ShopCategory - -- **ShopCategory** - migracja `/admin/shop_category/*` na Domain + DI + nowe endpointy AJAX - - NOWE: `Domain\Category\CategoryRepository` (`sortTypes`, `subcategories`, `categoryDetails`, `categoryProducts`, `save`, `categoryDelete`, `saveCategoriesOrder`, `saveProductOrder`, `categoryTitle`) - - NOWE: `admin\Controllers\ShopCategoryController` (DI) z akcjami `list/view_list`, `edit/category_edit`, `save`, `delete/category_delete`, `products/category_products`, `category_url_browser`, `save_categories_order`, `save_products_order`, `cookie_categories` - - UPDATE: routing DI (`admin\Site`) rozszerzony o modul `ShopCategory` - - UPDATE: menu admin przepiete na kanoniczny URL `/admin/shop_category/list/` - - UPDATE: widoki `shop-category/*` - wydzielenie skryptow do `*-custom-script.php`, ujednolicone strzalki drzewa (`button + caret + aria-expanded`) - - UPDATE: AJAX drzewek przepiety z `/admin/ajax.php?a=*` na `/admin/shop_category/*` - - UPDATE: zaleznosci `ShopProduct` przepiete z `admin\factory\ShopCategory` na `Domain\Category\CategoryRepository` - - CLEANUP: usuniete legacy `autoload/admin/controls/class.ShopCategory.php`, `autoload/admin/factory/class.ShopCategory.php`, `autoload/admin/view/class.ShopCategory.php` - - CLEANUP: usuniety preload `class.ShopCategory.php` z `libraries/grid/config.php` -- TEST: - - NOWE: `tests/Unit/Domain/Category/CategoryRepositoryTest.php` - - NOWE: `tests/Unit/admin/Controllers/ShopCategoryControllerTest.php` - - Testy punktowe: **OK (16 tests, 72 assertions)** - ---- - -## ver. 0.274 (2026-02-15) - ShopProduct mass_edit + UI trees - -- **ShopProduct (mass_edit)** - migracja akcji masowej edycji na Domain + DI - - NOWE: `admin\Controllers\ShopProductController` (DI) z akcjami `mass_edit`, `mass_edit_save`, `get_products_by_category` - - UPDATE: routing DI (`admin\Site`) rozszerzony o modul `ShopProduct` - - UPDATE: `Domain\Product\ProductRepository` rozszerzone o metody `allProductsForMassEdit`, `getProductsByCategory`, `applyDiscountPercent` (+ aktualizacja cen kombinacji) - - CLEANUP: usuniete legacy akcje `mass_edit`, `mass_edit_save`, `get_products_by_category` z `admin\controls\ShopProduct` -- **ShopProduct mass_edit UI** - przebudowa widoku i skryptu - - UPDATE: `admin/templates/shop-product/mass-edit.php` przepiety na nowy partial JS `mass-edit-custom-script` - - NOWE: `admin/templates/shop-product/mass-edit-custom-script.php` (nestedSortable + iCheck + stabilizacja drzewka) - - UPDATE: `admin/templates/shop-product/subcategories-list.php` ujednolicone strzalki (button + caret) - - FIX: zaznaczenie kategorii w drzewku nie zaznacza automatycznie produktow na liscie -- **Pages / Articles UI** - ujednolicenie drzewek - - UPDATE: `/admin/pages/list/` - nowe strzalki drzewa + `aria-expanded` + odswiezanie stanu branch/leaf - - UPDATE: `/admin/articles/edit/*` (zakladka wyswietlania) - nowe strzalki i checkboxy (iCheck) dla drzewka stron -- **ShopClients** - migracja `/admin/shop_clients` na Domain + DI + nowe widoki - - NOWE: `Domain\Client\ClientRepository` (`listForAdmin`, `ordersForClient`, `totalsForClient`) - - NOWE: `admin\Controllers\ShopClientsController` (DI) z akcjami `list`, `details` + aliasy legacy `view_list`, `clients_details` - - UPDATE: routing DI (`admin\Site`) rozszerzony o modul `ShopClients` - - UPDATE: menu admin przepiete na kanoniczny URL `/admin/shop_clients/list/` - - UPDATE: widoki `shop-clients/view-list` i `shop-clients/clients-details` przepiete na `components/table-list` - - CLEANUP: usuniete legacy `autoload/admin/controls/class.ShopClients.php`, `autoload/admin/factory/class.ShopClients.php` -- TEST: - - NOWE: `tests/Unit/admin/Controllers/ShopProductControllerTest.php` - - NOWE: `tests/Unit/Domain/Client/ClientRepositoryTest.php`, `tests/Unit/admin/Controllers/ShopClientsControllerTest.php` - - UPDATE: `tests/Unit/Domain/Product/ProductRepositoryTest.php` (nowe przypadki dla mass_edit) - - UPDATE: `tests/bootstrap.php` (stub `S::normalize_decimal()`) -- Testy: **OK (361 tests, 1125 assertions)** - ---- - -## ver. 0.273 (2026-02-15) - ShopProducer - -- **ShopProducer** - migracja `/admin/shop_producer` na Domain + DI + nowe widoki - - NOWE: `Domain\Producer\ProducerRepository` (`listForAdmin`, `find`, `save`, `delete`, `allProducers`, `findForFrontend`, `producerProducts`, `allActiveIds`) - - NOWE: `admin\Controllers\ShopProducerController` (DI) z akcjami `list`, `edit`, `save`, `delete` - - UPDATE: modul `/admin/shop_producer/*` dziala na `components/table-list` i `components/form-edit` z zakladkami jezykowymi (Opis + SEO) - - UPDATE: routing i menu admin na kanoniczny URL `/admin/shop_producer/list/` - - UPDATE: `shop\Producer` przepiety na fasade do `Domain\Producer\ProducerRepository` - - UPDATE: `admin\factory\ShopProduct` - 2 wywolania `admin\factory\ShopTransport` przepiete na `Domain\Transport\TransportRepository` - - UPDATE: `admin\controls\ShopProduct` - usuniety fallback do `admin\factory\Layouts` - - CLEANUP: usuniete legacy `autoload/admin/controls/class.ShopProducer.php`, `admin/templates/shop-producer/list.php`, `admin/templates/shop-producer/edit.php` - - CLEANUP: usuniete 6 pustych factory facades: `admin\factory\Languages`, `admin\factory\Newsletter`, `admin\factory\Scontainers`, `admin\factory\ShopProducer`, `admin\factory\ShopTransport`, `admin\factory\Layouts` - - TEST: dodane `tests/Unit/Domain/Producer/ProducerRepositoryTest.php` i `tests/Unit/admin/Controllers/ShopProducerControllerTest.php` -- Testy: **OK (338 tests, 1063 assertions)** - ---- - -## ver. 0.272 (2026-02-15) - ShopProductSets - -- **ShopProductSets** - migracja `/admin/shop_product_sets` na Domain + DI + nowe widoki - - NOWE: `Domain\ProductSet\ProductSetRepository` (`listForAdmin`, `find`, `save`, `delete`, `allSets`, `allProductsMap`) - - NOWE: `admin\Controllers\ShopProductSetsController` (DI) z akcjami `list`, `edit`, `save`, `delete` - - UPDATE: modul `/admin/shop_product_sets/*` dziala na `components/table-list` i `components/form-edit` + Selectize multi-select produktow - - UPDATE: routing i menu admin na kanoniczny URL `/admin/shop_product_sets/list/` - - UPDATE: `shop\ProductSet` przepiety na fasade do `Domain\ProductSet\ProductSetRepository` - - CLEANUP: usuniete legacy `autoload/admin/controls/class.ShopProductSets.php`, `autoload/admin/factory/class.ShopProductSet.php`, `admin/templates/shop-product-sets/view-list.php`, `admin/templates/shop-product-sets/set-edit.php` - - TEST: dodane `tests/Unit/Domain/ProductSet/ProductSetRepositoryTest.php` i `tests/Unit/admin/Controllers/ShopProductSetsControllerTest.php` -- Testy: **OK (324 tests, 1000 assertions)** - ---- - -## ver. 0.271 (2026-02-14) - ShopAttribute - -- **ShopAttribute** - migracja `/admin/shop_attribute` na Domain + DI + nowe widoki - - NOWE: `Domain\Attribute\AttributeRepository` (`listForAdmin`, `findAttribute`, `saveAttribute`, `deleteAttribute`, `findValues`, `saveValues`, `saveLegacyValues`, `valueDetails`) - - NOWE: `admin\Controllers\ShopAttributeController` (DI) z akcjami `list`, `edit`, `save`, `delete`, `values`, `values_save`, `value_row_tpl` - - UPDATE: modul `/admin/shop_attribute/*` dziala na `components/table-list` i `components/form-edit` - - UPDATE: nowy edytor wartosci cechy (`values-edit`) z walidacja serwerowa i stabilnym `row_key` (bez indeksow do wyboru domyslnej wartosci) - - UPDATE: routing i menu admin na kanoniczny URL `/admin/shop_attribute/list/` (bez aliasow legacy) - - UPDATE: przepiecie zaleznosci kombinacji produktu (`admin\controls\ShopProduct`, `admin\factory\ShopProduct`, `admin/templates/shop-product/product-combination.php`) na `Domain\Attribute\AttributeRepository` i `shop\ProductAttribute` - - CLEANUP: usuniete legacy `autoload/admin/controls/class.ShopAttribute.php`, `autoload/admin/factory/class.ShopAttribute.php`, `autoload/admin/view/class.ShopAttribute.php`, `admin/templates/shop-attribute/_partials/value.php` - - TEST: dodane `tests/Unit/Domain/Attribute/AttributeRepositoryTest.php` i `tests/Unit/admin/Controllers/ShopAttributeControllerTest.php` -- Testy: **OK (312 tests, 948 assertions)** - ---- - -## ver. 0.270 (2026-02-14) - Apilo payment/status sync hardening - -- **Shop/Order + Apilo** - utwardzenie synchronizacji platnosci i statusow zamowien - - FIX: `shop\Order::set_as_paid()` wysyla do Apilo mapowany typ platnosci (`payment_method_id` -> `apilo_payment_type_id`) zamiast stalego `type = 1` - - NOWE: retry queue dla chwilowej niedostepnosci Apilo (`temp/apilo-sync-queue.json`) dla sync platnosci i statusu - - NOWE: `shop\Order::process_apilo_sync_queue()` przetwarza zalegle syncy - - UPDATE: `cron.php` uruchamia przetwarzanie kolejki sync Apilo przy aktywnej integracji - - UPDATE: rozszerzone logowanie debug (`logs/apilo.txt`) o HTTP code i bledy cURL dla sync platnosci/statusu -- Testy: **OK (300 tests, 895 assertions)** - ---- - -## ver. 0.269 (2026-02-14) - ShopTransport - -- **ShopTransport** - migracja `/admin/shop_transport` na Domain + DI + nowe widoki - - NOWE: `Domain\Transport\TransportRepository` (`listForAdmin`, `find`, `save`, `allActive`, `allForAdmin`, `findActiveById`, `getTransportCost`, `lowestTransportPrice`, `getApiloCarrierAccountId`) - - NOWE: `admin\Controllers\ShopTransportController` (DI) z akcjami `list`, `edit`, `save` - - NOWE: widoki `shop-transport/transports-list.php` i `shop-transport/transport-edit.php` + `transport-edit-custom-script.php` - - UPDATE: routing i menu admin na kanoniczny URL `/admin/shop_transport/list/` - - UPDATE: `admin\factory\ShopTransport`, `front\factory\ShopTransport` przepiete na nowe repozytorium - - FIX: `save()` return type `?int` zamiast `int|bool` (spojnosc z PaymentMethod) - - FIX: `toSwitchValue()` helper zamiast `=== 'on'` (obsluga '1', 'on', 'true', 'yes') - - FIX: `\S::delete_dir()` przeniesione z repozytorium do kontrolera (DDD) - - FIX: Medoo `select()` syntax - ORDER w WHERE zamiast 4-arg form - - CLEANUP: usuniete legacy `autoload/admin/controls/class.ShopTransport.php`, `autoload/admin/view/class.ShopTransport.php`, `admin/templates/shop-transport/view-list.php` - - FIX: `transports-list.php` - zmienna `'viewModel'` zmieniona na `'list'` (zgodnie z `table-list.php` komponentem) -- Testy: **OK (300 tests, 895 assertions)** - ---- - -## ver. 0.268 (2026-02-14) - ShopPaymentMethod + Apilo token keepalive - -- **ShopPaymentMethod** - migracja `/admin/shop_payment_method` na Domain + DI + nowe widoki - - NOWE: `Domain\PaymentMethod\PaymentMethodRepository` (`listForAdmin`, `find`, `save`, `allActive`, `allForAdmin`, `findActiveById`, `isActive`, `getApiloPaymentTypeId`, `forTransport`) - - NOWE: `admin\Controllers\ShopPaymentMethodController` (DI) z akcjami `list`, `edit`, `save` - - NOWE: widoki `shop-payment-method/payment-methods-list.php` i `shop-payment-method/payment-method-edit.php` - - UPDATE: routing i menu admin na kanoniczny URL `/admin/shop_payment_method/list/` - - UPDATE: `admin\controls\ShopTransport`, `front\factory\ShopPaymentMethod`, `shop\PaymentMethod` przepiete na nowe repozytorium - - CLEANUP: usuniete legacy `autoload/admin/controls/class.ShopPaymentMethod.php`, `autoload/admin/factory/class.ShopPaymentMethod.php`, `autoload/admin/view/class.ShopPaymentMethod.php`, `admin/templates/shop-payment-method/view-list.php` -- **Integrations/Apilo** - stabilizacja tokenu i lepszy feedback - - NOWE: automatyczne odswiezanie tokenu Apilo przed wygasnieciem (`apiloKeepalive`, refresh lead time) - - UPDATE: cron uruchamia keepalive i odswieza konfiguracje Apilo - - UPDATE: bardziej szczegolowe komunikaty bledow dla przyciskow integracji Apilo (co zrobic dalej) -- Testy: **OK (280 tests, 828 assertions)** - ---- - -## ver. 0.267 (2026-02-14) - ShopStatuses - -- **ShopStatuses** - migracja `/admin/shop_statuses` na Domain + DI + nowe widoki - - NOWE: `Domain\ShopStatus\ShopStatusRepository` (`listForAdmin`, `find`, `save`, `getApiloStatusId`, `getByIntegrationStatusId`, `allStatuses`) - - NOWE: `admin\Controllers\ShopStatusesController` (DI) z akcjami `list`, `edit`, `save` (bez aliasow legacy) - - NOWE: typ pola `FormFieldType::COLOR` + `FormField::color()` + `FormFieldRenderer::renderColor()` (color picker HTML5 zsynchronizowany z polem tekstowym) - - UPDATE: modul `/admin/shop_statuses/*` dziala na `components/table-list` i `components/form-edit` - - UPDATE: `front\factory\ShopStatuses` jako fasada delegujaca do `Domain\ShopStatus\ShopStatusRepository` - - UPDATE: menu admin przepiete na kanoniczny URL `/admin/shop_statuses/list/` - - CLEANUP: usuniete legacy `autoload/admin/controls/class.ShopStatuses.php`, `autoload/admin/factory/class.ShopStatuses.php` - - UWAGA: statusy maja ID od 0 - kluczowe dla walidacji (find/save uzywaja `$id < 0`) -- Testy: **OK (254 tests, 736 assertions)** - ---- - -## ver. 0.266 (2026-02-13) - ShopCoupon - -- **ShopCoupon** - migracja `/admin/shop_coupon` na Domain + DI + nowe widoki - - NOWE: `Domain\Coupon\CouponRepository` (`listForAdmin`, `find`, `save`, `delete`, `categoriesTree`) - - NOWE: `admin\Controllers\ShopCouponController` (DI) z akcjami `list`, `edit`, `save`, `delete` - - UPDATE: kompatybilnosc aliasow legacy (`view_list`, `coupon_edit`, `coupon_save`, `coupon_delete`) obslugiwana przez nowy kontroler - - UPDATE: modul `/admin/shop_coupon/*` dziala na `components/table-list` i `components/form-edit` - - NOWE: widoki/partiale `shop-coupon/coupons-list`, `shop-coupon/coupon-edit-new`, `shop-coupon/coupon-categories-selector`, `shop-coupon/coupon-categories-tree`, `shop-coupon/coupon-edit-custom-script` - - CLEANUP: usuniete legacy `autoload/admin/controls/class.ShopCoupon.php`, `autoload/admin/factory/class.ShopCoupon.php`, `admin/templates/shop-coupon/view-list.php`, `admin/templates/shop-coupon/coupon-edit.php` - - UPDATE: menu admin przepiete na kanoniczny URL `/admin/shop_coupon/list/` - - FIX: ujednolicone UI drzewek i checkboxow miedzy kuponami i layoutami -- Testy: **OK (235 tests, 682 assertions)** - ---- - -## ver. 0.265 (2026-02-13) - ShopPromotion poprawki - -- **ShopPromotion** - stabilizacja po migracji - - UPDATE: dodane `date_from` w `Domain\Promotion\PromotionRepository` (save/find/list/sort) - - UPDATE: `admin\Controllers\ShopPromotionController` rozszerzony o pole `Data od` na formularzu i kolumne `Data od` na liscie - - UPDATE: `shop\Promotion::get_active_promotions()` filtruje aktywnosc po `date_from` i `date_to` - - FIX: zapis edycji promocji nie tworzy nowego rekordu (hidden `id` + fallback `id` z URL) - - TEST: rozszerzono `PromotionRepositoryTest` o asercje `date_from` -- Testy: **OK (222 tests, 614 assertions)** - ---- - -## ver. 0.264 (2026-02-13) - ShopPromotion - -- **ShopPromotion** - migracja `/admin/shop_promotion` na Domain + DI + nowe widoki - - NOWE: `Domain\Promotion\PromotionRepository` (`listForAdmin`, `find`, `save`, `delete`, `categoriesTree`, invalidacja cache aktywnych promocji) - - NOWE: `admin\Controllers\ShopPromotionController` (DI) z akcjami `list`, `edit`, `save`, `delete` - - UPDATE: routing DI (`admin\Site`) rozszerzony o modul `ShopPromotion` - - UPDATE: modul `/admin/shop_promotion/*` dziala na `components/table-list` i `components/form-edit` - - NOWE: widoki/partiale `shop-promotion/promotions-list`, `shop-promotion/promotion-edit`, `shop-promotion/promotion-categories-selector`, `shop-promotion/promotion-categories-tree`, `shop-promotion/promotion-edit-custom-script` - - CLEANUP: usuniete legacy `autoload/admin/controls/class.ShopPromotion.php`, `autoload/admin/factory/class.ShopPromotion.php`, `admin/templates/shop-promotion/view-list.php` - - UPDATE: menu admin przepiete na kanoniczny URL `/admin/shop_promotion/list/` -- Testy: **OK (222 tests, 609 assertions)** - ---- - -## ver. 0.263 (2026-02-13) - Integrations + cleanup Sellasist/Baselinker - -- NOWE: `Domain\Integrations\IntegrationsRepository` (settings Apilo/ShopPRO, OAuth, product linking, API fetch) -- NOWE: `admin\Controllers\IntegrationsController` (DI) dla akcji Apilo i ShopPRO -- UPDATE: `admin\factory\Integrations` jako fasada delegujaca do repozytorium -- **CLEANUP: usunieto integracje Sellasist i Baselinker z calego projektu:** - - Usuniete klasy: `admin\controls\Integrations`, `admin\controls\Baselinker`, `admin\factory\Baselinker`, `front\factory\Shop`, `shop\ShopStatus` - - Usuniete szablony: `integrations/sellasist-settings.php`, `integrations/baselinker-settings.php`, `admin/templates/baselinker/` - - Wyczyszczone referencje w: `cron.php`, `cron/cron-xml.php`, `shop\Order`, kontrolery/factory/front Shop* -- Testy: **OK (212 tests, 577 assertions)** - ---- - -## ver. 0.262 (2026-02-13) - Pages - -- NOWE: `Domain\Pages\PagesRepository` (CRUD menu/stron, drzewo stron, sortowanie, SEO) -- NOWE: `admin\Controllers\PagesController` (DI) dla akcji menu/page/AJAX -- UPDATE: widoki `admin/templates/pages/*` przepiete na dane z kontrolera/repozytorium -- UPDATE: endpointy AJAX przepiete z `admin/ajax.php?a=*` na `/admin/pages/*` -- CLEANUP: usuniete legacy `controls/Pages`, `view/Pages`, `factory/Pages`, `ajax/pages.php` -- Testy: **OK (186 tests, 478 assertions)** - ---- - -## ver. 0.261 (2026-02-13) - Articles (dalsza refaktoryzacja) - -- UPDATE: `Domain\Article\ArticleRepository` rozszerzone o metody UI/admin i `saveFilesOrder()` -- UPDATE: `admin\Controllers\ArticlesController` obsluguje AJAX: `article_image_alt_change`, `article_file_name_change`, `article_image_delete`, `article_file_delete`, `filesOrderSave` -- UPDATE: lista artykulow nie korzysta juz z `admin\factory\Articles::article_pages()` -- UPDATE: widok edycji przepiety z `/admin/ajax.php` na `/admin/articles/*` -- UPDATE: drag&drop sortowania listy zalacznikow -- CLEANUP: usuniete `autoload/admin/view/class.Articles.php` i `admin/ajax/articles.php` -- Testy: **OK (178 tests, 443 assertions)** - ---- - -## ver. 0.260 (2026-02-12) - ArticlesArchive - -- NOWE: `admin\Controllers\ArticlesArchiveController` (DI) -- UPDATE: `Domain\Article\ArticleRepository` rozszerzone o `listArchivedForAdmin()`, `restore()`, `deletePermanently()` -- UPDATE: `/admin/articles_archive/view_list/` migrowane na `components/table-list` -- CLEANUP: usuniete legacy `controls/ArticlesArchive`, `factory/ArticlesArchive`, `view/ArticlesArchive` -- Testy: **OK (165 tests, 424 assertions)** - ---- - -## ver. 0.259 (2026-02-12) - Scontainers - -- NOWE: `Domain\Scontainers\ScontainersRepository` (listForAdmin, find, save, delete, detailsForLanguage) -- NOWE: `admin\Controllers\ScontainersController` (DI) -- UPDATE: `/admin/scontainers/*` migrowane na `components/table-list` i `components/form-edit` -- UPDATE: `admin\factory\Scontainers` i `front\factory\Scontainers` jako fasady -- CLEANUP: usuniete `controls/Scontainers`, `view/Scontainers` -- Testy: **OK (158 tests, 397 assertions)** - ---- - -## ver. 0.258 (2026-02-12) - Newsletter (stabilizacja) - -- UPDATE: tymczasowo wylaczono flow `prepare/send/preview` (wymaga przebudowy) -- UPDATE: tymczasowo wylaczono modul `Szablony uzytkownika` -- UPDATE: aktywna obsluga tylko szablonow administracyjnych (`is_admin = 1`) -- CLEANUP: usuniete nieuzywane widoki `prepare.php`, `preview.php`, `email-templates-user.php` - ---- - -## ver. 0.257 (2026-02-12) - Newsletter - -- NOWE: `Domain\Newsletter\NewsletterRepository` (subskrybenci, szablony, ustawienia, kolejka wysylki) -- NOWE: `Domain\Newsletter\NewsletterPreviewRenderer` (render podgladu) -- NOWE: `admin\Controllers\NewsletterController` (DI) -- UPDATE: `/admin/newsletter/*` migrowane na `components/table-list` i `components/form-edit` -- UPDATE: `admin\factory\Newsletter` jako fasada; `front\factory\Newsletter` bez `admin\view\Newsletter` -- CLEANUP: usuniete `controls/Newsletter`, `view/Newsletter` -- Testy: **OK (150 tests, 372 assertions)** - ---- - -## ver. 0.256 (2026-02-12) - Layouts - -- NOWE: `Domain\Layouts\LayoutsRepository` (find, save, delete, listForAdmin, menusWithPages, categoriesTree) -- NOWE: `admin\Controllers\LayoutsController` (DI) -- UPDATE: lista `/admin/layouts/view_list/` migrowana na `components/table-list` -- UPDATE: widok `layouts/layout-edit` korzysta z danych z repozytorium -- NOWE: partial `admin/templates/layouts/subcategories-list.php` -- UPDATE: `Domain\Languages\LanguagesRepository::defaultLanguageId()` jako wspolna metoda -- UPDATE: `ArticlesController` korzysta z `LayoutsRepository` (DI) -- CLEANUP: usuniete `controls/Layouts`, `view/Layouts`; `factory/Layouts` jako fasada -- Testy: **OK (141 tests, 336 assertions)** - ---- - -## ver. 0.255 (2026-02-12) - Languages DI cleanup - -- UPDATE: SettingsController, BannerController, DictionariesController, ArticlesController pobieraja liste jezykow przez `Domain/Languages/LanguagesRepository` (DI) -- UPDATE: router DI przekazuje `LanguagesRepository` do kontrolerow -- UPDATE: legacy `admin/controls`, `admin/factory/Shop*` przepiete na `LanguagesRepository` -- FIX: `admin/factory/class.Languages.php` poprawione na ` | Kolumny dynamiczne per jezyk (np. pl, en) | - -**Uzywane w:** `Domain\\Languages\\LanguagesRepository`, `admin\\Controllers\\LanguagesController`, `front\\factory\\Languages` - -**Aktualizacja 2026-02-12:** modul jezykow i tlumaczen (`pp_langs`, `pp_langs_translations`) obslugiwany przez `Domain\\Languages\\LanguagesRepository`. - -## pp_layouts -Szablony layoutow (HTML/CSS/JS + flagi domyslne). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| name | Nazwa szablonu | -| html | Kod HTML | -| css | Kod CSS | -| js | Kod JS | -| m_html | Kod HTML mobilny | -| m_css | Kod CSS mobilny | -| m_js | Kod JS mobilny | -| status | Domyslny layout stron (0/1) | -| categories_default | Domyslny layout kategorii (0/1) | - -**Uzywane w:** `Domain\\Layouts\\LayoutsRepository`, `admin\\Controllers\\LayoutsController`, `front\\factory\\Layouts` - -## pp_layouts_pages -Przypisanie layoutow do stron CMS. - -| Kolumna | Opis | -|---------|------| -| layout_id | FK do pp_layouts | -| page_id | FK do pp_pages | - -**Uzywane w:** `Domain\\Layouts\\LayoutsRepository`, `front\\factory\\Layouts` - -## pp_layouts_categories -Przypisanie layoutow do kategorii sklepu. - -| Kolumna | Opis | -|---------|------| -| layout_id | FK do pp_layouts | -| category_id | FK do pp_shop_categories | - -**Uzywane w:** `Domain\\Layouts\\LayoutsRepository`, `front\\factory\\Layouts` - -**Aktualizacja 2026-02-12 (ver. 0.256):** modul `/admin/layouts` korzysta z `Domain\\Layouts\\LayoutsRepository` (DI kontroler + fasada legacy). - -## pp_newsletter -Adresy e-mail zapisane do newslettera. - -| Kolumna | Opis | -|---------|------| -| id | PK | -| email | Adres e-mail subskrybenta | -| hash | Hash potwierdzenia/wypisu | -| status | 1 = potwierdzony, 0 = oczekujacy | - -**Uzywane w:** `Domain\\Newsletter\\NewsletterRepository`, `front\\factory\\Newsletter` - -## pp_newsletter_send -Kolejka wysylki newslettera. - -| Kolumna | Opis | -|---------|------| -| id | PK | -| email | Adres docelowy | -| dates | Zakres dat artykulow (tekst) | -| id_template | FK do `pp_newsletter_templates` (NULL gdy brak szablonu) | - -**Uzywane w:** `Domain\\Newsletter\\NewsletterRepository`, `front\\factory\\Newsletter::newsletter_send()` - -## pp_newsletter_templates -Szablony tresci e-maili (uzytkownik + administracyjne/systemowe). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| name | Nazwa/klucz szablonu | -| text | Tresc HTML szablonu | -| is_admin | 1 = szablon administracyjny/systemowy, 0 = szablon uzytkownika | - -**Uzywane w:** `Domain\\Newsletter\\NewsletterRepository`, `admin\\Controllers\\NewsletterController`, `front\\factory\\Newsletter` - -**Aktualizacja 2026-02-12 (ver. 0.257):** modul `/admin/newsletter` korzysta z `Domain\\Newsletter\\NewsletterRepository` (DI kontroler + fasada legacy). - -## pp_scontainers -Kontenery statyczne (modul /admin/scontainers). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| status | 1 = aktywny, 0 = nieaktywny | -| show_title | 1 = pokaz tytul, 0 = ukryj tytul | - -**Uzywane w:** `Domain\Scontainers\ScontainersRepository`, `admin\Controllers\ScontainersController`, `front\factory\Scontainers` - -## pp_scontainers_langs -Tlumaczenia kontenerow statycznych (per jezyk). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| container_id | FK do pp_scontainers | -| lang_id | ID jezyka (np. pl, en) | -| title | Tytul kontenera | -| text | Tresc HTML kontenera | - -**Uzywane w:** `Domain\Scontainers\ScontainersRepository`, `front\factory\Scontainers` - -**Aktualizacja 2026-02-12 (ver. 0.259):** modul `/admin/scontainers` korzysta z `Domain\Scontainers\ScontainersRepository` (DI kontroler + fasada legacy). - -**Aktualizacja 2026-02-12 (ver. 0.260):** modul `/admin/articles_archive` korzysta z `Domain\Article\ArticleRepository` (`listArchivedForAdmin`, `restore`, `deletePermanently`) przez `admin\Controllers\ArticlesArchiveController`. - -## pp_shop_attributes -Cechy produktu (modul `/admin/shop_attribute`). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| status | Status: 1 = aktywny, 0 = nieaktywny | -| type | Typ cechy: 0 = tekst, 1 = kolor, 2 = wzor | -| o | Kolejnosc wyswietlania | - -**Uzywane w:** `Domain\Attribute\AttributeRepository`, `admin\Controllers\ShopAttributeController`, `admin\controls\ShopProduct`, `admin\factory\ShopProduct` - -## pp_shop_attributes_langs -Tlumaczenia cech produktu (per jezyk). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| attribute_id | FK do pp_shop_attributes | -| lang_id | ID jezyka (np. pl, en) | -| name | Nazwa cechy | - -**Uzywane w:** `Domain\Attribute\AttributeRepository`, `shop\ProductAttribute` - -## pp_shop_attributes_values -Wartosci cech produktu. - -| Kolumna | Opis | -|---------|------| -| id | PK | -| attribute_id | FK do pp_shop_attributes | -| is_default | Czy wartosc domyslna dla cechy (0/1) | -| impact_on_the_price | Wplyw na cene wariantu (NULL = brak) | - -**Uzywane w:** `Domain\Attribute\AttributeRepository`, `admin\Controllers\ShopAttributeController`, `admin\factory\ShopProduct` - -## pp_shop_attributes_values_langs -Tlumaczenia wartosci cech (per jezyk). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| value_id | FK do pp_shop_attributes_values | -| lang_id | ID jezyka (np. pl, en) | -| name | Nazwa wyswietlana | -| value | Wewnetrzna wartosc techniczna (opcjonalna) | - -**Uzywane w:** `Domain\Attribute\AttributeRepository`, `shop\ProductAttribute` - -## pp_shop_products_attributes -Powiazanie kombinacji produktow z wartosciami cech. - -| Kolumna | Opis | -|---------|------| -| product_id | FK do pp_shop_products (kombinacja) | -| value_id | FK do pp_shop_attributes_values | - -**Uzywane w:** `Domain\Attribute\AttributeRepository::refreshCombinationPricesForValue()`, `admin\controls\ShopProduct`, `admin\factory\ShopProduct` - -**Aktualizacja 2026-02-14 (ver. 0.271):** modul `/admin/shop_attribute` korzysta z `Domain\Attribute\AttributeRepository` przez `admin\Controllers\ShopAttributeController`. Usunieto legacy klasy `admin\controls\ShopAttribute`, `admin\factory\ShopAttribute`, `admin\view\ShopAttribute`. - -## pp_shop_coupon -Kody rabatowe sklepu (modul `/admin/shop_coupon`). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| name | Kod kuponu (UNIQUE) | -| status | Status: 1 = aktywny, 0 = nieaktywny | -| send | Czy kupon zostal wyslany (0/1) | -| used | Czy kupon zostal wykorzystany (0/1) | -| date_used | Data wykorzystania kuponu (NULL gdy brak) | -| used_count | Licznik uzyc kuponu | -| type | Typ kuponu (obecnie: 1 = rabat procentowy na koszyk) | -| amount | Wartosc kuponu (np. procent) | -| one_time | Czy kupon jednorazowy (0/1) | -| include_discounted_product | Czy obejmuje rowniez produkty przecenione (0/1) | -| categories | JSON z ID kategorii objetych kuponem (NULL = bez ograniczenia) | - -**Uzywane w:** `Domain\Coupon\CouponRepository`, `admin\Controllers\ShopCouponController`, `shop\Coupon`, `front\factory\ShopCoupon`, `front\factory\ShopOrder` - -**Aktualizacja 2026-02-13 (ver. 0.266):** modul `/admin/shop_coupon` korzysta z `Domain\Coupon\CouponRepository` przez `admin\Controllers\ShopCouponController`. Usunieto legacy klasy `admin\controls\ShopCoupon` i `admin\factory\ShopCoupon`. - -## pp_shop_promotion -Promocje sklepu (modul `/admin/shop_promotion`). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| name | Nazwa promocji | -| status | Status: 1 = aktywna, 0 = nieaktywna | -| condition_type | Typ warunku promocji (slownik w `shop\Promotion::$condition_type`) | -| discount_type | Typ rabatu (slownik w `shop\Promotion::$discount_type`) | -| amount | Wartosc rabatu (np. procent) | -| date_from | Data startu promocji (NULL = aktywna od razu) | -| date_to | Data konca promocji (NULL = bez daty konca) | -| categories | JSON z ID kategorii grupy I | -| condition_categories | JSON z ID kategorii grupy II | -| include_coupon | Czy laczyc z kuponami rabatowymi (0/1) | -| include_product_promo | Czy uwzgledniac produkty przecenione (0/1) | -| min_product_count | Minimalna liczba produktow (dla wybranych warunkow) | -| price_cheapest_product | Cena najtanszego produktu (dla wybranych warunkow) | - -**Uzywane w:** `Domain\Promotion\PromotionRepository`, `admin\Controllers\ShopPromotionController`, `shop\Promotion`, `front\factory\ShopPromotion` - -**Aktualizacja 2026-02-13:** modul `/admin/shop_promotion` korzysta z `Domain\Promotion\PromotionRepository` przez `admin\Controllers\ShopPromotionController`. Usunieto legacy klasy `admin\controls\ShopPromotion` i `admin\factory\ShopPromotion`. - -**Aktualizacja 2026-02-13 (ver. 0.265):** dodano obsluge `date_from` (repozytorium, formularz admin, lista admin, filtr aktywnych promocji na froncie) oraz poprawke zapisu edycji promocji po `id`. - -## pp_shop_payment_methods -Metody platnosci sklepu (modul `/admin/shop_payment_method`). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| name | Nazwa metody platnosci | -| description | Opis metody platnosci (wyswietlany m.in. w checkout) | -| status | Status: 1 = aktywna, 0 = nieaktywna | -| apilo_payment_type_id | ID typu platnosci Apilo (NULL gdy brak mapowania) | -| sellasist_payment_type_id | DEPRECATED (integracja Sellasist usunieta w ver. 0.263) | - -**Uzywane w:** `Domain\PaymentMethod\PaymentMethodRepository`, `admin\Controllers\ShopPaymentMethodController`, `front\factory\ShopPaymentMethod`, `shop\PaymentMethod`, `admin\controls\ShopTransport`, `cron.php` - -**Aktualizacja 2026-02-14 (ver. 0.268):** modul `/admin/shop_payment_method` korzysta z `Domain\PaymentMethod\PaymentMethodRepository` przez `admin\Controllers\ShopPaymentMethodController`. Usunieto legacy klasy `admin\controls\ShopPaymentMethod`, `admin\factory\ShopPaymentMethod`, `admin\view\ShopPaymentMethod` oraz widok `admin/templates/shop-payment-method/view-list.php`. - -## pp_shop_transports -Rodzaje transportu sklepu (modul `/admin/shop_transport`). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| name | Nazwa (systemowa, readonly) | -| name_visible | Nazwa widoczna dla klienta | -| description | Opis metody transportu | -| status | Status: 1 = aktywny, 0 = nieaktywny | -| cost | Koszt dostawy (PLN) | -| max_wp | Maksymalna waga paczki (NULL = bez limitu) | -| default | Domyslna forma dostawy (0/1) | -| delivery_free | Czy obsluguje darmowa dostawe (0/1) | -| apilo_carrier_account_id | ID konta przewoznika w Apilo (NULL gdy brak mapowania) | -| o | Kolejnosc wyswietlania | - -**Uzywane w:** `Domain\Transport\TransportRepository`, `admin\Controllers\ShopTransportController`, `front\factory\ShopTransport` - -## pp_shop_transport_payment_methods -Powiazanie metod transportu z metodami platnosci (tabela lacznikowa). - -| Kolumna | Opis | -|---------|------| -| id_transport | FK do pp_shop_transports | -| id_payment_method | FK do pp_shop_payment_methods | - -**Uzywane w:** `Domain\Transport\TransportRepository`, `Domain\PaymentMethod\PaymentMethodRepository::forTransport()` - -**Aktualizacja 2026-02-14 (ver. 0.269):** modul `/admin/shop_transport` korzysta z `Domain\Transport\TransportRepository` przez `admin\Controllers\ShopTransportController`. Usunieto legacy klasy `admin\controls\ShopTransport`, `admin\view\ShopTransport` oraz widok `admin/templates/shop-transport/view-list.php`. - -## pp_shop_apilo_settings -Ustawienia integracji Apilo (key-value). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| name | Klucz ustawienia (np. client-id, access-token) | -| value | Wartosc ustawienia | - -**Uzywane w:** `Domain\Integrations\IntegrationsRepository`, `admin\Controllers\IntegrationsController`, `admin\factory\Integrations` - -## pp_shop_shoppro_settings -Ustawienia integracji ShopPRO (key-value). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| name | Klucz ustawienia (np. domain, db_name) | -| value | Wartosc ustawienia | - -**Uzywane w:** `Domain\Integrations\IntegrationsRepository`, `admin\Controllers\IntegrationsController`, `admin\factory\Integrations` - -**Aktualizacja 2026-02-13:** modul `/admin/integrations/` korzysta z `Domain\Integrations\IntegrationsRepository` (DI kontroler + fasada legacy). Usunieto integracje Sellasist i Baselinker. - -## pp_shop_statuses -Statusy zamowien sklepu (modul `/admin/shop_statuses`). Statusy sa predefiniowane - brak dodawania/usuwania, mozliwa edycja koloru i mapowania Apilo. - -| Kolumna | Opis | -|---------|------| -| id | PK (zaczyna sie od 0!) | -| status | Nazwa statusu (read-only) | -| color | Kolor statusu (hex, np. #ff0000) | -| o | Kolejnosc wyswietlania | -| apilo_status_id | ID statusu w Apilo (NULL gdy brak mapowania) | -| baselinker_status_id | DEPRECATED (usuniety w ver. 0.263) | -| sellasist_status_id | DEPRECATED (usuniety w ver. 0.263) | - -**Uzywane w:** `Domain\ShopStatus\ShopStatusRepository`, `admin\Controllers\ShopStatusesController`, `front\factory\ShopStatuses`, `shop\Order`, `cron.php` - -**Aktualizacja 2026-02-14 (ver. 0.267):** modul `/admin/shop_statuses` korzysta z `Domain\ShopStatus\ShopStatusRepository` przez `admin\Controllers\ShopStatusesController`. Usunieto legacy klasy `admin\controls\ShopStatuses` i `admin\factory\ShopStatuses`. `front\factory\ShopStatuses` dziala jako fasada do repozytorium. - -## pp_shop_product_sets -Komplety produktow (modul `/admin/shop_product_sets`). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| name | Nazwa kompletu | -| status | Status: 1 = aktywny, 0 = nieaktywny | - -**Uzywane w:** `Domain\ProductSet\ProductSetRepository`, `admin\Controllers\ShopProductSetsController`, `shop\ProductSet`, `shop\Product` - -## pp_shop_product_sets_products -Powiazanie kompletow z produktami (tabela lacznikowa). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| set_id | FK do pp_shop_product_sets | -| product_id | FK do pp_shop_products | - -**Uzywane w:** `Domain\ProductSet\ProductSetRepository`, `shop\Product`, `front\factory\ShopProduct`, `admin\factory\ShopProduct` - -**Aktualizacja 2026-02-15 (ver. 0.272):** modul `/admin/shop_product_sets` korzysta z `Domain\ProductSet\ProductSetRepository` przez `admin\Controllers\ShopProductSetsController`. Usunieto legacy klasy `admin\controls\ShopProductSets` i `admin\factory\ShopProductSet`. `shop\ProductSet` dziala jako fasada do repozytorium. - -## pp_shop_producer -Producenci produktow (modul `/admin/shop_producer`). - -| Kolumna | Opis | -|---------|------| -| id | PK | -| name | Nazwa producenta | -| status | Status: 1 = aktywny, 0 = nieaktywny | -| img | Sciezka do logo producenta (NULL gdy brak) | - -**Uzywane w:** `Domain\Producer\ProducerRepository`, `admin\Controllers\ShopProducerController`, `shop\Producer`, `shop\Product`, `front\controls\ShopProducer` - -## pp_shop_producer_lang -Tlumaczenia producentow (per jezyk). FK kaskadowe ON DELETE CASCADE. - -| Kolumna | Opis | -|---------|------| -| id | PK | -| producer_id | FK do pp_shop_producer | -| lang_id | ID jezyka (np. pl, en) | -| description | Opis producenta (TEXT) | -| data | Dane producenta (TEXT, HTML) | -| meta_title | Meta title SEO (VARCHAR 255) | - -**Uzywane w:** `Domain\Producer\ProducerRepository`, `shop\Producer`, `shop\Product` - -**Aktualizacja 2026-02-15 (ver. 0.273):** modul `/admin/shop_producer` korzysta z `Domain\Producer\ProducerRepository` przez `admin\Controllers\ShopProducerController`. Usunieto legacy `admin\controls\ShopProducer` i `admin\factory\ShopProducer`. `shop\Producer` dziala jako fasada do repozytorium. diff --git a/temp/update_build/tmp_0.275/docs/PROJECT_STRUCTURE.md b/temp/update_build/tmp_0.275/docs/PROJECT_STRUCTURE.md deleted file mode 100644 index f3de582..0000000 --- a/temp/update_build/tmp_0.275/docs/PROJECT_STRUCTURE.md +++ /dev/null @@ -1,338 +0,0 @@ -# Struktura Projektu shopPRO - -Dokumentacja struktury projektu shopPRO do szybkiego odniesienia. - -## System Cache (Redis) - -### Klasy odpowiedzialne za cache - -#### RedisConnection -- **Plik:** `autoload/class.RedisConnection.php` -- **Opis:** Singleton zarządzający połączeniem z Redis -- **Metody:** - - `getInstance()` - pobiera instancję połączenia - - `getConnection()` - zwraca obiekt Redis - -#### CacheHandler -- **Plik:** `autoload/class.CacheHandler.php` -- **Opis:** Handler do obsługi cache Redis -- **Metody:** - - `get($key)` - pobiera wartość z cache - - `set($key, $value, $ttl = 86400)` - zapisuje wartość do cache - - `exists($key)` - sprawdza czy klucz istnieje - - `delete($key)` - usuwa pojedynczy klucz - - `deletePattern($pattern)` - usuwa klucze według wzorca - -#### Klasa S (pomocnicza) -- **Plik:** `autoload/class.S.php` -- **Metody cache:** - - `clear_redis_cache()` - czyści cały cache Redis (flushAll) - - `clear_product_cache(int $product_id)` - czyści cache konkretnego produktu - -### Wzorce kluczy Redis - -#### Produkty -``` -shop\product:{product_id}:{lang_id}:{permutation_hash} -``` -- Przechowuje zserializowany obiekt produktu -- TTL: 24 godziny (86400 sekund) -- Klasa: `shop\Product::getFromCache()` - `autoload/shop/class.Product.php:121` - -#### Opcje ilościowe produktu -``` -\shop\Product::get_product_permutation_quantity_options:{product_id}:{permutation} -``` -- Przechowuje informacje o ilości i komunikatach magazynowych -- Klasa: `shop\Product::get_product_permutation_quantity_options()` - `autoload/shop/class.Product.php:549` - -#### Zestawy produktów -``` -\shop\Product::product_sets_when_add_to_basket:{product_id} -``` -- Przechowuje produkty często kupowane razem -- Klasa: `shop\Product::product_sets_when_add_to_basket()` - `autoload/shop/class.Product.php:316` - -## Integracje z systemami zewnętrznymi (CRON) - -### Plik: `cron.php` - -#### Apilo -- **Aktualizacja pojedynczego produktu:** synchronizacja cen i stanow - - Czestotliwosc: Co 10 minut -- **Synchronizacja cennika:** masowa aktualizacja cen z Apilo - - Czestotliwosc: Co 1 godzine -- **Synchronizacja zaleglych syncow platnosci/statusow:** kolejka retry dla chwilowej niedostepnosci Apilo (`temp/apilo-sync-queue.json`) - - Przetwarzanie: przy kazdym uruchomieniu `cron.php` (limit wsadowy) - -**Uwaga:** Integracje Sellasist i Baselinker zostaly usuniete w ver. 0.263. - -## Panel Administratora - -### Routing -- Główny katalog: `admin/` -- Template główny: `admin/templates/site/main-layout.php` -- Kontrolery (nowe): `autoload/admin/Controllers/` -- Kontrolery legacy (fallback): `autoload/admin/controls/` - -### Przycisk "Wyczyść cache" -- **Lokalizacja UI:** `admin/templates/site/main-layout.php:172` -- **JavaScript:** `admin/templates/site/main-layout.php:235-274` -- **Endpoint AJAX:** `/admin/settings/clear_cache_ajax/` -- **Kontroler:** `autoload/admin/Controllers/SettingsController.php:43-60` -- **Działanie:** - 1. Pokazuje spinner "Czyszczę cache..." - 2. Czyści katalogi: `temp/`, `thumbs/` - 3. Wykonuje `flushAll()` na Redis - 4. Pokazuje "Cache wyczyszczony!" przez 2 sekundy - 5. Przywraca stan początkowy - -## Struktura katalogów - -``` -shopPRO/ -├── admin/ # Panel administratora -│ ├── templates/ # Szablony widoków -│ └── layout/ # Zasoby CSS/JS/ikony -├── autoload/ # Klasy autoloadowane -│ ├── admin/ # Klasy panelu admin -│ │ ├── Controllers/ # Nowe kontrolery DI -│ │ ├── controls/ # Kontrolery legacy (fallback) -│ │ └── factory/ # Fabryki/helpery -│ ├── Domain/ # Repozytoria/logika domenowa -│ ├── front/ # Klasy frontendu -│ │ └── factory/ # Fabryki/helpery -│ └── shop/ # Klasy sklepu -├── docs/ # Dokumentacja techniczna -├── libraries/ # Biblioteki zewnętrzne -├── temp/ # Cache tymczasowy -├── thumbs/ # Miniatury zdjęć -└── cron.php # Zadania CRON -``` - -## Baza danych - -### Główne tabele produktów -- `pp_shop_products` - produkty główne -- `pp_shop_products_langs` - tłumaczenia produktów -- `pp_shop_products_images` - zdjęcia produktów -- `pp_shop_products_categories` - kategorie produktów -- `pp_shop_products_custom_fields` - pola własne produktów - -### Tabele integracji -- Kolumny w `pp_shop_products`: - - `apilo_product_id`, `apilo_product_name`, `apilo_get_data_date` -- Tabele ustawien: - - `pp_shop_apilo_settings` (key-value) - - `pp_shop_shoppro_settings` (key-value) - -### Tabele checkout -- `pp_shop_payment_methods` - metody platnosci sklepu (mapowanie `apilo_payment_type_id`) -- `pp_shop_transports` - rodzaje transportu sklepu (mapowanie `apilo_carrier_account_id`) -- `pp_shop_transport_payment_methods` - powiazanie metod transportu i platnosci - -Pelna dokumentacja tabel: `DATABASE_STRUCTURE.md` - -## Konfiguracja - -### Redis -- Konfiguracja: `config.php` (zmienna `$config['redis']`) -- Parametry: host, port, password - -### Autoload -- Funkcja: `__autoload_my_classes()` w `cron.php:6` -- Wzorzec: `autoload/{namespace}/class.{ClassName}.php` - -## Klasy pomocnicze - -### \S (autoload/class.S.php) -Główna klasa helper z metodami: -- `seo($val)` - generowanie URL SEO -- `normalize_decimal($val, $precision)` - normalizacja liczb -- `send_email()` - wysyłanie emaili -- `delete_dir($dir)` - usuwanie katalogów -- `htacces()` - generowanie .htaccess i sitemap.xml - -### Medoo -- Plik: `libraries/medoo/medoo.php` -- Zmienna: `$mdb` -- ORM do operacji na bazie danych - -## Najważniejsze wzorce - -### Namespace'y -- `\admin\Controllers\` - nowe kontrolery panelu admin (DI) -- `\admin\controls\` - kontrolery legacy (fallback) -- `\Domain\` - repozytoria/logika domenowa -- `\admin\factory\` - helpery/fabryki admin -- `\front\factory\` - helpery/fabryki frontend -- `\shop\` - klasy sklepu (Product, Order, itp.) - -### Cachowanie produktów -```php -// Pobranie produktu z cache -$product = \shop\Product::getFromCache($product_id, $lang_id, $permutation_hash); - -// Czyszczenie cache produktu -\S::clear_product_cache($product_id); - -// Czyszczenie całego cache -\S::clear_redis_cache(); -``` - -## Refaktoryzacja do Domain-Driven Architecture - -### Nowa struktura (w trakcie migracji) -``` -autoload/ -├── Domain/ # Nowa warstwa biznesowa (namespace \Domain\) -│ ├── Product/ -│ │ └── ProductRepository.php -│ ├── Banner/ -│ │ └── BannerRepository.php -│ ├── Settings/ -│ │ └── SettingsRepository.php -│ ├── Cache/ -│ │ └── CacheRepository.php -│ ├── Article/ -│ │ └── ArticleRepository.php -│ ├── User/ -│ │ └── UserRepository.php -│ ├── Languages/ -│ │ └── LanguagesRepository.php -│ ├── Layouts/ -│ │ └── LayoutsRepository.php -│ ├── Newsletter/ -│ │ └── NewsletterRepository.php -│ ├── Scontainers/ -│ │ └── ScontainersRepository.php -│ ├── Dictionaries/ -│ │ └── DictionariesRepository.php -│ ├── Pages/ -│ │ └── PagesRepository.php -│ ├── Integrations/ -│ │ └── IntegrationsRepository.php -│ ├── Promotion/ -│ │ └── PromotionRepository.php -│ ├── Coupon/ -│ │ └── CouponRepository.php -│ ├── ShopStatus/ -│ │ └── ShopStatusRepository.php -│ ├── Transport/ -│ │ └── TransportRepository.php -│ ├── ProductSet/ -│ │ └── ProductSetRepository.php -│ ├── Producer/ -│ │ └── ProducerRepository.php -│ └── ... -├── admin/ -│ ├── Controllers/ # Nowe kontrolery (namespace \admin\Controllers\) -│ ├── class.Site.php # Router: nowy kontroler → fallback stary -│ ├── controls/ # Stare kontrolery (niezależny fallback) -│ ├── factory/ # Stare helpery (niezależny fallback) -│ └── view/ # Widoki (statyczne - bez zmian) -├── shop/ # Legacy - fasady do Domain -└── front/factory/ # Legacy - stopniowo migrowane -``` - -**Aktualizacja 2026-02-14 (ver. 0.268):** -- Dodano modul domenowy `Domain/PaymentMethod/PaymentMethodRepository.php`. -- Dodano kontroler DI `admin/Controllers/ShopPaymentMethodController.php`. -- Modul `/admin/shop_payment_method/*` dziala na nowych widokach (`payment-methods-list`, `payment-method-edit`). -- Usunieto legacy: `autoload/admin/controls/class.ShopPaymentMethod.php`, `autoload/admin/factory/class.ShopPaymentMethod.php`, `autoload/admin/view/class.ShopPaymentMethod.php`, `admin/templates/shop-payment-method/view-list.php`. - -**Aktualizacja 2026-02-14 (ver. 0.269):** -- Dodano modul domenowy `Domain/Transport/TransportRepository.php`. -- Dodano kontroler DI `admin/Controllers/ShopTransportController.php`. -- Modul `/admin/shop_transport/*` dziala na nowych widokach (`transports-list`, `transport-edit`). -- Usunieto legacy: `autoload/admin/controls/class.ShopTransport.php`, `autoload/admin/view/class.ShopTransport.php`, `admin/templates/shop-transport/view-list.php`. -- `admin\factory\ShopTransport` i `front\factory\ShopTransport` przepiete na repozytorium. - -**Aktualizacja 2026-02-14 (ver. 0.270):** -- `shop\Order` zapisuje nieudane syncy Apilo (status/platnosc) do kolejki `temp/apilo-sync-queue.json`. -- `cron.php` automatycznie ponawia zalegle syncy (`Order::process_apilo_sync_queue()`). -- `shop\Order::set_as_paid()` wysyla mapowany typ platnosci Apilo (z mapowania metody platnosci), bez stalej wartosci `type`. - -### Routing admin (admin\Site::route()) -1. Sprawdź mapę `$newControllers` → utwórz instancję z DI → wywołaj -2. Jeśli nowy kontroler nie istnieje (`class_exists()` = false) → fallback na `admin\controls\` -3. Stary kontroler jest NIEZALEŻNY od nowych klas (bezpieczny fallback) - -### Dependency Injection -Nowe klasy używają **Dependency Injection** zamiast `global` variables: -```php -// STARE -global $mdb; -$quantity = $mdb->get('pp_shop_products', 'quantity', ['id' => $id]); - -// NOWE -$repository = new \Domain\Product\ProductRepository($mdb); -$quantity = $repository->getQuantity($id); -``` - -## Testowanie (tylko dla deweloperów) - -**UWAGA:** Pliki testów NIE są częścią aktualizacji dla klientów! - -### Narzędzia -- **PHPUnit 9.6.34** - framework testowy -- **test.bat** - uruchamianie testów -- **composer.json** - autoloading PSR-4 - -Pelna dokumentacja testow: `TESTING.md` - -## Dodatkowa aktualizacja 2026-02-14 (ver. 0.271) -- Dodano modul domenowy `Domain/Attribute/AttributeRepository.php`. -- Dodano kontroler DI `admin/Controllers/ShopAttributeController.php`. -- Modul `/admin/shop_attribute/*` zostal przepiety na nowe widoki (`attributes-list`, `attribute-edit`, `values-edit`). -- Usunieto legacy: `autoload/admin/controls/class.ShopAttribute.php`, `autoload/admin/factory/class.ShopAttribute.php`, `autoload/admin/view/class.ShopAttribute.php`, `admin/templates/shop-attribute/_partials/value.php`. -- Przepieto zaleznosci kombinacji produktu na `Domain\Attribute\AttributeRepository` i `shop\ProductAttribute`. -- Dla `ShopAttribute` routing celowo nie wykonuje fallbacku akcji do legacy kontrolera. - -## Dodatkowa aktualizacja 2026-02-15 (ver. 0.272) -- Dodano modul domenowy `Domain/ProductSet/ProductSetRepository.php`. -- Dodano kontroler DI `admin/Controllers/ShopProductSetsController.php`. -- Modul `/admin/shop_product_sets/*` dziala na nowych widokach (`product-sets-list`, `product-set-edit`). -- Usunieto legacy: `autoload/admin/controls/class.ShopProductSets.php`, `autoload/admin/factory/class.ShopProductSet.php`, `admin/templates/shop-product-sets/view-list.php`, `admin/templates/shop-product-sets/set-edit.php`. -- `shop\ProductSet` przepiety na fasade do `Domain\ProductSet\ProductSetRepository`. - -## Dodatkowa aktualizacja 2026-02-15 (ver. 0.273) -- Dodano modul domenowy `Domain/Producer/ProducerRepository.php`. - -## Dodatkowa aktualizacja 2026-02-15 (ver. 0.274) -- Dodano modul domenowy `Domain/Client/ClientRepository.php`. -- Dodano kontroler DI `admin/Controllers/ShopClientsController.php`. -- Modul `/admin/shop_clients/*` dziala na nowych widokach opartych o `components/table-list`. -- Usunieto legacy: `autoload/admin/controls/class.ShopClients.php`, `autoload/admin/factory/class.ShopClients.php`. -- Routing i menu admin przepiete na kanoniczny URL `/admin/shop_clients/list/`. -- Dodano kontroler DI `admin/Controllers/ShopProducerController.php`. -- Modul `/admin/shop_producer/*` dziala na nowych widokach (`producers-list`, `producer-edit`). -- Usunieto legacy: `autoload/admin/controls/class.ShopProducer.php`, `admin/templates/shop-producer/list.php`, `admin/templates/shop-producer/edit.php`. -- `shop\Producer` przepiety na fasade do `Domain\Producer\ProducerRepository`. -- `admin\controls\ShopProduct` uzywa `ProducerRepository::allProducers()`. -- Usunieto 6 pustych factory facades: `admin\factory\Languages`, `admin\factory\Newsletter`, `admin\factory\Scontainers`, `admin\factory\ShopProducer`, `admin\factory\ShopTransport`, `admin\factory\Layouts`. -- Przepieto 2 wywolania `admin\factory\ShopTransport` w `admin\factory\ShopProduct` na `Domain\Transport\TransportRepository`. -- Usuniety fallback do `admin\factory\Layouts` w `admin\controls\ShopProduct`. - -## Dodatkowa aktualizacja 2026-02-15 (ver. 0.274) -- Dodano kontroler DI `admin/Controllers/ShopProductController.php` (akcje `mass_edit`, `mass_edit_save`, `get_products_by_category`). -- Routing `admin\Site` rozszerzono o mapowanie `ShopProduct` do nowego kontrolera. -- `Domain/Product/ProductRepository.php` rozszerzono o metody dla mass-edit: `allProductsForMassEdit`, `getProductsByCategory`, `applyDiscountPercent`. -- Usunieto legacy akcje mass-edit z `autoload/admin/controls/class.ShopProduct.php`. -- Widok `/admin/shop_product/mass_edit/` przepiety na nowy partial `admin/templates/shop-product/mass-edit-custom-script.php`. -- Ujednolicono UI drzewek (strzalki/expand) w: - - `admin/templates/pages/pages-list.php` + `admin/templates/pages/subpages-list.php` - - `admin/templates/articles/subpages-list.php` + `admin/templates/articles/article-edit-custom-script.php` - -## Dodatkowa aktualizacja 2026-02-15 (ver. 0.275) -- Dodano modul domenowy `Domain/Category/CategoryRepository.php`. -- Dodano kontroler DI `admin/Controllers/ShopCategoryController.php`. -- Modul `/admin/shop_category/*` dziala przez DI i kanoniczny URL `/admin/shop_category/list/` (z zachowaniem aliasu `view_list`). -- Widoki `shop-category/*` maja wydzielone skrypty `*-custom-script.php` i ujednolicone strzalki drzewa (`button + caret + aria-expanded`). -- Endpointy AJAX dla drzewka kategorii i kolejnosci produktow przepiete na `/admin/shop_category/save_categories_order/`, `/admin/shop_category/save_products_order/`, `/admin/shop_category/cookie_categories/`. -- Usunieto legacy: `autoload/admin/controls/class.ShopCategory.php`, `autoload/admin/factory/class.ShopCategory.php`, `autoload/admin/view/class.ShopCategory.php`. -- Przepieto zaleznosci `ShopProduct` z `admin\factory\ShopCategory` na `Domain\Category\CategoryRepository`. -- Usunieto preload `autoload/admin/factory/class.ShopCategory.php` z `libraries/grid/config.php`. - ---- -*Dokument aktualizowany: 2026-02-15* diff --git a/temp/update_build/tmp_0.275/docs/REFACTORING_PLAN.md b/temp/update_build/tmp_0.275/docs/REFACTORING_PLAN.md deleted file mode 100644 index 257c0f6..0000000 --- a/temp/update_build/tmp_0.275/docs/REFACTORING_PLAN.md +++ /dev/null @@ -1,297 +0,0 @@ -# Plan Refaktoryzacji shopPRO - Domain-Driven Architecture - -## Cel -Stopniowe przeniesienie logiki biznesowej do architektury warstwowej: -- **Domain/** - logika biznesowa (core) -- **Admin/** - warstwa administratora -- **Frontend/** - warstwa użytkownika -- **Shared/** - współdzielone narzędzia - -## Docelowa struktura - -``` -autoload/ -├── Domain/ # Logika biznesowa (CORE) - namespace \Domain\ -│ ├── Product/ -│ │ ├── ProductRepository.php -│ │ ├── ProductService.php # (przyszłość) -│ │ └── ProductCacheService.php # (przyszłość) -│ ├── Banner/ -│ │ └── BannerRepository.php -│ ├── Settings/ -│ │ └── SettingsRepository.php -│ ├── Cache/ -│ │ └── CacheRepository.php -│ ├── Order/ -│ ├── Category/ -│ └── ... -│ -├── admin/ # Warstwa administratora (istniejący katalog!) -│ ├── Controllers/ # Nowe kontrolery - namespace \admin\Controllers\ -│ ├── controls/ # Stare kontrolery (legacy fallback) -│ ├── factory/ # Stare helpery (legacy) -│ └── view/ # Widoki (statyczne - OK bez zmian) -│ -├── Frontend/ # Warstwa użytkownika (przyszłość) -│ ├── Controllers/ -│ └── Services/ -│ -├── Shared/ # Współdzielone narzędzia -│ ├── Cache/ -│ │ ├── CacheHandler.php -│ │ └── RedisConnection.php -│ └── Helpers/ -│ └── S.php -│ -└── [LEGACY] # Stare klasy (stopniowo deprecated) - ├── shop/ - ├── admin/factory/ - └── front/factory/ -``` - -### WAŻNE: Konwencja namespace → katalog (Linux case-sensitive!) -- `\Domain\` → `autoload/Domain/` (duże D - nowy katalog) -- `\admin\Controllers\` → `autoload/admin/Controllers/` (małe a - istniejący katalog) -- NIE używać `\Admin\` (duże A) bo na serwerze Linux katalog to `admin/` (małe a) - -## Zasady migracji - -### 1. Stopniowość -- Przenosimy **jedną funkcję na raz** -- Zachowujemy kompatybilność wsteczną -- Stare klasy działają jako fasady do nowych - -### 2. Dependency Injection zamiast statycznych metod -```php -// ❌ STARE - statyczne -class Product { - public static function getQuantity($id) { - global $mdb; - return $mdb->get('pp_shop_products', 'quantity', ['id' => $id]); - } -} - -// ✅ NOWE - instancje z DI -class ProductRepository { - private $db; - - public function __construct($db) { - $this->db = $db; - } - - public function getQuantity($id) { - return $this->db->get('pp_shop_products', 'quantity', ['id' => $id]); - } -} -``` - -### 3. Fasady dla kompatybilności -```php -// Stara klasa wywołuje nową -namespace shop; - -class Product { - public static function getQuantity($id) { - global $mdb; - $repo = new \Domain\Product\ProductRepository($mdb); - return $repo->getQuantity($id); - } -} -``` - -## Proces migracji funkcji - -### Krok 1: Wybór funkcji -- Wybierz prostą funkcję statyczną -- Sprawdź jej zależności -- Przeanalizuj gdzie jest używana - -### Krok 2: Stworzenie nowej struktury -- Utwórz folder `Domain/{Module}/` -- Stwórz odpowiednią klasę (Repository/Service/Entity) -- Przenieś logikę - -### Krok 3: Znalezienie użyć -```bash -grep -r "Product::getQuantity" . -``` - -### Krok 4: Aktualizacja wywołań -- Opcja A: Bezpośrednie wywołanie nowej klasy -- Opcja B: Fasada w starej klasie (zalecane na początek) - -### Krok 5: Testy -- Napisz test jednostkowy dla nowej funkcji -- Sprawdź czy stare wywołania działają - -## Status migracji - -### ✅ Zmigrowane moduły -| # | Modul | Wersja | Zakres | -|---|-------|--------|--------| -| 1 | Cache | 0.237 | CacheHandler, RedisConnection, clear_product_cache | -| 2 | Product | 0.238-0.252, 0.274 | getQuantity, getPrice, getName, archive/unarchive, allProductsForMassEdit, getProductsByCategory, applyDiscountPercent | -| 3 | Banner | 0.239 | find, delete, save, kontroler DI | -| 4 | Settings | 0.240/0.250 | saveSettings, getSettings, kontroler DI | -| 5 | Dictionaries | 0.251 | listForAdmin, find, save, delete, kontroler DI | -| 6 | ProductArchive | 0.252 | kontroler DI, table-list | -| 7 | Filemanager | 0.252 | kontroler DI, fix Invalid Key | -| 8 | Users | 0.253 | CRUD, logon, 2FA, kontroler DI | -| 9 | Languages | 0.254 | languages + translations, kontroler DI | -| 10 | Layouts | 0.256 | find, save, delete, menusWithPages, categoriesTree | -| 11 | Newsletter | 0.257-0.258 | subskrybenci, szablony, ustawienia | -| 12 | Scontainers | 0.259 | listForAdmin, find, save, delete | -| 13 | ArticlesArchive | 0.260 | restore, deletePermanently | -| 14 | Articles | 0.261 | pelna migracja (CRUD, AJAX, galeria, pliki) | -| 15 | Pages | 0.262 | menu/page CRUD, drzewo stron, AJAX | -| 16 | Integrations | 0.263 | Apilo/ShopPRO, cleanup Sellasist/Baselinker | -| 17 | ShopPromotion | 0.264-0.265 | listForAdmin, find, save, delete, categoriesTree | -| 18 | ShopCoupon | 0.266 | listForAdmin, find, save, delete, categoriesTree | -| 19 | ShopStatuses | 0.267 | listForAdmin, find, save, color picker | -| 20 | ShopPaymentMethod | 0.268 | listForAdmin, find, save, allActive, mapowanie Apilo, DI kontroler | -| 21 | ShopTransport | 0.269 | listForAdmin, find, save, allActive, allForAdmin, findActiveById, getTransportCost, lowestTransportPrice, getApiloCarrierAccountId, powiazanie z PaymentMethod, DI kontroler | -| 22 | ShopAttribute | 0.271 | list/edit/save/delete/values, nowy edytor wartosci, cleanup legacy, przepiecie zaleznosci kombinacji | -| 23 | ShopProductSets | 0.272 | listForAdmin, find, save, delete, allSets, allProductsMap, multi-select Selectize, DI kontroler | -| 24 | ShopProducer | 0.273 | listForAdmin, find, save, delete, allProducers, producerProducts, fasada shop\Producer, DI kontroler | -| 25 | ShopProduct (mass_edit) | 0.274 | DI kontroler + routing dla `mass_edit`, `mass_edit_save`, `get_products_by_category`, cleanup legacy akcji | -| 26 | ShopClients | 0.274 | DI kontroler + routing dla `list/details`, nowe listy na `components/table-list`, cleanup legacy controls/factory | -| 27 | ShopCategory | 0.275 | CategoryRepository + DI kontroler + routing, endpointy AJAX (`save_categories_order`, `save_products_order`, `cookie_categories`), cleanup legacy controls/factory/view | - -### Product - szczegolowy status -- ✅ getQuantity (ver. 0.238) -- ✅ getPrice (ver. 0.239) -- ✅ getName (ver. 0.239) -- ✅ archive / unarchive (ver. 0.241/0.252) -- ✅ allProductsForMassEdit (ver. 0.274) -- ✅ getProductsByCategory (ver. 0.274) -- ✅ applyDiscountPercent (ver. 0.274) -- [ ] is_product_on_promotion -- [ ] getFromCache -- [ ] getProductImg - -### 📋 Do zrobienia -- Order -- ShopProduct (factory) - -## Kolejność refaktoryzacji (priorytet) - -1-27: ✅ Cache, Product, Banner, Settings, Dictionaries, ProductArchive, Filemanager, Users, Pages, Integrations, ShopPromotion, ShopCoupon, ShopStatuses, ShopPaymentMethod, ShopTransport, ShopAttribute, ShopProductSets, ShopProducer, ShopProduct (mass_edit), ShopClients, ShopCategory - -Nastepne: -28. **Order** - -## Form Edit System - -Nowy uniwersalny system formularzy edycji: -- ✅ Klasy ViewModel: `FormFieldType`, `FormField`, `FormTab`, `FormAction`, `FormEditViewModel` -- ✅ Walidacja: `FormValidator` z obsługą reguł per pole i sekcje językowe -- ✅ Persist: `FormRequestHandler` - zapamiętywanie danych przy błędzie walidacji -- ✅ Renderer: `FormFieldRenderer` - renderowanie wszystkich typów pól -- ✅ Szablon: `admin/templates/components/form-edit.php` - uniwersalny layout -- Wspierane typy pól: text, number, email, password, date, datetime, switch, select, textarea, editor, image, file, hidden, lang_section, color -- Obsługa zakładek (vertical) i sekcji językowych (horizontal) -- **Do zrobienia**: Przerobić pozostałe kontrolery/formularze (Product, Category, Pages, itd.) - -Pelna dokumentacja: `docs/FORM_EDIT_SYSTEM.md` - -## Zasady kodu - -### 1. SOLID Principles -- **S**ingle Responsibility - jedna klasa = jedna odpowiedzialność -- **O**pen/Closed - otwarty na rozszerzenia, zamknięty na modyfikacje -- **L**iskov Substitution - podklasy mogą zastąpić nadklasy -- **I**nterface Segregation - wiele małych interfejsów -- **D**ependency Inversion - zależności od abstrakcji - -### 2. Nazewnictwo -- **Entity** - `Product.php` (reprezentuje obiekt domenowy) -- **Repository** - `ProductRepository.php` (dostęp do danych) -- **Service** - `ProductService.php` (logika biznesowa) -- **Controller** - `ProductController.php` (obsługa requestów) - -### 3. Type Hinting -```php -// ✅ DOBRE -public function getQuantity(int $id): ?int { - return $this->db->get('pp_shop_products', 'quantity', ['id' => $id]); -} - -// ❌ ZŁE -public function getQuantity($id) { - return $this->db->get('pp_shop_products', 'quantity', ['id' => $id]); -} -``` - -## Narzędzia pomocnicze - -### Autoloader (produkcja) -Autoloader w 9 entry pointach obsługuje dwie konwencje: -1. `autoload/{namespace}/class.{ClassName}.php` (legacy) -2. `autoload/{namespace}/{ClassName}.php` (PSR-4, fallback) - -Entry pointy: `index.php`, `ajax.php`, `api.php`, `cron.php`, `cron-turstmate.php`, `download.php`, `admin/index.php`, `admin/ajax.php`, `cron/cron-xml.php` - -### Static Analysis -```bash -composer require --dev phpstan/phpstan -vendor/bin/phpstan analyse autoload/Domain -``` - -## Testowanie - -### Framework: PHPUnit -```bash -composer test -``` - -### Struktura testów -``` -tests/ -├── Unit/ -│ ├── Domain/ -│ │ ├── Article/ArticleRepositoryTest.php -│ │ ├── Banner/BannerRepositoryTest.php -│ │ ├── Cache/CacheRepositoryTest.php -│ │ ├── Coupon/CouponRepositoryTest.php -│ │ ├── Dictionaries/DictionariesRepositoryTest.php -│ │ ├── Integrations/IntegrationsRepositoryTest.php -│ │ ├── PaymentMethod/PaymentMethodRepositoryTest.php -│ │ ├── Producer/ProducerRepositoryTest.php -│ │ ├── Product/ProductRepositoryTest.php -│ │ ├── ProductSet/ProductSetRepositoryTest.php -│ │ ├── Promotion/PromotionRepositoryTest.php -│ │ ├── Settings/SettingsRepositoryTest.php -│ │ ├── ShopStatus/ShopStatusRepositoryTest.php -│ │ └── User/UserRepositoryTest.php -│ └── admin/ -│ └── Controllers/ -│ ├── ArticlesControllerTest.php -│ ├── DictionariesControllerTest.php -│ ├── IntegrationsControllerTest.php -│ ├── ProductArchiveControllerTest.php -│ ├── SettingsControllerTest.php -│ ├── ShopCouponControllerTest.php -│ ├── ShopPaymentMethodControllerTest.php -│ ├── ShopProducerControllerTest.php -│ ├── ShopProductSetsControllerTest.php -│ ├── ShopPromotionControllerTest.php -│ ├── ShopStatusesControllerTest.php -│ └── UsersControllerTest.php -└── Integration/ -``` -**Lacznie: 338 testow, 1063 asercji** - -Aktualizacja 2026-02-15 (ver. 0.273): -- dodano testy `tests/Unit/Domain/Producer/ProducerRepositoryTest.php` -- dodano testy `tests/Unit/admin/Controllers/ShopProducerControllerTest.php` - -Aktualizacja 2026-02-14 (ver. 0.271): -- dodano testy `tests/Unit/Domain/Attribute/AttributeRepositoryTest.php` -- dodano testy `tests/Unit/admin/Controllers/ShopAttributeControllerTest.php` - -Pelna dokumentacja testow: `TESTING.md` - ---- -*Rozpoczęto: 2025-02-05* -*Ostatnia aktualizacja: 2026-02-15* -*Changelog zmian: `docs/CHANGELOG.md`* diff --git a/temp/update_build/tmp_0.275/docs/TESTING.md b/temp/update_build/tmp_0.275/docs/TESTING.md deleted file mode 100644 index bcaefc2..0000000 --- a/temp/update_build/tmp_0.275/docs/TESTING.md +++ /dev/null @@ -1,456 +0,0 @@ -# Testowanie shopPRO - -## Szybki start - -### Pelny zestaw testow -```bash -composer test -``` - -Alternatywnie (Windows): -```bash -./test.ps1 -./test.bat -./test-simple.bat -./test-debug.bat -``` - -Alternatywnie (Git Bash): -```bash -./test.sh -``` - -### Konkretny plik testowy -```bash -./test.ps1 tests/Unit/Domain/Product/ProductRepositoryTest.php -./test.ps1 tests/Unit/admin/Controllers/ArticlesControllerTest.php -``` - -### Konkretny test (`--filter`) -```bash -./test.ps1 --filter testGetQuantityReturnsCorrectValue -``` - -## Aktualny stan suite - -Ostatnio zweryfikowano: 2026-02-15 - -```text -OK (351 tests, 1091 assertions) -``` - -Aktualizacja po migracji ShopClients (2026-02-15, ver. 0.274) - testy punktowe: -```text -OK (10 tests, 34 assertions) -``` - -Aktualizacja po migracji ShopCategory (2026-02-15, ver. 0.275) - testy punktowe: -```text -OK (16 tests, 72 assertions) -``` - -Nowe testy dodane 2026-02-15: -- `tests/Unit/Domain/Client/ClientRepositoryTest.php` -- `tests/Unit/admin/Controllers/ShopClientsControllerTest.php` -- `tests/Unit/Domain/Category/CategoryRepositoryTest.php` -- `tests/Unit/admin/Controllers/ShopCategoryControllerTest.php` - -## Struktura testow - -```text -tests/ -|-- bootstrap.php -|-- Unit/ -| |-- Domain/ -| | |-- Article/ArticleRepositoryTest.php -| | |-- Attribute/AttributeRepositoryTest.php -| | |-- Banner/BannerRepositoryTest.php -| | |-- Cache/CacheRepositoryTest.php -| | |-- Coupon/CouponRepositoryTest.php -| | |-- Category/CategoryRepositoryTest.php -| | |-- Dictionaries/DictionariesRepositoryTest.php -| | |-- Integrations/IntegrationsRepositoryTest.php -| | |-- PaymentMethod/PaymentMethodRepositoryTest.php -| | |-- Producer/ProducerRepositoryTest.php -| | |-- Product/ProductRepositoryTest.php -| | |-- ProductSet/ProductSetRepositoryTest.php -| | |-- Promotion/PromotionRepositoryTest.php -| | |-- Settings/SettingsRepositoryTest.php -| | |-- ShopStatus/ShopStatusRepositoryTest.php -| | |-- Transport/TransportRepositoryTest.php -| | `-- User/UserRepositoryTest.php -| `-- admin/ -| `-- Controllers/ -| |-- ArticlesControllerTest.php -| |-- DictionariesControllerTest.php -| |-- IntegrationsControllerTest.php -| |-- ProductArchiveControllerTest.php -| |-- SettingsControllerTest.php -| |-- ShopAttributeControllerTest.php -| |-- ShopCategoryControllerTest.php -| |-- ShopCouponControllerTest.php -| |-- ShopPaymentMethodControllerTest.php -| |-- ShopProducerControllerTest.php -| |-- ShopProductControllerTest.php -| |-- ShopProductSetsControllerTest.php -| |-- ShopPromotionControllerTest.php -| |-- ShopStatusesControllerTest.php -| |-- ShopTransportControllerTest.php -| `-- UsersControllerTest.php -`-- Integration/ -``` - -## Tryby uruchamiania - -### 1. TestDox (czytelna lista) -```bash -./test.bat -``` -Uruchamia: -```bash -C:\xampp\php\php.exe phpunit.phar --testdox -``` - -### 2. Standard (kropki) -```bash -./test-simple.bat -``` -Uruchamia: -```bash -C:\xampp\php\php.exe phpunit.phar -``` - -### 3. Debug (pelne logowanie) -```bash -./test-debug.bat -``` -Uruchamia: -```bash -C:\xampp\php\php.exe phpunit.phar --debug -``` - -### 4. PowerShell (najbardziej niezawodne) -```bash -./test.ps1 -``` -- najpierw probuje `php` z PATH -- jesli brak, probuje m.in. `C:\xampp\php\php.exe` -- zawsze dodaje `--do-not-cache-result` - -## Interpretacja wynikow - -```text -. = test przeszedl -E = error (blad wykonania) -F = failure (niezgodna asercja) -``` - -Przyklad sukcesu: -```text -................................................................. 65 / 82 ( 79%) -................. 82 / 82 (100%) - -OK (82 tests, 181 assertions) -``` - -## Dodawanie nowych testow - -1. Dodaj plik w odpowiednim module, np. `tests/Unit/Domain//Test.php`. -2. Rozszerz `PHPUnit\Framework\TestCase`. -3. Nazwy metod zaczynaj od `test`. -4. Trzymaj sie wzorca AAA: Arrange, Act, Assert. - -## Mockowanie (przyklad) - -```php -$mockDb = $this->createMock(\medoo::class); -$mockDb->method('get')->willReturn(42); - -$repo = new ProductRepository($mockDb); -$value = $repo->getQuantity(123); - -$this->assertEquals(42, $value); -``` - -## Przydatne informacje - -- Konfiguracja PHPUnit: `phpunit.xml` -- Bootstrap testow: `tests/bootstrap.php` -- Dodatkowy opis: `tests/README.md` - -## Aktualizacja suite - -Ostatnio zweryfikowano: 2026-02-12 - -```text -OK (119 tests, 256 assertions) -``` - -Nowe testy dodane 2026-02-12: -- `tests/Unit/Domain/User/UserRepositoryTest.php` (25 testow: CRUD, logon, 2FA verify/send, checkLogin, updateById) -- `tests/Unit/admin/Controllers/UsersControllerTest.php` (12 testow: kontrakty + normalizeUser) - -Aktualizacja po migracji widokow Users (2026-02-12): -```text -OK (120 tests, 262 assertions) -``` - -## Aktualizacja suite (finalizacja Users) -Ostatnio zweryfikowano: 2026-02-12 - -```text -OK (120 tests, 262 assertions) -``` - -Aktualizacja po migracji Languages (2026-02-12): -```text -OK (130 tests, 301 assertions) -``` - -Nowe testy dodane 2026-02-12: -- `tests/Unit/Domain/Languages/LanguagesRepositoryTest.php` -- `tests/Unit/admin/Controllers/LanguagesControllerTest.php` - -## Aktualizacja suite (release 0.254) -Ostatnio zweryfikowano: 2026-02-12 - -```text -OK (130 tests, 301 assertions) -``` - -Nowe testy dodane 2026-02-12: -- `tests/Unit/Domain/Languages/LanguagesRepositoryTest.php` -- `tests/Unit/admin/Controllers/LanguagesControllerTest.php` - -## Aktualizacja suite (release 0.255) -Ostatnio zweryfikowano: 2026-02-12 - -```text -OK (130 tests, 303 assertions) -``` - -## Aktualizacja suite (release 0.256) -Ostatnio zweryfikowano: 2026-02-12 - -```text -OK (141 tests, 336 assertions) -``` - -Nowe testy dodane 2026-02-12: -- `tests/Unit/Domain/Layouts/LayoutsRepositoryTest.php` -- `tests/Unit/admin/Controllers/LayoutsControllerTest.php` - -Zaktualizowane testy 2026-02-12: -- `tests/Unit/Domain/Languages/LanguagesRepositoryTest.php` (defaultLanguageId) -- `tests/Unit/admin/Controllers/ArticlesControllerTest.php` (konstruktor + LayoutsRepository) - -## Aktualizacja suite (release 0.257) -Ostatnio zweryfikowano: 2026-02-12 - -```text -OK (150 tests, 372 assertions) -``` - -Nowe testy dodane 2026-02-12: -- `tests/Unit/Domain/Newsletter/NewsletterRepositoryTest.php` -- `tests/Unit/admin/Controllers/NewsletterControllerTest.php` - -## Aktualizacja suite (release 0.258) -Ostatnio zweryfikowano: 2026-02-12 - -```text -OK (150 tests, 372 assertions) -``` - -## Aktualizacja suite (release 0.259) -Ostatnio zweryfikowano: 2026-02-12 - -```text -OK (158 tests, 397 assertions) -``` - -Nowe testy dodane 2026-02-12: -- `tests/Unit/Domain/Scontainers/ScontainersRepositoryTest.php` -- `tests/Unit/admin/Controllers/ScontainersControllerTest.php` - -## Aktualizacja suite (release 0.260) -Ostatnio zweryfikowano: 2026-02-12 - -```text -OK (165 tests, 424 assertions) -``` - -Nowe testy dodane 2026-02-12: -- `tests/Unit/Domain/Article/ArticleRepositoryTest.php` (rozszerzenie o testy `restore`, `deletePermanently`, `listArchivedForAdmin`) -- `tests/Unit/admin/Controllers/ArticlesArchiveControllerTest.php` - -## Aktualizacja suite (release 0.261) -Ostatnio zweryfikowano: 2026-02-13 - -```text -OK (176 tests, 439 assertions) -``` - -Nowe testy/rozszerzenia 2026-02-13: -- `tests/Unit/Domain/Article/ArticleRepositoryTest.php` (nowe przypadki dla `pagesSummaryForArticles`, `updateImageAlt`, `markFileToDelete`) -- `tests/Unit/admin/Controllers/ArticlesControllerTest.php` (nowe kontrakty dla akcji `imageAltChange`, `fileNameChange`, `imageDelete`, `fileDelete`) - -## Aktualizacja suite (release 0.261) -Ostatnio zweryfikowano: 2026-02-13 - -```text -OK (178 tests, 443 assertions) -``` - -Nowe testy/rozszerzenia 2026-02-13: -- `tests/Unit/Domain/Article/ArticleRepositoryTest.php` (nowe przypadki dla `saveFilesOrder`) - -## Aktualizacja suite (Pages migration) -Ostatnio zweryfikowano: 2026-02-13 - -```text -OK (186 tests, 478 assertions) -``` - -Nowe testy dodane 2026-02-13: -- `tests/Unit/Domain/Pages/PagesRepositoryTest.php` -- `tests/Unit/admin/Controllers/PagesControllerTest.php` - -Zaktualizowane testy 2026-02-13: -- `tests/Unit/admin/Controllers/ArticlesControllerTest.php` (konstruktor z `Domain\\Pages\\PagesRepository`) - -## Aktualizacja suite (Integrations refactor, ver. 0.263) -Ostatnio zweryfikowano: 2026-02-13 - -```text -OK (212 tests, 577 assertions) -``` - -Nowe testy dodane 2026-02-13: -- `tests/Unit/Domain/Integrations/IntegrationsRepositoryTest.php` (16 testow: getSettings, getSetting, saveSetting, linkProduct, unlinkProduct, getProductSku, apiloGetAccessToken, invalid provider, settings table mapping) -- `tests/Unit/admin/Controllers/IntegrationsControllerTest.php` (10 testow: kontrakty metod, return types, brak metod sellasist/baselinker) - -Zaktualizowane pliki: -- `tests/bootstrap.php` (dodany stub `S::remove_special_chars()`) - -## Aktualizacja suite (ShopPromotion refactor, ver. 0.264) -Ostatnio zweryfikowano: 2026-02-13 - -```text -OK (222 tests, 609 assertions) -``` - -Nowe testy dodane 2026-02-13: -- `tests/Unit/Domain/Promotion/PromotionRepositoryTest.php` (6 testow: find default, save insert, delete, whitelist sortowania, drzewo kategorii) -- `tests/Unit/admin/Controllers/ShopPromotionControllerTest.php` (4 testy: kontrakty metod i DI konstruktora) - -## Aktualizacja suite (ShopPromotion fix + date_from, ver. 0.265) -Ostatnio zweryfikowano: 2026-02-13 - -```text -OK (222 tests, 614 assertions) -``` - -Zmiany testowe 2026-02-13: -- rozszerzenie `tests/Unit/Domain/Promotion/PromotionRepositoryTest.php` o asercje `date_from` - -## Aktualizacja suite (ShopCoupon refactor, ver. 0.266) -Ostatnio zweryfikowano: 2026-02-13 - -```text -OK (235 tests, 682 assertions) -``` - -Nowe testy dodane 2026-02-13: -- `tests/Unit/Domain/Coupon/CouponRepositoryTest.php` (8 testow: find default/normalize, save insert/update, delete, whitelist sortowania, drzewo kategorii) -- `tests/Unit/admin/Controllers/ShopCouponControllerTest.php` (5 testow: kontrakty metod, aliasy legacy, DI konstruktora) - -Ponowna weryfikacja po poprawkach UI (drzewko + checkboxy): 2026-02-13 -- `OK (235 tests, 682 assertions)` - -## Aktualizacja suite (ShopStatuses refactor, ver. 0.267) -Ostatnio zweryfikowano: 2026-02-14 - -```text -OK (254 tests, 736 assertions) -``` - -Nowe testy dodane 2026-02-14: -- `tests/Unit/Domain/ShopStatus/ShopStatusRepositoryTest.php` (9 testow: find z ID=0, find null apilo, save update, save z ID=0, empty apilo sets null, reject negative ID, getApiloStatusId, getByIntegrationStatusId, allStatuses, whitelist sortowania) -- `tests/Unit/admin/Controllers/ShopStatusesControllerTest.php` (5 testow: kontrakty metod, brak aliasow legacy, return types, DI konstruktora) - -## Aktualizacja suite (ShopPaymentMethod refactor, ver. 0.268) -Ostatnio zweryfikowano: 2026-02-14 - -```text -OK (280 tests, 828 assertions) -``` - -Nowe testy dodane 2026-02-14: -- `tests/Unit/Domain/PaymentMethod/PaymentMethodRepositoryTest.php` (14 testow: find invalid/null/normalize, save update/null/non-numeric apilo, listForAdmin whitelist, allActive, allForAdmin, findActiveById, isActive, getApiloPaymentTypeId, forTransport) -- `tests/Unit/admin/Controllers/ShopPaymentMethodControllerTest.php` (5 testow: kontrakty metod, brak aliasow legacy, return types, DI konstruktora) - -## Aktualizacja suite (ShopTransport refactor, ver. 0.269) -Ostatnio zweryfikowano: 2026-02-14 - -```text -OK (300 tests, 895 assertions) -``` - -Nowe testy dodane 2026-02-14: -- `tests/Unit/Domain/Transport/TransportRepositoryTest.php` (14 testow: find invalid/null/normalize/nullables, save insert/update/failure/default reset/switch normalization, listForAdmin whitelist, allActive, getApiloCarrierAccountId, getTransportCost, allForAdmin) -- `tests/Unit/admin/Controllers/ShopTransportControllerTest.php` (5 testow: kontrakty metod, brak aliasow legacy, return types, DI konstruktora z 2 repo) - -## Aktualizacja suite (Apilo sync hardening, ver. 0.270) -Ostatnio zweryfikowano: 2026-02-14 - -```text -OK (300 tests, 895 assertions) -``` - -Zmiany testowe 2026-02-14: -- brak nowych testow; pelna regresja po zmianach sync Apilo (TPAY -> Apilo) przeszla bez bledow - -## Aktualizacja suite (ShopAttribute refactor, ver. 0.271) -Ostatnio zweryfikowano: 2026-02-14 - -```text -OK (312 tests, 948 assertions) -``` - -Nowe testy dodane 2026-02-14: -- `tests/Unit/Domain/Attribute/AttributeRepositoryTest.php` (5 testow: domyslne dane cechy, whitelist sortowania/paginacji, zapis wartosci i domyslnej, usuwanie pustych tlumaczen, jezyk domyslny) -- `tests/Unit/admin/Controllers/ShopAttributeControllerTest.php` (7 testow: kontrakty metod, brak aliasow legacy, return types, DI konstruktora, walidacja `validateValuesRows`) - -## Aktualizacja suite (ShopProductSets refactor, ver. 0.272) -Ostatnio zweryfikowano: 2026-02-15 - -```text -OK (324 tests, 1000 assertions) -``` - -Nowe testy dodane 2026-02-15: -- `tests/Unit/Domain/ProductSet/ProductSetRepositoryTest.php` (7 testow: find default/normalize, save insert/update, delete invalid, whitelist sortowania/paginacji, allSets) -- `tests/Unit/admin/Controllers/ShopProductSetsControllerTest.php` (5 testow: kontrakty metod, aliasy legacy, return types, DI konstruktora) - -## Aktualizacja suite (ShopProducer refactor, ver. 0.273) -Ostatnio zweryfikowano: 2026-02-15 - -```text -OK (338 tests, 1063 assertions) -``` - -Nowe testy dodane 2026-02-15: -- `tests/Unit/Domain/Producer/ProducerRepositoryTest.php` (9 testow: find default/normalize, save insert/update, delete invalid/success, whitelist sortowania/paginacji, allProducers, producerProducts) -- `tests/Unit/admin/Controllers/ShopProducerControllerTest.php` (5 testow: kontrakty metod, aliasy legacy, return types, DI konstruktora) - -## Aktualizacja suite (ShopProduct mass_edit, ver. 0.274) -Ostatnio zweryfikowano: 2026-02-15 - -```text -OK (351 tests, 1091 assertions) -``` - -Nowe testy dodane 2026-02-15: -- `tests/Unit/Domain/Product/ProductRepositoryTest.php` (rozszerzenie: `allProductsForMassEdit`, `getProductsByCategory`, `applyDiscountPercent`) -- `tests/Unit/admin/Controllers/ShopProductControllerTest.php` (7 testow: kontrakty metod, return types, DI konstruktora) diff --git a/temp/update_build/tmp_0.275/libraries/grid/config.php b/temp/update_build/tmp_0.275/libraries/grid/config.php deleted file mode 100644 index 238b9c9..0000000 --- a/temp/update_build/tmp_0.275/libraries/grid/config.php +++ /dev/null @@ -1,48 +0,0 @@ - 'mysql', - 'database_name' => $database['name'], - 'server' => $database['host'], - 'username' => $database['user'], - 'password' => $database['password'], - 'charset' => 'utf8' - ); - -$mdb = new medoo( [ - 'database_type' => 'mysql', - 'database_name' => $database['name'], - 'server' => $database['host'], - 'username' => $database['user'], - 'password' => $database['password'], - 'charset' => 'utf8' - ] ); diff --git a/temp/update_build/tmp_0.275/tests/Unit/admin/Controllers/ShopCategoryControllerTest.php b/temp/update_build/tmp_0.275/tests/Unit/admin/Controllers/ShopCategoryControllerTest.php deleted file mode 100644 index 679731c..0000000 --- a/temp/update_build/tmp_0.275/tests/Unit/admin/Controllers/ShopCategoryControllerTest.php +++ /dev/null @@ -1,80 +0,0 @@ -repository = $this->createMock(CategoryRepository::class); - $this->languagesRepository = $this->createMock(LanguagesRepository::class); - $this->controller = new ShopCategoryController($this->repository, $this->languagesRepository); - } - - public function testConstructorAcceptsDependencies(): void - { - $controller = new ShopCategoryController($this->repository, $this->languagesRepository); - $this->assertInstanceOf(ShopCategoryController::class, $controller); - } - - public function testHasExpectedActionMethods(): void - { - $this->assertTrue(method_exists($this->controller, 'view_list')); - $this->assertTrue(method_exists($this->controller, 'list')); - $this->assertTrue(method_exists($this->controller, 'category_edit')); - $this->assertTrue(method_exists($this->controller, 'edit')); - $this->assertTrue(method_exists($this->controller, 'save')); - $this->assertTrue(method_exists($this->controller, 'category_delete')); - $this->assertTrue(method_exists($this->controller, 'delete')); - $this->assertTrue(method_exists($this->controller, 'category_products')); - $this->assertTrue(method_exists($this->controller, 'products')); - $this->assertTrue(method_exists($this->controller, 'category_url_browser')); - $this->assertTrue(method_exists($this->controller, 'save_categories_order')); - $this->assertTrue(method_exists($this->controller, 'save_products_order')); - $this->assertTrue(method_exists($this->controller, 'cookie_categories')); - } - - public function testViewActionsReturnString(): void - { - $reflection = new \ReflectionClass($this->controller); - - $this->assertEquals('string', (string)$reflection->getMethod('view_list')->getReturnType()); - $this->assertEquals('string', (string)$reflection->getMethod('list')->getReturnType()); - $this->assertEquals('string', (string)$reflection->getMethod('category_edit')->getReturnType()); - $this->assertEquals('string', (string)$reflection->getMethod('edit')->getReturnType()); - $this->assertEquals('string', (string)$reflection->getMethod('category_products')->getReturnType()); - $this->assertEquals('string', (string)$reflection->getMethod('products')->getReturnType()); - } - - public function testMutationActionsReturnVoid(): void - { - $reflection = new \ReflectionClass($this->controller); - - $this->assertEquals('void', (string)$reflection->getMethod('save')->getReturnType()); - $this->assertEquals('void', (string)$reflection->getMethod('category_delete')->getReturnType()); - $this->assertEquals('void', (string)$reflection->getMethod('delete')->getReturnType()); - $this->assertEquals('void', (string)$reflection->getMethod('category_url_browser')->getReturnType()); - $this->assertEquals('void', (string)$reflection->getMethod('save_categories_order')->getReturnType()); - $this->assertEquals('void', (string)$reflection->getMethod('save_products_order')->getReturnType()); - $this->assertEquals('void', (string)$reflection->getMethod('cookie_categories')->getReturnType()); - } - - public function testConstructorRequiresCategoryAndLanguagesRepositories(): void - { - $reflection = new \ReflectionClass(ShopCategoryController::class); - $constructor = $reflection->getConstructor(); - $params = $constructor->getParameters(); - - $this->assertCount(2, $params); - $this->assertEquals('Domain\\Category\\CategoryRepository', $params[0]->getType()->getName()); - $this->assertEquals('Domain\\Languages\\LanguagesRepository', $params[1]->getType()->getName()); - } -} diff --git a/temp/update_build/update_0.273.zip b/temp/update_build/update_0.273.zip deleted file mode 100644 index b277f343642c976c854bc0e9aa6d067581fd25a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45279 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 diff --git a/temp/update_build/update_0.275.zip b/temp/update_build/update_0.275.zip deleted file mode 100644 index ab9d40356d6f67e6aa42428bec070268e3c15912..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77819 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

p#> zcIc%Xm5a6ONZL^61I9b4fbX*G!vIdp;Ffr%BWJvA7hsQ*uI0d19!5$MSaqno%UnWE zPg&Vv0gha$AzGoD4?TGI0pE07l_Lq-kIpvgg;B_^FFr~`j-5PQnOZnaM-qU{VVR-I zyspQEdOKj#Rd*Z?D}$t}q1}^8Yjf=Tr@qOzY-_|eU~3qC%WehE=Nr#whQ?=x$LB?6 z=dY)kJAB~;yWmnEp})VzGJ4_OcV#@uW6^82)BcNh$Dfs$$PexJ1gm^QJp%Rh?5^nF zIE2lCBB5ET)7o3s(ILpyDJ?eEAblss;M^ts0Ss5r{W(Ei_gv5p2zq2QU=&fTVAhaP z-U-X_FM}OXq{XK;LtNJ%aEprC7+{$N$Lg$0T~V>Ig4SHr%opeYjq#wXF#M1}SP0Tyk4s0xuH z?FG!PFS7`#>5MmMP#l#_`N6;+oP;&z%K49>L5q7s)#0d~W|ECgrW<9lgQfiIHQ7?R(muG1kRb@kj(7BIbQLp;x) zCiELgG{1&05@;zFTf82Bbn23rUOSus^MwOD1%<`;6VF9rL=bDp)@%!YdwH!wJU^y8 z<8JuxyZfFZKzPAaI^j;3FIWl2b?=)3o6pDR$8IFW)ArL1CMW%auN za@%E9dC*eq@X=Uj^r@D$(iTTIe(=G{7_^%dkm=oXWLp5GHkNjuBjwG6*{aHZSh#b+1OW18>jSOclXK2WGN`U3}Gm?0>N-I7i6{%VNxtbGLs|M{ZUUpfH z?z|c$tu#rsW-D=``7NAUe6d=m^W}<>Ck331RG$UcCE`eA#0)5C3gn8_K;sZ9wFzFZ zpH|e!Ibog2s@gYq9aXi&_BZKDx=)1H`lWd@bs{!1y)nh#yXd+*kQ?l9^Qz0R^8mu4 z4&Ui^Uhtyt18H4W*Zc=g+#|u;Vr5%+N|P<~ZZIh~2Q*MVvMsR*@t$A0c0s1+EUfO$ znV!qK4c8qd*+0pFiTP6y(j2D!zZ=O5J5pgm(l4SQDEvblbmvNP6=SA zo9DKZv!c7}31eSRR4HfO>j!GIwjTdBxfTFqFDbLEu_MMrj$^-(r8 z?|=pcL)lId$};1{HRXIy1FtT%3Q+rHWsh}Dj|6xq{-{T0nUHH6m;*p=Jp_a~6^{H~ z6_g}BP}6)$Y!dDh|DtrReRzW9PT(}!;Z3CQ)E8DIU$@Fgdk~cnKT1&0tCAo$$?TnL zm8#2>4c62%L9VB=_^qVnv>HgFVNAuAcx!`ErkK?!cWmZN6tfPaqT`qiCBrNBk)p46 zX+aO#8+I*3@BCskfN5g}hviwG*powDs_!#N*e7Aeu{PS;o$AE#iYg1?dfPd}W z|9dU-5BBvx?db*okIAh6l}!340{fpv8~!u;e@cA)ujXR@|Mk*8GQ>pR(CL3psr{F_ zvHJg@Dcd0c0cierWB*^3^A{v5=U{8(Z1^AK*z4v0R_t7JTRLKo#_wt$|IkTb(CYci zQaGD3G)bhKMIfa+h(Bx>mvJv4VFXyxxWxbEdMNCtE**=uJup5X8~oH}zRq}>0>&xb zh^eZtxj+4VxH?KZPhDkAP8(-=Cle{EOvWJsjJTv9T}{W!XeK5DXL&PK5tL4cueM)} z>2qQ&l9(nEDu8U|h$KJ%G{)xog7sBN?UFH5>X12e0GU2|DU}MtQL1%GJx1bFvVEUC zD0{<6s?>rnbb(?}bXOnDziddkk4+VUMB&d65#z1|<*~geR5tQ;L9Bjlg zII1uMkYSrUJHLN~!138G%41pqO`!Ssb?mrh2KY^qY6ju>Ku|JFtZ^Se|A`v-4fyRW z?Rkt9jU*HKdZ!+rYfK?APFB0mM!jF=qc}B*Sk(bDp{_1<@7G1UV87-!hjpPB#*lSq znAVS_Fp&z=>EdBHmn8PKnl~s`C3JdiJwcwuZHHC(Zsn6PUZgtl+&2Ow4GICr&oj#) zk;DSjK*_<{YEM;wTkFnODKPZC?VsgGP9b`F?kQH*RJb@WfBS9~#TE~Y6%%o8og>;h$Y>dkvDaiqf)lDiDDlYi?G867xircuN*kNg4cchY61n4?n-~cLDe6 zg&m{zRuPU7u2{(xT;hMwSXMK3RK2D}9O#^Ue zBalc79jEpK`ou|i*am%%xaHpY49K}g9CrM>!S-=Xzo?RUgVq>Dt*vGCb zcp2gva8$7<>2v{(*6sxSEnw{_`n4IQ7^=@5E+?>MY?NGY{5A4R(uW0lebj{ACH8ty zPz63;--SK`9*e-K*{K@sr9`UaY%Z@WFXSFu=NZ(`GJMf&8YiRb>t_1fM<;2KSh9A{ z4n~yXWBpOi3R_;^)fAkI_>v5(nfCq^;7a`PkSH0b%r**scy^_pfNDB|u&qMLW;iHb zO)h0xs{^0Cl?{^8)aTL<#!Y^Mq`itA1sIfOcqPcjNx*Wj>Xg`2>f<1*H>zm$LcFA- zgR5JtZ<$H@A;{|V(L!c5BGTiAb0e$JP`PnG| zqiLS(&nOQnHiun~L>1x`EucD!NGk8i-Kd>GI&|#g+l~+0sHFE;km#|1NoP}9hik!( zx(cy#ZvNU8C)akv7Zqd4PB1nX8wjUn**Y1QKb+Yd&wfQ07Aw^#;H%*-%S*QCm&k~x zN>)i-7Z7=(ExX>sr0&mqtS}r|u<6x&TbQ@@SU}2k>7>OOp5?p%$_}%W$oOKeFIF*v z)*SNO*(j5dVQ~cM``XY4N%7m~iHeqbT7auaAWgj;HjX&Xkypu0vC7;8!qV~IKSG|A zyWzij1f;*VrOuAt4d;q&@m!xWrhZg^fQYaukQk>0|Y3e`+EzB(tJrG5{mMU>_ zU;QJ0m1$k{N1TXKc7(w~oeHa8l$=z?psR!22?GtTBp$^uDRlM$=sSbc$F>jjHC!w1$>IN9JppBnJSuclxTkV$w-lI1fJ|L2-@B&tr8`&1BOr#l$oD>ACQ5W(CBS}5~q zEYeP{Vo!0RN($}pcNp2=*##1@vwOG*ycBX>+SkMCBxqh}YOZgBMnMEU%NO12MjM;hf}xwizkcx|J;VhOH=wO&i>StwtXQ)t3Mu}w1hhde1wC)+$zKCCjRrL$(j z(Xx7fgMT^BV_85F1!B^obQCj7iVm)u-h*I9H-!V`peaMScvsI5Ie6~M2iSyGsBwQR zZoXl%1OBy9(-_N440Iphb}Mq9S>K8m27N|I%`v?8@AdM{2@TXa=)$g`iDq`hsAq!l z(XjbIn|vedfJ+!Z_(Tols<0h8WiwAQ0@2^oztuYKHE=Ook{g)YSLhi-Nf`r4pv?vjTN7{8Urt9g=-H-1tpjZ`f+1*8eHg)VQ#uEAW=D8rf@MQ`$%k zgQ{j*P~MWf4QB$}m)uTFVyGG*RUJ_a#poq})(LdP+FLab{x%1x)9vH)gyr=}CP&aV z+c$~6+wBJJ;u|co=n9Tg`5IILGxQNN@)$%Jc?cje8DPpGO{Vho<(wq_nQ+yH$TLch|rr_kAuB-wgE&J5Ta!ymH3fDVjYo5U=r@kx`-Us ze@buX7j=F=NGJGN6L8N+@O+i(jQPI`g7N6*MYeV$fy+Kyd+MmO-XK|q)Ts+>d8}f)^ z5%I(}PRF5Z(id8FI04mv3H&6fFsXTrDo>iPR4Z&%jW zLe{7;yH8^P1RXSJk=4V6)dg8rh2brY(H2L`EMP)D*RprADlbgsduYZ*)J>Jvg#n!o zmTG}HgI8%XTJ845sxBRM6Y{%IGJ*R9G+`G_Gk4WldK-ynRMe${9p5!znHWrPPC6n; zJVdbZ_w?wK51U||7|siy;-kLj3@igUwOD1aPrulgGeXP2=`}iR3%mZkzqW&P#?vA1g#SM0-2~DRYm2fy%HxC|nm;+K zO7`Z|&tm+0!3ba1LVAx3fQt66kvOcUZ}Sv=+{q>Hc_0RHXL+75>*_*5-zUR|k(Xq8 zk6RX}g7OtjuR?&zGQVcFi&J8Y1yv&rjI=#jl=RH6^{BDzabjw{*%KBQFxB*y$=Z>0BsH-`(aaSdw~i| zEg#$3Q^vJ=Lg$j)`9g$gb4itmN&F4eQj+YL#M=6cai*b*H#kv*ds*gNskeUCH^C6Mqc&?v9Ys zFwRmML~`U1rBO5iR<(FrqykY^WW|AuF)Jz}tEGqdp@4_pDkQQj8*+1at7RV=xO5$! zO;4VI_%;zGTXYddRm%Z`1VM;8Q89gs^!K9)Xw4+^c%^3w{(JyzxFvUg%Zdj1NpY_t zBBApixH0R?jcI+wDNDJmce)N1(o%fQAL2ICKb!h50AN3F=XZZP%)gdZb=fsK;Ii%T zd5hWGe4ws_7EU{iZC_~WBec~j*?}+e=;kyFT$e0t5kg>6K6`!Lt$0D5&XT8To6lvE zjS}Yfk-RMcKwP5s3!P^f^8lgWI>1ee``=K&^e754MK>bz#hI<X=0^iAizWd2%N`7*PTHS%eUp@IC4D|lgkOx(6N9Ce0P&9zsrt3XzKsp*TP zYGBz3Yw6^H`MA;b&9MB-1SLRu=P`q?(c89{OYM4l!m1T!;W;xFSvmHmf-m3?J> z-V2JA%|^P>QpiTT(d&Za$a2N!isfc#7I~}w%*|~>Vn0(A4l5?Lb>WO<>qgqryOta2 z*~ZByyV={d`b06@MNpzUQ}uMKh2iEWfKb+%jZ5-3+*G{}Pc1@>GTr+6dPzi{^kquZ zlYYjWc8XJ(#P;CN`?YZ`-o8wU5T1(FTPL{H88Sl~w}d3pC-K|wH+*-Nl4QD^26eZw zE?y5d9}V%0Z24YNOk?vvHzCyhP=6}j zHXGc!(y@Eq;$Fy$NY3*o*wAt>%YkbkI->+%_UpQhyk5nC#!1kU-F=9&9PEE*|FG6e z@fT$5WdJ|Y>4dNh3cTL$ZEHGr<#xaCp~JMWU!L+xNy+FmWchjOKpY0=`6r>$jh9k0 zL8P4Rv>2gNqxz*ZE;qO2GvxzP8aI}KNrM@~WlXUrLTqaIqYqtdX)QOFyS>0U59)`f zNFS-RqJZGy_;?hp0&D;lGPtD@*qXJ08Y*>QE-zrv7wGIBGv%x7r&f0_1)GoN2`2XiqNd% z$>__*qPux3e2%}y*kz2HW^*h9HeY-=YDhYfxFB|B`!!Ij1tC%zg!9kAxf>Xn`9LSV zR^*|<%kH4b;Po%=pNck81FcuWRp5rUBGbb^E}N(&8LGk714+bm2f?}$7dm^1QJfi} zBOG9Bs1m+#^4p|<_q+me`7Nl^C^+3m#Oqn_>gTB{Q8OheV4lifbJ^#~92%zyyRM7j z@g(ISMm{N|g#Hoh;4wplY)qqQW#zh49~c zyNciPzr)nz12}GGUMN|5y4Qljv5k-5)Oc~R4T-2RQ7JHx#23I7)*;&e(||PcYdIO=m>GceZw3`&?C*JK z6LIVcK9LLb#FwHA1p{DXg;2&3(A3<_Eqan*)J0_k zXc#}Nd@O<~2TI23d_dV4%imFmqCxN?)RAeF(SGO`N4nxOO^YGg%a{;mVwjCuwZW%8 zPYQWZbEAZ9w)PqrEqBg5vyXzn6A-#xhF9J_f9(M`L&d7)n$2u`C!QZrrq7wvyrS&S zb>m+_DCP>NmiGB>t`t-)7PGD?w>9xejyN=T1?4m1P($2v7x%Rlw1a2K4X_~4-8N&6 z8m_0XIp9yfArFgdcx(9-GE#qUG^iOzD|@qY_<`y5<+-C%{P-bWzamXF9khESaf1EC zG0k|A%m)a0=s0efz7{)@K|SS?Aw412<>laK@n+J;BX;2o-HW7soQ_<1ebJL$NMR@G zE^pqNDBJiodg^M7@UabD9PGstW3(S}b*Sb=eL2N_ zxRA7-;m=nDp6RjCqL7V2dcsA5PTP1Au{Bh-ChGa^4D?Eh+1fzh}&;EyiGzS{mM&4a3EkmcZ_drwG2Fo}Wt5cUpYWw_K6On7nH(fs%VF3;y@&QK3 zMhQRco#%e|?2s5L&_K&4 zG}?!HWi;rT6b^6(D#2srqtP@Fb=VQ5w~4E&h>Z^C99s!nd7RIWw5lt_p1CJ|q1AU6{IuJrx*wndUpH@Dw#XKY*mq0Ua(r-KHg8iH14ZsCj9|pMxJw)*f)+j zP8}5YH|-^6iBeNhsJbbtv|L9_p=}7?sH=TyCd(gBtxQkN(NZ?ha;LQIGet7|APdF} zNBiMGI5KE3uoNFjLxeBs<;`~VXaL*Hw6z^K8-(db($bE~?|V|J2GwmT#h}F$x4tFT z1a9FPrN7+;uo^DZrIfm!vYoi*-2GJ^U48PYIJlf)6KaOGyGm;_wXkkMhrCXY1g~w~ zc)5H`b99N$WI%4+@V2~OXWHgZxo-umDc-`gH)+f7D=X+b6a1~?`uK8rdefYTH=7VA zi9z)so1JWZmO~*8e9ZKa?zKVM7_Sdb3G@XY_bCZ%Ch0;0T|zyH2FWO@TdWzOmJzje zeNu6iS_E?Lsr8h;EYkrys7clP=Z;5v@T$-(4fjj{l=&>HYY1-Vu#%ib-mMt+>a zdOra#k0fyiL07!j8Q&lMxYjS+p|XHkyi&K{VH(i%Ei6SV*uvUXuLv*ZyK<1!Cw^+O zrbGOkG~j%lLh}Bav=&(}OesF{0C4b6b>WbmP5iv!?jZ4ZVH#1u3>PghJ{Hl8(aCxszxUD2Z~v$)vZm!| z>EIdm6ZR{gl&+d9)`r)P!&~WIDY{zgER{)RtH9ELivpmYK=>t-!VG94;8FnzOYmHU zR#C#?%}0QzP}t&EzkQ#BNg zCjeDknE@_EX=-ZnF*Aat%)(Z*~?fu*CdNJ zFGO^RYd)x(u09E83Ry4`rsk~|&pS;@wn73&PxFUZqzod{PcRcRS{5a{#OwFAt{g`8 z!KA)WRtF${l-|LxLIZWt z!b&5(w0`~{=cm`^ZOMAJCM0Q^IzyRnRNDons+6FL13zT{Dw2%v!vKa!?7;BP44$M& zX~(w8aI{)rp6TNoNJf7<=o;X1~aUN zQcATf92kufm31>P9(NKsCy=o*l?~?|do|e&4DNrPLeId_|2)hXTp68F+I@V0 z(7>I4Lpf7e$SrQc+D_M(W%hR-;d+Q0x>oLau?o6Q46A0wcm8;oxj(r46i;zrhfO-S zZ4GeWrWem*ESd{06f$nlYh55u&+6sJ#f4l=sJfXAE>U3CnG`hcEWM8YV`wnWAT>Ls ze@VM6zaVWT4Q0-1T7O+*@E)?gCT)d6R*#}J#06_$=>*4^;u>nX>Rc(RC)!$f@qsh{ z^w%)s@P1miwL|#4^56^C{B}ygvxw>QVuLu_$D1v15lA>k8^~e~uB;NHY$g#CG94bD z9~)Bh6bli_;2XD!0gQ!}uV6Rf>oH5EUqzQMH=7o-e}tJ9XJK@sjAz`orqXjk|Ac*< zJgW$6L^dNZTf)6lHd}uexetb5+IP=Qor6?~isKEW1<_CqjLEs}3Di;0V&2@Ft3JZ@ zB;>F+%wpABF;I&mJ0;N)OAT+(Ih?H#R#&n1_z<;Qx)`Ln&eNTxnh@vEK@;ENP@yt+ z(}wqHd8J=AyM-k+vF0is@4S$zI(AuLQdHI1w4b!%HRv7|>qTWIf-98x^6Q&NBn9FGul*ZIr&qb(u_=oL|1`iW+lNVT0qnoqmWbbtWQ{5$DE7SZnbfc^I2yJZ{L z-=^^7E+gXYvk^m7FN8N33JWhA{eg?{9*2Q;*M9+Te=VW*-g%`Ii-BS#p+QTI`g z>$89ly&zSu8Y`d~@2kT?X2l;uTTq8x%Et(6SeP2`soo(#2+!xj)rgl+88o+4$Nj#$T|UZS{iqr7;byl|o5y;1VqD|ua3 zzN%H9I%wLqKsNGCURdHjxG5E{Sq?3h4rBh6zJCn2)R5#{mW5rBFN z%?Sv4&ge=iLOb{0eY42F*&U-xeCoQXMUZ)UV&% z58)(ljsZT*FPvBZk`&PnTZy9o9pPWDmS;{M&bxF(WT34{W#J)pq2`Avx{C>1m%yW z#DeuzcK!+iNQ0O)qo9=fq%o?#O_by(eC?kcGO=D^wMt=3%^T5@%|E=vYsIK0bHe=8 z#wA>s}A+qju1{>h0pylXT-gi?g$pB-3L1}(#{wI*P=lwbp zZB#b*YY)Qf=Y8n`@B8%`JSX#qgrRK6rAC88qdJ{gz zHcXs|5W4}&|M{Yuw!1g2)6@I6uC476c^&I4n*GN4IXqq6vd-E;O2XVA5m_<(f+16! z10o|N5(O(Cs)vN#oDeMZmIt1H3>3dB!mHZe4FqsmP>c!@Z6MtoVGk7Ueld1yCya}$ zOI_A}2d*s!*@S<+xnxvI0y&tJ^i{U8umH?k(db?EsCc`p1yaF`1s0*YWl-_x9@-}) zqJ9E(w*Z4QkO;l)^-F&hdf@P7YOfCMF0z*N0*G+}qS$kFcr~!t`8^`dH;*O&4K(H8 zL&F+dh}BNoG$P`kXj`JN3$t~2dsA;%^QGO5I*W2k75Cm^C8ZbM@8X>l@t4m6Z)r8u zvy7}wtt!ah6lTv%0?7>PLd(e=`n|ro=QVP9rfKY_slgphm9jenF6p79zg74S+2#TE z#n`Y1Nmcp%y#6#aW(X&aNUkSdA#@C zErQ5xXYd6gyQ<+t=^sX7c>@gpaUSYkNpTFbM$<|cq26_dhK3X|zVgP`D>`48S_5ZKiQ!anmGIalLd+L8L zd;Nb}pIXA&u)$(|-qP&{0ulkcB)`5+Y?O&7y>5|qFBgSb8nVMd%JY^M#Ge@bgOAF8*x5MMl^U$j_Fw@Jgvy ze@Kle`y2oPc!W|SelmJF9K8o;}USy9?5jmGM6l5s=={GgXG-6@b z26ur1Er2uv32QS85A)f$f@TYkYDQ0l!QmbOc4Hs({KU|RPQc-xEN~wbp0DHT$3;z2 zdVt(=JInKaeh4CMM=S=b-cQIxo?3t;be#|uY;=mxMxS}ZYwnMbx*R)EXz2u_h8#V- z59fKj)15F+MbrTaOMI}FOww?0pg<3~_n?H?pGOdV#M99s_kd_7Iq8ra(zod^4Rfnu zSC(=RW(RsZAI9EBA~rZ}6p;d*TPRbs^N4_iaItCOF+pkXTn#d{K^u5gD=rc}~f&5a)Z`uKg!KIiVE zgV6RFC(Gt?1^yy9ec9deU(lu^m%$8k3OC$}*NNQcl{3FW_IYLEZz$AX5l|csn=MFH z#cT2u7@c6VK1Nuni=o+yfKZ`OSn1+R^Az^V(XSAuF+$tUriK@zn4sM;wi5upZN?bI zUNsoER#MNrIGQFGZudE^e~GMCt;T||LT~-L^*{vY5LVLDNa-e_@EYOQ?CHB1CuP|N zxt4)k3eve=cS=kqU5U9qM~y|IjB3_RC0*T#vjfRL1RGtbjy7j6=jr-^9@pJy;dn%Lh=ku|1;bFn?rX%;T zBubhn;QAOL;xUCs9iW)&LWuLI zS9gBFaA_w|7{$tUToY-FUaQXiowQ_9eo+NL5HtVaA&4qe^I#UlaYcn=N$VJ3OrS%` z!bR-VYB3xa48(((kR7!1IBA~q}!1c`-76{Ax~;cD1v#3{a@Dp?CtvH z_`-7sbdaW&DMQpYRS9mFR4}ii*_Rb0DacQMP(gHAL#**#Sq3m9n`4*Qlt+mED#&Fy zTJ5J6W37>BCnj(hYss`SVhj?Xp$6C4PF1PVKj3{FFgX@yw*6_9K>e|QS(JZST-j3e zy~ug*WDFjRqqILLlk=b$beQTy9!>aT1(QcNo~_jylITitB%yeE2+|;MnQuFbz#$Tg zGYT+R2pE&`{dX6rXc%m_N~00xw`BGX$f$M8LFsSjavgY%Zu`(Y~%E0n%)}eE*Q(rf?0ovh6 zcRRtI#3xYYcBe!aVI((gqPFH(ja12j)HR@aeE?D3CLzoh!t9spE(|y9w((YhN0JOX z(A;)>5h@M4zr*feT$gH4HgBYS*j;iXI0fKv{)!>_z~Hmmb!eKRC9}|H6(QKQ*}-=m zF>R<}W`Um`$2Fg=ijyuu3PCJRqr}ckhQ;MSlLBq0T4>b(Q zODL^PgOtWULd~g*;ai0Pi5?7j@fX2TM^{G%RBKn7zFEEPjcGs$K%$Gv*Yl~hDgP#; zZqeGLD|@!9O4|Q4+W^Ml5w4ri44&KOFY}DC0Kan@Lr zos2Tt@0C5zR75*Ctayyy=vB1J<_VRa$}W<>V{JjNeYn)K7ny}JHLAagRCBb1u|bWwEF2*8I%yb6YoBGmr^rMj0C zG@baisVy$CYIaY>VbilKh(;d*5cX%ET~>M%gicSlOy~1qoapx;jxME~PKl${&~w?V z6yXb73e1SWmh^9C{vi2ue(T=q?-<;hxL>is*kDk2?n?LWII0euXc$??6_vFJjmUx3 z8N3NI%lpa$2M+G#s{dT;(*U^uOzcYn*G2;&OM}{n8i&dQcCD67WDiPSR#WBVkng5h z0(q(G&SbFPt7vK87SFAJzbe|nwrNrRma3=GesQw@K%Tu-63sUjXaccNQ3qCbUqz`? z;Q^QPuk@HxhSJl;C*~r@UhRW~-^eWh%1bU0d1A**&)7S<@b&%}?9Ju=xkJv*?)ABQ zKFVx0ajA8|V>W&Hi9QY3^8G~)Ju^?dghP#DyZC9?w0h}nG@;3}V-dB2NAlEBr4?Lp zuqXO3KYu;#+ViWKn8@Tz#x1v4^Fb@`bmoHkYM2PUQ{@x(mAd9vi}CXCLgvAJNder( zaf-KR&Q$hX3bdw}hoh!;Uu#3h*flQ=d3?M@zRgt0u;v_8Wrkk&hUhc!Y76ar3r>+n zV!H&u(SmdB8mgO$l!~r44B%?9R-vcZ&hPK8{c#)Q#ShZ$zzu3p#brb9dKD!~q-MaH zWOYfF@^7NxUjh{}Tbe(BuNJI=k5H)VtY8Ww zVC>9NRaQIPG?i_&k9fLU02{e(cSv?WD;VjzZnazBm2|>+{s8}jq%Jkgkc<46*zu3F z`=1Fp+rQ8mT#*0(SpQu@{;$Li#lK{R|3wP_=kxzf;*S3Bc@0ad6E+(n$XigeyqiEG zVl63GOxCClS50;e5C(lB3E3p@L=INcQubl#`AQYHBYtzX5ce2sCTM599E@JkuW@OF z6bhL1X4Br2+$TMs8;xd|Po4xB`nUve!1t!a*x7S(^q3%NcLzSTJCW=mCr%-Y2#BvC z4MlG5(L{g3<7`K<0#3-g!slR)k2XTgdQU*Z9Nid;~KPJ@R>kXp3KHTBf0f$U%GbI(i1!W>?_RVq#^RK(M0!) z3(AEU1u7TMW2et|T0+^$+z!A%ptUf9V30%FTC5nV4N(WpZIGkGCI?vCi!b+00I*N$ zKpX=b|5*>MRM6yBq0sLiH|O5%r-&shj>8$@-@R0g0&$B0uJ%>pzE?hdH*=aYx{s=f zFTG4*XT^Sh#T@pxb4;>Y=wDq6R$`577=u=GU7M13s+a8ngBs_;#StfbvCfTnO zLf9Jz3I^%7RuKn5g+!|i4Xe7*Z|KqGeg(H1C)cgn298}liACz*tL)|94x|+bfRo}q zD4;pNn3jh(q^0|aS(tsQ7xlKDUYfxaQ}H|gYbucO=Nrxq71ErWQGvA=_*Dex)EecB1FDu`2!XnMQG2H_2_Cs1 zQ01yB$O`cnS+7IjWgFtD_S;GJIQ(-76A5@|Mi!wQ66GfuLbhi@EHL%Dq8fisbE4VR zl!!v15RN0YR=bDYQc7lBlsk69k|#kwlVLkBwiqTBG+{fZSggCf*cWW_-6-)~jtX1@ zv4gleMFYK_$Vx8#EWCdN(p!hcDns~UGomde??>?69~$X|67;vUwPp5Xa`CEAyE4~m z!KKNqf^;6R zFTyssSvm^kK)V(%q1`8eTnA1ACML}flvRDfhZH$~euSk*H}kQTbe$)#I+NZsiyEdS6{aZzXRp3(fSY|cL9lIf;6)-Z{2>gcyROFvyKW}lnzHqsEe-ma1U!jUhRuBeJ;5Qg~JxbWo2%{^M({5C|P^lo- z3?rtOa#DyzIp2MSiwOLtIXrGKc>ZP1!Q8sROBr&tEZn+b!;i*eB&IZgNKs$nm}eAt z0!@hJoA3Lhky{$l>hJN6AbZe0Zts7x*a-WlG|1d;B`Qp~R8{BgS2cN?>P>A=#s$Ta zPtsB4r{2KM$@l+d7*8$Cy}vO z()o*~1|1q19k@dGA`|bg{D{E$Nl@HS0w$n%_&akS+eRZl`Z}QKlR+bXlP}7t=B=O45b&ze+ zO^JYPuvytxAdI|e_wh+%ls2AQ^>F33Pc9HMlP52fp27W`1`duGE7|iWduy)^CN$*? zOzZudL|x>+SXY*sws8D#+Y;sQBjxC7*8LhF**C}a;w)=(dbp8iKqixSd5+ZJ&zD6_ zDwP^TowLTb5THt3|61YkNqzB+Xh3zArxIqyQD=sF-yHmeJF`VF+H}NHA+Do-M4zoc z8NNN(w?=!uD_8?2D~OeXH38chVG|*YIU(<8-(0GT`Qh8J+!E?yUg|cwp6Z_NQBYI6 zfM~`j-JLQzxB}d=P z0Pv6B`M+nk!u;otZe(q4L#J<{@Af|wzxj8p)BjTG`HxUe#@2RL`cB6Ge^{*e|8li| z#&i6el+hUe4Q={AC$s*$+y0kS&;N1T|A=n)p9I$bAD;s4-(UT&1knF5=s)PU+5aLg z)crS;CH?P%TI-wJ&{*la+dBV~c5C_HYYYuzsXK14y#Ga;zdPIM5;-v98{%}54P<|P zJ6$&13|!Z(I}82A!~%qXpaCTEJHBr|0J(-F8_LJj$x_^QJ8k1|b@J8w$k_O148(^V zAEgkB$ur0MmySwvp?N>9r=GTYZF@u=QNZ2>o}*{&Wa?~VcGcuj;w0Hm=Aw56S-GdK zgN5_~RO6+$hn<)kd|G|IjddUB2O?yE3Q0IBsLRK$9v`w7L{UZnYkIKZ7dEm; zv8g!H{&8EjBt!J#=Q18_MFJfI6N-QkLDoegel?Nqef|8bZ0rYPjEKk6W6H-8G18KQ zAlD@150ICwAjWr)2|FjCu_rAfD-J#mkP_vt#&X~5P}Jk+V4OAu>_}X+@M28nRDJ9o?3vfOao?3!+_Q&-%>QFX_eRA9*NVF2h15mA<$C7}8 z8_wn?kK^=iZ~YID81xqMjN)uX$YMPOZ4nj~rd;yjjx2#3(eF|q_U6yey`e~B;^-ZKO}YB6VNWz1P9 zv@<3ln50sLAu)Af=J(pr(V7TF?*)K3Kg#Nb0b8Fk4~CZs=n!xSe_eIGkev_5$MoR7 z!wpQ*#rLHLgO3-we*& zZbIsl1Kw{5eGW^Vf{2xZdbO9oB1PpfdGx+blh;tJqJMkwp$q`viOTLwfpqgo zxYfisfTeh`^39$7m45Wj4cbw8MM}!F5hTq}a^sXzGFU?#NVaYpjvF5;SnI_-+gn7; zSP~jXI|o$onr5tD_!X`zgdVIgWvQ$s!}SkHb^4H{`_GaFlbcG%`t7I6BAhyNSnL9F-D!yDEEXKaKss#P;39n zkGNP<#OyV1{Aw(#W@-1{fAS+Qq!u4%KD<@`Rm^&q&WI-8tMAZDj7|+L8)a1sh}#x_ zR67$N%k*o+vdf=`kLYaPe+dJf3g`$SgZvh)ad)oj(2s((6^jd!O)?HJ-$U;?0hB1T zJ_SxDw9OhUqv46FZ7_$ly_0kE76v@4{36k?4P=qM4kS>EL`!!U7AY>I$s8h%Wpio% z!@b{V6&$sf9S7dOz>gLWrAWCauL~PKe=dv4rnXGh?YhK|ggxPT0`d*LW96!f%LvG9 zQlPiwTxKz$7UQXd_!2mFmmLfA3{}U z&wb7jg;H{CNwds_zBPZ^_?ry#5ho;`FfT8?un9+gLg_5LbbTg_5t=B|?ty}}ubMn= z?s&Eb!|US(`sk+r>Qv9#6T&ERU)SQp^Hk`D`wpo!aoBWG^Vgby925ohUv#Ou195o0 zzdN&$Q2}~1fa1tJ@zmSQ1wE5w^HGkV3~g?_PhrSCtr@wbmPKxaf67FgaC4Qpgj+~J z7RgMxy136UP^vHGm-4nWwS(-b`4B{r)yvH$`a*eshH`|TynHBugCVO|$inE?j|ueH z*PnH+h=#_(CVHK6d6F-?L|Z zN|GF=N~aJKNtm<5jmM%fNS!{CCLNwO=@^Q_B@N%6SzElZ{+P?Sxk?h%KPA}0`XLrdMtXx_TEUGp8S9r#Cd?pOhJL$GR614%HX^mWDUy3PCwf-q*t(Gd(HVI1pbx zGf-u%PF*yJf1k+TJZSizGyAO_=;xwgzlcY3ehFf4jROSk6w?hnJ6|rNRnsd$Yvc5r zd0RIp@^2u*azh!jwE-ue7X$2>J+7&0~vu972zfjWiC_k#DA3a*0t zJC$X#ydlNtkK6@%I%j-YmZ$}ozT&n8vM>c1%VceJwQhC(ZkJ4@CN{N}G`e(; ztE6jrp5C6fV(k2$d*jjFFPgEMHDj80-qt(6^4nOa)m*jdd>mD)+fq7i&f4VDU^lDw zq_HMPzvR8hW(x@N60TvE>utT7+=YGqnm-EIL-j<(?gbTe;QvJ@-7ezxYaHMWL?g^a zu5KTP*tzVGli{z43rs4r^Y4c>hqR_KH3&r{hE(ranYV9t4qk3<>t1i$^*ZijuS^b( zTSy}RSp05&;KqvU=@la@R!Voc(){!*J>1eh$GB+Y(`MM-)RXszN6Fqu?-ezAh@$KU zUn?Y(PwWMusmK=^d6}Ty0^|eEA&|sxfg~S$dDo9&q!Z*Wm|b*IVFbF|QqQE(Mn^KL zA787k(E*r`?G;sJ+Rao(bFTI~3 zZhw0K^@ve?$OjrHf9k+t%6uQNien$34sdo!CMRFTjb`#ER{Sm0;hm>(QcJBY_LOwy zr?M8p?nDV!WyezNihW%6-Mk*uC+sP-Nih_FMNRqgAG@m1jGX-Za{+=1d1RkZk2O>& zr26frMI=$A#=Vj*v;`0yMdnt<5UN=e-D%Y3IG{#2e|E!7dmj7ERqGr`Cn++D^9=cgqHbtnhk%F=Q z7CmPx@DD(jdRWj781xh{Fp@b$%Lrt#KQW4z4si7+t3*|BErQ_sT8{SraQhboZUxk4otPZQI8$|_3==UXcGX`f+A(JELmU0GR)E>c>L_%;5# z_v7|{D5P0Jg^~KczepPnvoRalIMN?tj@pbPLbB0B0YP!v^B&4)N*uotvuZrNMnY-@ z^ezV{@mx+^As#JX~UEgGb5;WLGy1 zz8OrKUDymM2IEHt7c?ACzY@=Ny$T~cxcLbDa~6f7y}Sn}a%oxpOWzewV824T{%E=}LR5=B+Yq)kjuDUq< z#dodcgkifI<>n^{fv{-tHWNi->W;b!yIG#IygiL>Jqz}QC>l*h2fy_1`_uWTNT3Sl z%6s{U70RCA*>*?HvivYpg_!(tS+Gmnk#nG?WT^nP>`;LbpLMZO_r&PXi;iXs+oe)^ z!a&k2VNdE~@A;ZZtp#8Nf*02nfyJ_X$qAY_n^LuKCLWqbpmiuwerF`|5tkyjn?_RL zP_EWy=!0$+b0Xqd{dX*Lw_eh&^tyeHWKCeLWcqX6u`;^_A$)>=jjhtbs>??B5{I|E zqfuIOwx%nKZ0KR&SU|+>uW=wg>@SE^v&#wapgR9ZO*``&inwJV6pLmDRIB_5!Nhc* zv!R4ro<@I}RA$QbdW^l!LU4XOmuRn>!h}5wcjb}%{O|~qhT2@l5GHd3#*<_Jlec56KW@qn_!8iM zEom~=(XDB*yBz5~oub;dh#Z5Lin}{3^IR)8L8VpL)FFJbZTZ$_3?xv;I~X4;PBFsT zU5ktn>&MzUzUn1Z;vu&3L%CD-Cpd7_Dn>z}9T z_Ru{EiDcX3$b8AGvv8gqrR%2W>-KiOVXO1)b#fxE6zzgd4NDmN?j3kHOb=hF#I_}; zW4gDlB)iH0bl{{{R1Z^Xa-?}xNk+}ep7EzLLSaUc{DRP8eR+2T?NeSp(su&}Uw zq46jj{8IbEeKH)sJuz;y=PW6=UBr+z$g;UtFhZD|)S6g-okdN3*>$*1ac#i80I_0l z>NJ^3r(X@-5_+R+31=^adIHU!h2mLt5m_wYo9H*WK4}jO4AXod@jVmrMxD(XuL*)) zu7%=7Y5R(4HyFaj@_z0P!nq{$J(XLJd?&dd20`Q8*bV5oh>PhTGCH<}sV{PO?GSO7 z^%~~z^6>tAo~@vTtkW{k(*5$I1)Lua#e+8>Mu3tYWf>c%SPLinYpz=gqN{^``|Oaa zYCs1}W`t0S%*nWX72kQt`jLx$?fcqajBc`R&z6zy^apjMm|=6k49;hP3Wmknu!LKG zqpEc9OV+1R*Gf-*CP+SGR&EgnDTI0V#T4Kq($TFH2MMp5m#Hu<#2ziw-X)?IcYT`K z{xVT!Xn*x?L>`X~WRw3BkCe7v3saa32VJvI^1TLWSV$40qI3F8kj(mbfsxP$(Wvp5 z#mS@jt`HnQi-z(yRd&xCXLIRv0&2@m2NSY2?(bOIa-KWWhQQj>v~B7xlBW}bhpKS1 zJG8vbP5qq4DkNm1wTZWbQb|ftB+LdLXT!PO%;8L5ezJN=?$G8um7Vmt-xnVRPk7}M z1H}giS7v6?Sr=7Dx@Vcaz2Dm%cUi^6rgYViPa}wfrunvH3vT>CzSmvf-yt5=AuxPt znJ(Wuy4>aqBFo?1whM0OGZ;>1^C+0#cWZACRqun{Lnv_MKPUvPUUVffqXU@Yp(6M4 z0(>w)CDBNFqKmow8!{^S;_(sIV?tNLE!;%YVNTg&MfzfB+BQ}1rRsw^vDoqPcnlWO zV#P_bVV7-&RgNkEm3|@jP{2i;GJW5tmJ;WbPjg}kiAeWX>SqkrSgb{01z#;T5`WbKgPjIY}6o8z+*7rQ1 z`eh8T2l?=Fvf+7f;Y?WS99}JAb0`hu`Or+bO`Ws^;7#$Gag`Dtxm2KpG@qh>ks^@` zlVc85=%}>|a^h4M0htL{Z4P)!r~%0Tuo$4peG<|!t( z7_X+^QO`1cXg;Bc3!`R=)qjcof&M-{%Rs)RX%hZ_DEr3fP`j+j*tTuk=1p>A+qUiG z#>tIs+rF`F+qOM|j9)Bm2ep1*bWuCq^7?fH6ig~KugokZOYg(oFPMG%KP z&yS1j-BeE}6vpK5EtxSn+rgbMJow3Qsg?*%UXfl3Z9u+(9WP5~zH!(+9z)BOpgpC+ zAP{5lXk=>PE5U+boHsiwEmi>b(i;w%HYtRIWLRMa9DDqrVsN~+ zvYDqk?@b{&v{=XtJq5cV+>FT96?{7hc4YY{J3v=#N9H-7W0CQb!I;rR1=Q|-1%JL; zE%vPu?LFXjqJtuUURU_0h_OTOa@u}gp&{+OY!(Fz1$dP^5WaaWi2`e@V{mWyIr-6s z7Q@}>LvF;q%=E(>&Y2MP?>=w7{;c*}C90?P{_se7Z{T%g?_F%}n|6&zjG7snOG^}R zO>jdan!Y$e$H+^vFD|24IYlY;ADh&6D6U;UhMkqOYHp$zGT3qrVc{VfRE?fRbG6-3vd06Z*bD8{SjwEX2{XXk6zV#+=LFcheV zlwse7=R-5-8%K1@2u2{wQKp`7iy>#t{(FkCyYbTuj*UC5>ssyBWSD4omZ5iT&h$ec zw}PjlO}=B+(!kmu>9ZQ`1nrL|+!ji^(jI%#m`G$R!h@m@YF2U(*cf0ZTdttj6Cca- z88mFCadh(5A9&bP+yGqxGrM?sa))@E#n?;1>OyGfJnP#ZvpuhPR&a(9a8{cm)uxoU zs!$P^%jo`_tf}Q~t=WbX21`ww8Q!Kk)@;h%X2Zv1{<&V+^3vcJ|ml7Sv>-cc!FM&r)5-mz^mePFrKr@wf3{8`3RJi`A1|4`3 zSxz9FKzz$7k_X3OgoX?b8Gi0Ahb+)Ss%He@Val@`423rsI||Urn5L7kkkKQ>^iceG zT8Xbtr=$a$uw+;0?9_<`)?va9h^v|eX$&08ChQqt&`{J;vK4f&9*CONdaOa3;mrQb zWbs9NW!}=z0z9Z>J;0R%#IP>Z(e%8lqi7_gd(**!VKA0E%$2|(%1KcFBF=_Ss1E~xlH;`JGW z6oSHUUz#gI2pym}iu7k#um~w&|3xS|E?lrIO#?^0{U@KXV#)E$a*+t#y_!^Vf-Z z^7=GpCindV|6N77H!iFZ-p_MQMaL~1GExz8m}Ghlk$E;R*>eCdl}MItHrUk!=j-ys zU5e+EA$H$pztk*d(k-6yy(6BIJ)_e7CL$afQ@vQn=mSsZWABr-{r9o1`C}6n>4tE1 zA6XUg)=Gzs%;~n?wrzzHV|TM?PUNXn1G^dX{RzfKC`+r^nq`%c|a}J;KbBR(@iRy4$HrzPjGZV zx9)%9D$4`IvxfKRihgzHS0b_sKWgs=QU7p2j$F&{#G2f=_ZwrG7?$z4kU#otn%rzE z)ucaiu1q)bNz5n+eJL*@5sZJrl)xVO@w#F}oLI2Gq5nv$pcm9vTE5^>uKb=G$8Z0K zlGFFSVc^qZ6QabTZQ8D5Vu30{*;R!ZqEhkRSUhU2%$mnkJH32(Sbj9qe8qU4G!rV7 ztKA5EbE`B9YCqQV`Bm5W_OG1@!gWV5C}B^@{}4)QD6DAr0Ay@bBWdMDE0R{ z2k$|pW|(ZBk}^4~JN!#U;U_9O-|3d-kL2N!$}APNvVP1R8&4cza5GU>okZkdL(H}K zm*&A1O3m?)>1dU0jn#b@8mU~XR9#G;`uq8I+ycF4y_M51R;uhz_(00fVZY4g$5Z>LVP8Vi{CLR zJsQH3M3m{f_z&p>L^5;`IZ>N>tr#daB4)dIu&m)v*meo5)IuF3#n(w7d?+v7%htX) zuMz@6zB+0*_D0N{w;P}1ms{k=J;B$3$u2SrCByF!Ds<0nGH9TYTS+P~l2Mp!?@Ng(6n4bG6@~5?6VBQoe?)j|f2}TMqIRn{ zH|?8xqrX0-o4aX}0obXlQ_E91fYQ|~6H`c{?=osZr3M-|tQiqX@1K_MpLJ(qx~63B~()`sZpV(!Tu4Ocroz~1*B=v-{ zRl$ek?)-AHPWLzO`&>WF3zOxp{oE-7+ za4Ly(5%zh9p+uwBzeSxQm_=}Ae{8m?VeaEC$Vt_Ha1=X1;lHsUDHdLgA#~1%{s(FF0ZHx|Fgm* zosif7Mw1HdBV1$a==v5VcsPm7Fkb;8|}@^wA)0yW5M?=1s`3R?4@7lDXNu~P~A_VsgC zY3vQjw_AxQ7!ROY#%Va<1)Y^DMSnJFOZ3kI+B2rtf$9bT>>t9aRfM_{nKg}DJQ=da zLFqv;N!Cg5cX@SWtf$9DS8s(!Sok$-CZkj|#GjogHIxUy8d@P7zp7o51$QJ8MxE5~ zJ9%45n)LO7v#wy_b%33;qdg52z<(gzg+hK;BtrJ*;M%O%Ozg`f<=urVNjmXxT{Nq< zR!>!>VwH0(=0qvhdbdNqKN+pNBpgRw7!852Ucjl1Jy~oK8zxQ#W@2x;voVhpeT_-8DAj$5HEm)Gud%!j()4!9-i)Y6 zyaVB9n2@jKkp?~^A#ARejNa7$#Enp=zO9mU{i1r%j4Ko?FRX3qJ;3~gN|7FMjozki|R z_1CGPgh~IfSSvcW-Dg<3RO;kLYLOse=4Z5hhhne4_KKAj*7Ru$Dy0kHf~Q#N#PJXb zXz{Ja(3<0#QML$uH24zEtV>=*pJ90x^bkiq`?Du9W$eS|29IB>jzHg*$Mq9EHtvu1 zNP3CxA|hiDANbr5dY`>7pS=Nr%9oF^@w|mQ#hFUcjoD(CDs$8uU1es?SUjuWi&LXn zs!g7X1ii`mE(kB+Km?Ep=X@g>OC*!zn3{>Soh-KV?4LCb!tA%lC=Rw-K*>>5SIt|( z5q~d_qkm0H@xG>(7<|L2L}hD>=DeO<#6Kyz%nC@mS0{yMew>1u;6fSB39^&O&jZG zr19Qfr{sBNP-bo5x1N*cRxv-m>M5GYZv{LcK#x=yX(sw$DME!GQn7{rSZ9w50Z8;; z%G*#*B?vRbC37Ll2DmbnO?YlbPrhe|YU3@|<N5VkkZ&f zWD88X@+AlY!PzD74`Qf20;n~7Pf1Jm47XWOmb*}hALavZREr3V@!`#d_t$59&jmAs zYZ(@^H(jGrrS9oRq?8Pbn(-`ImSsjW>_+mG8gH#bQ&*a*k+8(?$$1UDK9O_5CL+@?k3cg#! z;~s;!w5bZP$n$@AY}`}#Bvm=l=p5!%%UZ2v-`XCbIuk3p(c<>ziqCaZhFsr4997?Q zIZbNAx_R6&Une=7>~O~&k#AlYr{C2&ud;9JoGi;?-WhItYk66EqJ~D?$Gbc;*nqak zYf~xtrz*UTR1+NIrDRU&2AJ{IpwFn_CGmUKT}Dw$1=&?niR!KzaxDT+cn|2TOI1N- zF^7I{=_D16)`Yy^`lX^1Bnj_c^w(M^8E>#3yK(L5hEFk#=}@W`S7;LFEtwB~2FC`? zl3mJs9=ds^6kC|Mm&qYJx<(Q<7MU0-k2|o=NG(h8V_C~j#eum>uv@J44u`mTCaMyq zocg{zE_;7?%dj2jDNtDn4%dWKK;cJ}IFQ?d$LEo-Pu{@r!(^aREivU7;sw<(z@m#K z&g<={g(6b_xdQ=3o+qV;?GEX4a?iq7N-`c|1IC)gEQ2KIaSrDus9T3S(fZI~#RE}> zEf1D&{oP8A+es8j2II&nf+H&t4WhjJLU$4}F}DT$oXQZCM~_MHKKJm3YSZ9I+&1j< zy?<_g0p)#E*J^4wL4Lj~re&4vFhr3>ffoC+&6@2;)-t$J<)Z_25Yv_wm)Y8yPJtG#mw#hbE6cMOfwD*PkUORejbl`o7=AlLnmD-dphwZRO%YIVP!%?qAT!tgQHHz%r7wpXbqH<>( z*Dq>dHtSH(X;Ipn<)oq`&X8(Ln2zegDJs{NzI!C-2`pxQ+snQ94=WJ8Gq6xujzjK@ zY8PbR)<$shnJo$mKjR#bUTfH@*+ylcN9Zbn=|eq-dtj6`8OzQH?*`W>E1FGAMO#!5 z?5y)dC8%(H+=zeDBgSvdG?=m3&K@d)%#{|!6(BPq<_+j)_ZyvN-5SA7TYd1{)Ua|} zQl}&0s@(V8wmLuPi6QlmQ_L|AJ`FZ^kYm{?5QfZk=n@C{IN?I=% z=Jyp-j?J(7E8a(|;O28Kx*Amdo5+K@^kGr*tBe*n1l0V1#;x(5l6HUxM4KAyLSnr< zh=+%kl3n#48FX4PTRmxc2c>B0@>8?pI>CB+;0udmXOd5ODIL^PSWGa>sqaxIWjou=6pJ-8sM1++j23^rjTY#BxGlRjQc=pERPcxv+G?sLG&h$opP~Is_mR~{POpW08S}de8 z`WauljnTy%oZnJN=xp6&v`nu#vH|UrLk-2{^wSH_3X7z*K-ksil|-N`f^-i|(w&4( zIXj2%Q#T}jK}=SF0yc9RnnA|j6W_D8Wmf#al5CfD)UVPMlsnM$k~)dy5E?vPIOOfw z-@@I?b z#d)9N>ifF!M6PY#UGbHk(&YH)0$Obhv0_bpDnaW{O9r69x4X;r-2l)oelD!bgJH#a zU-B?_XZ(SWwWdvk4m=O6#z=j2C5D!B+IbzApT^mTA4T*lw`&HSJwVf`lG|y3c(2bvpl1qeu ztUGcrnB!2iew#cFRyUi=AA1tpONPMY)1|(KLXKWp_$T+za0A;}>FY{>FS^_+WO_Z= z>l{gU0@-mPE$9+x&UHvWB3wMAG%j3FjLQ*s#7jS+7iES`T<-jhZtN>K)1FJ^?!nB8 z7@pdIsqfhfernuIpkTxXPKmAAM&hi*-P7ji+X(uX4dctsv8-qB^jOI6gB=9uD(58ZAxR%aA|BPEVXIR6g zm1Oha^XFGNP) zvHWhlhQJ@p>dmvhU|x`)n(=W8=xzGXmjqGly$Io{5bjTUskDzYPkU3Xr)VBoa#LcW zEZsB*#2F0i-EztL`iFkI?4f#}SXp)Lk$Gfui>OL?Q5x%1ohz zo4&uh?zGVi958`yao4?=%7U4Mpq*tT0FfCqWpl{U#k^DU5j!B%Q;~Lk0*g1Z8T?#C zJ{|e-(J{tT)NdTOVxaL2DQ}H_>yT-z)=b;T6!rE z!sD+_DpF;_cqRD5m6MtcfZ}_3&||Q`-vfbFq-b|C z;%jeYl%NJf7t$E~n*oSM#_+i~>O&#Hd@JNdtYf(ja@dYLX9jnxBWUCIs8L4pVkGiQo1ai-i~ zM6q7F7cE-F1Py5)&?C8VRu%^e)bUbH6n2qC0@5qFB|pr#7W2=|o3$YPqHl-F?wY-x za_x@@!RHNz^iOR1EVyAST`@Jz8A`%Sjtwg-l#^&1nUd*cPmSrc#S%niI=BAxE7R(U zHcj86*6h2E6_5;{jWFUB!XFS>xg_v+CU>JDEt3SAtMm!fi!4CtQz;0uLoOw8y+<1W zFh49MfLL9=)La8=Z2cyY{Ij&x^+}F52XnJ3sFj$BIr`YB)q*+Y#lwfXYWw*#E~mzp zk?WZLhS9$7kvt9%1GM#fdTD(|0KEdoY}O3|mQN@!d3sc~&ag%CaLQ}g_eh#28GQ9PcOe5 zCA)Mh4)=tIcS-I=^2xxzleZ-Z6v=R*aoErdaU_YE(3~qlkRN`^J7N%lZER9ai>9k= zzX+%VPNt{4zfDo=5nxpW4nb*C3M+alaE(W|u*4{6n^NSoJ}k@#R`CeTyN6ancu|?^1i*Vtg<JK#NxpcHnB{47EQ`L;kdY=aBM3 zNKhMFuoP6mEh$t+@U$#09y5HFc_L^V1AGR0ys!l%&pEhlwRdn&|FYbyOG za^qc{Yo|v|vx-L@yu}{aS(TdI<>5<4D-EIKZBy)SYgnA}ddWU$%U*ieI_KTZ*r_xS zIr=zI)Vp)^RP61aCY(cEwXQK+Pf6Do0XMKczNwF%SU^?rXw$J86glUWl>{qr#(Q8< zIM;z*Z*_*#g>Z}OE3xpqj;PCyRj2nh9n^9Wiqk@xtp*1bdbaH+Xr9;Gn=5|boBNmU z=!>3cf_cL~Mo$5@ytmLGiXDmqUe7)MZ5;<2E!;sQ__jxWYYzTaBmA>HGUr>X!216d zpE)`k{7;vXxv?XymAT{JDzty&jto{>3twYE@TR}VFESB?>~EQpu$qIu&xH=Q-ijmr zX|;l<5*tZ+G+SN0&(V3oc7|>~h&3_8DXuXjfI04W4_6LF&+NtkYJN@pWBOW4xu11h zzcVsF1|MKik|jTL;CE@bp+fhXXvt14EWNh3A|(U`EU)0|`J(+Y{Te`iLeCvlG|vwZ zi;vGTHcXE%?K#$_N=2?sHkkyLcPp3d+*AoiY*%o)GyTNMwWUD{$U}wO>2@&O-UKJ2 zghPVsJd3^baL26@9`tqK3J7l>I{BjYEKcEE>&4%QF8SmSPa;S_c6}}R7ZS~2m_omN z0#Mm~MBVlOnBh)i=-Gj?$~5izV9n;irfFzeRFv^hqSTn@^GdRZ;^6T6gfkr}hrF1U zGX#)C(;qs-xefHG+_dnH)UnZ;O7z4hcW}8@9Qb6%xoubau@kqV^vAnFRyWqcg^u$;bw ztuW|D+Jbsca5@THnlWwU?!@*SV_#0cXQOd`Nn41CUi#`9*jK-rUEhNSygtow<#`LO zrPsry9W^pb;rzFyH}PAK!3YEZ@E0=w#w@ev-@EBu5di=M|21a+VW;~)5KC+5?C4}` zP3vgrU~cy}ehrrXrHZmrbo>^FN<$Il@$qag#dzc}}fli63 zo>`z<{ad3U1IPW!WK4qDyy~D*Mf6QPiVaJVLNoU#;4 z^wyh~^A%f+*2^WzWwZaFZjE*S*=rh=B0+dlM^3NXSwR{+tCApfnXBQ)lp&AE)oj3Y zBtg`TyUF9z5GIKyP4O85Lzs@FC~Zr}%C4112^xUa>33R$w6m!LJcGDq_tl+vBT^@H zWyMuEzS-b-HMSFA$!CKMm`D?pV#E|k_CqyS#+)cQt3`;^EeIqHp~@kR^!IP#pYa18 zKBwGTdgKZdv2f-k{ypUzAVqzvmp#J=42S3bCgDeeQ-_$^(+X{(4F(~a#63gdRB#?F zZ%Td|!I);i5@z=DPL)XFcd5~%`SqtHY5K<7)|2ajORZR|cqBj8a2y>lD04@S3%IJE=kr7m*FLTs*>9lardX7=jV6*CH>Z`Gd}B z>>x8;Z#%6MOcn*SYITR@Xuty{{{T8Bx%Q@-c-L#Jq?JV-Q=irnMuHicD>llM%uMRB zJJzJ3AF`?IS@*#=l|@CSGc?z&HX+O#ED`kMl+Xm=-q&&4PXQ4_MfjZpf=oq4x1_#Q zss;DnhYeKn#k-%>BC(`B8#wFgA}xaF@Bj#}kR`Ab_D5& zoSmooIoHA&nK{Zg(GQuRT2|1*z8ykH0m{+<9dfzsR!(j0o%T6vQl0&@0Wlu`F>bRaQ6;h*sey)1(Ytw`ofuY!Pa_wJ>d} zZ;2hrV6w5BiPmAQ`_qBk*irn*3hH7XHByh>9tE?LjF8=BW~|_c3xa0Y_zdO>zXg@j z9?WY;tzFJotm?Zf4J6NRyD{xDcEb3r_n$jgt*{jNn6rt1u3rLR_LVY!{ZMExbn~v( z;08$}*jf)e^TuBO6h>XQVojH7t`8NJ(M)%!wUD#c&^;wJ2&ItDtvduQ*Ss9ZUW{ig zzIe8oaKak-YK~GXpHV}hz1tAFZR#v#bznUy+?_^KX z4Spcf;BR$qx^G&dU5dJn6874|=yLtdOiAC$KPs-BZaK(t(-H9ju6s6UssB{?+GC$} zD1Bb4ZS$M4iZ!L@abV=+1i!1}17Y1C)2m^|M|*p^4+e3W8gDjwBqSzt|M0a}o1MZI z7j6%&PMhzyv_d9g*~lX)K^<{jM^3LQZPd%`UOriA77h-68~c;|>dW)7Z)Aevn5>ZM zjC7rgTb*wU)=d~Y#dWLD284GaQUY=3i<8&;G5=p8|51?Ua#FBwp7q_C{_a`-Eb=$} zwg52y=RNBm@jU-d>#wpAea3>&scXKaPeEOXiha<1@F?5Oxf_u98_sT_l8D?zA=~+4 z*riFc${jK*P#j=0qV{f$Z37LY!wl)I-t>KfeJ_>P*47~xiD;Xyc;x=^@KKDkwpL{A z2816l3Hk}1A^#mzK`=5krs-!=t^8`7NR2$KKqwMyUM7f)r!Fl@kJL71q9^N4QR?c32g~ zV*@2Ot*M+b*a0cW$Ir(vp^mAno+aUP|5#Sqe4^ zxiG+jk7W(H3z5Mp2d%^zW->yL8VC}YSv-;L8PjOKS5nx4uBaxQPk|x9vb2aIR>*Yn)TTmMF3=_VGOCB;_tf2VEn@QQ*ttPuu zTVlM$-JB*(3x>8dYjB)SSo@LC^YBPIv5?Gxr{)CMGL-Q<<(RZGkyAt=I9yI5n|Zr; zk39V8x7E7U95RJLY@ouUAoUevBh$t&&gPus{tNw9bQxdEE54rZ&53emqGR)E)brP& z#!-H{*H&N8-mcNSbj%O<4v7fXbaD$%Ft~5NDYu-8T16)vdHcvH;X1Kw#%WB3ReQMz zg^-F>imr_v5<`CAU!ig8K?g_A9++6dL|Hym{e6AVrtOR%(XBPclL->8j=wGyU@rAp zo#u1;KpAxPaFeaTWv>>J>|XAzJM`afV^K%#B5d6xe4n2C*me0oTcDa)ZW?`%=-_B# zVgfZiI#HSa^9YFo}BL-%!ZRHv)cca8G$q zo5UhXhs+Q5H7dKhG4|oqq>rXX$rFmaMnjo8Oi;?W3vIlCC)_k(ikseiU9*Se*fp!5 z*7BjGH>sgE!B=9p+OVgF$JJpBq&b@7^qB;64=3WQ719tF*4R7Wz0rE7 z&kQvnFU_jl!HlyHiS<+f-irmC`lk9PTW~5cae0;<>h&K7cs7kQV%CxDO%Me9` z+y2xE#oNmz18;RHhwZy{IFZP7Ank%6sUFgPX28mDD86LI<{B2t5dn?qC=+?CG1GJo zMT!I$ac<=_f0+?=&!Uw*t#XCB1U2bG$`Y|RF-^I_mJH83(gjC4Lv3N+tKTM)6!))( zySsUb39B6Pxo%JIkI%=c4F$}JiHG-`v=cPCJtq;#d#LPQr_7OJbmo+?l0xVoTx^`i zr={dJa*$aBdf0t!IdOo*ODSIqJy^GoQB;P^g~^mNqYBVFA&~15*_dyt$(lUbqvaAa@<8C*ukRHfV3}|ZScJeTlh~#6z5*7>I`4VW$4$m3~ zmkUQ_hd9A7b4~pQ;$dK;Y&#VRDW;@-B~jIh2(ZksWMAPD&%@GW36!kss)(+Glg2qB zvv~uNVDdmLWAJV+Tj3T=NEtt`^Cnuu=t9~u($+Gdf5Dzu)d;9NI$h=1`c`Bi5gf4% zwPjv#VAWzVpSSiv!M~GK8gF;I(R+#Y;$;Y86x^2Tm#WxNmoVzfvBm*#LBBFC*!Vas zPO46!42e(o0zebpKGJd;%{Cb$h~R!LwY0Afv>JxPlGl4JRZR#9RW9iJ@k;Re zDc%zCI0yrkOF{gQ48TN{rh|89Z}otB8>Izo_@W=Fw2#+sF#;d8sR5_D)hMYJ`RxeS z2eF#HrqX8pX2yXVYQxd1kIsrD38o7&L7)n>@|yJp9Gy9q2Dp(-%tykfz*>_WK!MW= z4j~he%x>8$EkUjbI?*z)5$APm6zq#!=}GP@-3P^@@HKTc#f8~hO_Q==;8UkSxvl%zKx|~+kR^%RyvN{uqP)OT& zPRFt4fy~Q%58mKI@h2T@;fr@~(vk_a@Dj|Bd)PR}FusrqvDPEbM^u15n2z-~&jF6O zH&g0wSI;-%K81pM+^p?GWHY`!VFbHwV|R1=pfC zrgih_hIs*b3xD*%1lm>{;&xPc+D`kTdE$`AbC>sN^8BPC;X~q&sxW zmCAKnK?@?T6I{dbZvsqwXYxE**z=h+whDn|NLwF-+D=~ z{+Umie&+yj{QvW*f0VrcZFKc-NL8lFTJ(3N^M?QJo5G%Wk-Y)*m=;k(9 z#^5Z)eh(5CU@`U!h^EyoK#9pxH6OQ(scDrX=?4xgOn;v7*o=0-c8B7ScQKW?4^~+p^>ifTtQ5G4QCkfC%jLa~ zc@BDu6f{9bqT8HunL~5u+%Ex5#cB}XK^1W*ZzCn7l*ltkMDg#7JLDKZyRCtTm;&ioh_>3~8#2Nz#fuvqm(ZmHbRYckdL0U3@hGZOY*;~(50Q%Ai5#!Zf-_2S zq>nz{$j)FA1Rjs0JqIkRfdcTW7$fPBNF{Vf97xdFv}x^Sy_Z1}W2s_M6rHM0C7tOT z!xZ&xoYcEzI@1N^C0Bsh{OAKKd#qSJHbft8QXp8ew`;>Lud4I2EUr&4s&t|k39Zj& z&HA8dC4X*|^7V<`d_i{>4|QeOQa_l6n?{@%W)i4rlnp<6P;-c*;+<2hF3r#vfBHbw zP-2&G27KMt!p;moy>&rxX7fX?#}L+NY6n?=OHjzPOTuP6BXX~hd$5;bMA0+SWB|%T zB{g^OE`1lc$>u-kql#?q0HLje^Kl<4x2`^)Uy9rL*?XeNm0x6gkBzceqUi;HjieKj z55tDZQc%OU(WsC-<8AVhD;BlpEd9Vm^tm^n$@ zI3E7;K&|it`x#9qL&~HK`#pt=+ICU~Jbmi2-$A3z%qYBiu>}>}v22}G%T6p(tAJiI zwI*AWNS8DoVWcxkg*N7uS|EGlSqN;YaT9M+dy*MQRgcD`E{r%E;;e|*z``0Z%CLxz zvJ8>{6awU3ODTUc?2ub}v`cf=J7x~EmLE;XUA^1=Abq}PSo zg^=FYjvo#@-YLoypy?4_8Gy^2ko)3`P(Zp6NA}}+FA=>F&97tIhC8IWe#I4*G(N4B zlcKVwQ3Q9S@ABsBiOpd}cy^Yn1KQd`WCzIOXHE3yf9)FCo-PlIKOj zsa_Wc11Jo*QBd&3SM@GzIL!1#V|(c%$#WfP_5g#|tRgtvrMIx8DN9em!GdG@sV0uv zLj$T91U!VANH!5Pn944g7RaY?(`|C;^Gc8KS>>M=iO7a@<{GruyIn z+j@8&hKPT$!ncN=`gLUT6Ww9fNS?xFy+!UdSlA47kw6kkLwFa?(J)=Du*O0P+?6V@ z=BV4IIgsF3c5Nt5Nk#Y<=p4@nnCvs#6x;seo%t6}Op>01lbI@~e*>eZwp3v~fSOK>UlJz8@g3-ftYELuB>m?nPCh$b7UJlYPpyrzQH$CR&CHjNJNM;8YgUpCKV#mC@$*lWrIVM` z8uSHATVyByxUERT4SI(HKQCGb)hih8Si-=hh=UR&XH+MuSu{sfur8MKI$kDfS0y{O zw#2-4&Gb3k{8uv~2o0aj}4&{e3-jt z6QItYV-saL0(Z@920*lyKSX*a&=8{G$6AB20&1ySqp1IYL3UpABkihXGku-xY_5;h z=}=egoKr0qNgOA0MylT#ANd@*VX?;;c%RdAZk=E`ucrKvGVJ(S8-_@m(2!gPv$^>Y%fy$qHnb zY$uq2t1j3ZaNgG&7YN)4DLWT;PP-=Y(}ZwZ#>H()g6blfwE`-59Jpz({1j#Ag4(|n zX4F9`i?q}*_yy*@p7*RdL`BAXDWbLT1_g-A7eFUgYgKTjN*0#7SnSA=>3_{6AhTIH zM|}SB?@z8&AR>;8WKcu?d6u{Ly{N*G$^n>TGxDOqkJ(qfhOCc-u8Jbb}W3r@Gt^kelc1Xt#0>+@NSUukZ z|Ln^^t`b*_X~F4SMs@;v0=PMEz>M57`prp9(;2iY28}g(kaI@jpxZuCA(|_HV4~EA z*dfqU>zLNZBi8^uR@6HLxF<>@e&uM$TQ9+Y(q85!=v@sQvfm)gJ++owt~be{YuGp1 zH)73FrQ<*tLXQfD$8F9o2 zX7vj-Ml?K^R;d6Ik_K`6Y1M^Qpzlb(*U(`NCPWREnR|bnmo|o*S@zbI}cSPR2VfNF8!M6|59OId5K=Ydx2Q(Pg{aYM6NKI|^w|raBC^_T{|$ z4da1t{Z!^SYJpI2iII(4B1&W~;$l*%>=K=YE*vFA;(IL%qR@!jFcTHrhpDA@q#j%5 zs+StO4lJN^t{btp$sWi0)OeO0XEbHmfadS~I{M(THJF6$Hac6-BpA!kD<8?5kQ@vV zlh~-$n-3OmzJDS+eUK`w;=4~ey_X*RMAPXob^1V2jc^o89Lw7Tz6Ft}hi{`iy~M~| zW5VE|?88G;BO(qPj8iDU@B6LjOZ0Dm4|05n&htR}kPs>6*o7((S9S~b{2>*bJ&$R+E_y-Kx z;^H~7Ic;Lpil98VvWSX&;r8-qtBeG-tYjMJ3`0S}cBsV#&PgrRURe_rD}cjtaHS!- z+R#ardCW!-)wJilt;r5==X&YlqJu)$a>#KbDkxs%BUO-{%chlvf(x&VnIV2>4%E=l z>}6#<=JjfbWd_{-2US-U|&u)~p?! z7tvEcyD>jbOKE?In9ELRexHUyR4w<*}#&qM)Q$)<=UPZEp z6^hpYW6Iy$HUcFVtv#Xkr4ml)10-P%{_7b_Bu-?9XU6gR!zEHizx4O0qpdgne+y># z2ya^>Ps)eT82r!y-tdGy4&5R#yeq1SD8<9c#DTi~nl-4mZ^co!SPVJnB)G;{InI3m z@n%l2yU*$mEuAFD+#ISmbGXCBV!)KcA(+mZp_Q2#IC8-06zbD@z5Z@C*S;t zwTMR0SGF&sKyRZ&OzZ)EC14@y{gE_;7&N%~O>rf5<#hw}G_PR8fbY)I5wW}bnfr#Y zp3H>9)7+sYclTa)BiK8V1-b0@1le+6O9J+K%3gcR#ygc2sU#92;SB6zG}ge zE(NQUKVT_HL?M172sKc6$FQA+b?A4rpGVKNluUU6f8Xc~t%j0y5ZuGO4}A{Z4)LTw zVWglV5PR{+d*5aTZV(M?cMB;QguoGUB@}Pplrb^dV&Vdq#l zw|ym*yE-G0iJ@>#@I~WZ7r?Lwqftb`4PDG?1i5zxQk%vJ<#bg*TzF%w*$yy?Myt<^Wkp(a!~S$t+jnTyjpz|i8t zp0VLT?d{&z7{n26sUV+M#_2G)wfUvLi{^9vwk0Th;pps52;#<1p&|X%Vu#VcmhE8u zC`g(rdA!4*pAQ1QiFM(hQ1hWPme|PvubY&-l~xdVp~By)uaAu!k5fZ{NQ*`Ta1;qW zD6G2*Ac3l{y!KkNUJOrWiQn#iwVL*YY|74XA=sU`3&fQF153&sdSQUV!`WDioOLQ} z{h@b6VC8fhL*M~#fKaSUg1|8{Sb6^gx-dp+>@6UrioXhsHrn|GxqW-+k+-~_D z9y8Q&e^{BgrI9mgVDX?V)a|Pc82Wh+3Fnq?p=5ZQ&q~Zr^+^lA0nlSoOUrz=1k(J& zS$!vc%;2Zg*pybHO+*MT9-G>i^V7xiG5ufX5l1;*^Xpq&@z<&Q`#b{v(*=q2-wT5N zPjQ9&|H`Lw{0E;U{@2%{D5Z($@3{0%;v2X*h>?m0`AcXCnU05P;X*t$6wVujiig!$ zUiG9(k2CBC#IjCRa!CIi6>Wjg+7Iu$x0N$5zVayQLVwZ9(FHHI?AAI65??QvpDnF^EVP+p^%FTv zbc9Hrwj_hwP{!7_%Qni6B*sp*S*m?3msyZaQt4l~-jB8zt6TgWes~=hBN|yOmypo#)QI&N|IBj2?CNm>W+$98vuCzoIUkdcuUEDq^upw`Zi*&Vpnu zs!{RPdAbcveU;Kw_V{EIACy~u(e=#9JDP?zC7Pq6MVVV#3xgAG?V{w_k!uPM$XURj zc(M*$D@|*fhmTV7i0=L={@q!t2w6bDS8KCR&`JLKa7R!SZ684sE&DeYgPsUch%tnkZ*4_2=LJPmp~_+M~#aAaKh`3>j4K>IhG|9MX6 z0r8Lc|NmRs&OhM%Zv<}tW=dG8vSBmFfYK?xiwg%xS(%bpJ4P!F3S-|xQUIvBq11XK zu{+U7yr!=DzaCzp$)#rtE*1k?ZeyaoJMX-YaJX@RW%U5of0iyfar&XN?ScIOVQfsH znwaTE_*J}je1hyJ7iQs9&qyLk9L2os9g5{9PoI3@?kZ!qZM6?+bIyVjvnYm~&HVLh zh2xF@Z86T5?qRvlt0&LxM2FdBSrwVs;AUGqBsWoDJ$Qm+T+6p7GXeG2OX|4&ekB?$ z)1Wj>f*^uZDU?)&7>P<@sQ`S*VZyez45=`>xlpiudy?i3U7M0Fx|R^Y!Surs&+XxB zkdTnXPgadQ_cV3-@7=ke=oJ9Y%@&mZqqQpmhkEVeW6zS%M3$t`rEY`x+LK8XS;rt` z5ZRZEP#2d`rZCCU!li{9S(D0Kx>1c?%Sc>XU zzw$i|UhwX4Ss~J>8tnVKF>qdDh7P` z!tAnMiiT}3Oy z?CN!`TMg7~9-O!yeCwNhqG#p%e6Qe@I!0=df<@ac{c5`#+s1AO;3JDSy}Xx{F#5fs zYD>O~rs213$>x`X_orQHdX%BBy0ewjL{YapNZt}h$?@vVHvN*9lUJJR*HFKbH#|R- zH>PvU&qVqZdc@bYW%a&LD4qD0Y(KO_t_?~rkVLH0%L_`p9c--LrqgTwJMpk4(*E$} z_b6?e>teK3>Q1AOuK*#o0qn=paeteT{ZmPKGEsQCn&0N zWqiRZTR;1|(#e2}UoMT;ENi8EVp(v3Fzx~8pklu9hP*X#0&eFYJ-D1nOdho!o%rjV zy8TdXhe2}51Kd(w=}Q&;-o?T)XSOzuDJEMK;;$6Aa<#^)?eLF{L-MLPhw>FF7zFm8 zQ;K?2^-DyA8YWEH@6fiV=`P~xt9-LWw{AS*aK`jZd9_A&55k-zcK;2w+*RFBsma14 zu|vEEt$8I0u`JtBhN|ndDtOPDRE0EwrKUeWB`yCdE1mF3YLBCNTkV$LF|OK%sjn{g z$>}C>f7!lwzmESPGCMmqF$!r;9kFRM6bN6lD{=T|*Rt|L9-?nvc+R?`(bzhq*P!9< zRle!3yk1I`ddEL?Ord0&riv<<->&Yc-u)7dJNo*-*Ys=Og>xiKk1*s$Tj{azl&P@W{mYjdNdiZ|+wU z?(MjoV86sm)TK%B)PMVybIKT3_cn(Fy05r@@{4g^Z>3?LM`J@Buk~p1lP=GLM5WGv z)nwjM%YoXrk&2J~2Pe1lx^C{%26F}oUDiR}4{i3z!h(8|NrH)~fw9(^V{QnEwRPuI z6RB#K7#02`=fu;?;aRw>FDN}E_ef;2@7dK!vE>=oV{7+QO?DFZ9sPoP+V8#rslRgN zTN*X^o45A}w#qbGd$q1{2`&c3Q7L&hze_3R4Yyckxu)u4JGDk)`Fg+2it=^bHZmnu zqFRryHD3Rjs7Za)TV!L!`<+8ogDBLCuxY)YC8Xyh?d?!jc-Mn^;f?AIo@dAl;|Ae& zmx5HDZ*)(W-4Dxz<6a3O@ngnU&YY)1s_UrH#!I4OEyey6!hKMu z{3;okm|(R#ZQTajYD$K{E>gc+O}f;p%R;+r^3~-IMh)@vYjJh^l;xl!T$@FH$^5Dy zVL+Y0Mup}1rKThi@gv!yG|u!BeiB+M5)JvCFJhzC%M)rUngaSLTi)*(7TwnlicW^v zShfZ<0$>zaj}P>wI>ZWAh#^aaBh@9U0xmnKR zuyKlBr>#fe$pX z1GYZ4l-4*PSQsd<6r;bs?T@&g=Bq+Skm8xC56}BwNwq&!e5lT#dZa1Vq13G`w!1YK zWrnkRcs!)w9!c0f^E%4HPV2^pw#I|bMPowbJ5RV@5DJIN4ZZosIEFW-W9}4$256uq zNw`{WE7DkUSRWNtpKX-p%YXO};Vpuin*P`^8zru)>nC0qJV@?uDVp#&i0@ZCzCk%f zKhaH@Q!JH~($Lf0%*$v{DAA@nW1k9 zlRhozuTd%vlZ#Yy>{0|D(Dq;GGf%C8Oj?OQwE7?O@$_+UVuP+_`tfI)%g3acI;q&n z$B`XQoY|EMF)2lI03Ud|9mYH0p?fBaGMCxAxJk_rgU_+WX$1sBbfKZI!?k+59b1&a z%b8RU%v8Pj$UrgyXh9K=Qkn7yuzjx&;N4l&BdlUVh@S;Pn|->Y*#id<9?^w{?wbkq z!&}o_ZtRab;3|rTE}Mupa`iPpYH`quTzA31$OL`pfSJj2{{%B*$+d}v!jCaUA)(a% zGXL}zg_%M_XF=OI@Pu)}yRo0-;7P&1%3Ozoj5VMqRe|cCG)z62@RgN%M;~uzHy6fp z%&`KZ7eBg7>kWo$wn`%q7Vc1SWdgbYo!6sOCaa0|ezeg(9RuTiC@-hUI>?5j=m6#_ zorD3Xc>ivTK*%rwpcEMZd(l|*9<-T`of#Hmu8lRv=qv!q_cnLQkQfvhnlpWNdOHKj z1Y@kPqm5k@5XIesD;^5LQWOFq#q>xWh72H#jxJgoYmCt|+Gl5CfHqpd1J!bWTYD1f zwhD$`QxA_ZGNBE}z`^R6VIhops0S%Jb0UGOr=d$cfO-e|47K<&2Z-C~LPHCAGO7PR z6ghZ`(9nli>YsOs0}-48F{Fi4zV^95T)!VTBM|TsM5e?k%tTmM z7c$}3d^U`j^8K`J3>(-O1%Nd(cbFH2E_Wtvm|V!S$w4{$GKaaC-G-^2=8#-WE&^6c zy3o*^cc)FC*3Y!_v8eSSyrR+2_Oqi+o$)RT46s(x1)649gR#e9Ii37~#S+fw0$42R zLMDh6vh*JSnJ1?uJmkR|4NfZnxMJu+Cdg4(VlJ3D296A93*fI1U@kYys{a*vY8=@n zF@S@EIt#xG4&G8g7c${;&%c6C?>W!sods|cz@>Be)jn{?hAw1+Y45BiFpia`exVyM zOV7d_SJ2_+fIxs>1_Jj9=|U#(4A0vfM&V;~5f5encxyhhKMs$wZ2;pCfc2GpHs=E1 z4|vBfxDP-VGQoU&{^qcII{-c^pt~5}A_}^T=|U!)rOm^Nh4mWGGzQ*tqsC-RCkM1# znc8ETt-jMkmpNzW=uw5kg8+fI7=Xqex{wL7{PTdHDjf@G^MM-#Ive1J#LPwHrqBWm zVkFHReGYIFK$OA{(wJ8)AVggFWsn~4i-fS-GSBRjf~2`|OwV*?|17m_T%5cmc^ zIA);>nNYA|+K`1Ey3BMud~X*V8PEl)-V!XZ7-Ku9UwNQy5pbJZ9U(7{Ku{z(pl|;J Dm;lk( diff --git a/temp/update_build/ver_0.200_20260211_000158/admin/templates/banners/banners-list-custom-script.php b/temp/update_build/ver_0.200_20260211_000158/admin/templates/banners/banners-list-custom-script.php deleted file mode 100644 index 56ab843..0000000 --- a/temp/update_build/ver_0.200_20260211_000158/admin/templates/banners/banners-list-custom-script.php +++ /dev/null @@ -1,100 +0,0 @@ - - - diff --git a/temp/update_build/ver_0.200_20260211_000158/admin/templates/banners/banners-list.php b/temp/update_build/ver_0.200_20260211_000158/admin/templates/banners/banners-list.php deleted file mode 100644 index 3e70c9a..0000000 --- a/temp/update_build/ver_0.200_20260211_000158/admin/templates/banners/banners-list.php +++ /dev/null @@ -1,5 +0,0 @@ - $this->viewModel]); ?> - -viewModel->customScriptView)): ?> - viewModel->customScriptView, ['list' => $this->viewModel]); ?> - diff --git a/temp/update_build/ver_0.200_20260211_000158/admin/templates/filemanager/filemanager.php b/temp/update_build/ver_0.200_20260211_000158/admin/templates/filemanager/filemanager.php deleted file mode 100644 index dc2d008..0000000 --- a/temp/update_build/ver_0.200_20260211_000158/admin/templates/filemanager/filemanager.php +++ /dev/null @@ -1,4 +0,0 @@ -filemanager_url ?? '/libraries/filemanager-9.14.2/dialog.php')); -?> - diff --git a/temp/update_build/ver_0.200_20260211_000158/admin/templates/product-archive/products-list-custom-script.php b/temp/update_build/ver_0.200_20260211_000158/admin/templates/product-archive/products-list-custom-script.php deleted file mode 100644 index aacad98..0000000 --- a/temp/update_build/ver_0.200_20260211_000158/admin/templates/product-archive/products-list-custom-script.php +++ /dev/null @@ -1,100 +0,0 @@ - - - diff --git a/temp/update_build/ver_0.200_20260211_000158/admin/templates/product-archive/products-list.php b/temp/update_build/ver_0.200_20260211_000158/admin/templates/product-archive/products-list.php deleted file mode 100644 index 3e70c9a..0000000 --- a/temp/update_build/ver_0.200_20260211_000158/admin/templates/product-archive/products-list.php +++ /dev/null @@ -1,5 +0,0 @@ - $this->viewModel]); ?> - -viewModel->customScriptView)): ?> - viewModel->customScriptView, ['list' => $this->viewModel]); ?> - diff --git a/temp/update_build/ver_0.200_20260211_000158/autoload/Domain/Product/ProductRepository.php b/temp/update_build/ver_0.200_20260211_000158/autoload/Domain/Product/ProductRepository.php deleted file mode 100644 index e397697..0000000 --- a/temp/update_build/ver_0.200_20260211_000158/autoload/Domain/Product/ProductRepository.php +++ /dev/null @@ -1,247 +0,0 @@ -db = $db; - } - - /** - * Pobiera stan magazynowy produktu - * - * @param int $productId ID produktu - * @return int|null Ilość produktu lub null jeśli nie znaleziono - */ - public function getQuantity(int $productId): ?int - { - $quantity = $this->db->get('pp_shop_products', 'quantity', ['id' => $productId]); - - // Medoo zwraca false jeśli nie znaleziono - return $quantity !== false ? (int)$quantity : null; - } - - /** - * Pobiera produkt po ID - * - * @param int $productId ID produktu - * @return array|null Dane produktu lub null - */ - public function find(int $productId): ?array - { - $product = $this->db->get('pp_shop_products', '*', ['id' => $productId]); - return $product ?: null; - } - - /** - * Zwraca liste produktow z archiwum do panelu admin. - * - * @return array{items: array>, total: int} - */ - public function listArchivedForAdmin( - array $filters, - string $sortColumn = 'id', - string $sortDir = 'DESC', - int $page = 1, - int $perPage = 10 - ): array { - $allowedSortColumns = [ - 'id' => 'psp.id', - 'name' => 'name', - 'price_brutto' => 'psp.price_brutto', - 'price_brutto_promo' => 'psp.price_brutto_promo', - 'quantity' => 'psp.quantity', - 'combinations' => 'combinations', - ]; - - $sortSql = $allowedSortColumns[$sortColumn] ?? 'psp.id'; - $sortDir = strtoupper(trim($sortDir)) === 'ASC' ? 'ASC' : 'DESC'; - $page = max(1, $page); - $perPage = min(self::MAX_PER_PAGE, max(1, $perPage)); - $offset = ($page - 1) * $perPage; - - $where = ['psp.archive = 1', 'psp.parent_id IS NULL']; - $params = []; - - $phrase = trim((string)($filters['phrase'] ?? '')); - if (strlen($phrase) > 255) { - $phrase = substr($phrase, 0, 255); - } - - if ($phrase !== '') { - $where[] = '( - psp.ean LIKE :phrase - OR psp.sku LIKE :phrase - OR EXISTS ( - SELECT 1 - FROM pp_shop_products_langs AS pspl2 - WHERE pspl2.product_id = psp.id - AND pspl2.name LIKE :phrase - ) - )'; - $params[':phrase'] = '%' . $phrase . '%'; - } - - $whereSql = implode(' AND ', $where); - - $sqlCount = " - SELECT COUNT(0) - FROM pp_shop_products AS psp - WHERE {$whereSql} - "; - - $stmtCount = $this->db->query($sqlCount, $params); - $countRows = $stmtCount ? $stmtCount->fetchAll() : []; - $total = isset($countRows[0][0]) ? (int)$countRows[0][0] : 0; - - $sql = " - SELECT - psp.id, - psp.price_brutto, - psp.price_brutto_promo, - psp.quantity, - psp.sku, - psp.ean, - ( - SELECT pspl.name - FROM pp_shop_products_langs AS pspl - INNER JOIN pp_langs AS pl ON pl.id = pspl.lang_id - WHERE pspl.product_id = psp.id - AND pspl.name <> '' - ORDER BY pl.o ASC - LIMIT 1 - ) AS name, - ( - SELECT pspi.src - FROM pp_shop_products_images AS pspi - WHERE pspi.product_id = psp.id - ORDER BY pspi.o ASC, pspi.id ASC - LIMIT 1 - ) AS image_src, - ( - SELECT pspi.alt - FROM pp_shop_products_images AS pspi - WHERE pspi.product_id = psp.id - ORDER BY pspi.o ASC, pspi.id ASC - LIMIT 1 - ) AS image_alt, - ( - SELECT COUNT(0) - FROM pp_shop_products AS pspc - WHERE pspc.parent_id = psp.id - ) AS combinations - FROM pp_shop_products AS psp - WHERE {$whereSql} - ORDER BY {$sortSql} {$sortDir}, psp.id {$sortDir} - LIMIT {$perPage} OFFSET {$offset} - "; - - $stmt = $this->db->query($sql, $params); - $items = $stmt ? $stmt->fetchAll() : []; - - return [ - 'items' => is_array($items) ? $items : [], - 'total' => $total, - ]; - } - - /** - * Pobiera cenę produktu (promocyjną jeśli jest niższa, w przeciwnym razie regularną) - * - * @param int $productId ID produktu - * @return float|null Cena brutto lub null jeśli nie znaleziono - */ - public function getPrice(int $productId): ?float - { - $prices = $this->db->get('pp_shop_products', ['price_brutto', 'price_brutto_promo'], ['id' => $productId]); - - if (!$prices) { - return null; - } - - if ($prices['price_brutto_promo'] != '' && $prices['price_brutto_promo'] < $prices['price_brutto']) { - return (float)$prices['price_brutto_promo']; - } - - return (float)$prices['price_brutto']; - } - - /** - * Pobiera nazwę produktu w danym języku - * - * @param int $productId ID produktu - * @param string $langId ID języka - * @return string|null Nazwa produktu lub null jeśli nie znaleziono - */ - public function getName(int $productId, string $langId): ?string - { - $name = $this->db->get('pp_shop_products_langs', 'name', ['AND' => ['product_id' => $productId, 'lang_id' => $langId]]); - - return $name ?: null; - } - - /** - * Aktualizuje ilość produktu - * - * @param int $productId ID produktu - * @param int $quantity Nowa ilość - * @return bool Czy aktualizacja się powiodła - */ - public function updateQuantity(int $productId, int $quantity): bool - { - $result = $this->db->update( - 'pp_shop_products', - ['quantity' => $quantity], - ['id' => $productId] - ); - - return $result !== false; - } - - /** - * Przywraca produkt z archiwum (wraz z kombinacjami) - * - * @param int $productId ID produktu - * @return bool Czy operacja się powiodła - */ - public function unarchive(int $productId): bool - { - $this->db->update( 'pp_shop_products', [ 'status' => 1, 'archive' => 0 ], [ 'id' => $productId ] ); - $this->db->update( 'pp_shop_products', [ 'status' => 1, 'archive' => 0 ], [ 'parent_id' => $productId ] ); - - return true; - } - - /** - * Przenosi produkt do archiwum (wraz z kombinacjami) - * - * @param int $productId ID produktu - * @return bool Czy operacja się powiodła - */ - public function archive(int $productId): bool - { - $this->db->update( 'pp_shop_products', [ 'status' => 0, 'archive' => 1 ], [ 'id' => $productId ] ); - $this->db->update( 'pp_shop_products', [ 'status' => 0, 'archive' => 1 ], [ 'parent_id' => $productId ] ); - - return true; - } -} diff --git a/temp/update_build/ver_0.200_20260211_000158/autoload/admin/Controllers/BannerController.php b/temp/update_build/ver_0.200_20260211_000158/autoload/admin/Controllers/BannerController.php deleted file mode 100644 index 666a64c..0000000 --- a/temp/update_build/ver_0.200_20260211_000158/autoload/admin/Controllers/BannerController.php +++ /dev/null @@ -1,337 +0,0 @@ -repository = $repository; - $this->formHandler = new FormRequestHandler(); - } - - /** - * Lista banerow - */ - public function list(): string - { - $sortableColumns = ['name', 'status', 'home_page', 'date_start', 'date_end']; - - $filterDefinitions = [ - [ - 'key' => 'name', - 'label' => 'Nazwa', - 'type' => 'text', - ], - [ - 'key' => 'status', - 'label' => 'Aktywny', - 'type' => 'select', - 'options' => [ - '' => '- aktywny -', - '1' => 'tak', - '0' => 'nie', - ], - ], - ]; - - $listRequest = \admin\Support\TableListRequestFactory::fromRequest( - $filterDefinitions, - $sortableColumns, - 'name' - ); - - // Historycznie lista banerow domyslnie byla sortowana rosnaco po nazwie. - $sortDir = $listRequest['sortDir']; - if (trim((string)\S::get('sort')) === '') { - $sortDir = 'ASC'; - } - - $result = $this->repository->listForAdmin( - $listRequest['filters'], - $listRequest['sortColumn'], - $sortDir, - $listRequest['page'], - $listRequest['perPage'] - ); - - $rows = []; - $lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1; - foreach ($result['items'] as $item) { - $id = (int)$item['id']; - $name = (string)($item['name'] ?? ''); - $homePage = (int)($item['home_page'] ?? 0); - $isActive = (int)($item['status'] ?? 0) === 1; - $thumbnailSrc = trim((string)($item['thumbnail_src'] ?? '')); - if ($thumbnailSrc !== '' && !preg_match('#^(https?:)?//#i', $thumbnailSrc) && strpos($thumbnailSrc, '/') !== 0) { - $thumbnailSrc = '/' . ltrim($thumbnailSrc, '/'); - } - - $thumbnail = '-'; - if ($thumbnailSrc !== '') { - $thumbnail = '

'; - } - - $rows[] = [ - 'lp' => $lp++ . '.', - 'thumbnail' => $thumbnail, - 'name' => '' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '', - 'status' => $isActive ? 'tak' : 'nie', - 'home_page' => $homePage === 1 ? 'tak' : 'nie', - 'slider' => $homePage === 1 ? 'nie' : 'tak', - 'date_start' => !empty($item['date_start']) ? date('Y-m-d', strtotime((string)$item['date_start'])) : '-', - 'date_end' => !empty($item['date_end']) ? date('Y-m-d', strtotime((string)$item['date_end'])) : '-', - '_actions' => [ - [ - 'label' => 'Edytuj', - 'url' => '/admin/banners/banner_edit/id=' . $id, - 'class' => 'btn btn-xs btn-primary', - ], - [ - 'label' => 'Usun', - 'url' => '/admin/banners/banner_delete/id=' . $id, - 'class' => 'btn btn-xs btn-danger', - 'confirm' => 'Na pewno chcesz usunac wybrany element?', - ], - ], - ]; - } - - $total = (int)$result['total']; - $totalPages = max(1, (int)ceil($total / $listRequest['perPage'])); - - $viewModel = new \admin\ViewModels\Common\PaginatedTableViewModel( - [ - ['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false], - ['key' => 'thumbnail', 'label' => 'Miniatura', 'class' => 'text-center', 'sortable' => false, 'raw' => true], - ['key' => 'name', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true], - ['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true], - ['key' => 'home_page', 'sort_key' => 'home_page', 'label' => 'Strona glowna', 'class' => 'text-center', 'sortable' => true, 'raw' => true], - ['key' => 'slider', 'label' => 'Slajder', 'class' => 'text-center', 'sortable' => false, 'raw' => true], - ['key' => 'date_start', 'sort_key' => 'date_start', 'label' => 'Data rozpoczecia', 'class' => 'text-center', 'sortable' => true], - ['key' => 'date_end', 'sort_key' => 'date_end', 'label' => 'Data zakonczenia', 'class' => 'text-center', 'sortable' => true], - ], - $rows, - $listRequest['viewFilters'], - [ - 'column' => $listRequest['sortColumn'], - 'dir' => $sortDir, - ], - [ - 'page' => $listRequest['page'], - 'per_page' => $listRequest['perPage'], - 'total' => $total, - 'total_pages' => $totalPages, - ], - array_merge($listRequest['queryFilters'], [ - 'sort' => $listRequest['sortColumn'], - 'dir' => $sortDir, - 'per_page' => $listRequest['perPage'], - ]), - $listRequest['perPageOptions'], - $sortableColumns, - '/admin/banners/view_list/', - 'Brak danych w tabeli.', - '/admin/banners/banner_edit/', - 'Dodaj baner', - 'banners/banners-list-custom-script' - ); - - return \Tpl::view('banners/banners-list', [ - 'viewModel' => $viewModel, - ]); - } - - /** - * Edycja banera - */ - public function edit(): string - { - $bannerId = (int)\S::get('id'); - $banner = $this->repository->find($bannerId); - $languages = \admin\factory\Languages::languages_list(); - - // Sprawdź czy są błędy walidacji z poprzedniego requestu - $validationErrors = $_SESSION['form_errors'][$this->getFormId()] ?? null; - if ($validationErrors) { - unset($_SESSION['form_errors'][$this->getFormId()]); - } - - $viewModel = $this->buildFormViewModel($banner, $languages, $validationErrors); - - return \Tpl::view('components/form-edit', ['form' => $viewModel]); - } - - /** - * Zapisanie banera (AJAX) - */ - public function save(): void - { - $response = ['success' => false, 'errors' => []]; - - $bannerId = (int)\S::get('id'); - $banner = $this->repository->find($bannerId); - $languages = \admin\factory\Languages::languages_list(); - - $viewModel = $this->buildFormViewModel($banner, $languages); - - // Przetwórz dane z POST - $result = $this->formHandler->handleSubmit($viewModel, $_POST); - - if (!$result['success']) { - // Zapisz błędy w sesji i zwróć jako JSON - $_SESSION['form_errors'][$this->getFormId()] = $result['errors']; - $response['errors'] = $result['errors']; - echo json_encode($response); - exit; - } - - // Zapisz dane - $data = $result['data']; - $data['id'] = $bannerId ?: null; - - $savedId = $this->repository->save($data); - - if ($savedId) { - \S::delete_dir('../temp/'); - $response = [ - 'success' => true, - 'id' => $savedId, - 'message' => 'Baner został zapisany.' - ]; - } else { - $response['errors'] = ['general' => 'Błąd podczas zapisywania do bazy.']; - } - - echo json_encode($response); - exit; - } - - /** - * Usuniecie banera - */ - public function delete(): void - { - $bannerId = (int)\S::get('id'); - if ($this->repository->delete($bannerId)) { - \S::delete_dir('../temp/'); - \S::alert('Baner zostal usuniety.'); - } - - header('Location: /admin/banners/view_list/'); - exit; - } - - /** - * Buduje model widoku formularza - */ - private function buildFormViewModel(array $banner, array $languages, ?array $errors = null): FormEditViewModel - { - $bannerId = $banner['id'] ?? 0; - $isNew = empty($bannerId); - - // Domyślne wartości dla nowego banera - if ($isNew) { - $banner['status'] = 1; - $banner['home_page'] = 0; - } - - $tabs = [ - new FormTab('settings', 'Ustawienia', 'fa-wrench'), - new FormTab('content', 'Zawartość', 'fa-file'), - ]; - - $fields = [ - // Zakładka Ustawienia - FormField::text('name', [ - 'label' => 'Nazwa', - 'tab' => 'settings', - 'required' => true, - ]), - FormField::switch('status', [ - 'label' => 'Aktywny', - 'tab' => 'settings', - 'value' => ($banner['status'] ?? 1) == 1, - ]), - FormField::date('date_start', [ - 'label' => 'Data rozpoczęcia', - 'tab' => 'settings', - ]), - FormField::date('date_end', [ - 'label' => 'Data zakończenia', - 'tab' => 'settings', - ]), - FormField::switch('home_page', [ - 'label' => 'Slajder / Strona główna', - 'tab' => 'settings', - 'value' => ($banner['home_page'] ?? 0) == 1, - ]), - - // Sekcja językowa w zakładce Zawartość - FormField::langSection('translations', 'content', [ - FormField::image('src', [ - 'label' => 'Obraz', - 'filemanager' => true, - ]), - FormField::text('url', [ - 'label' => 'Url', - ]), - FormField::textarea('html', [ - 'label' => 'Kod HTML', - 'rows' => 6, - ]), - FormField::editor('text', [ - 'label' => 'Treść', - 'toolbar' => 'MyTool', - 'height' => 300, - ]), - ]), - ]; - - $actions = [ - FormAction::save( - '/admin/banners/banner_save/' . ($isNew ? '' : 'id=' . $bannerId), - '/admin/banners/view_list/' - ), - FormAction::cancel('/admin/banners/view_list/'), - ]; - - return new FormEditViewModel( - $this->getFormId(), - $isNew ? 'Nowy baner' : 'Edycja banera', - $banner, - $fields, - $tabs, - $actions, - 'POST', - '/admin/banners/banner_save/' . ($isNew ? '' : 'id=' . $bannerId), - '/admin/banners/view_list/', - true, - ['id' => $bannerId], - $languages, - $errors - ); - } - - /** - * Zwraca identyfikator formularza - */ - private function getFormId(): string - { - return 'banner-edit'; - } -} diff --git a/temp/update_build/ver_0.200_20260211_000158/autoload/admin/Controllers/FilemanagerController.php b/temp/update_build/ver_0.200_20260211_000158/autoload/admin/Controllers/FilemanagerController.php deleted file mode 100644 index ba2535e..0000000 --- a/temp/update_build/ver_0.200_20260211_000158/autoload/admin/Controllers/FilemanagerController.php +++ /dev/null @@ -1,46 +0,0 @@ -ensureFilemanagerAccessKey(); - $filemanagerUrl = $this->buildFilemanagerUrl($akey); - - return \Tpl::view('filemanager/filemanager', [ - 'filemanager_url' => $filemanagerUrl, - ]); - } - - private function ensureFilemanagerAccessKey(): string - { - $expiresAt = (int)($_SESSION['rfm_akey_expires'] ?? 0); - $existingKey = trim((string)($_SESSION['rfm_akey'] ?? '')); - - if ($existingKey !== '' && $expiresAt >= time()) { - $_SESSION['rfm_akey_expires'] = time() + self::RFM_KEY_TTL; - return $existingKey; - } - - try { - $newKey = bin2hex(random_bytes(16)); - } catch (\Throwable $e) { - $newKey = sha1(uniqid('rfm', true)); - } - - $_SESSION['rfm_akey'] = $newKey; - $_SESSION['rfm_akey_expires'] = time() + self::RFM_KEY_TTL; - - return $newKey; - } - - private function buildFilemanagerUrl(string $akey): string - { - return self::FILEMANAGER_DIALOG_PATH . '?akey=' . rawurlencode($akey); - } -} - diff --git a/temp/update_build/ver_0.200_20260211_000158/autoload/admin/Controllers/ProductArchiveController.php b/temp/update_build/ver_0.200_20260211_000158/autoload/admin/Controllers/ProductArchiveController.php deleted file mode 100644 index 5883b59..0000000 --- a/temp/update_build/ver_0.200_20260211_000158/autoload/admin/Controllers/ProductArchiveController.php +++ /dev/null @@ -1,165 +0,0 @@ -productRepository = $productRepository; - } - - public function list(): string - { - $sortableColumns = ['id', 'name', 'price_brutto', 'price_brutto_promo', 'quantity']; - - $filterDefinitions = [ - [ - 'key' => 'phrase', - 'label' => 'Nazwa / EAN / SKU', - 'type' => 'text', - ], - ]; - - $listRequest = \admin\Support\TableListRequestFactory::fromRequest( - $filterDefinitions, - $sortableColumns, - 'id', - [10, 15, 25, 50, 100], - 10 - ); - - $result = $this->productRepository->listArchivedForAdmin( - $listRequest['filters'], - $listRequest['sortColumn'], - $listRequest['sortDir'], - $listRequest['page'], - $listRequest['perPage'] - ); - - $rows = []; - $lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1; - foreach ($result['items'] as $item) { - $id = (int)($item['id'] ?? 0); - $name = trim((string)($item['name'] ?? '')); - $sku = trim((string)($item['sku'] ?? '')); - $ean = trim((string)($item['ean'] ?? '')); - $imageSrc = trim((string)($item['image_src'] ?? '')); - $imageAlt = trim((string)($item['image_alt'] ?? '')); - $priceBrutto = (string)($item['price_brutto'] ?? ''); - $priceBruttoPromo = (string)($item['price_brutto_promo'] ?? ''); - $quantity = (int)($item['quantity'] ?? 0); - $combinations = (int)($item['combinations'] ?? 0); - - if ($imageSrc === '') { - $imageSrc = '/admin/layout/images/no-image.png'; - } elseif (!preg_match('#^(https?:)?//#i', $imageSrc) && strpos($imageSrc, '/') !== 0) { - $imageSrc = '/' . ltrim($imageSrc, '/'); - } - - $categories = trim((string)\admin\factory\ShopProduct::product_categories($id)); - $categoriesHtml = ''; - if ($categories !== '') { - $categoriesHtml = '' - . htmlspecialchars($categories, ENT_QUOTES, 'UTF-8') - . ''; - } - - $skuEanParts = []; - if ($sku !== '') { - $skuEanParts[] = 'SKU: ' . htmlspecialchars($sku, ENT_QUOTES, 'UTF-8'); - } - if ($ean !== '') { - $skuEanParts[] = 'EAN: ' . htmlspecialchars($ean, ENT_QUOTES, 'UTF-8'); - } - $skuEanHtml = ''; - if (!empty($skuEanParts)) { - $skuEanHtml = '' . implode(', ', $skuEanParts) . ''; - } - - $productCell = '
' - . '' . htmlspecialchars($imageAlt, ENT_QUOTES, 'UTF-8') . '' - . '
' - . '' - . $categoriesHtml - . $skuEanHtml; - - $rows[] = [ - 'lp' => $lp++ . '.', - 'product' => $productCell, - 'price_brutto' => $priceBrutto !== '' ? $priceBrutto : '-', - 'price_brutto_promo' => $priceBruttoPromo !== '' ? $priceBruttoPromo : '-', - 'quantity' => (string)$quantity, - '_actions' => [ - [ - 'label' => 'Przywroc', - 'url' => '/admin/product_archive/unarchive/product_id=' . $id, - 'class' => 'btn btn-xs btn-success', - 'confirm' => 'Na pewno chcesz przywrocic wybrany produkt z archiwum?', - 'confirm_ok' => 'Przywroc', - 'confirm_cancel' => 'Anuluj', - ], - ], - ]; - } - - $total = (int)$result['total']; - $totalPages = max(1, (int)ceil($total / $listRequest['perPage'])); - - $viewModel = new \admin\ViewModels\Common\PaginatedTableViewModel( - [ - ['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false], - ['key' => 'product', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true], - ['key' => 'price_brutto', 'sort_key' => 'price_brutto', 'label' => 'Cena', 'class' => 'text-center', 'sortable' => true], - ['key' => 'price_brutto_promo', 'sort_key' => 'price_brutto_promo', 'label' => 'Cena promocyjna', 'class' => 'text-center', 'sortable' => true], - ['key' => 'quantity', 'sort_key' => 'quantity', 'label' => 'Stan MG', 'class' => 'text-center', 'sortable' => true] - ], - $rows, - $listRequest['viewFilters'], - [ - 'column' => $listRequest['sortColumn'], - 'dir' => $listRequest['sortDir'], - ], - [ - 'page' => $listRequest['page'], - 'per_page' => $listRequest['perPage'], - 'total' => $total, - 'total_pages' => $totalPages, - ], - array_merge($listRequest['queryFilters'], [ - 'sort' => $listRequest['sortColumn'], - 'dir' => $listRequest['sortDir'], - 'per_page' => $listRequest['perPage'], - ]), - $listRequest['perPageOptions'], - $sortableColumns, - '/admin/product_archive/products_list/', - 'Brak danych w tabeli.', - null, - null, - 'product-archive/products-list-custom-script' - ); - - return \Tpl::view('product-archive/products-list', [ - 'viewModel' => $viewModel, - ]); - } - - public function unarchive(): void - { - if ( $this->productRepository->unarchive( (int) \S::get( 'product_id' ) ) ) - \S::alert( 'Produkt został przywrócony z archiwum.' ); - else - \S::alert( 'Podczas przywracania produktu z archiwum wystąpił błąd. Proszę spróbować ponownie' ); - - header( 'Location: /admin/product_archive/products_list/' ); - exit; - } -} diff --git a/temp/update_build/ver_0.200_20260211_000158/autoload/admin/class.Site.php b/temp/update_build/ver_0.200_20260211_000158/autoload/admin/class.Site.php deleted file mode 100644 index 7d196bd..0000000 --- a/temp/update_build/ver_0.200_20260211_000158/autoload/admin/class.Site.php +++ /dev/null @@ -1,356 +0,0 @@ - $user['login'], - 'ts' => time() - ]; - - $json = json_encode($payloadArr, JSON_UNESCAPED_SLASHES); - $sig = hash_hmac('sha256', $json, self::APP_SECRET_KEY); - $payload = base64_encode($json . '.' . $sig); - - setcookie( $cookie_name, $payload, [ - 'expires' => time() + (86400 * 14), - 'path' => '/', - 'domain' => $domain, - 'secure' => true, - 'httponly' => true, - 'samesite' => 'Lax', - ]); - } - } - - public static function special_actions() - { - $sa = \S::get('s-action'); - $domain = preg_replace('/^www\./', '', $_SERVER['SERVER_NAME']); - $cookie_name = 'admin_remember_' . str_replace( '.', '-', $domain ); - - switch ($sa) - { - case 'user-logon': - { - $login = \S::get('login'); - $pass = \S::get('password'); - - $result = \admin\factory\Users::logon($login, $pass); - - if ( $result == 1 ) - { - $user = \admin\factory\Users::details($login); - - if ( $user['twofa_enabled'] == 1 ) - { - \S::set_session( 'twofa_pending', [ - 'uid' => (int)$user['id'], - 'login' => $login, - 'remember' => (bool)\S::get('remember'), - 'started' => time(), - ] ); - - if ( !\admin\factory\Users::send_twofa_code( (int)$user['id'] ) ) - { - \S::alert('Nie udało się wysłać kodu 2FA. Spróbuj ponownie.'); - \S::delete_session('twofa_pending'); - header('Location: /admin/'); - exit; - } - - header('Location: /admin/user/twofa/'); - exit; - } - else - { - $user = \admin\factory\Users::details($login); - - self::finalize_admin_login( - $user, - $domain, - $cookie_name, - (bool)\S::get('remember') - ); - - header('Location: /admin/articles/view_list/'); - exit; - } - } - else - { - if ($result == -1) - { - \S::alert('Z powodu 5 nieudanych prób Twoje konto zostało zablokowane.'); - } - else - { - \S::alert('Podane hasło jest nieprawidłowe lub użytkownik nie istnieje.'); - } - header('Location: /admin/'); - exit; - } - } - break; - - case 'user-2fa-verify': - { - $pending = \S::get_session('twofa_pending'); - if ( !$pending || empty( $pending['uid'] ) ) { - \S::alert('Sesja 2FA wygasła. Zaloguj się ponownie.'); - header('Location: /admin/'); - exit; - } - - $code = trim((string)\S::get('twofa')); - if (!preg_match('/^\d{6}$/', $code)) - { - \S::alert('Nieprawidłowy format kodu.'); - header('Location: /admin/user/twofa/'); - exit; - } - - $ok = \admin\factory\Users::verify_twofa_code((int)$pending['uid'], $code); - if (!$ok) - { - \S::alert('Błędny lub wygasły kod.'); - header('Location: /admin/user/twofa/'); - exit; - } - - // 2FA OK — finalna sesja - $user = \admin\factory\Users::details($pending['login']); - - self::finalize_admin_login( - $user, - $domain, - $cookie_name, - $pending['remember'] ? true : false - ); - - header('Location: /admin/articles/view_list/'); - exit; - } - break; - - case 'user-2fa-resend': - { - $pending = \S::get_session('twofa_pending'); - if (!$pending || empty($pending['uid'])) - { - \S::alert('Sesja 2FA wygasła. Zaloguj się ponownie.'); - header('Location: /admin/'); - exit; - } - - if (!\admin\factory\Users::send_twofa_code((int)$pending['uid'], true)) - { - \S::alert('Kod można wysłać ponownie po krótkiej przerwie.'); - } - else - { - \S::alert('Nowy kod został wysłany.'); - } - header('Location: /admin/user/twofa/'); - exit; - } - break; - - case 'user-logout': - { - setcookie($cookie_name, "", [ - 'expires' => time() - 86400, - 'path' => '/', - 'domain' => $domain, - 'secure' => true, - 'httponly' => true, - 'samesite' => 'Lax', - ]); - \S::delete_session('twofa_pending'); - session_destroy(); - header('Location: /admin/'); - exit; - } - break; - } - } - - /** - * Mapa nowych kontrolerów: module => fabryka kontrolera (DI) - * Przy migracji kolejnego kontrolera - dodaj wpis tutaj - */ - private static $newControllers = []; - - /** - * Zwraca mapę fabryk kontrolerów (inicjalizacja runtime) - */ - private static function getControllerFactories(): array - { - if ( !empty( self::$newControllers ) ) - return self::$newControllers; - - self::$newControllers = [ - 'Articles' => function() { - global $mdb; - - return new \admin\Controllers\ArticlesController( - new \Domain\Article\ArticleRepository( $mdb ) - ); - }, - 'Banners' => function() { - global $mdb; - - return new \admin\Controllers\BannerController( - new \Domain\Banner\BannerRepository( $mdb ) - ); - }, - 'Settings' => function() { - global $mdb; - - return new \admin\Controllers\SettingsController( - new \Domain\Settings\SettingsRepository( $mdb ) - ); - }, - 'ProductArchive' => function() { - global $mdb; - - return new \admin\Controllers\ProductArchiveController( - new \Domain\Product\ProductRepository( $mdb ) - ); - }, - // Alias dla starego modułu /admin/archive/products_list/ - 'Archive' => function() { - global $mdb; - - return new \admin\Controllers\ProductArchiveController( - new \Domain\Product\ProductRepository( $mdb ) - ); - }, - 'Dictionaries' => function() { - global $mdb; - - return new \admin\Controllers\DictionariesController( - new \Domain\Dictionaries\DictionariesRepository( $mdb ) - ); - }, - 'Filemanager' => function() { - return new \admin\Controllers\FilemanagerController(); - }, - ]; - - return self::$newControllers; - } - - /** - * Tworzy instancję nowego kontrolera z Dependency Injection - */ - private static function createController( string $moduleName ) - { - global $mdb; - - $factories = self::getControllerFactories(); - if ( !isset( $factories[$moduleName] ) ) - return null; - - $factory = $factories[$moduleName]; - if ( !is_callable( $factory ) ) - return null; - - return $factory(); - } - - /** - * Mapowanie nazw akcji: stara_nazwa => nowa_nazwa - * Potrzebne gdy stary routing używa innej konwencji nazw - */ - private static $actionMap = [ - 'gallery_order_save' => 'galleryOrderSave', - 'view_list' => 'list', - 'article_edit' => 'edit', - 'article_save' => 'save', - 'article_delete' => 'delete', - 'banner_edit' => 'edit', - 'banner_save' => 'save', - 'banner_delete' => 'delete', - 'clear_cache' => 'clearCache', - 'clear_cache_ajax' => 'clearCacheAjax', - 'settings_save' => 'save', - 'products_list' => 'list', - 'unit_edit' => 'edit', - 'unit_save' => 'save', - 'unit_delete' => 'delete', - ]; - - public static function route() - { - $_SESSION['admin'] = true; - - if ( \S::get( 'p' ) ) - \S::set_session( 'p' , \S::get( 'p' ) ); - - $page = \S::get_session( 'p' ); - - // Budowanie nazwy modułu - $moduleName = ''; - $results = explode( '_', \S::get( 'module' ) ); - if ( is_array( $results ) ) foreach ( $results as $row ) - $moduleName .= ucfirst( $row ); - - $action = \S::get( 'action' ); - - // 1. Sprawdź czy istnieje nowy kontroler - $factories = self::getControllerFactories(); - if ( isset( $factories[$moduleName] ) ) - { - $controller = self::createController( $moduleName ); - if ( $controller ) - { - // Mapuj nazwę akcji (stara → nowa) lub użyj oryginalnej - $newAction = self::$actionMap[$action] ?? $action; - - if ( method_exists( $controller, $newAction ) ) - { - return $controller->$newAction(); - } - } - - } - - // 2. Fallback na stary kontroler - $class = '\admin\controls\\' . $moduleName; - - if ( class_exists( $class ) and method_exists( new $class, $action ) ) - return call_user_func_array( array( $class, $action ), array() ); - else - { - \S::alert( 'Nieprawidłowy adres url.' ); - return false; - } - } - - static public function update() - { - global $mdb; - - if ( $results = $mdb -> select( 'pp_updates', [ 'name' ], [ 'done' => 0 ] ) ) - { - foreach ( $results as $row ) - { - $class = '\admin\factory\Update'; - $method = $row['name']; - - if ( class_exists( $class ) and method_exists( new $class, $method ) ) - call_user_func_array( array( $class, $method ), array() ); - } - } - } -} diff --git a/temp/update_build/ver_0.200_20260211_000158/autoload/admin/controls/class.ShopProduct.php b/temp/update_build/ver_0.200_20260211_000158/autoload/admin/controls/class.ShopProduct.php deleted file mode 100644 index e076736..0000000 --- a/temp/update_build/ver_0.200_20260211_000158/autoload/admin/controls/class.ShopProduct.php +++ /dev/null @@ -1,414 +0,0 @@ - update( 'pp_shop_products', [ 'price_brutto_promo' => $price_brutto_promo, 'price_netto_promo' => $price_netto_promo ], [ 'id' => \S::get( 'products' )[0] ] ); - - \admin\factory\ShopProduct::update_product_combinations_prices( \S::get( 'products' )[0], $price_netto, $vat, $price_netto_promo ); - - echo json_encode( [ 'status' => 'ok', 'price_brutto_promo' => $price_brutto_promo, 'price_brutto' => $price_brutto ] ); - exit; - } - echo json_encode( [ 'status' => 'error' ] ); - exit; - } - - // get_products_by_category - static public function get_products_by_category() { - global $mdb; - - $products = $mdb -> select( 'pp_shop_products_categories', 'product_id', [ 'category_id' => \S::get( 'category_id' ) ] ); - - echo json_encode( [ 'status' => 'ok', 'products' => $products ] ); - exit; - } - - static public function mass_edit() - { - return \Tpl::view( 'shop-product/mass-edit', [ - 'products' => \admin\factory\ShopProduct::products_list(), - 'categories' => \admin\factory\ShopCategory::subcategories( null ), - 'dlang' => \front\factory\Languages::default_language() - ] ); - } - - static public function generate_combination() - { - foreach ( $_POST as $key => $val ) - { - if ( strpos( $key, 'attribute_' ) !== false ) - { - $attribute = explode( 'attribute_', $key ); - $attributes[ $attribute[1] ] = $val; - } - } - - if ( \admin\factory\ShopProduct::generate_permutation( (int) \S::get( 'product_id' ), $attributes ) ) - \S::alert( 'Kombinacje produktu zostały wygenerowane.' ); - - header( 'Location: /admin/shop_product/product_combination/product_id=' . (int) \S::get( 'product_id' ) ); - exit; - } - - //usunięcie kombinacji produktu - static public function delete_combination() - { - if ( \admin\factory\ShopProduct::delete_combination( (int)\S::get( 'combination_id' ) ) ) - \S::alert( 'Kombinacja produktu została usunięta' ); - else - \S::alert( 'Podczas usuwania kombinacji produktu wystąpił błąd. Proszę spróbować ponownie' ); - - header( 'Location: /admin/shop_product/product_combination/product_id=' . \S::get( 'product_id' ) ); - exit; - } - - static public function duplicate_product() - { - if ( \admin\factory\ShopProduct::duplicate_product( (int)\S::get( 'product-id' ), (int)\S::get( 'combination' ) ) ) - \S::set_message( 'Produkt został zduplikowany.' ); - else - \S::alert( 'Podczas duplikowania produktu wystąpił błąd. Proszę spróbować ponownie' ); - - header( 'Location: /admin/shop_product/view_list/' ); - exit; - } - - public static function image_delete() - { - $response = [ 'status' => 'error', 'msg' => 'Podczas usuwania zdjecia wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::delete_img( \S::get( 'image_id' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } - - public static function images_order_save() - { - if ( \admin\factory\ShopProduct::images_order_save( \S::get( 'product_id' ), \S::get( 'order' ) ) ) - echo json_encode( [ 'status' => 'ok', 'msg' => 'Produkt został zapisany.' ] ); - - exit; - } - - public static function image_alt_change() - { - $response = [ 'status' => 'error', 'msg' => 'Podczas zmiany atrybutu alt zdjęcia wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::image_alt_change( \S::get( 'image_id' ), \S::get( 'image_alt' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } - - // szybka zmiana statusu produktu - static public function change_product_status() { - - if ( \admin\factory\ShopProduct::change_product_status( (int)\S::get( 'product-id' ) ) ) - \S::set_message( 'Status produktu został zmieniony' ); - - header( 'Location: ' . $_SERVER['HTTP_REFERER'] ); - exit; - } - - // szybka zmiana google xml label - static public function product_change_custom_label() - { - $response = [ 'status' => 'error', 'msg' => 'Podczas zmiany google xml label wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::product_change_custom_label( (int) \S::get( 'product_id' ), \S::get( 'custom_label' ), \S::get( 'value' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } - - // szybka zmiana ceny promocyjnej - static public function product_change_price_brutto_promo() - { - $response = [ 'status' => 'error', 'msg' => 'Podczas zmiany ceny wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::product_change_price_brutto_promo( (int) \S::get( 'product_id' ), \S::get( 'price' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } - - // szybka zmiana ceny - static public function product_change_price_brutto() - { - $response = [ 'status' => 'error', 'msg' => 'Podczas zmiany ceny wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\ShopProduct::product_change_price_brutto( (int) \S::get( 'product_id' ), \S::get( 'price' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } - - // pobierz bezpośredni url produktu - static public function ajax_product_url() - { - echo json_encode( [ 'url' => \shop\Product::getProductUrl( \S::get( 'product_id' ) ) ] ); - exit; - } - - // zapisanie produktu - public static function save() - { - $response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania produktu wystąpił błąd. Proszę spróbować ponownie.' ]; - $values = json_decode( \S::get( 'values' ), true ); - - if ( $id = \admin\factory\ShopProduct::save( - $values['id'], $values['name'], $values['short_description'], $values['description'], $values['status'], $values['meta_description'], $values['meta_keywords'], $values['seo_link'], - $values['copy_from'], $values['categories'], $values['price_netto'], $values['price_brutto'], $values['vat'], $values['promoted'], $values['warehouse_message_zero'], $values['warehouse_message_nonzero'], $values['tab_name_1'], - $values['tab_description_1'], $values['tab_name_2'], $values['tab_description_2'], $values['layout_id'], $values['products_related'], (int) $values['set'], $values['price_netto_promo'], $values['price_brutto_promo'], - $values['new_to_date'], $values['stock_0_buy'], $values['wp'], $values['custom_label_0'], $values['custom_label_1'], $values['custom_label_2'], $values['custom_label_3'], $values['custom_label_4'], $values['additional_message'], (int)$values['quantity'], $values['additional_message_text'], $values['additional_message_required'] == 'on' ? 1 : 0, $values['canonical'], $values['meta_title'], $values['producer_id'], $values['sku'], $values['ean'], $values['product_unit'], $values['weight'], $values['xml_name'], $values['custom_field_name'], $values['custom_field_required'], $values['security_information'], $values['custom_field_type'] - ) ) { - $response = [ 'status' => 'ok', 'msg' => 'Produkt został zapisany.', 'id' => $id ]; - } - - echo json_encode( $response ); - exit; - } - - // product_unarchive - static public function product_unarchive() - { - if ( \admin\factory\ShopProduct::product_unarchive( (int) \S::get( 'product_id' ) ) ) - \S::alert( 'Produkt został przywrócony z archiwum.' ); - else - \S::alert( 'Podczas przywracania produktu z archiwum wystąpił błąd. Proszę spróbować ponownie' ); - - header( 'Location: /admin/product_archive/products_list/' ); - exit; - } - - static public function product_archive() - { - if ( \admin\factory\ShopProduct::product_archive( (int) \S::get( 'product_id' ) ) ) - \S::alert( 'Produkt został przeniesiony do archiwum.' ); - else - \S::alert( 'Podczas przenoszenia produktu do archiwum wystąpił błąd. Proszę spróbować ponownie' ); - - header( 'Location: /admin/shop_product/view_list/' ); - exit; - } - - public static function product_delete() - { - if ( \admin\factory\ShopProduct::product_delete( (int) \S::get( 'id' ) ) ) - \S::set_message( 'Produkt został usunięty.' ); - else - \S::alert( 'Podczas usuwania produktu wystąpił błąd. Proszę spróbować ponownie' ); - header( 'Location: /admin/shop_product/view_list/' ); - exit; - } - - // edycja produktu - public static function product_edit() { - global $user, $mdb; - - if ( !$user ) { - header( 'Location: /admin/' ); - exit; - } - - \admin\factory\ShopProduct::delete_nonassigned_images(); - \admin\factory\ShopProduct::delete_nonassigned_files(); - - return \Tpl::view( 'shop-product/product-edit', [ - 'product' => \admin\factory\ShopProduct::product_details( (int) \S::get( 'id' ) ), - 'languages' => \admin\factory\Languages::languages_list(), - 'categories' => \admin\factory\ShopCategory::subcategories( null ), - 'layouts' => \admin\factory\Layouts::layouts_list(), - 'products' => \admin\factory\ShopProduct::products_list(), - 'dlang' => \front\factory\Languages::default_language(), - 'sets' => \shop\ProductSet::sets_list(), - 'producers' => \admin\factory\ShopProducer::all(), - 'units' => ( new \Domain\Dictionaries\DictionariesRepository( $mdb ) ) -> allUnits(), - 'user' => $user - ] ); - } - - // ajax_load_products ARCHIVE - static public function ajax_load_products_archive() - { - echo json_encode( [ - 'status' => 'deprecated', - 'msg' => 'Endpoint nie jest juz wspierany. Uzyj /admin/product_archive/products_list/.', - 'redirect_url' => '/admin/product_archive/products_list/' - ] ); - exit; - } - - // ajax_load_products - static public function ajax_load_products() { - - $response = [ 'status' => 'error', 'msg' => 'Podczas ładowania produktów wystąpił błąd. Proszę spróbować ponownie.' ]; - - \S::set_session( 'products_list_current_page', \S::get( 'current_page' ) ); - \S::set_session( 'products_list_query', \S::get( 'query' ) ); - - if ( $products = \admin\factory\ShopProduct::ajax_products_list( \S::get_session( 'products_list_current_page' ), \S::get_session( 'products_list_query' ) ) ) { - $response = [ - 'status' => 'ok', - 'pagination_max' => ceil( $products['products_count'] / 10 ), - 'html' => \Tpl::view( 'shop-product/products-list-table', [ - 'products' => $products['products'], - 'current_page' => \S::get( 'current_page' ), - 'baselinker_enabled' => \admin\factory\Integrations::baselinker_settings( 'enabled' ), - 'apilo_enabled' => \admin\factory\Integrations::apilo_settings( 'enabled' ), - 'sellasist_enabled' => \admin\factory\Integrations::sellasist_settings( 'enabled' ), - 'show_xml_data' => \S::get_session( 'show_xml_data' ) - ] ) - ]; - } - - echo json_encode( $response ); - exit; - } - - static public function view_list() - { - $current_page = \S::get_session( 'products_list_current_page' ); - - if ( !$current_page ) { - $current_page = 1; - \S::set_session( 'products_list_current_page', $current_page ); - } - - $query = \S::get_session( 'products_list_query' ); - if ( $query ) { - $query_array = []; - parse_str( $query, $query_array ); - } - - if ( \S::get( 'show_xml_data' ) === 'true' ) { - \S::set_session( 'show_xml_data', true ); - } else if ( \S::get( 'show_xml_data' ) === 'false' ) { - \S::set_session( 'show_xml_data', false ); - } - - return \Tpl::view( 'shop-product/products-list', [ - 'current_page' => $current_page, - 'query_array' => $query_array, - 'pagination_max' => ceil( \admin\factory\ShopProduct::count_product() / 10 ), - 'baselinker_enabled' => \admin\factory\Integrations::baselinker_settings( 'enabled' ), - 'apilo_enabled' => \admin\factory\Integrations::apilo_settings( 'enabled' ), - 'sellasist_enabled' => \admin\factory\Integrations::sellasist_settings( 'enabled' ), - 'show_xml_data' => \S::get_session( 'show_xml_data' ), - 'shoppro_enabled' => \admin\factory\Integrations::shoppro_settings( 'enabled' ) - ] ); - } - - // - // KOMBINACJE PRODUKTU - // - - // zapisanie możliwości zakupu przy stanie 0 w kombinacji produktu - static public function product_combination_stock_0_buy_save() - { - \admin\factory\ShopProduct::product_combination_stock_0_buy_save( (int)\S::get( 'product_id' ), \S::get( 'stock_0_buy' ) ); - exit; - } - - // zapisanie sku w kombinacji produktu - static public function product_combination_sku_save() - { - \admin\factory\ShopProduct::product_combination_sku_save( (int)\S::get( 'product_id' ), \S::get( 'sku' ) ); - exit; - } - - // zapisanie ilości w kombinacji produktu - static public function product_combination_quantity_save() - { - \admin\factory\ShopProduct::product_combination_quantity_save( (int)\S::get( 'product_id' ), \S::get( 'quantity' ) ); - exit; - } - - // zapisanie ceny w kombinacji produktu - static public function product_combination_price_save() - { - \admin\factory\ShopProduct::product_combination_price_save( (int)\S::get( 'product_id' ), \S::get( 'price' ) ); - exit; - } - - //wyświetlenie kombinacji produktu - static public function product_combination() - { - return \Tpl::view( 'shop-product/product-combination', [ - 'product' => \admin\factory\ShopProduct::product_details( (int) \S::get( 'product_id' ) ), - 'attributes' => \admin\factory\ShopAttribute::get_attributes_list(), - 'default_language' => \front\factory\Languages::default_language(), - 'product_permutations' => \admin\factory\ShopProduct::get_product_permutations( (int) \S::get( 'product_id' ) ) - ] ); - } - - // generate_sku_code - static public function generate_sku_code() { - $response = [ 'status' => 'error', 'msg' => 'Podczas generowania kodu sku wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( $sku = \shop\Product::generate_sku_code( \S::get( 'product_id' ) ) ) - $response = [ 'status' => 'ok', 'sku' => $sku ]; - - echo json_encode( $response ); - exit; - } - - // product_xml_name_save - static public function product_xml_name_save() { - $response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania nazwy produktu wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \shop\Product::product_xml_name_save( \S::get( 'product_id' ), \S::get( 'product_xml_name' ), \S::get( 'lang_id' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } - - // product_custom_label_suggestions - static public function product_custom_label_suggestions() { - $response = [ 'status' => 'error', 'msg' => 'Podczas pobierania sugestii dla custom label wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( $suggestions = \shop\Product::product_custom_label_suggestions( \S::get( 'custom_label' ), \S::get( 'label_type' ) ) ) - $response = [ 'status' => 'ok', 'suggestions' => $suggestions ]; - - echo json_encode( $response ); - exit; - } - - // product_custom_label_save - static public function product_custom_label_save() { - $response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania custom label wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \shop\Product::product_custom_label_save( \S::get( 'product_id' ), \S::get( 'custom_label' ), \S::get( 'label_type' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; - } -} diff --git a/temp/update_build/ver_0.290.zip b/temp/update_build/ver_0.290.zip deleted file mode 100644 index 3577bf8c454d34e86f96d4bb19778abdacc38952..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36607 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 diff --git a/temp/update_build/ver_0.290_files.txt b/temp/update_build/ver_0.290_files.txt deleted file mode 100644 index 5c689ac..0000000 --- a/temp/update_build/ver_0.290_files.txt +++ /dev/null @@ -1,5 +0,0 @@ -F: ../autoload/front/controls/class.ShopCoupon.php -F: ../autoload/front/factory/class.ShopCoupon.php -F: ../autoload/front/controls/class.ShopOrder.php -F: ../autoload/front/factory/class.ShopOrder.php -F: ../autoload/front/view/class.ShopOrder.php diff --git a/temp/update_build/ver_0.291.zip b/temp/update_build/ver_0.291.zip deleted file mode 100644 index ca67eaa5788ee65178ac3bf0c8173a93d63148c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9105 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 diff --git a/temp/update_build/ver_0.291_files.txt b/temp/update_build/ver_0.291_files.txt deleted file mode 100644 index 715550b..0000000 --- a/temp/update_build/ver_0.291_files.txt +++ /dev/null @@ -1,2 +0,0 @@ -F: ../autoload/front/controls/class.ShopProducer.php -F: ../autoload/shop/class.Producer.php diff --git a/temp/update_build/ver_0.292.zip b/temp/update_build/ver_0.292.zip deleted file mode 100644 index e9921100d6345c17498aed25e54bb3063fd3c944..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80982 zcmaHyV~}P|x2DTRmu=g&Z9Zk&wr$(C*;UnL+qP|XVcvt8Ip2vhlRHv7R<6iDJJyx= zUa2Sp3Wf^wZ^gS#N$1}O|Jfk^(;K?F*xT3}n&=ps*jn1@DE>c`N$+6cFs*%Sx7C64gWq@CS2iNG>2Y0_9~FDu_wKH-)VTdv7QVuc-ZHd(3_w;( zd@$QSiJsrfD?BsaBFXvEJ0`Fci&~OyLU}?TTPNr0#hQUL4;$>+PCw_}_DJf(oJWO# z>SG)kf45F*h!I7aIE#*@z)^6D>cc@6;djjmrBwOh`(>@5Uuq&KU?7YV3hkxZDkfNGwUknVYOyq~6Vu_vw5Hy_e5AxSE5hsnbuc+sKf1 zl8%JX$EpAlCIv#C96*|4>e=^c_7F%+zZN-5o^8y%#c})?yr|h8HGMJ%2#VXI3)A*iDb5~X2*4UmXDZ= zXA{FR;c5+kRU>j%7m`k~x%#zw?Mt5N{az@?= z3F()-9#7*BT`TC&znKHP^!&Og6lUx@L9BeV{l?C z`UVoz8u+F{)f^^}_&kDl!P)qn^)bEakNOUZR>eW(%o5Fyxt4VtQhb4sa}3hZW(MSW zYFJdV1Aar@5qm@uvw5Th;$Z$fJO*XMh%k+(Q7Jpa`I_tutCJMC)LDujV4vWO5&lYB z>>oN%XB5{_Bszyw^J)up`Hfu@KpCajH-xD~e$NVvuC6s$&Wj9@FHjHBMS~n>7-pe+ z0Lrw6IK~+Zv9{?{!;|6Z1K+}=v6Vvlb=QJozmee(%HZ{($0vyyLGjw2Kz8)q>n_k* zuyPO_F}Pdoe-y#&molTa!ZWQx^xP@y7``0k&S*fY9VdPOg=*|~-KS0AQjL!^HTH+x zPlE+i#o~s{lk})of~qmwUDR~sx50+|EH4>Z>yvFAauGEX53NsdbDA1e&U$%A8<;7D zliK0Vq~Irh83MSf;YVm4LsLSaa{NmXmtZ?O7|S1 zF_79?pP_?%onH$hKA;M(!(%zaNODR6hNx49;=bEe+I!dY9uMh=qlfL~ydl1ry*S_V zI8X=McpbN@0X4oMA%6_jxOCP~udc5h?b{-U!*BgCKmo0{e7VAmp@Rl-K{SL#CkZD) zea=gZU)y-yx1C7h>>!6)uN$b$h~*`jlkM0S&yA;hoZF70N_eEPNkc@zl#xq z)A!M#p=oV>1Z^ehz=)K&!P$Sc%jd+P_fUV|SPyS3%x2NSeV4A9kTgsNN-`(Q8)vLg zhRUGGU{F!%FsCnvxuj;r9B)ZWLiXsHbTB@>yK;*A?t?I+*N9Y6!(zy?bs-e1D|Q4} z$*dI087QKq#AT54!w)9uG3eL_;jsQaKK-kGsce>T1Q5C_XlOwI;9G?HjwAQ|zzZn9 z2kY+XE zow6w0^Kbn?qL0bkrAqLeo|<5ZYyAQ{IP0#7B2e$^3VZi|+dxze7SiY7Z4x9g4go+@ zt1%YDP}lt%h;n05#QJ*LBP(PJXFdQYmaf+5z3g>~XR6v%ES{4q25J3d9RBPgtq`z3 ziF7oFoT-A7P2bj9hlLwm6&OGAO-0Ez99>#j{%%S%bM7?~@fuj&Al>wu5Y7!ivN`nK z+iMK8dQ~$D?__A9r-!V_KjI{giarXAI96z^crbZ+ra1O$UR18N-%HumwekAHsU?qH zS&oU8{@T@a_I~=+&%4swKHAY5GHi8c+G82=l zyiu&Yyx`yViaAZDLR>(*KANDiXT>VCl*DPAH=<#n? zdyO!**Ti?V5h)a~-XzdeVinY)J)O&l zmI+S%*ND$neZFJg3rD8hNrZn&5xo+pyF8IP3&QrGrJb2e%6aVC@eCdt7KuU_tGfo# zuFhlW+L$=Hg>2|GVV%6Cr~?39g=v-Q5vyYm!aQ?&s}_v41y$bBOST75mN5Wk>m7T% zgDZqD<$Id|rWo>$boN{}N27WvTo9kpYMK+mD5}jIM>3BK&D^Vxe11l$Tx3OJ+o_C> zn`}U@hmzHvKy14akv>MWkJMkVNn(7oGkAOV)G%N!)l=}&nUiY}9Ou6&_`*)=2I zPijT7OlbmU<{d6dVtwJ9mR`$JR)})Fu@fPg=Jm;ar^;uO=E7g?dzZ;s5uno% z7*trp92j@o{+M1l;gvV8)$mb2R3@bj8yat_jlk^nhAG7-2x&_NI>poov&v%gc@Nzu z_G}RhR1QAkL#t~roVtFdKvM0zXHA0_IX!~2Wi_Qq#> zTgYKPgx3R?CJL*JiG)`ke_oFkpOH#rq12t|e%=@RJ!c5XNmn2aQ$aaD+uFlBibaLA zj_(htjemt+F^OEH$KMutjet%GVY8$NbJ|lO`+#oJdwd*j1^2noF{8?p{O5ePQ6CiRqX(4Q~#i1sg{PhD4&sj z2MZ#6X9iqCLeB}Y=S`-Nkb4kM%Z`-jmm8_Eev@jSLe)Y(bP6Bb@N?=QK`h{-2pU5y zYYPQQVkm{HcTI{!rs5rt!O6i9=Nui=dOziQCyCyxLzp^{aJzOjOfxE!8sWp}#P~aN zel>uyLYHyJZ3g7;lo=@rl+U|awM*sSr(LfB6ilPb%FR)n5(ju|ju@kc5J z7}lgA?(x(UfSII-GM`*D?;x6AJ*AcsVw&T`^uQhF)bku+CQecYTSbS)Pa?BbNHqQ_ zPkxdPL%Q=}Xwil)$A){&wrd_iOuH$t+^j9|XIuRvFunr>9LN2P(E~HGucQFm6XEg3 zLJHDZcE5xe98V!&Vi!6QvQv)(u^8dr4Z_b1fGl27O!^T~{= z>$3S}Qb!Q)Usq%un)EN>RH=h9=WMWFrB*I62=hR9?SbS|scxB}XZUmJUJz#^0okla z5Zu^B-V7#hFJuJ3pp*ooiIPYPyh&k8o4($`mk03>a4KUL$Mi~HasZ;2jsZBers>$y z`K-n)YZ5m+rFd3|Uj^%>4S>N|zB+ZC&1#wCMczz{IW)QI>T@ z(gx>5jtvMx@RzX&!kOzY>%lEW3mN|ABvS0c=@Z$(2D>GDq1|~cVZN;fE`1IK&^D773Nk1Kndq@1F<5^ zw#>szsCFzj(UdAe*Yux9$@|Bn_S}Lgn^P}#N3-JbPt`soy4DTrSCbAiC-4l<{D+{v z{6+>*HJL6_aPCYD;55&~dN(#pTNqP7x^?6T;a}ahOUrnBI5q*zKc|Hn5)KD;E})j} z1S4>(@E989diNSprZ_%)?F?6q!6S>&my?k^Sh^c$F6=#`r^$=wS58Mc3KTa!K4$uH z2&mJzU!G>OHb*f#x@%GUP*^FyjSi}e0#XR%MRPnR*#X*7g&EBXz=EY0+Su8)in}y^ z^e*p&&+i|cZTt+_`~DOY;L0W^E84Y%wIjOGi-C*<#>^=jglHC-XitP1J4v{^bZ74z zOF#Z|&Lz7PXQAv7tTe$h+z`6LFb)x1g!Qd}jE#4rBZR1WObR1>r4oId~H9FIO z0!bfa@HV@0>^B8WFO{|UD+Rvb|24?LYlz5}{39nJnE?S&{r`iUvZ;f;v!#o@ljpyM zxNAOL=S@kc+qwsT%<2qq%H)r`T7rSrk}>3-mEknir0!0dsL`OY#1IzAIUoyw)+HIk zJJLIr=d^ay4-E_7u0A2@ZRbr@(Qh6U7Cyf1e}6!?s&n6;KhKi^%)`gLSjH{+3dt^R zeyXw#_lt`Z3i&b3CA3Jq`FoyvWomj`{JsyDixd%`)6q}P%7&~n=BA-Lx8Ig7TLM^k zx8GY5+7`~npo(V!wd0{y+BzoZn7Z_4ht$*N7OWtw!$vy8V0F_4Z?aGIYP#j7?%qy9 z2`r*5&w6{>`ntyr)o1!JI&@K3(ow{nUu?B^Emw`<8s{|^cljnwE^f<0i%+n5Humm{ zsTxu%B49^)1zN8t*`=n>H0^kHit)XZ&5YUW+!=3x_-52cpe42a@0js zjn&Si-sP()LD%&06q)+&nbR7>=`)v8nPoa~)E}nO# zf736fWAY2V<7lq=jSR|fR&?EK_KgkV-@P)b1lM=|-dpG{s#^$U+E5t>FH#3V`mxDOJdo!2S#8GRR2(l&RiyhNb&%2W?B*8(g0ng zblhi?mZ3~4ZD*h5v(yVzj}(2!gm5Z0l6@gkmI2xocb$d0rJ{E8H?b{a$&Kg+wU_%{ zz3Av+70LRVVK_dNIE>VH+^Lmj!TR<^YhM91zXhS+za|eC00=Pg{X}s?=SWF5pl$CmDvZtH(^+Hcbaa{HPX}{FIxg$%iq)N#g!wTx>`+gO&HHgIDEb6ns>wWmQuN;(PAa)-n?F>`OM zuA~V3e7doUk}yoBb>dB*FhcLCR1P+oKb0Zqi6qu$X}B4gWD>Y0GV-+3Nr?3vlP1hm z4ghx3_+ZF)l(Q@*$^xu#5cdQzw$39Zg9>wG_M0-=3vb^Dxv&PTWNiMK3Vx9UKr-Ao z@)2oP!-iC^#RO%jUxM@c0Wtm zGMrGHD=}#o%xsdH8IgfXSZxGT#{#Z3OP*Xwj-z!M;VXie)i4**GYF8f<|mdII>GFn zi{ADK9C?f9UE|sA&WplF#7vI-DS*GnsGO>8uo6MxF>fLb@Nvy>a!}U2;B_5wT5boul3^i1K+??dZ!{Cg9ZgOY2Xydc$?;Q5+;o|V7h_|@P*kM6{Fngeu zp)rew)3^u1bh*%ih?i3|Sj^(`w!h8Oz@maEvMqbvBJW<6uMo$NTfFMe9_CR}c_tcn4C^qAl+2gDFOJh4^@MCaagTX!&sGZt0$9DU^Vix7>R=4) zA<-#MOo+2wmGT2c$`NiU=5uLhaAfEm=houh^0&_a_i8+-YdXS)rjh>2r*w3VTcNU>L`aT&ajs;2rV~2u^vX07t{q6eUUrlE#k}?p^_l*r~OXOiziQYjAodSDr3o_ zo@-bwP8e6zU~~tl#tKr3OQ8iDrq@c4+F(IGRTMZ2oD~QmdKj5a)l5!+pD7IEjxi|6 zEg|Q#sotK6Pb?=wO3E4J+qndLK`S70e#8q0`jH*i+wjYc9C!1Y&A5>DEas@z)%jtA z7OrRNK{Q+4Z8?S`Dt+ct-5wslHmZ~wT|FIz$ojBVx(qRVUN>AqX0!Goa`|>eo|V?E z$-)?rv}l#_gu5w|pbK1aEF*LB858;_?>imKIxeo7J&uKaS%Sk}bOazR-=@Y-vBeb6Xmc-GPXgu3Od|$r~8tOrUum9LafQIOxa5mkLw_J`h_l2;U`v zE`;^{6%|3sOd^bZU7z%W74b;IbUk4KsbR z=ff{?_7o~EQ%Vu30`N@aBoz9H_G!Y@h;jduHs?CUQ&JRi9JW1QK6lSfcTUw9IKYIq z(kVMGm-Qz*4THBsU0Uw|F5Z@pK#B>*xBV(x2*6%|)2YEaK?(!a@6IWtwWq|u=#2G! zQ$oIcny3s)7~u>6qC~7DO2YGFct2o9h-wa`Wu*dw#PfXOa}g_Y&So)lzw~U)p>g=g zU>iOruD=WGsDL>y zuo?!cdjDAY!)rDs#s&-Acy*qz@*t91UXz1;W4`>R_{y|&{AvN<2Wv`KZ||S^qh^TS zlWxfbKPT4}q&h#Nl|?BSK%BvnyXk&t5^{y+$XzUfGCKZtW6Uo{?aergwkuNQ(RcY* z$Mgq%gW96BsoIei86gK&Enxn%MV5itro;gIQXIRC`vvMT_B0Ug(D3cmk&AwTYfWg; zlH5wRc|Ar>K%KPYu%A-AQc*mY&_Fq88W z6W20io)Y?9i3&K>QL*q{Vs_zOnXAOvyrv4oBc}A*sOs3+&FdFv2n7&@0Rk8Wv0csl z*2L9$VJsu}_L^MH?@K7f;T(=e%bOn0ZMw4s!-R8Sao}Qm2a(l7cO7oNOx?qSK4ack zKbfp}0*ZBy#KiqyAvw%INYP`Q@9stKz>Z3Ey6SL{{em3V*(JnC( z7{f(XPOo*XD^iKFx(N!=AxFPc9n-g)p%826T07|HoOfIA#_N0K=NNaxJ;C0+Jdu;^ z$J2X3fP#g1M^$NO9O94Ch^mGQW8FrZy_KRet_1-D30IGF!GUUIu!y0rP>aqNBb@1l z&KJZRvss$)ljfc?R_~u9T!|Ti%qH^QDOk3*I0%7EAO(W*mxd`>)d2c zYUo%cM(ZVL8=sHH5>yuwdbyz!&k#A3MGuc!qvRDnjxo1x%a98>WD{7L$rLX5>10zb zlS~NN2+)(wpq_`_a`ir_yQqVC)4*rfrE9nOY~p-1(TE6h!j{IHzFUKbj~82Iy-{N0 z9&*Gyj$?~v&S_J|v=c|DpV(P)X~@#;veLSUnGsSke{j^G0@PKvvDrL+|7$8rw6RO= zuBBIw2PmDUNiN8=Y;DlJ?L=_vmn~U{01pBU(tPSrVJdk5;Z9}eL z(e|R{VzGh0j>MluF4fXqz%1KPR!?6Su}WMG^dk>1 z@jbfTSHNVyvN48?YyIsn`{R?#I&{&!d1+%Cq55f;KAhdL0a7?Tfi29+ZiNfdkndziuU-C8=V+h$9~9A^<7omT zw?@h(+!q$sg%(G_CR`}WRnIm^k8rjf=fH?K4$f8VrmzIadNDsY?-t8O@tqF%YPnK) zPoi$A%G8b^88MkmyWIgahEqh#I!$wZ@&k#Z$wt+KR>S=QY|r86e1&ZL6G+(({e+!a z^_QN=q~CL~DcXc~sS1yMs+(tbX>UnUvq4&ic9YRH>u<{Ii>Ad>3A-Gl`yleh-ANt$ znP|9KsE4J*_<7@4;x?99^Bb#}vJTp0nkjC$<=+zz(WD}^w1s*m!a?K68fcDGr8vYB z&u*zI-5yBEtiN&}Z{x0jd4D8)?Mc&S>g9C8+hzoPQ6Hb%5k z@*2&>X)c2>Q1&UhJ3xAmHdS|BCL}@wT`Y4V@tvbqzGDVPck~mS@ zNu&=c&Gm)apt^`O4>$Fc+SvS3+DpWg7A6^Onv%w|0k&SDfbDLTa4(Rj?NZz*&`O$- z*71-rQ6DPuN_t2PGr8#ZCpYo+64%x>PxIkM(~r70bV9Jbl-GYg)N*g0 z7iu+D+WqVK=TXO8e;zouS?0&B7;zrKad5Q#LWN`I1;${dzt*QDx&;3-`UrQ^3f_s= zzovh$!LD6e$4eVtm<;osQmId5TGP{oCNG6>?ACO&YNqpg%u|8W!-0po0dKhyp{`E zM#;%ldV3?9L#U$v$`!z<8A0V0y5@25vZOEhv7Iv;#h&K-`uPYFWNaf=<$TVRvg0D|L|sKpAk7=N>MgcKb4&o|v${GTBzYai zd5`*taf)$9pZPuOFQmQTgUDfD;|;@`0Ds4`Qe+<7GDc^&=nT3HJz@Re4gq}5qk;EJ z^CFR%F-27^QID2dXJa=yfw0?7R77FooXdZ;WVLGmZQ771F7Eo=q^B}_Kq_A{Y#@A` zJsX=^%v85|LESdeuhqACRot#Yw;~rI_zi@BxIANx^Az7v z#dNRsj;dS6neD+(Lsa8Bv?mTnZ?Y*fHPd%5Ioa$GaPK?RzK0x{aS^LXVDmSh@621I z%SJ==ZnctA!0B$xvXlE`_-}0%AUu_-a_4Yf4o0}-J@$g^+#o%m>U_)f;{ka?lD3tf z9Nit@QT-#Y47nWC@76zQcf)?-${@pWa%akVkFik)Iu~RMtl#?;nvf9TQYMNyGQ77| zZ7B2M9bY15S_a~!{Z=p7LLY9`MMJ1KTZoiDysg5uYJPf9Np2;_@uVcJ&xe9^N?a?e%@Ey!s{#<)hS#&EOS0C|7R9XyoEKf(QyhI%4gPvh84RB0>lKR~Rz$ z#%2~I|2E|*v|jhTj80783?ZF9&Jn3P4UvIFrjEkTKPVODZn0~~k)1f%lvX6z>05p$ zjK%soQ(!jHl1YQy@|ZFoiN++6g>PkO*jIZiTuX+c0+E2y(q_TUjtnKb zzh{#-|MTLNui}F;SYF%()GXiM_3*fHgXXN4andUFeYD~~gGfrC!GTR)2uiBS_*RrsogOu+|{8RU< z=8l*9I{$M)088|0cYgooFMo(2O)W+(fd)6X-Dy~W5jn7W9jwng;4 zoHYfUOuMVmiKlDwfsvEMB>r}nNmjF!#4CdPWIR?LLs8p{60K_o@#LCF_#9+nrQ!m| zYI0-66H3dxpzzw|KR?tf@BDa+f8t}A4O8O>O9s-LN1jfD_Oh55V)ZB+LFJ||g%B9%; z#1%jH<|z1m-T#sKeg*&8UE!u%Z+!3FzxLHOd;Nj@SE=(O1jghR5(o&55(tRve~>yA z4Lxm5?OfzcT`cTPbpB=b-=t5iOS?^W)Nca9+dlLiQd4;ǶOxKr|(i`LG*nH6|> zGe&eg>*ZQvwN*=yE25VW@1*-OSgLWig|f2-tU!{;a00~HcMlJbqtjdmbUVAZIT6kf z6fgu(MDFilEFF(AiqVKE5N~^DV`t+7;h4Y&pMU`%9?}T(Y#ag(4xq1)#7BH&F!I27 zXwI8&ZvIR75%X;V?*jO&Scvcm*p;j5D}c{2Hwt6y7qlY?LCh#Fc@)J^iBnoa5=o;% z>=bTykG;N<1MpDZ4w*-nwzjex?B_2cWC{KNB`^#Eydd5!WR6+9{H0?uys7*8%RXm* zLT~?G1WCbyO%T;1`oIl3jTKi$E|{XaYpy?;m1B-Vwig{>VjX#G5ru;AkVsrmTWgQ! zq;Mxt#ljbJkr|Ti9tr6MRe@Si^++rZ`&>~oCW|cdCgT7avyeKRsYE_mwf>e-N)!Wv z!AAJG9Y_d-9y~AI)vV5w$^d>u`XFdhrkRkV9(o9oQTUNUgN+PYVb+;=-JKlJPFd(- zicwh(pHt>2)KjjB^&eyxZm#QBRyaeyi(kk?L~J!ux`&xk$)nC~Ez1)OC0;9Pl3LQQ2He9Db30|2mN=|*6F;JwtX!!J+yY-d%g~s` zc;>v_E~bG*Rm0$olkSb`i(?!^W10?F>Wef`#xOQSM-TW!vDtjo$CEOemQ&5dd+Be* zm$^5?@kDBhQAlL#$$MdrhD6JNn{gt>i>CR7l>?qv!U$jS+43sn!JW&UelAYVulJ)Z z8%?Xj`MoF1kbTVAAV%GH{M}&2GX&t=(vAJ;$(;g7{xX;os5{lg2oF*vs%`nU*WF=C zt&GY)&qI z6Yhdm1Rb%#o7Dj=9S)+Ob?F>;YN|UXB)pM13AS!%$U$^yv89H8@3*G-%Yz4ZfV$se zrN`v<1<1B z#59}*am^EGn13Wn>nbQRo8h5N{0fERuTm*9(o1?e8%AyGt`B8<5{Xl8j${_}Ek%&w zP7!p^dIdSeq1E|`EKmijl8v_+bjhi5o#l@|+?a*AAP5q$#;RsYS@K4RhJ`09CayZ8 zs>Pfvm8}WR({c{faktJ23uNjk5tEyh?sKrl<@mD&rYGl3VoSBA1Iuo-{^;J9Em?ft zIb^AY2u(T570LS|#9wl$X*7Lk(8U?8z7> z0sS!BNGZJQ2QYZbn^0W+0Pd-3C}ki;!8{tze!5UVWBHya$vae7ebhAR$9K}fYo7sc zt|tTtX^p)Dm-%Fu7BzJUTZ8jb%Qn-jimh2`j!-p0sS^j}twXg?sqIrzGy|l$qEg>V zR!0(g%D3yXx90m%Fo(f#e^~Jjf7hCRDQvY`%<;z;#EW>npy?5g+s0kV5bFr}REnh8 zQ2#6|i~SsxZ~zJ9z9=l%Rm#Z#N5u8_4hW3T=|3(nJ zNXPvAI@RBUfJ?YGU@UBw=*tlgR7kMb=7C;2MNpB}9A-dAj03RMJ;^`mjP` z3}VG3_&WAw4Yi{(E?3c8dxoOd_|(x&-7gbs6Mn)A3YCH&D;z#tM0`=;m1VGw`>B1J zrnZdj`$&mtuxKgEtwTw}X(#{jm{nc{I;NLT;3 zm@xlwLOzbNi62it(jcpJrfyRQXq(|&HDMztye+mDn%yAPPv4v`oc}efmCUiH{d0mg zZ3W#4-?C$hb^;=P^JV+)sgO#YFRJF+kx`d|XPG8U3Vz}g5AitbfKW>+`21e|IYcrW zd(Ezq+3P-wFIN~n9~@T<=1a&ewB&4175Izpr*sHggeitmc-0tD86;!m=5{j|_HWk) zef2bp&3$yL8Csji>lBy-6)N$Adrtn z36eDvv@$9)`jC*=6X?ACUQBUC65yt2y3MY$NcKUY6tx+x5**d2l!e|BGG-DDy<6gTs6n6l zGS#ZoF}VCPod!OM|0BafbPh%5;$!P$Cl8PiUn^@p{JJYs zOhhlPL{R)?gE@TOKI+Mi`8qkfi86V=pDnLXse7+p-7 zTLcJ!04V+WuoV3+5=xQ(yJ`VOXgA^i?F-UM6(XQ(8q7Lk5k}rjdwW<2^Tcp>G6w%h$7)xs7wLSMA5+QKPGT)NCw(fs}G?F&*Z*e#;w zecSuWM4hP}CFj+Iu8-O@^# z^nd?$&e0v>jQ_P45H^n{#5YZ@!o+T@4|&icN<+e~7!K;vVZSW+lX&QqQ?B?F?vg`# z#yGC`bG@u@DwPt$@XPlRxA$8cnPkG=GG!0z+-yZKlt$;<4!6`)M}Cu=J(sRUByY{+ zorM9>1c_A3R}!dIyI85dV@8}0p~S*fNd}c-cUJ4ZAheBux;Dq1)L*fv?(sfb?xBL9 zaFUYB!FF^kT%|(zYUhQ$zB9N$Bllt%olI>^)9IrKY5(<$49+0sbUp=s-!H|;`x9II zf>|Cij;P4sTIj$OWb~{!tDmWomhhG}`9Z%ew~gh@;oC*x(xvug6=0#Zpa75*=n zhQ}S{q&sk|+p;wbL9NaRw9>LzyH|gfD2-TJx;KCszbs@$P*@@Ji!&VLFJ!s56%u>F zJQ~EZHQ(qvlYeW!o~y@cYhzpzY4%=!jkBO#Sq%n0?`d@!0b)_@aMUB|l!RbVv*9xr`S zfP#>e9ey^YkWYe#C&?ur>(|;?QX_ryeFPjJJLaQ-PS2IwBDo-7CkT7DB(9+FQKk^ifuSUPw|mgx_nn&>8@T0)46Apd+9NY#F>u%zh7j`4zy}FROn|c0v zFsqV6XS^>Z2{gzz2X=02Td6ui(H}L~+HoYk;N3s-CL+UNy!dfRHUXP-QN)JEFHOdj zAp#WM>zv?B?}DSDi=MaVs}i#tI1nfD%+4T}WLSXS^o*VwJ%57&WdxbPXy(u#&zMI` zZQ>0y(FKzp#CrKAXvqQ)3yJr}k2~b_ugh&xOZNzF?!}?>nLNRkpo$nb@Ee=MoX^!n z_0;>IzV(K)bCObRmjj{IFX3D!kf;W!VHHJL(!5nsYCii21D>5F8FEQbw6IXJCEfeG zv$H+0ub1I$G`O1$4!Je9u*l_=}@ z7W#)NQOJ&a*-a%OPs?JoyH=IMl7|M(l1P1rjUH4&it0D&+!?3)B$U6r4gV2Y^&|T~ znkMg6@XwdA-g`014rQL6=8G3WJqBW?KBT5O@;l3!e;=SMW@Pm1B&WA3wxSCHMbaZ4 z6iHwx*+Sr*u7GBFq^;{e=KXt_w8y42osdo`&Fs`wdH1cE}vc0@JEV^J?)@W z!tVW+V2b{20rJhb6;E;Q67gVxZoE)h?TCC_616wI=|N1NOnWd>!j~f+A(z?yLV`E= zd3mQeccOz2qudSUteA5SJ6GrI>WP0~00R4iZ@<}e&E<>Q9>)H=h`-+NL^P-dXUryo z|MS-}#^0^4Kdv`}RdVNRm7y1d+(4o<5t)k?>`I-U!h9_vPoK*Q&F9m#pE)%p4w(V- z1JcZMiNnJ+q{fFNLFz5M@n=X(oN(ed*crga%@pkBD#aC<^_lY!Q&T$hA>NU?V(S=T z;!_0>0?7wk1;z}R+@}!Pu;zGTWPK{_GGpju_c0%P@Q{z!kf~`Y^lQa2F=+Nf*vrwh zBwCj2Vo0NuAo+espo^x-oH*UzOjekE_ZGiW*AAC&F2)iJL(s38rW~2%V>+XN*=3=^ ze=or1oY&E=w{XpOxM-*i@O9(LoZr@=?fbBserxWptA94wKA4H)Z!sPQ&-q|77*{0@ zW+E9I1{TV8-j3&~Zw;Ekr&;^VVOgP>s>Wqw(L#DB^gI`TL5z3}68@a%#8iU2FoY>3%H27KKrVhiYToomTxUCFZJB^9q3Z5oRiU%kzEQnX z-mqTnHOS$xJMxPv6d`3ob24AR?F>;$4Y;>QO8~w}siT60blQebBBrT9eXx+k-ZQ3B zUxs8QlxKz;I0i~M%JscQ7S|}~P7=1H+k=LLRfj0)JxU;BnTdqGL{ete z(ncFa7EnXC&49CQEqzMxHRP{u=lCAKt;Zun05 zG5rXNR*2-+6bXD*Dc5Ax<^{{g-(UI*j#m~%lv3B4ClfyA)?r5)41>GA5gg(sgaeU$ zq`OtJ@9YD>rcjWgMRXmDFxRcutga!h;_3B%-Y&}fX-D9%Fk{8XUGyd9nm)I`G)W@{ z_}+1*-iWE?6vUo+hVN7y$(FN-R*py*wTD6*g?|OpJ7SunD*66JSNsfuUue6-rbNr} z3$8jrs;eLSu)BfNu*FvqUt77?3_X|dy+h(<^mM{IST#U!CMgv$^H2|1zZLHoF*sY= zaC;hR6tHz)!Do`7$!Xej%jdPV=&3V}5(HgU?wBD&tPZ}}`!xZj-U@U2J{;^G>}pv5 zP@=MHGQYAExS*8|Bep8E@@uvU4Y$}$fRT2jC}Y9h+6W-=^SJvn{w<<^ybiyyB`l(2 z7EHCl^X`>DtgL2w^C7Sr^2&KLOTV#JnevwHw%{ZXyhF(VHT-~ zW^jWL`_}Z2%tEL>cd2Wtu1^Nu!q)x^N>OfSg-b9Gpa%@SW2wLxELT{EBpJR@d=^D_ zJ?=y^8Ci*h^pVWPC_j<&WuaAVIq&uuw!{{;FpoAqi=psJ<$WAeu0q_H05vSk)~G2h z_1!HJVFzwOq`-@w1PmA>NGu&H2R?qoR;10LB?I>RZFmFArjc1+~9WJxBLFAdd( z7t*lqkl{nBLo4F5x~ZJPW6L1p#G6st6M; z!H!9bQ8P9bt;sTUWh@=+Z_s3h+^({_i(n?J2?AGegyJ=-fuS>=^}g$iB0s#{6OvO* z71f7OyKkE+pw?is@R+Xxs}HF9?Kyz?fkeg!73<84xj1>>ARz(@V%)SYEbzJK)riEb zm2%NS{oXp9{raj`&`wtd(F(Ai4Fy_#)s5=xeI+L>{i)OFNBxx=2!RamPpKbTQ4+lK z$-D1U5p}A<8dPSX5(7DG-^^L61eV3SP^iI*!CQ*0whBHgWr|Nu8+g7=g1UOxXf@Dj z;gd$OQw39VKu=e|G!}u)m>B3tpQk!gHz?F)9H#2jp2~fF1ezlwcYVWW)HovxuLKUa z#so+`mUESr%~nxx2{#0`?q|37xqDjQM}n2nDyA0`ra%v{7)n6`SHb``#z+U1u;LDA zB*faF>j&sktX}*f>Y1fj2m7t_>@V?NI8<3+AOD(fXUoU!(e`R;|N8WFj&Bv!RihPf zCygKO6ld~QdfI~*!nN9vad>|M*-x!9Of&C94XaWR#MB?8398$tRBjdw9~;WRq&Njt zoT{nG)Z8QdCirYdUDy_fSz6GD5hx!mg#rQ$5TzY;tQybxTA6ljz$-DtG)l#WKZIg z5{<>HGnV}5yIW^fEm2$%2mVOtMQvMa&O#~jYs?KtED>SbKNqvaQhoFG z)R%jRd`HcNNQ;s%H!%*K@JUm+rzB?$JiLjh<;7+h;YqP52L^Jzs zudZ#jN*Yruz#L|mLr6X+uirGfPMvl?&DTG}IinloeoU`+1O_?4Md#<&QVn&kn`qR9 z*aNmFNoANmfNF~ou}^(>?($SkX7Aij)XDd0^{*a@Ja-ylpBvF{{KqMs{6J7!bmatojY#dXL>D@N5LsZ%yxtGHB*dd(c_7uP z*g<3oj?U*y`gm`ujp^W6MDD{X42t=>^bg9k=EA2BzU1 zwQw+DwLShrCJDyx&;HlPSpnC_I4eyK*l=nXyMu7?a};#cBe0P}3KCkUhb^9@JP7{p z@nC}A9j+lIXBgp-MY`aED>lXgYs50AN;;}=Pa`i4)*Q`0B_v`UjeVX{BB`1sLguk4 zjVqsGPay5OT{W~dQMcg;F)obP08?jiyyhfX&=zKL&V~*;H`Sn~p|@v&vST@Rsl)7u zYcLI<8d2dWVQtzA816B-owhT%^b4lQyseB^3y#V()ZOL2(@w3(XcD;Z6>l{$mZ*rz zxQZBDE=7Y1uR)t%`c2K4yfeq~)q~5xA5Jto)LLUXlUg-Cw?PEE24BpuR7$%wpeK5$ z&h_S0oU0uD651$8#TUp0JNw7L?Ya=+P-ueXgJy=dqa{lND2+OP0l!E`4y--y>~bEp{g?KwJP$<%#-IF>%yvI ztAWH&x4&iW3*A`q>=d(2xG!qqx~E+iHtL(&x!!n5XCRcl zv09Si|K<(Z2ZEfzf&5UAA4FJZV+Vo)2oN7qfO+|g0CCW^bX@XYVuq+Q7+RZ4k4h(d z`bP|ni&Sq7Lmr(AZR-c@=1Hq&M?t^@B)9 zZO<~S=p?ZA)<*j;}fJ3s&=yNg=CMHn+HvD3@U_!)`*B zx^<9~b?ZuCu4%n}bJ21W&lGvWL4pjJ#>UZu`I6AbukfOlx+1c{_ZEp_l8PIr4m?wP z?5}c#)tgFi8iTKwvy`6*y8{4(@W#Qpq5v%U?ndX4D;NGs@9JqO>s%*RK7tw4E2_8+`drr?=0RIZXjNQDt zx#=Yp=C7MiJ#?uTAC3uLkN=Awgc}00*TRhPLjTBKe*auAtt_Jpw5_eqVd9bL$Su4p zuBzQOxx;4BBw?pd=fm##z?6kSqb`5s#i1fzkk-U=+(p(T54Tze_bGs51sKAGG%;NF^DsywxZygXLym;fB|EIg zSPwmUq_AyE7bKsCvBn)(y7U7s>pr^}4K35h87hGK!;=@JX^j!Ac2OucBq$&E4k=xc z=|Sz_j>7KFMHtOt0Zu;+u9$z;ODbmYU)uCZfIKR@NUM_89Ou+1upI8pEGvcf?3|+h{Rs4 zrXE^WHoGGunm++V$klFfUbCDa&&BRtrK;$<^oTY8b@r&Co+JF~6C3k!K%qf?NkUdPO;hk0Q#qFK_Z(P`l)kzFXOT zzAUn`giV`SkbP=^!RWhY8K<@h%g!>rz7WIrPn*i0M0!rS7&jOr2aDe&$R+Qr1Ut@z z&x@K-i_hHBkkAy*0|~Q@y&u1b2Bd@vt=UgV&t&xLh4Dz+I;Qz5{2YrU>B_KTs(>d4 z&+cu}z{;ymPp8Vz!;EV#QQ_43SMD+ATsZD(#X8=)5r|Gf;3*nXZOhtLQM|*woNv%V zc5v9kF1}C#u(iv6bSl{2xU7)bbf(w`HQ2Rw71vkbB^sl+A&7O-l-=BJw@FIRTUBzl zPq;9P%=#J5g!(yZLV^+6Wfro+l>&3uR@s2TDj)<=hBzTyUG`^DgknSAHUo8)@%HdU z_#lx_$z!DOFayy@X3Bl&3^A1IB7c-p;(sq#s~}zaxicYsblDo0&rS2LPb{JN@Ukvs zmyh}=YcIXX#@^_S|3=rnLmuKTUIe`3e1f0+?pC_ST%Ikl(rH9NyUyB3S=-vI#}|fu ze(m%`QpgWjtlbv94etpUD`ibd=2>yCV*FD-(kiy{(9>1K&5Th;^}GARV&ma?ghjrI zUf&#w?Q|Kd2eJ^RxU7S@&#zK#)LoP08Vm7xKT^=^T=;U`ryT*IgY)`?H+S2iW5tnS zjz6O$r_UHStqbr3?cPvAV`b(Z?1(c*Uk|5|Rr7pLHBmI!C79wS__MfUc7j0M$PvF@ z7*#Yqkr9_vftWP}-;5VG5HGxW{lF?NwrlUH4y8~jL0(dTyNrh3sug>T@FxX#tK~4@ zB!MK!QGRjGI#wBJ7#CI$)AsALJfEhsE~QX`#nIbC#V4W{=2Q(&_hQmKr~x7E6=%z@ zJa=CTkSVl@3=3{i=*L&U^;*?~?7X>N$CTEM+*js&Yv2FWNI<9g1(-J-&o}us*AmoE zi_QH`MY~CpUAqAs(=rwpBvBMLSnQuUuvnNTz5Vy5PN+6igTX3A*dNNRLQ+ zywEXBAwV!G1G<-6aA<)(7ImI%37TR_B__AbJ&DLg9?zQ*qZJV4J);h6fAU=asp2da zRgZNj%7E0zCQ_zyWwUBZ5nr`SVN{bX&*i2$z@>Orsdi;wOCA-n?~GGctmV7pOaI$Y zNITOhlq0GaQ%oOrV@`d3kEP8@jo!Dnv~2qeVNT7cZRA(HWd^I4PL9KUNO24cBe1{t zrQ2`A=+3W;*kx@6vM+)srhY|M38lKH;y;xIN9VL+pwSz%?6?&AgB|m8<5ZyNZ7Q{q z#LyY;!V@m)-<|Z~+eQaBFw=glw6B8U7s`*BMJ)+K6no`>b+?@yp7# ziByo%uSnmubW-VprwT8g&Czr2a4z9+C0U2=|Blg^KQJ?MtBo3BCC?HyK(Ua;eGqrQ z)#Bfd>sNwf*}YuH<2+6#9t%x}#}~0)7i9BxVitn)iDAW!-QZ~5$HuhJsJovLY29&v z^ZPb*@bxi|Xh7kkj%__M^hDk+7+EFTfYmK`E{w>IheYn@lSzYF-Pd!<bSNuKiWj z{S$H?x^Q*E_q^L{s{*Y2tu}dl&@RWQo^PUTUo9tN34Y#3<%!f_ey|2>7AB@ldrD=$Y)r&;(7`qm2%tBd$x2U00Qu4x`bCo(9t%scHwxOE;nhRH7FMUB$hw zO_F6UbJ>i%yaZMogy}=$NbncnA&trR4H#p{Sd1|RVbdM&62Msdj`Xw$Yf}8n)uBj) zyeZ2OwSmtoay;1wPC+KA#*I6_O4T!7Gl@Vaclh8XuR7!)!6wKRQ}=a0c|w@Lhmpp7fK7J3h#_cT5X?lk@?{mOx7mg;3um6iP9U1l_;pA72E zD2zk|8K%2`x&##=Q_O{C!DNbK_rfclWfExNCHOPyB>019$aCTmO}xPBZCocm3WWSb zvv_jWa1arTa;J<%+!a0ro5UmnAsZ$hs1_0)yFd_RTo!I2LQEp!Ao!?c(0s&luvv+X z^;q~2!yF$1;2bqGAd}}V0M7($1N?vJS z;njMC%G!6Fiaih$uISq!?-q2lft(*hVY%k=iib$*w2UAPZ-Uc+HwcddXiXe^KsLgJ zhTa`?l(xOs6di3p84Fm=-MI3tj1+SD$sw0<#*#n_&P^VGpFFaBsA%-cwb1zZNg0bc zbU2HM9d`VvaqFhIN`alcy=??t83^GGQf)d2nrU7g@Y&i~C&Etds4N|}Z;){11gn-I zI(UVgNOkhiJmvOPBUJeAXn;%0f%Q=c-V_=nJQnv)6a`i&Xsgxp6(J_C(@gtxAQ4Ez zNFz2PZ5kqp9BZMukqM0nGgpGCfw<>&a#74R5eOfT9DpY7s}6+WL$2Y2Ctwy{#@^xjf9_ZGKboQLc{Yw2Gr1V}>K!Bfm)Ak}_&}-(>8hLk zvYFPEdA9rwPTof{GdIh>&mYkQ{GDTDadj!Y2|)+kdHr|@)ay~SQkIUp&TRjXUQ)0#pwUshW>YaXulajFuZYcLJ*|ZJ!|(!FmsqVY$^E}UE1TL=#MbKAm{!#{rl}+ z^m^#>pD=A90m%ijtYq_u4YIdpH^mAHT^Gq$&hkmPT7NvGcEk@GpW)$HVKvFEcn zCbU0fw@yPe8n`5ZA~-@3WiK5_kHhuC9wQ-#BxmnPfs+8rCT}zYiiBwUY13^H9!{f; z>l(AjsCx6?mOWMX);KGCl@Bwz_8d+gT+_GXS?LHaokJTmFRvzlhoHVUQX#bKyc>GA z$L3N6tVFlW7ap7w(t?L7;bMPTt*V{jrq*9*jtW zK9ph$f<3)|h0)XoqSm2MSt>9?F`$yW?4qjeAEj)@(-vW<-<9ZWXx6d$FgnjM>y+hv zZy)UxiRDV^&Y;E|v}u-N5=)HE?=s&%pDtd%71uIVkVe7PQ9x-^)V#_(ieMaNwv<6j zTbsxHFN2YUE->^{c74wTA`Koc28N8D!nj-YmiB&}_HkLdu42*0N$0tkJ{Of%zFsS+ zq~DZ#Mq68k*vJKRR zY+_)s8l+)Z>q<=H)a9!zvMv2j$WS8wnh9en!sUxP9X z1qdoMs1XgaNywIOZ!DGB*Gln{=4cTNHNvXU61lSFyZtT{Li2W(@Bg z(l!OpSnuU0%Z+r!vyv4d{t$1#WyF>X$3R)Jr>IbVB-*p$snjdQx%!sEHm$UgA&mUQ!#*MREUY+tY5@B%)P3x$sgC8AXOYylD(X!5z)gNZlR7gCn${xr%p<<$QTcc+Q~bm zYZCp!Ad~G-B3zz}n`dmbk(sK{Dz>fTZltm*B~RCiyAOKbQv%_%rQJ9#yD}Ot^@EnCs`;$8bDnVcwqgj z6bv<@KJXKrE;K|Zy#IsRAzL^dr|GP%hzoNZuaGWm%Z(P;8_M|);4boO(TU{^2MRA^ z%rT!prwxxx#(g`{3%*#yHWNo)%)A=pp?5`@7Tl=U5^X=j8RbfTfr??EvIG#ROF7Hu zTarmt&5#F@5X(5K>>ce+jjJVoX42{iuIU=UsYOD&>l7?QmMYi(@qw}2iM{1QZ8s`Y zFgcU)ob1zCoHqu&^R3hK+JBUd$^remZ6v9kr@BC+Aowj*1BAja{5UOvwbNAzxD%KA z#ZkH}Ix4Dyj}*r|4Eo$G&v?o0@Ey7ewm zhjgkvAaX0%q52M5J|=zwnIrD`9fJ(8FvIP!YIGpyzAEr8c2(ow75c+Qq^2SeH{L)< zc`y6x=jUMJi0Ah%d5OHaD498O7PAS{RZ@JkBaZTN)}I7yeztZZRDrA#ig6HF8FpLp zx+Oq(ds~4Q&Zy}7xGo+Vd1-;LaXf1A4>!)a z*3wJ!1{c$IkrmU_6jx0<_e3uZPn+At-zA0c#?a+8gQmJ!%9)5VOT>K%_wJ0}ziZ|1 zzd!Tv+VZ^M+i4eBPLfJ-va_TwkeNf-eZxgDdY&Noo$2)_*o5HXsSng7J*Y}@%~7u& zfeap;jKcqKG((8YXGC&8)(UVRB}n@Yn@PgpI^{@^kT3^^`~orp_rO}pSE+@`S> zCm}TW8JXDb*y;T$-T>?2O=zLF;ScE>@R1KvHQNy0yCO|&?-Y+uw;z$q7Wsz8Ay==&|)Q0W{${Q3>w+kThgc1b+!8@DLi z=hZVg%{#RT#p8_Duz2!t4V35R)Xrqf=oeNA*(Luom@w+hr>e@|^S3AvApQD+x`)k( z2Y(KHL;pK74hD%M7CM(^1|5(8LVw*^1|Gs0B<8;C_w|`r^Fe5&O9XwJ#h& z9?m8XSX(*|U|v;WStj1lyT__X-~-4JW2p@8bFY=uVY(FgIKiRTAQM>@oA2b5tO%yE z*We$)RtcOdonOFnNG(me$)S02Y0zE@J^_;*96XBIM!Jw^2Co(W%G|)hl8Tfb7v7$N zYLk}%j7EMIOLo_7;rmGsExD<(W>-&tW7cJ<& z4ZX4Sd-nmoHB&B{Wx#Z*W8VDJ*PC=_?fu@5Jg#(G^z7{FhnKne!}l0tzwRd|6O|gr zpyv_~AK?9aa6&Ws`x^h6pR1wHmaO*GwBvq>@>A2F_qWTQgR?EDf$#U#!o^<>kE~xK zl$zpv4kaHKB5tsILP4G@JybC`EgEb%2QCfn_>@F!AQ7-E8K$LhZWKuR`*=6>U?BuG znItDQE-ss9C1k%de^FQ`$FDVgS>=x3jB-~dU|a&l_-%Cs)%Vcp>sV z%2tp3xTcf=xQt*5g#~X5lR0{|KbTxgA5Z!G0kQsb6KndZ==}@Pfb7ix(n_u!AYFQgPh1ni53Pw(S&FQPmQXh z;8=-$)m48Ct8wX!phH8n=Bt9gT=5#xq^-dWgn~3vE&PEsntIt+5+O<7jviDwzaY;H zUyH~ykq))M>w5Be=-8>`yn1OCDj_gb5-uMohKkmO*<^#6zRchSt)2DE(YcGD6&5)E zxEO~8RVpv{kRHEq)fyouh>|kVLx*>*)f5GS3vy@`Q*GG9h63rM|E1L9o@#!i7$2Cv zDIC-mvjfH)%^{R;Uo5{r_5F#kltw7vp7)CrOI?|&8qrgA4!!BowLxp&O_x4o?+lc+ z!wJjanV9O^(Is?_W^IfM5THZ8z7;wqm4WyHzfU;C_G!q5x3D7+W)M#KsLIG1sDNl@ znjgn#!JIKxa;@3|U&eB@an5V3fvEmFYM~;qIK?gRoYQs0>~5Jp105%{ZgG@8g~++q zJOD2<^46lHu5DSZ>#U2cC-6K6YC`PHj{Yo5u|CEiaO z^on6hVYsF&>|s=jg>|C71`oZU5`o?b=tlhvER_ZuN(i-_8Xo`lVqNeBZ!S-J72N9? zmtZW)mn~eaKQK!Xsamm+QGZ+T(P(}gO!HFP z0s=jMyHAXkgFkB|Ri8T8Cz1YbdBSbunamF0ggF`_Q^A9LOqkQWzL8X4(;?dES-LoP z<;6*KHC+0Q(?WAXYq;Duz)CLK(>yS#;fzPuLGx2uAAB8pF?4sL35v@*i$}qy0qliQ z>x`@Nk!rK^F$%}?nBHOF+ur8W-o}>YH?L`r0jtYje(FZN8TB15XWFKk-vnLjFoluUus$N3j<5_cunzSMVvmpY?&vfQ zD6|Wn=#cex^x~==gQFmZ@i`Z7M`Ke!8v9@1%9gdVY#AeO&;EtH-Qyq4=PU!xzLm~l z1gx)g@ry>HY8)%=SrwiCHdKpJ$Tx^xk(a67o&OODlMBMCM|GLOcS+~+`(h>X&<8hq zsmB~rf#e|y%(m`IoXJanry^o5&}IMnTvP44u`f%$dX8U$<{Oq64(_}x-w|T=T%2om zv323oa--1js?Zg9?Ni?g9YTubP2KnSOMSj28{*ghIjwmH*>zeRBv9u3l;=qgZV%mR z8EX5$)^(l{HI^Hn&`(`j$fmNH>>LlYY6SC%;VepD(1&AUfz{k%i*yHEpZK9#Z z4)*wl;^RZ1w_k#^o>Xih+DD%zn86G6w#a%a#+G_$vq}_bimKeazg>r^b{#?>1{Uj<$#*o>jMto_xp|6nD05p z41Vw3BR-GIg!A(p{R&I1E#~OSQaWNfDim+Qurv27a~<8Si?Ipha|yUxP-V-Lrv2R* zfp@0a3ifb5=Xiw}fqgTuTg5s!si2a$xlEX^x6H3iMiH~FwapnB+XObA zvbh?pW**@6bHV7#h8@@&y*^@La=zgPr7gjnuo22xoU=YoUJ0gtFcA21DzZT{)v-cA zhKwUFwlHjxDT@_alah4qr!zmY#XKvu;S|}vz3#@AENFGel9FaAM*C2PwP3~b%+b>6 z@rt#Oc5ma_Q0-DMWq;7<0M}A>sswH}%d84p)9sSFx2+a&zN+GEMU83!@8`vHd-d-A z!t1lU@%S%-*!4D_>nHa9$^HJG{qc*wzIAQst%(nLqbd&vgS3d4y0lR!cwy=bLaG7o zB8wOnuzbHJPb{R%NBNl$-AmjUavCRq z@qmtX+PZERI|zKuuTYNd=sfj$oi=YySNwkr>Nb7ERgPOAtAQPD>F|4I@ioqI;gmVlb%~J866g=iJSZ&tj+x zT+bEHV!eO0%SB(6hiTzj_}!Xj&AAIyLY~A7;(rMq`kt)oG^7_g9^#q&etH=6@Snpq zUYjn19A)$P^(A#pf+fk&7Py&2u5b;DP6+syj&4i0(ikU@h{3e$D*a`(Z^qUVcZ4kn#g z!X#*AfZ{P0g!1olZ#8lm$$GQS42=9aK+~%O`90$TJui>YPOc{ekg_BY6#7QB0 zOnDgc$DTDabW)^5|Hw9WN=yh6O6Gb9>$UReP=n}ZNd1az&Uk2c&HX(k$&Rp`OifL_ z9w*>k)~2YF&E8z#*{Uhs4YeeE$(R#ysAeid?#bJ$I7PBZ9B>o__N zgcN(Dqi<~Q_msE{)a;5RQ&o(Jq8l7u>NMkaR8-I&A|>6q2e{%T#ydk?J~YUf!HY|O z)o=C)$f-Y*Zg_3n(Ns!A3b00yg-D^;lz-^8+bw3Q3sxyZHnnb=qNG+iaUV_}EbO4; z3w2mJss<_((GW+va63oN2XXUov}x?zjx6DW>r__#GhS%aB#n+gC`tSFL?$=XVO0FH z&3NeA?EpUvq%ZD3dSBGT$PWu%(`;~HOB%Dj7c|#6S-b)tNWw_!KF;KmW2eSK(-N27 zY@;EkN9v0_L=k2w;g>rlK+E3+=k)gTUW_6ZC_TR{Bs0xOZet^BNc_8m(W*q;2kji$ zhG=X*@WBS55t;Bdh3;c&5VQ8Nxr}-d|K`dai2ABH2+`_o=yhCI?1N2)w zUNK?sTT)`g|FU>3qGsM4(>BbgUf=#gVr@yIwGe;1NGX)9`YMw#BmgY?2&^b5cme6S zdj;!W!my$O)*snue%&S>jsB^ER)=Br`4G*Uq0!b(#S$9l1Rz+?pWjP;}7Qo4^6@XXlsvi|cRrKs?kyAN%o!+Zm`2_nWy6 zo(n?L^Q&||AnMD(Y%I`+y}zLUoj91mi=j+~00hLW_V4=NiG#NGE|&KHOnaQ{|10_* zIj2CeXBze0LTbSXKN%W5*)Che9eaAXl^45;~md6uIyQ)>Zh z{YU*RXJF@`f;cA*WEpapjDI}AzOrufCnIk!e&08uc*>5fQPP-~D5;#2+r8A05+ch) z0spuCgJ4Arb@Zw|{6kB{(h{muL_#0WH=sdtt+IThpnn;LHc0RG%lXajufv<&X}E7o zB**F+Ha5BgIhSu;|3;l;=7~8|(AYg4Y5n2X6%p{0Pns$G&lQ`Dgaz-EL<%|^UK91y zMns4p>!Csr?T04uspYc?Ef=`-Oo@8Z?&i@L$P4p_cH~6Ow4zSh{g;gNUCG5`IHskX z*P;BZ8KUgs9AIPff>*6ObaQ znqtyEZkCLPfm|ZBAGjeS1Jls%-%=d}WNu-KlW$lBd&$SJ7g=cTLxmE(T7qS+=@^+@ zoRtj21OX59tuQ-(f&o)?UNuXGTPm&=-wcUbM8ce@${ypvRw#HNC4J0A_Gl@x;9+Y- zZeTpjoZ%2V-{UxxBpe=M4t`V8CP_g+^IaT|-O8-31S%FtY2mF6bJi&oP>qNt9kqe> zgc4*$S%?=!($WdNxdVJ$WP87Zxv3@vEh~RGcOV`wAin8Q>u42*K0Er|chT4jkt!mN z3UqUn`3=^G2hXSwagS5~9G)m=RCR6P^rX{pO$aBVN8KeSW zZ1@EGf1+B{aodn$S61+zMpSl>S84*T1+OB1i|)2IdUmLnCR?hJ0pR9mv-!}TejAv0 z9E{ntXB;mB`WG?*oBpl+-Z5@_KSwi;9R%mWjEH-E;!EcZ+>B+zmD|Vjv&dCt+<)c- zZU}FR8QIOFcKew%h*3#AE87bwwF%8Ta>Ch*`Ka+{hQ(dZ8ahgZRiSKY5#`%PGh$}l zo9JSQpy1g0jc`%WwZP+WIQ~FfQr@8g6EpZ31D(}qKRiV)zF=Z3dCk5~yXKH?gKQgn z3AzuHS&pbJ{G(-Ol9F2#pW#sb{zq>0ghF8E}GTC07pNhd#>BX`PM75Q? zAAly2PQAV$@5nJ+h}srgKtSAu+~&~rs~|M}_=H(;tBjT9-v^{8D(E;Ut_Zb96hbYF z-Gu^q(NrwcP&N*dNZ`REt1tM1>D?DhSIdgV?7t$j6E)?gWnn*yK9oTBA1bUMG;EI| zcCiTtyQa~I#c55U4m-etk=E4Vw(9AMVnvaYlaZg%zTjyObRy|;cBT5;a@+wwPjk;! z-4p?coh=z;h4tmK7c9TG4BMNgz-qISk`LgpvS*a1ck*V^c~lE#AflvMANei0AS~Ue z6^b*f>WrD>zR|AlD}!X`PV5Xr8pgoF=|299yaH;bzB$WeEoWF7VE2swr`5m)u3u$4 z)0pz|xq$n0QMuL*J37gx#4}VzzE6lWNz=2w#FbaMlB^JV93aI9Hy?RN@FS5UWTrE5>nAXX4Z-Yz?PZyJnMpu>Q--IEIw`K1qhA>lqb9bSh8Q0Q z6jiFG4@DHT?2%LNjFT$=j*MN6s5WXV#&IZWDs$R|ayvz{`W>KK#8N7-RjSfPMk`P6 z%g7TB3|!BYUB~03r%7Mmm3>)AP$|iBHBPptOpy8TJXH&VRVgec_Xh8i#+WITcAP04a-2Eo9ahb zu}a zD>&54<&II7cFhH`;djy@;hC*f-yW4mkCXVGA8q}^GAg1jnpYV~jU3arp+T z68*6czABZ0#0p!R^5gGm34T`{#o*nPhnLv)Zr!K>=%7%w;|9=raz{VeM`YjBwvIF5 z2Ro74Yt@Z&Bm6D`+I^WJ7*zG>*4iHR&#D|4YveoJDT_$8>IKVE{s+ktj+@nL-ay!KXBdl=nxMDVZ;x60;8Tu z2P}7{sD0>(PIgkJqR@+J{C%Q7l{w}vsJ~{TMOh}P15NKhks+ODd}e^By*I0Df5Hp* z1cptpSTotfSyESeRKBwy{BTlt3G;&u=NCb0*BdQt;Tyr(s|?dwW}`LJ1ZPF&E!AQe z*6Cx}XSb^;#AGuBZ64eB*+&BQ*HVd!m*B-sSeux=N7~izghYP3wLq1zp8siFL|t^%9m{X z;0grtF|mL0YW3|7ba42N0ki&3WFJOPdwM0ZoPQ}qB>uQR#xoZ__)~h_RlV{|fNotg z+~wqA2cQ!lyEUDwYrV>EFIUIr#yx!^VUepOat06=%f>%!tfON5ahWZFERu-xj9O&p zd21vQ@`5-&QzAL)YMlza^egrHDuwx(Nb^{)CC;!6=S_dAoz0O<>@$|Giu}L||5ZkD zN^r9Q)4>9%l1y0_ZCjPmqBv(67H{C2EJ-<`&nPwJDzs22%fB7#HkJBY%-2g zz1Hj>!OU@b3;v_Cc{6hUsZ4N#TGQE9ixjhw>Hzl)suYjSqGi z!*gwLX?~I&)M82+&5-6~QUtcWXuE}kBi8Q?fjn|;H0PoDbkiiaJv)b$)*nZ2NZ7uD z$0Vff3CJ?{pw$$72ABXIWP4l|vOHh=p~5A^maz!i&3FLl@R=~VNTs6{>Vj`o+YuYt z!d6Nz?JfnwDLW{~KHIq<=nsJ8Yr*o7<%z;wj?i*lPGI&hrzB*q*>D%}OmIL>w67Z) zUH;{OU$SpPlv7H!>z50UXH;{GJ_BNB2wVvXCUu(Sc#kr{Lyb3qQut8&vAVo)U9u_L zdK@i!t&7gx>&kk50nX96#i_}lC8f%EdzO6*8DF~|UmJ3-9QcO#Ek~6k^vlyl(Z@Ud9%mm%6DBVX8V(Ettju7@VhrG}LK*K|8tm$LxdmY(b_r!+X zHPQfuZ+^nJWAO8JxxV|Rje1!pCz!x%YtIcX0sh&yWxLMX`~T3Z33=(*l7R&Ry7;GA z^S`y7Do%!W&JOlYE;|1=`k!s5rTy0Uvv|X6S<>UleePo%cK`as+{5SVBGaHL z!7S6}R8m5TK0k(`)`_MfU%&tDPp>9k8hO%OoI_q}$z;^j=c`|jKjI)ItMubj4`0A1ll)F5)r)HP!f;hk7WHWhl3&M^q(I&1uIQQCQx6;jY4bX%p_KW83eA zMzT=FEueY%bWz=w*4Qr7XE27(Q7Y0N0?tkYBvW*?Xr-YDZB(nY)YK3|P6|7pf+}BQ`o>lWZ8f7&2$UA)<;a81px|pnXDyQ$ zTxS$O*Azm0%a?_<^a^*o{1#Z(%a|f{PUz_hoDBpvFYmVUxan5q7@CJ3{CHLTOZH_> z<9Qr>*>f^FgI59l=ggZ|h49cd(Po}uupecP?#Wr2?nS6tA<&$@z8L6;yk=jJ+vDCs z*EGgD-tt2P=ka?uJpIs5K3aOF9WPbIv6AE92XkH& zyat@eaQj z1do?I1Nq?0+zn%&9)B$C|3dYCQ3^&Nxso#w=jl9m4guZP@n6pzYz@Z)QDHpMKK<

9T@l;Ua*YhAWJ7_*tAIMRWE_hTY^*baqS!Y{EmT#q7L9IAF^>9$+L$1ButoyfeTEhJoD9Z&XyTxEgChGmGQ6&B!qvl>RB4#9J?++=Cvf`?tbxx61| z2I3(bCF_XOCtGU86tp_J-Lr#;;n!+YG=c_IA{@$ic!|RybA=H3~8;bbt?S(PN4Im++YcShH8$4!j2Ky&!<$UKU>>T}`{{&mh9)h}@MM zNE1u(UC$_~mFtD{KbGgPVF@F0*6$fIl9(f89U%(Eb`I@_@a$u2x1csda+5aj%FEHR zVuq`x!&vzEOAa#ICs{ZRdzMp~X#7?s-S8SkYU(DVW2I!sEjORwUs|5tzSLEe@MiVy-z1TKIAtG7(_zf?HuVZ22kKGpqRA&o_q(|c9OENky=@CEy&!o=0mBEmv-HT zGg&z`SEimbWr?P+7GSjoZn#@O2PF3+l8x5ShOo^N*V9@#F6QnUkdxe&7E||`ep8i@x1ACjw_BZHrWUz61^kP>W-+zP#b0DvWKB2D zl6_!xlxqIL^bdf={W6*^bv*??$&oYc#-$eBNzXh`mHKdt&gi=3f<`gNGN=XXp}qpH zo5!_K#5RnHyPhHa+_ZRuonFYk^h>YoZj1#)V%Ex~#IG2ijZq_UtW7hdWm+c1T;^eF zZf^)JShd0CHa%bQ=dyp8X2$P(E~cg_v1XooK**O&)l;17>DW#On*v}mqk>UtYq{Q@{TPXu*-`6=dxo6HzpUi0o&s49Ck)Rnz&TkJ0?}r zQ+bYn)xFBb%IQ;Pds*)ayV!btEVswIJGEvTjOX89Z7MLsJh5q{>@29sqygz{*MQ!g zhqsy@cxiIdy3RQV7C{(a%B>@gM`DG;Tm5Nsn32GXX9UM)9yN_UI!I!w!S#K`-*FJs z8fQx-IHQ=(&eWC@y-*OtVut^l79oqOp=r9Y)GD8|=~Od34lSYV&W&hoj=0lo#a3tM z0Z+Ql{4C%_5#LmL%8(edv09F(Hr&%T%+3!-N+`+GV}iFX$@O~pq#6+_tIiJV82lS} z@5S~<=+NV4$vJ6e2c7P*B^)n`PVJ|al%~j z=Mim>z39hBY2KEgk<=R7gMj9{Xq1xQGo${livlm}PshS2<}YgRRSki?3KsXh``iED z0ipBIb>aYMARsmYARyNN9}qHgvbS^55&3s>vbV7@b#m5Gwy<{)HgvW&b@_j9|BneD z?ydb6$IHLk9FY!5ki&{|3;5OWCP^g8u>FwRW)01q5KqK_Z1YePgFR91;_0RTRuN51 zNq}z3Ef~&v;XepFhbYm)Wl5K9+qP}nwr%T_ZQHhO>y&NVHu|jFJ-M$}uinFdvWJlw znfb*E;{}HqWx3!K>ZgRq{UYJ_(T7ic6-<64Q+Bx0qI3^VqZoiIgXxMJ0Ke?gKo90pm&W7 zKG@eDZSqg;Kpy0&hoId(Fy22^vBlx4$=n$o6 zHovI!?L&;55f05a78)3Eks1KO(oK#E$$n}`Zs;{GP#`z4{1t5oCDB@ZLp;}fKnL%Z zkYa@9afdjnA!Xvn+Mk6Kd zq={^@g1n1eX&W>L`XCVDYGaCSiH$W^L)?Be1${gAg$?YKP{s|aNy9eCUg^MS1G%4` zQOMw-X?5c-rcn!9l_tS(l0MXfFpP(f7RJggxD-|yGC`5Rk~%@wV0q*`XfzsH=8VJi zB(uLab>)5a&R+t(|AxAv7u#FLJam9(I4$6A=um&+dQ~}RR+$SHuk48go|ez_Dd2`_w(;eEs6i;t}iW$&e^!r zGr2Bq4iWF&m@cVeuz^-oYFc4?_cOv4$hnye3hJttX|Q6Vix?-L4ig;ZzThs{Ldqa?qGBZDk8?Ac+8n2~5qeC)$`aP=&=5 zp+}Xz!z;_PX$qVxU0V_4y=*kJ8U9qWD-cT5dblcLN#lV#B4t7%M`RoJ^s>-#{uKpd ztE!LPL#a0*M0Ig=EC3EB8$>)(aaM!(*%s)}h$(#+XW+8_53klg;=I(>m&yyA( zXUsVs5(r_7%RE?)C|;HA%V?oZzNi6G3yzN(ND!ORsUlUrIiwlF7I?GVOFyqCBeONu zgK9?t?DF<{-Fm{QVvxaLVCHR_#pEpiQW+z_`gq0OMPRnrG&xGt*-wXGgMy9Na*-Bt7(H>+e@Vy~?r@G#xDx=`D zbHJ%KhN*>(sMgW);Q5u{)6DtaHlUFdN}Usm=gM>^3a?YA&K6`94+`~J*%sP_qzI?J zvg>X+{T>S^;e!*_uV*T9B1*m739-K3p`u^3a`nEW3%G+MrCNftYc*fEJyf@(3UYM! z7vBEN3e#9&xvyExrtH2DN1M(FiQ{~{sy8Wt&p}6i*FV^U454>bwdsOnas)5)v*BA9b84x`$$(ipzu;bwf(0g+WR_NU0DAH zPvQKBVS)>6X+kG5sEjll^#IzbW*8aXY7hStiwfNVf(EzJYH0L|7fxI{@OxJ1#LRH$uHi7Vp0 zqG^-pa+SJ%4&1576a6CfFJomG)q5@fv0g9#-;c|lG z<+RT z33GQ5FbRluo2&E9lI{J4a8eWa_HMZg_|g67O=KmL;<(-=+OqzJ&cmxdLjvv2?|~B* z?RW2o^dYq98^}Kxvz(DZ7-g3FbG2X-y%rZaWrqeEX_ci(XLHPDcq!V9|1@&*rq?tU zLYsFV)jN1xYT}KOos`Wtavd2Y;{M+>1X8y%CzzHyl!PqM#=%vGB05gZIakU2?21)bD-x+I;HxtlXsnv372KjIe!&fE4XVv zH$`nMYbSziP+H97f|R9fTJ}fzWFP>eMk^7Q{R&O@grqS7(i!!U% zPVO*rO1YdC1)IFhQF&Wf%OmOQQpM*LcLlY})?ctQPTm}0pc%@wQSFy@YVC_`i_Dsg zR(>>2>0i9UtwU45o-c)DQ(^CM6km@=wt|T4#)PTfKL1C+NSoTQ&@m_gz~6s)%1r$x5c?|=0i!Y{u-FR(R8%GRW0W((*E4W-VQWwcj=At!bHFakzIYsW;Q zl#=Wf+wLE6UP{gfV_dc3*6Oa$?I8DVV!uy>slabu_*qE!dfB<)_uO{tA@E1tGzQeJYl4_Y^Xe1BC^eqY+~mVa75OzwcXF&zA%OUGjB#c_ zBgm5{8oi6EXBC&b#^|^XL?F+lJdD^b9}656<<;GecnNgj{Y%GbOqIjVE=M7?*7@Ad zp_q<0wc*$T(Tlfc&Qkrxv`8&x>9Z^<;?FX;#6%`~WV}#1?|tiEViUmOju3x{6M3b0 ztkxo>GXw05v%mDKrG(8-Bk2Fp2rgWvl7FZgV~B~_M^;fZf_*^xpyqQF(li7qjtYh2 zLBQ2P7;q!S0ojB%JO+)pxaz_FIGYfRLjxIds!--}VGanSZR?F$!Gh&nLX[U|_I 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

1hf8>5vL`w<@Ib8CZQS1bIY2;wd>$K%p`V7& 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 diff --git a/temp/update_build/ver_0.293_files.txt b/temp/update_build/ver_0.293_files.txt deleted file mode 100644 index 0a506e8..0000000 --- a/temp/update_build/ver_0.293_files.txt +++ /dev/null @@ -1,2 +0,0 @@ -F: ../autoload/front/controls/class.Site.php -F: ../autoload/front/view/class.Site.php diff --git a/temp/ver_0.294.zip b/temp/ver_0.294.zip deleted file mode 100644 index 80fefac4d0355b424aa19d93b9fc9a8a6de76bd6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 154376 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�^8 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 diff --git a/temp/ver_0.294_files.txt b/temp/ver_0.294_files.txt deleted file mode 100644 index 5b811be..0000000 --- a/temp/ver_0.294_files.txt +++ /dev/null @@ -1,12 +0,0 @@ -F: ../autoload/shop/class.Basket.php -F: ../autoload/shop/class.Category.php -F: ../autoload/shop/class.Coupon.php -F: ../autoload/shop/class.Order.php -F: ../autoload/shop/class.Product.php -F: ../autoload/shop/class.ProductAttribute.php -F: ../autoload/shop/class.ProductCustomField.php -F: ../autoload/shop/class.ProductSet.php -F: ../autoload/shop/class.Promotion.php -F: ../autoload/shop/class.Search.php -F: ../autoload/shop/class.Shop.php -F: ../autoload/shop/class.Transport.php diff --git a/tests/Unit/Domain/Order/OrderAdminServiceTest.php b/tests/Unit/Domain/Order/OrderAdminServiceTest.php new file mode 100644 index 0000000..569a0da --- /dev/null +++ b/tests/Unit/Domain/Order/OrderAdminServiceTest.php @@ -0,0 +1,230 @@ +createMock(OrderRepository::class); + } + + return new OrderAdminService($orderRepo, $productRepo, $settingsRepo, $transportRepo); + } + + public function testConstructorAcceptsOnlyOrderRepository(): void + { + $orderRepo = $this->createMock(OrderRepository::class); + $service = new OrderAdminService($orderRepo); + $this->assertInstanceOf(OrderAdminService::class, $service); + } + + public function testConstructorAcceptsAllDependencies(): void + { + $orderRepo = $this->createMock(OrderRepository::class); + $productRepo = $this->createMock(ProductRepository::class); + $settingsRepo = $this->createMock(SettingsRepository::class); + $transportRepo = $this->createMock(TransportRepository::class); + + $service = new OrderAdminService($orderRepo, $productRepo, $settingsRepo, $transportRepo); + $this->assertInstanceOf(OrderAdminService::class, $service); + } + + public function testSearchProductsReturnsEmptyForEmptyQuery(): void + { + $productRepo = $this->createMock(ProductRepository::class); + $productRepo->expects($this->never())->method('searchProductByNameAjax'); + + $service = $this->createService(null, $productRepo); + $result = $service->searchProducts('', 'pl'); + + $this->assertSame([], $result); + } + + public function testSearchProductsReturnsEmptyWithoutProductRepo(): void + { + $service = $this->createService(); + $result = $service->searchProducts('test', 'pl'); + + $this->assertSame([], $result); + } + + public function testSearchProductsReturnsFormattedResults(): void + { + $productRepo = $this->createMock(ProductRepository::class); + $productRepo->method('searchProductByNameAjax') + ->with('koszulka', 'pl') + ->willReturn([ + ['product_id' => 10], + ['product_id' => 20], + ]); + + $productRepo->method('findCached') + ->willReturnCallback(function ($id) { + if ($id === 10) { + return [ + 'language' => ['name' => 'Koszulka biała'], + 'sku' => 'KB-001', + 'ean' => '', + 'price_brutto' => 49.99, + 'price_brutto_promo' => 39.99, + 'vat' => 23, + 'quantity' => 15, + 'parent_id' => 0, + ]; + } + return null; // product 20 not found + }); + + $productRepo->method('getProductImg') + ->willReturn('/images/products/test.jpg'); + + $service = $this->createService(null, $productRepo); + $results = $service->searchProducts('koszulka', 'pl'); + + $this->assertCount(1, $results); + $this->assertSame(10, $results[0]['product_id']); + $this->assertSame('Koszulka biała', $results[0]['name']); + $this->assertSame('KB-001', $results[0]['sku']); + $this->assertSame(49.99, $results[0]['price_brutto']); + $this->assertSame(39.99, $results[0]['price_brutto_promo']); + $this->assertSame(15, $results[0]['quantity']); + } + + public function testSaveOrderProductsReturnsFalseForInvalidOrderId(): void + { + $service = $this->createService(); + $this->assertFalse($service->saveOrderProducts(0, [])); + } + + public function testSaveOrderProductsDeletesRemovedProducts(): void + { + $orderRepo = $this->createMock(OrderRepository::class); + $productRepo = $this->createMock(ProductRepository::class); + $settingsRepo = $this->createMock(SettingsRepository::class); + $transportRepo = $this->createMock(TransportRepository::class); + + // Existing products + $orderRepo->method('orderProducts') + ->with(1) + ->willReturn([ + ['id' => 100, 'product_id' => 5, 'quantity' => 2, 'price_brutto' => 10, 'price_brutto_promo' => 0], + ['id' => 101, 'product_id' => 6, 'quantity' => 1, 'price_brutto' => 20, 'price_brutto_promo' => 0], + ]); + + // Product 100 is submitted with delete flag + // Product 101 is not submitted at all (also deleted) + $orderRepo->expects($this->exactly(2))->method('deleteOrderProduct'); + $orderRepo->method('findRawById')->willReturn(['id' => 1, 'transport_id' => 1]); + $transportRepo->method('findActiveById')->willReturn(null); + + // Stock should be returned for both deleted products + $productRepo->method('getQuantity')->willReturn(10); + $productRepo->expects($this->exactly(2))->method('updateQuantity'); + + $service = new OrderAdminService($orderRepo, $productRepo, $settingsRepo, $transportRepo); + $result = $service->saveOrderProducts(1, [ + ['order_product_id' => 100, 'delete' => '1', 'quantity' => 2], + ]); + + $this->assertTrue($result); + } + + public function testSaveOrderProductsUpdatesQuantityAndAdjustsStock(): void + { + $orderRepo = $this->createMock(OrderRepository::class); + $productRepo = $this->createMock(ProductRepository::class); + $settingsRepo = $this->createMock(SettingsRepository::class); + $transportRepo = $this->createMock(TransportRepository::class); + + // Existing: qty=3 + $orderRepo->method('orderProducts') + ->willReturn([ + ['id' => 100, 'product_id' => 5, 'quantity' => 3, 'price_brutto' => 10, 'price_brutto_promo' => 0], + ]); + + // Submit: qty=5 (increased by 2 → stock decreases by 2) + $orderRepo->expects($this->once())->method('updateOrderProduct') + ->with(100, $this->callback(function ($data) { + return $data['quantity'] === 5; + })); + + $orderRepo->method('findRawById')->willReturn(['id' => 1, 'transport_id' => 1]); + $transportRepo->method('findActiveById')->willReturn(null); + + $productRepo->method('getQuantity')->with(5)->willReturn(20); + $productRepo->expects($this->once())->method('updateQuantity') + ->with(5, 18); // 20 + (3 - 5) = 18 + + $service = new OrderAdminService($orderRepo, $productRepo, $settingsRepo, $transportRepo); + $service->saveOrderProducts(1, [ + ['order_product_id' => 100, 'product_id' => 5, 'quantity' => 5, 'price_brutto' => 10, 'price_brutto_promo' => 0], + ]); + } + + public function testSaveOrderProductsAddsNewProductAndDecreasesStock(): void + { + $orderRepo = $this->createMock(OrderRepository::class); + $productRepo = $this->createMock(ProductRepository::class); + $settingsRepo = $this->createMock(SettingsRepository::class); + $transportRepo = $this->createMock(TransportRepository::class); + + $orderRepo->method('orderProducts')->willReturn([]); + + $orderRepo->expects($this->once())->method('addOrderProduct') + ->with(1, $this->callback(function ($data) { + return $data['product_id'] === 10 + && $data['name'] === 'New Product' + && $data['quantity'] === 2; + })); + + $orderRepo->method('findRawById')->willReturn(['id' => 1, 'transport_id' => 1]); + $transportRepo->method('findActiveById')->willReturn(null); + + $productRepo->method('getQuantity')->with(10)->willReturn(15); + $productRepo->expects($this->once())->method('updateQuantity') + ->with(10, 13); // 15 - 2 + + $service = new OrderAdminService($orderRepo, $productRepo, $settingsRepo, $transportRepo); + $service->saveOrderProducts(1, [ + [ + 'order_product_id' => 0, + 'product_id' => 10, + 'parent_product_id' => 10, + 'name' => 'New Product', + 'vat' => 23, + 'price_brutto' => 50, + 'price_brutto_promo' => 0, + 'quantity' => 2, + ], + ]); + } + + public function testGetFreeDeliveryThresholdReturnsZeroWithoutSettingsRepo(): void + { + $service = $this->createService(); + $this->assertSame(0.0, $service->getFreeDeliveryThreshold()); + } + + public function testGetFreeDeliveryThresholdReturnsValue(): void + { + $settingsRepo = $this->createMock(SettingsRepository::class); + $settingsRepo->method('getSingleValue') + ->with('free_delivery') + ->willReturn('150.00'); + + $service = $this->createService(null, null, $settingsRepo); + $this->assertSame(150.0, $service->getFreeDeliveryThreshold()); + } +} diff --git a/tests/Unit/Domain/Order/OrderRepositoryTest.php b/tests/Unit/Domain/Order/OrderRepositoryTest.php index 98cac9b..bc93a8b 100644 --- a/tests/Unit/Domain/Order/OrderRepositoryTest.php +++ b/tests/Unit/Domain/Order/OrderRepositoryTest.php @@ -209,6 +209,138 @@ class OrderRepositoryTest extends TestCase $this->assertSame($expectedPrefix . '006', $number); } + // --- Order product CRUD tests --- + + public function testGetOrderProductReturnsNullForInvalidId(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->never())->method('get'); + + $repository = new OrderRepository($mockDb); + $this->assertNull($repository->getOrderProduct(0)); + $this->assertNull($repository->getOrderProduct(-1)); + } + + public function testGetOrderProductReturnsArray(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->method('get') + ->with('pp_shop_order_products', '*', ['id' => 5]) + ->willReturn(['id' => 5, 'order_id' => 1, 'name' => 'Test']); + + $repository = new OrderRepository($mockDb); + $result = $repository->getOrderProduct(5); + + $this->assertIsArray($result); + $this->assertSame(5, $result['id']); + } + + public function testAddOrderProductReturnsNullForInvalidOrderId(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->never())->method('insert'); + + $repository = new OrderRepository($mockDb); + $this->assertNull($repository->addOrderProduct(0, ['name' => 'Test'])); + } + + public function testAddOrderProductInsertsAndReturnsId(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->once())->method('insert') + ->with('pp_shop_order_products', $this->callback(function ($data) { + return $data['order_id'] === 10 + && $data['product_id'] === 5 + && $data['name'] === 'Test Product' + && $data['quantity'] === 2; + })); + $mockDb->method('id')->willReturn('99'); + + $repository = new OrderRepository($mockDb); + $result = $repository->addOrderProduct(10, [ + 'product_id' => 5, + 'name' => 'Test Product', + 'quantity' => 2, + 'price_brutto' => 19.99, + ]); + + $this->assertSame(99, $result); + } + + public function testUpdateOrderProductReturnsFalseForInvalidId(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->never())->method('update'); + + $repository = new OrderRepository($mockDb); + $this->assertFalse($repository->updateOrderProduct(0, ['quantity' => 3])); + } + + public function testUpdateOrderProductUpdatesFields(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->once())->method('update') + ->with('pp_shop_order_products', $this->callback(function ($data) { + return $data['quantity'] === 3 + && $data['price_brutto'] === 25.50; + }), ['id' => 7]); + + $repository = new OrderRepository($mockDb); + $result = $repository->updateOrderProduct(7, [ + 'quantity' => 3, + 'price_brutto' => 25.50, + ]); + + $this->assertTrue($result); + } + + public function testUpdateOrderProductReturnsFalseForEmptyData(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->never())->method('update'); + + $repository = new OrderRepository($mockDb); + $this->assertFalse($repository->updateOrderProduct(7, [])); + } + + public function testDeleteOrderProductReturnsFalseForInvalidId(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->never())->method('delete'); + + $repository = new OrderRepository($mockDb); + $this->assertFalse($repository->deleteOrderProduct(0)); + } + + public function testDeleteOrderProductCallsDelete(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->once())->method('delete') + ->with('pp_shop_order_products', ['id' => 12]); + + $repository = new OrderRepository($mockDb); + $this->assertTrue($repository->deleteOrderProduct(12)); + } + + public function testUpdateTransportCostDoesNothingForInvalidId(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->never())->method('update'); + + $repository = new OrderRepository($mockDb); + $repository->updateTransportCost(0, 15.0); + } + + public function testUpdateTransportCostUpdatesOrder(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->once())->method('update') + ->with('pp_shop_orders', ['transport_cost' => 12.50], ['id' => 5]); + + $repository = new OrderRepository($mockDb); + $repository->updateTransportCost(5, 12.50); + } + public function testGenerateOrderNumberStartsAt001(): void { $mockDb = $this->createMock(\medoo::class); diff --git a/tests/Unit/admin/Controllers/ShopOrderControllerTest.php b/tests/Unit/admin/Controllers/ShopOrderControllerTest.php index f055c68..2b72a32 100644 --- a/tests/Unit/admin/Controllers/ShopOrderControllerTest.php +++ b/tests/Unit/admin/Controllers/ShopOrderControllerTest.php @@ -41,6 +41,7 @@ class ShopOrderControllerTest extends TestCase $this->assertTrue(method_exists($this->controller, 'toggle_trustmate_send')); $this->assertTrue(method_exists($this->controller, 'delete')); $this->assertTrue(method_exists($this->controller, 'order_delete')); + $this->assertTrue(method_exists($this->controller, 'search_products_ajax')); } public function testViewActionsReturnString(): void @@ -70,6 +71,7 @@ class ShopOrderControllerTest extends TestCase $this->assertEquals('void', (string)$reflection->getMethod('toggle_trustmate_send')->getReturnType()); $this->assertEquals('void', (string)$reflection->getMethod('delete')->getReturnType()); $this->assertEquals('void', (string)$reflection->getMethod('order_delete')->getReturnType()); + $this->assertEquals('void', (string)$reflection->getMethod('search_products_ajax')->getReturnType()); } public function testConstructorRequiresOrderAdminService(): void @@ -78,7 +80,9 @@ class ShopOrderControllerTest extends TestCase $constructor = $reflection->getConstructor(); $params = $constructor->getParameters(); - $this->assertCount(1, $params); + $this->assertCount(2, $params); $this->assertEquals('Domain\\Order\\OrderAdminService', $params[0]->getType()->getName()); + $this->assertEquals('Domain\\Product\\ProductRepository', $params[1]->getType()->getName()); + $this->assertTrue($params[1]->isOptional()); } } diff --git a/updates/0.20/ver_0.295.zip b/updates/0.20/ver_0.295.zip new file mode 100644 index 0000000000000000000000000000000000000000..6aa0d93f93fd1e6aa099963b75e55fd979715b28 GIT binary patch literal 25124 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 z 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 literal 0 HcmV?d00001 diff --git a/updates/changelog.php b/updates/changelog.php index a34c25c..6bc7f2b 100644 --- a/updates/changelog.php +++ b/updates/changelog.php @@ -1,3 +1,9 @@ +ver. 0.295 - 19.02.2026
    +- NEW - Edycja produktów w zamówieniu z panelu admina (dodawanie, usuwanie, zmiana ilości/cen) +- NEW - Wyszukiwarka produktów AJAX w formularzu edycji zamówienia +- NEW - Automatyczna korekta stanów magazynowych i przeliczanie kosztu dostawy +- FIX - Cena promo w zamówieniu = 0 gdy identyczna z ceną bazową +
    ver. 0.294 - 19.02.2026
    - FIX - Code review zakończony (96/96 klas, ~1144 metod): 27 fixów across all layers - FIX - Domain: null guard na query()->fetchAll() w 8 repozytoriach, redundancja DI w PromotionRepository diff --git a/updates/versions.php b/updates/versions.php index 6de390c..2b5c3dd 100644 --- a/updates/versions.php +++ b/updates/versions.php @@ -1,5 +1,5 @@