From 101e5fec966cb097e5136dcf6319a77097a1305d Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Wed, 29 Apr 2026 17:23:52 +0200 Subject: [PATCH 01/18] Handle Banner settings LIS-111 --- .../BannerSettingsController.php | 63 +++++++++ .../Requests/BannerSettingsRequest.php | 15 +++ .../Requests/SaveBannerSettingsRequest.php | 50 ++++++++ .../Responses/BannerSettingsResponse.php | 35 +++++ .../Responses/SuccessfulBannerResponse.php | 21 +++ .../Responses/UnsuccessfulBannerResponse.php | 49 +++++++ .../Entities/BannerSettings.php | 121 ++++++++++++++++++ .../Repositories/BannerSettingsRepository.php | 103 +++++++++++++++ .../Exceptions/InvalidURLException.php | 14 ++ .../Domain/BannerSettings/Models/Banner.php | 110 ++++++++++++++++ .../BannerSettings/Models/BannerSettings.php | 61 +++++++++ .../BannerSettingsRepositoryInterface.php | 41 ++++++ .../Services/BannerSettingsService.php | 112 ++++++++++++++++ 13 files changed, 795 insertions(+) create mode 100644 src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php create mode 100644 src/BusinessLogic/AdminAPI/BannerSettings/Requests/BannerSettingsRequest.php create mode 100644 src/BusinessLogic/AdminAPI/BannerSettings/Requests/SaveBannerSettingsRequest.php create mode 100644 src/BusinessLogic/AdminAPI/BannerSettings/Responses/BannerSettingsResponse.php create mode 100644 src/BusinessLogic/AdminAPI/BannerSettings/Responses/SuccessfulBannerResponse.php create mode 100644 src/BusinessLogic/AdminAPI/BannerSettings/Responses/UnsuccessfulBannerResponse.php create mode 100644 src/BusinessLogic/DataAccess/BannerSettings/Entities/BannerSettings.php create mode 100644 src/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepository.php create mode 100644 src/BusinessLogic/Domain/BannerSettings/Exceptions/InvalidURLException.php create mode 100644 src/BusinessLogic/Domain/BannerSettings/Models/Banner.php create mode 100644 src/BusinessLogic/Domain/BannerSettings/Models/BannerSettings.php create mode 100644 src/BusinessLogic/Domain/BannerSettings/RepositoryContracts/BannerSettingsRepositoryInterface.php create mode 100644 src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php b/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php new file mode 100644 index 0000000..05bcd68 --- /dev/null +++ b/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php @@ -0,0 +1,63 @@ +bannerSettingsService = $bannerSettingsService; + } + + /** + * Gets active banner settings. + * + * @throws Exception + */ + public function getBannerSettings(): BannerSettingsResponse + { + return new BannerSettingsResponse($this->bannerSettingsService->getBannerSettings()); + } + + /** + * Sets banner settings. + * + * @param BannerSettingsRequest $settingsRequest + * + * @return Response + * + * @throws Exception + */ + public function setBannerSettings(BannerSettingsRequest $settingsRequest): Response + { + try { + $this->bannerSettingsService->setBannerSettings($settingsRequest->transformToDomainModel()); + } catch (InvalidURLException $e) { + return new UnsuccessfulBannerResponse($e->getMessage()); + } + + return new SuccessfulBannerResponse(); + } +} diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/Requests/BannerSettingsRequest.php b/src/BusinessLogic/AdminAPI/BannerSettings/Requests/BannerSettingsRequest.php new file mode 100644 index 0000000..b3ba9dd --- /dev/null +++ b/src/BusinessLogic/AdminAPI/BannerSettings/Requests/BannerSettingsRequest.php @@ -0,0 +1,15 @@ +> + */ + protected $bannerConfigs; + + /** + * @param array> $bannerConfigs + */ + public function __construct( + array $bannerConfigs = [] + ) { + $this->bannerConfigs = $bannerConfigs; + } + + /** + * Transforms the request to a BannerSettings object. + * + * @return BannerSettings + */ + public function transformToDomainModel(): object + { + $arrayOfBannerConfigs = []; + foreach ($this->bannerConfigs as $bannerConfig) { + $arrayOfBannerConfigs[] = new Banner( + $bannerConfig['country'] ?? '', + $bannerConfig['displayLocation'] ?? '', + $bannerConfig['linkUrl'] ?? '', + $bannerConfig['imageUrl'] ?? '' + ); + } + + return new BannerSettings( + $arrayOfBannerConfigs + ); + } +} diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/Responses/BannerSettingsResponse.php b/src/BusinessLogic/AdminAPI/BannerSettings/Responses/BannerSettingsResponse.php new file mode 100644 index 0000000..d8a1d94 --- /dev/null +++ b/src/BusinessLogic/AdminAPI/BannerSettings/Responses/BannerSettingsResponse.php @@ -0,0 +1,35 @@ +bannerSettings = $bannerSettings; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return !$this->bannerSettings ? [] : $this->bannerSettings->toArray(); + } +} diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/Responses/SuccessfulBannerResponse.php b/src/BusinessLogic/AdminAPI/BannerSettings/Responses/SuccessfulBannerResponse.php new file mode 100644 index 0000000..71f1eb7 --- /dev/null +++ b/src/BusinessLogic/AdminAPI/BannerSettings/Responses/SuccessfulBannerResponse.php @@ -0,0 +1,21 @@ +message = $message; + $this->statusCode = $statusCode; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'message' => $this->message, + 'errorCode' => $this->statusCode + ]; + } +} diff --git a/src/BusinessLogic/DataAccess/BannerSettings/Entities/BannerSettings.php b/src/BusinessLogic/DataAccess/BannerSettings/Entities/BannerSettings.php new file mode 100644 index 0000000..a343fc4 --- /dev/null +++ b/src/BusinessLogic/DataAccess/BannerSettings/Entities/BannerSettings.php @@ -0,0 +1,121 @@ +storeId = $data['storeId'] ?? ''; + $this->bannerSettings = new DomainBannerSettings( + $this->inflateBannerConfigs(static::getDataValue($bannerSettings, 'bannerConfigs', [])) + ); + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + $data = parent::toArray(); + + $data['bannerSettings'] = $this->bannerSettings->toArray(); + + return $data; + } + + /** + * @inheritDoc + */ + public function getConfig(): EntityConfiguration + { + $indexMap = new IndexMap(); + + $indexMap->addStringIndex('storeId'); + + return new EntityConfiguration($indexMap, 'BannerSettings'); + } + + /** + * @return string + */ + public function getStoreId(): string + { + return $this->storeId; + } + + /** + * @param string $storeId + */ + public function setStoreId(string $storeId): void + { + $this->storeId = $storeId; + } + + /** + * @return DomainBannerSettings + */ + public function getBannerSettings(): DomainBannerSettings + { + return $this->bannerSettings; + } + + /** + * @param DomainBannerSettings $bannerSettings + */ + public function setBannerSettings(DomainBannerSettings $bannerSettings): void + { + $this->bannerSettings = $bannerSettings; + } + + /** + * @param array> $bannerConfigs + * + * @return Banner[] + */ + protected function inflateBannerConfigs(array $bannerConfigs): array + { + $arrayOffBannerConfigs = []; + foreach ($bannerConfigs as $bannerConfig) { + $arrayOffBannerConfigs [] = new Banner( + $bannerConfig['country'], + $bannerConfig['displayLocation'], + $bannerConfig['linkUrl'], + $bannerConfig['imageUrl'] + ); + } + + return $arrayOffBannerConfigs; + } +} diff --git a/src/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepository.php b/src/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepository.php new file mode 100644 index 0000000..f53d33a --- /dev/null +++ b/src/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepository.php @@ -0,0 +1,103 @@ +repository = $repository; + $this->storeContext = $storeContext; + } + + /** + * @inheritDoc + */ + public function setWidgetSettings(WidgetSettings $settings): void + { + $existingWidgetSettings = $this->getWidgetSettingsEntity(); + + if ($existingWidgetSettings) { + $existingWidgetSettings->setWidgetSettings($settings); + $existingWidgetSettings->setStoreId($this->storeContext->getStoreId()); + $this->repository->update($existingWidgetSettings); + + return; + } + + $entity = new WidgetSettingsEntity(); + $entity->setStoreId($this->storeContext->getStoreId()); + $entity->setWidgetSettings($settings); + $this->repository->save($entity); + } + + /** + * @inheritDoc + */ + public function getWidgetSettings(): ?WidgetSettings + { + $entity = $this->getWidgetSettingsEntity(); + + return $entity ? $entity->getWidgetSettings() : null; + } + + /** + * @return void + * + * @throws QueryFilterInvalidParamException + */ + public function deleteWidgetSettings(): void + { + $entity = $this->getWidgetSettingsEntity(); + + $entity && $this->repository->delete($entity); + } + + /** + * Gets the widget settings entity from the database. + * + * @return WidgetSettingsEntity|null + * + * @throws QueryFilterInvalidParamException + */ + protected function getWidgetSettingsEntity(): ?WidgetSettingsEntity + { + $queryFilter = new QueryFilter(); + $queryFilter->where('storeId', Operators::EQUALS, $this->storeContext->getStoreId()); + + /** + * @var WidgetSettingsEntity $widgetSettings + */ + $widgetSettings = $this->repository->selectOne($queryFilter); + + return $widgetSettings; + } +} diff --git a/src/BusinessLogic/Domain/BannerSettings/Exceptions/InvalidURLException.php b/src/BusinessLogic/Domain/BannerSettings/Exceptions/InvalidURLException.php new file mode 100644 index 0000000..0833726 --- /dev/null +++ b/src/BusinessLogic/Domain/BannerSettings/Exceptions/InvalidURLException.php @@ -0,0 +1,14 @@ +country = $country; + $this->displayLocation = $displayLocation; + $this->linkUrl = $linkUrl; + $this->imageUrl = $imageUrl; + } + + /** + * @return string + */ + public function getCountry(): string + { + return $this->country; + } + + /** + * @param string $country + */ + public function setCountry(string $country): void + { + $this->country = $country; + } + + /** + * @return string + */ + public function getLinkUrl(): string + { + return $this->linkUrl; + } + + /** + * @param string $linkUrl + */ + public function setLinkUrl(string $linkUrl): void + { + $this->linkUrl = $linkUrl; + } + + /** + * @return string + */ + public function getImageUrl(): string + { + return $this->imageUrl; + } + + /** + * @param string $imageUrl + */ + public function setImageUrl(string $imageUrl): void + { + $this->imageUrl = $imageUrl; + } + + /** + * @return string + */ + public function getDisplayLocation(): string + { + return $this->displayLocation; + } + + /** + * @param string $displayLocation + */ + public function setDisplayLocation(string $displayLocation): void + { + $this->displayLocation = $displayLocation; + } +} diff --git a/src/BusinessLogic/Domain/BannerSettings/Models/BannerSettings.php b/src/BusinessLogic/Domain/BannerSettings/Models/BannerSettings.php new file mode 100644 index 0000000..e279447 --- /dev/null +++ b/src/BusinessLogic/Domain/BannerSettings/Models/BannerSettings.php @@ -0,0 +1,61 @@ +bannerConfigs = $bannerConfigs; + } + + /** + * @return Banner[] + */ + public function getBannerConfigs(): array + { + return $this->bannerConfigs; + } + + /** + * @param Banner[] $bannerConfigs + */ + public function setBannerConfigs(array $bannerConfigs): void + { + $this->bannerConfigs = $bannerConfigs; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + $bannerSettingsArray = []; + + foreach ($this->bannerConfigs as $bannerConfig) { + $bannerSettingsArray['bannerConfigs'][] = [ + 'country' => $bannerConfig->getCountry(), + 'linkUrl' => $bannerConfig->getLinkUrl(), + 'imageUrl' => $bannerConfig->getImageUrl(), + 'displayLocation' => $bannerConfig->getDisplayLocation() + ]; + } + + return $bannerSettingsArray; + } +} diff --git a/src/BusinessLogic/Domain/BannerSettings/RepositoryContracts/BannerSettingsRepositoryInterface.php b/src/BusinessLogic/Domain/BannerSettings/RepositoryContracts/BannerSettingsRepositoryInterface.php new file mode 100644 index 0000000..e3648d2 --- /dev/null +++ b/src/BusinessLogic/Domain/BannerSettings/RepositoryContracts/BannerSettingsRepositoryInterface.php @@ -0,0 +1,41 @@ +bannerSettingsRepository = $bannerSettingsRepository; + } + + /** + * Retrieves banner settings. + * + * @return BannerSettings|null + * + * @throws Exception + */ + public function getBannerSettings(): ?BannerSettings + { + return $this->bannerSettingsRepository->getBannerSettings(); + } + + /** + * Sets banner settings. + * + * @param BannerSettings $bannerSettings + * + * @return void + * + * @throws Exception + */ + public function setBannerSettings(BannerSettings $bannerSettings): void + { + foreach ($bannerSettings->getBannerConfigs() as $bannerConfig) { + $this->assertValidUrl($bannerConfig->getLinkUrl()); + } + + $this->bannerSettingsRepository->setBannerSettings($bannerSettings); + } + + /** + * Returns banner data + * + * @param string $country + * + * @return Banner|null + * + * @throws Exception + */ + public function getBannerData(string $country): ?Banner + { + $bannerSettings = $this->getBannerSettings(); + + if ($bannerSettings === null) { + return null; + } + + foreach ($bannerSettings->getBannerConfigs() as $bannerConfig) { + if ($bannerConfig->getCountry() === $country) { + return $bannerConfig; + } + } + + return null; + } + + /** + * Validates the URL + * + * @throws InvalidURLException + */ + private function assertValidUrl(string $url): void + { + if (mb_strlen($url) > 2048) { + throw new InvalidURLException('URL is too long (max 2048 characters)'); + } + + if (!filter_var($url, FILTER_VALIDATE_URL)) { + throw new InvalidURLException('URL format is invalid'); + } + + $scheme = parse_url($url, PHP_URL_SCHEME); + if (!in_array($scheme, ['http', 'https'], true)) { + throw new InvalidURLException('URL must use http or https'); + } + } +} From 3d8dc81f99354a8d59ef02bf4010f8a33db38dbe Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Wed, 29 Apr 2026 17:32:40 +0200 Subject: [PATCH 02/18] Fix typo error LIS-111 --- .../Domain/BannerSettings/Services/BannerSettingsService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php index 461ef7e..1da3637 100644 --- a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php +++ b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php @@ -28,7 +28,7 @@ class BannerSettingsService * @param BannerSettingsRepositoryInterface $bannerSettingsRepository */ public function __construct( - BannerSettingsRepositoryInterface $bannerSettingsRepository, + BannerSettingsRepositoryInterface $bannerSettingsRepository ) { $this->bannerSettingsRepository = $bannerSettingsRepository; } From 5d90d9d6aedced5b3615838ea1c0fc795cf5ce0c Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Wed, 29 Apr 2026 17:52:41 +0200 Subject: [PATCH 03/18] Code refactor and service registration LIS-111 --- src/BusinessLogic/BootstrapComponent.php | 13 +++++ .../Repositories/BannerSettingsRepository.php | 52 +++++++++---------- .../BannerSettingsRepositoryInterface.php | 2 + 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/BusinessLogic/BootstrapComponent.php b/src/BusinessLogic/BootstrapComponent.php index 742f6d7..dc4890e 100644 --- a/src/BusinessLogic/BootstrapComponent.php +++ b/src/BusinessLogic/BootstrapComponent.php @@ -36,6 +36,8 @@ use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\WidgetSettings\SaveWidgetSettingsHandler; use SeQura\Core\BusinessLogic\DataAccess\AdvancedSettings\Entities\AdvancedSettings; use SeQura\Core\BusinessLogic\DataAccess\AdvancedSettings\Repositories\AdvancedSettingsRepository; +use SeQura\Core\BusinessLogic\DataAccess\BannerSettings\Entities\BannerSettings; +use SeQura\Core\BusinessLogic\DataAccess\BannerSettings\Repositories\BannerSettingsRepository; use SeQura\Core\BusinessLogic\DataAccess\ConnectionData\Entities\ConnectionData; use SeQura\Core\BusinessLogic\DataAccess\ConnectionData\Repositories\ConnectionDataRepository; use SeQura\Core\BusinessLogic\DataAccess\CountryConfiguration\Entities\CountryConfiguration; @@ -61,6 +63,7 @@ use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\RepositoryContracts\AdvancedSettingsRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Services\AdvancedLoggerSettingsProvider; use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Services\AdvancedSettingsService; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; use SeQura\Core\Infrastructure\Logger\Interfaces\LoggerSettingsProviderInterface; use SeQura\Core\BusinessLogic\Domain\Connection\ProxyContracts\ConnectionProxyInterface; use SeQura\Core\BusinessLogic\Domain\Connection\RepositoryContracts\ConnectionDataRepositoryInterface; @@ -254,6 +257,16 @@ static function () { } ); + ServiceRegister::registerService( + BannerSettingsRepositoryInterface::class, + static function () { + return new BannerSettingsRepository( + RepositoryRegistry::getRepository(BannerSettings::getClassName()), + ServiceRegister::getService(StoreContext::class) + ); + } + ); + ServiceRegister::registerService( TransactionLogRepositoryInterface::class, static function () { diff --git a/src/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepository.php b/src/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepository.php index f53d33a..e53aaa0 100644 --- a/src/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepository.php +++ b/src/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepository.php @@ -2,10 +2,10 @@ namespace SeQura\Core\BusinessLogic\DataAccess\BannerSettings\Repositories; -use SeQura\Core\BusinessLogic\DataAccess\PromotionalWidgets\Entities\WidgetSettings as WidgetSettingsEntity; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\BannerSettings; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\Multistore\StoreContext; -use SeQura\Core\BusinessLogic\Domain\PromotionalWidgets\Models\WidgetSettings; -use SeQura\Core\BusinessLogic\Domain\PromotionalWidgets\RepositoryContracts\WidgetSettingsRepositoryInterface; +use SeQura\Core\BusinessLogic\DataAccess\BannerSettings\Entities\BannerSettings as BannerSettingsEntity; use SeQura\Core\Infrastructure\ORM\Exceptions\QueryFilterInvalidParamException; use SeQura\Core\Infrastructure\ORM\Interfaces\RepositoryInterface; use SeQura\Core\Infrastructure\ORM\QueryFilter\Operators; @@ -16,10 +16,10 @@ * * @package SeQura\Core\BusinessLogic\DataAccess\BannerSettings\Repositories */ -class BannerSettingsRepository implements WidgetSettingsRepositoryInterface +class BannerSettingsRepository implements BannerSettingsRepositoryInterface { /** - * @var RepositoryInterface Widget settings repository. + * @var RepositoryInterface Banner settings repository. */ protected $repository; @@ -41,63 +41,61 @@ public function __construct(RepositoryInterface $repository, StoreContext $store /** * @inheritDoc */ - public function setWidgetSettings(WidgetSettings $settings): void + public function setBannerSettings(BannerSettings $settings): void { - $existingWidgetSettings = $this->getWidgetSettingsEntity(); + $bannerSettingsEntity = $this->getBannerSettingsEntity(); - if ($existingWidgetSettings) { - $existingWidgetSettings->setWidgetSettings($settings); - $existingWidgetSettings->setStoreId($this->storeContext->getStoreId()); - $this->repository->update($existingWidgetSettings); + if ($bannerSettingsEntity) { + $bannerSettingsEntity->setBannerSettings($settings); + $bannerSettingsEntity->setStoreId($this->storeContext->getStoreId()); + $this->repository->update($bannerSettingsEntity); return; } - $entity = new WidgetSettingsEntity(); + $entity = new BannerSettingsEntity(); $entity->setStoreId($this->storeContext->getStoreId()); - $entity->setWidgetSettings($settings); + $entity->setBannerSettings($settings); $this->repository->save($entity); } /** * @inheritDoc */ - public function getWidgetSettings(): ?WidgetSettings + public function getBannerSettings(): ?BannerSettings { - $entity = $this->getWidgetSettingsEntity(); + $entity = $this->getBannerSettingsEntity(); - return $entity ? $entity->getWidgetSettings() : null; + return $entity ? $entity->getBannerSettings() : null; } /** - * @return void - * - * @throws QueryFilterInvalidParamException + * @inheritDoc */ - public function deleteWidgetSettings(): void + public function deleteBannerSettings(): void { - $entity = $this->getWidgetSettingsEntity(); + $entity = $this->getBannerSettingsEntity(); $entity && $this->repository->delete($entity); } /** - * Gets the widget settings entity from the database. + * Gets the banner settings entity from the database. * - * @return WidgetSettingsEntity|null + * @return BannerSettingsEntity|null * * @throws QueryFilterInvalidParamException */ - protected function getWidgetSettingsEntity(): ?WidgetSettingsEntity + protected function getBannerSettingsEntity(): ?BannerSettingsEntity { $queryFilter = new QueryFilter(); $queryFilter->where('storeId', Operators::EQUALS, $this->storeContext->getStoreId()); /** - * @var WidgetSettingsEntity $widgetSettings + * @var BannerSettingsEntity $bannerSettings */ - $widgetSettings = $this->repository->selectOne($queryFilter); + $bannerSettings = $this->repository->selectOne($queryFilter); - return $widgetSettings; + return $bannerSettings; } } diff --git a/src/BusinessLogic/Domain/BannerSettings/RepositoryContracts/BannerSettingsRepositoryInterface.php b/src/BusinessLogic/Domain/BannerSettings/RepositoryContracts/BannerSettingsRepositoryInterface.php index e3648d2..da4ec2b 100644 --- a/src/BusinessLogic/Domain/BannerSettings/RepositoryContracts/BannerSettingsRepositoryInterface.php +++ b/src/BusinessLogic/Domain/BannerSettings/RepositoryContracts/BannerSettingsRepositoryInterface.php @@ -36,6 +36,8 @@ public function getBannerSettings(): ?BannerSettings; * Deletes banner settings. * * @return void + * + * @throws Exception */ public function deleteBannerSettings(): void; } From e19cf189fe4d1573ebfc407c906f92574b1c61a2 Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Thu, 30 Apr 2026 17:37:46 +0200 Subject: [PATCH 04/18] Add unit tests LIS-111 --- src/BusinessLogic/AdminAPI/AdminAPI.php | 16 +++ src/BusinessLogic/BootstrapComponent.php | 20 +++ .../Services/BannerSettingsService.php | 4 - .../BannerSettingsControllerTest.php | 129 ++++++++++++++++++ tests/BusinessLogic/Common/BaseTestCase.php | 26 ++++ 5 files changed, 191 insertions(+), 4 deletions(-) create mode 100644 tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php diff --git a/src/BusinessLogic/AdminAPI/AdminAPI.php b/src/BusinessLogic/AdminAPI/AdminAPI.php index 4e41273..18d3301 100644 --- a/src/BusinessLogic/AdminAPI/AdminAPI.php +++ b/src/BusinessLogic/AdminAPI/AdminAPI.php @@ -4,6 +4,7 @@ use SeQura\Core\BusinessLogic\AdminAPI\Aspects\ErrorHandlingAspect; use SeQura\Core\BusinessLogic\AdminAPI\Aspects\StoreContextAspect; +use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\BannerSettingsController; use SeQura\Core\BusinessLogic\AdminAPI\Connection\ConnectionController; use SeQura\Core\BusinessLogic\AdminAPI\CountryConfiguration\CountryConfigurationController; use SeQura\Core\BusinessLogic\AdminAPI\Deployments\DeploymentsController; @@ -98,6 +99,21 @@ public function widgetConfiguration(string $storeId): Aspects ->beforeEachMethodOfService(PromotionalWidgetsController::class); } + /** + * Returns a BannerSettingsController instance. + * + * @param string $storeId + * + * @return Aspects + */ + public function bannerSettings(string $storeId): Aspects + { + return Aspects + ::run(new ErrorHandlingAspect()) + ->andRun(new StoreContextAspect($storeId)) + ->beforeEachMethodOfService(BannerSettingsController::class); + } + /** * Returns a PaymentMethodsController instance. * diff --git a/src/BusinessLogic/BootstrapComponent.php b/src/BusinessLogic/BootstrapComponent.php index dc4890e..19e1630 100644 --- a/src/BusinessLogic/BootstrapComponent.php +++ b/src/BusinessLogic/BootstrapComponent.php @@ -2,6 +2,7 @@ namespace SeQura\Core\BusinessLogic; +use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\BannerSettingsController; use SeQura\Core\BusinessLogic\AdminAPI\Connection\ConnectionController; use SeQura\Core\BusinessLogic\AdminAPI\CountryConfiguration\CountryConfigurationController; use SeQura\Core\BusinessLogic\AdminAPI\Deployments\DeploymentsController; @@ -64,6 +65,7 @@ use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Services\AdvancedLoggerSettingsProvider; use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Services\AdvancedSettingsService; use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; use SeQura\Core\Infrastructure\Logger\Interfaces\LoggerSettingsProviderInterface; use SeQura\Core\BusinessLogic\Domain\Connection\ProxyContracts\ConnectionProxyInterface; use SeQura\Core\BusinessLogic\Domain\Connection\RepositoryContracts\ConnectionDataRepositoryInterface; @@ -580,6 +582,15 @@ static function () { } ); + ServiceRegister::registerService( + BannerSettingsService::class, + static function () { + return new BannerSettingsService( + ServiceRegister::getService(BannerSettingsRepositoryInterface::class) + ); + } + ); + ServiceRegister::registerService( TransactionLogService::class, static function () { @@ -745,6 +756,15 @@ static function () { } ); + ServiceRegister::registerService( + BannerSettingsController::class, + static function () { + return new BannerSettingsController( + ServiceRegister::getService(BannerSettingsService::class) + ); + } + ); + ServiceRegister::registerService( TransactionLogsController::class, static function () { diff --git a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php index 1da3637..be84e6f 100644 --- a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php +++ b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php @@ -7,10 +7,6 @@ use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\Banner; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\BannerSettings; use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; -use SeQura\Core\BusinessLogic\Domain\Connection\Services\ConnectionService; -use SeQura\Core\BusinessLogic\Domain\Connection\Services\CredentialsService; -use SeQura\Core\BusinessLogic\Domain\Deployments\Services\DeploymentsService; -use SeQura\Core\BusinessLogic\Domain\PaymentMethod\Services\PaymentMethodsService; /** * Class BannerSettingsService diff --git a/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php b/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php new file mode 100644 index 0000000..cb041ec --- /dev/null +++ b/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php @@ -0,0 +1,129 @@ +bannerSettingsRepository = TestServiceRegister::getService(BannerSettingsRepositoryInterface::class); + } + + public function testGetSettings() + { + // arrange + $settings = new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/image.jpg' + ), + new Banner( + 'PT', + 'displayOnCartPage', + 'https://www.sequra.com/it/faq#shoppers', + 'https://shop/sequra/pt/image.jpg' + ) + ] + ); + StoreContext::doWithStore('store1', [$this->bannerSettingsRepository, 'setBannerSettings'], [$settings]); + + // act + $result = AdminAPI::get()->bannerSettings('store1')->getBannerSettings(); + + // assert + self::assertEquals( + [ + 'bannerConfigs' => [ + [ + 'country' => $settings->getBannerConfigs()[0]->getCountry(), + 'linkUrl' => $settings->getBannerConfigs()[0]->getLinkUrl(), + 'imageUrl' => $settings->getBannerConfigs()[0]->getImageUrl(), + 'displayLocation' => $settings->getBannerConfigs()[0]->getDisplayLocation() + ], + [ + 'country' => $settings->getBannerConfigs()[1]->getCountry(), + 'linkUrl' => $settings->getBannerConfigs()[1]->getLinkUrl(), + 'imageUrl' => $settings->getBannerConfigs()[1]->getImageUrl(), + 'displayLocation' => $settings->getBannerConfigs()[1]->getDisplayLocation() + ] + ] + ], + $result->toArray() + ); + } + + public function testSetSettings() + { + // arrange + $settings = new BannerSettingsRequest( + [ + [ + 'country' => 'ES', + 'displayLocation' => 'displayOnHomePage', + 'linkUrl' => 'https://www.sequra.com/es/faq#shoppers', + 'imageUrl' => 'https://shop/sequra/es/image.jpg' + ], + [ + 'country' => 'PT', + 'displayLocation' => 'displayOnCartPage', + 'linkUrl' => 'https://www.sequra.com/it/faq#shoppers', + 'imageUrl' => 'https://shop/sequra/pt/image.jpg' + ], + ] + ); + + // act + AdminAPI::get()->bannerSettings('store1')->setBannerSettings($settings); + + // assert + $savedSettings = StoreContext::doWithStore('store1', [$this->bannerSettingsRepository, 'getBannerSettings']); + self::assertEquals($settings->transformToDomainModel(), $savedSettings); + } + + public function testSetSettingsInvalidURL() + { + // arrange + $settings = new BannerSettingsRequest( + [ + [ + 'country' => 'ES', + 'displayLocation' => 'displayOnHomePage', + 'linkUrl' => 'https://www.sequra.com/es/faq#shoppers', + 'imageUrl' => 'https://shop/sequra/es/image.jpg' + ], + [ + 'country' => 'PT', + 'displayLocation' => 'displayOnCartPage', + 'linkUrl' => 'string', + 'imageUrl' => 'https://shop/sequra/pt/image.jpg' + ], + ] + ); + + // act + AdminAPI::get()->bannerSettings('store1')->setBannerSettings($settings); + + // assert + $savedSettings = StoreContext::doWithStore('store1', [$this->bannerSettingsRepository, 'getBannerSettings']); + self::assertNull($savedSettings); + } +} diff --git a/tests/BusinessLogic/Common/BaseTestCase.php b/tests/BusinessLogic/Common/BaseTestCase.php index 415bf31..b27a798 100644 --- a/tests/BusinessLogic/Common/BaseTestCase.php +++ b/tests/BusinessLogic/Common/BaseTestCase.php @@ -3,6 +3,7 @@ namespace SeQura\Core\Tests\BusinessLogic\Common; use PHPUnit\Framework\TestCase; +use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\BannerSettingsController; use SeQura\Core\BusinessLogic\AdminAPI\Connection\ConnectionController; use SeQura\Core\BusinessLogic\AdminAPI\CountryConfiguration\CountryConfigurationController; use SeQura\Core\BusinessLogic\AdminAPI\Deployments\DeploymentsController; @@ -35,6 +36,8 @@ use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\WidgetSettings\GetWidgetSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\WidgetSettings\SaveWidgetSettingsHandler; use SeQura\Core\BusinessLogic\DataAccess\AdvancedSettings\Entities\AdvancedSettings; +use SeQura\Core\BusinessLogic\DataAccess\BannerSettings\Entities\BannerSettings; +use SeQura\Core\BusinessLogic\DataAccess\BannerSettings\Repositories\BannerSettingsRepository; use SeQura\Core\BusinessLogic\DataAccess\ConnectionData\Entities\ConnectionData; use SeQura\Core\BusinessLogic\DataAccess\ConnectionData\Repositories\ConnectionDataRepository; use SeQura\Core\BusinessLogic\DataAccess\CountryConfiguration\Entities\CountryConfiguration; @@ -57,6 +60,8 @@ use SeQura\Core\BusinessLogic\DataAccess\TransactionLog\Entities\TransactionLog; use SeQura\Core\BusinessLogic\DataAccess\TransactionLog\Repositories\TransactionLogRepository; use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Services\AdvancedSettingsService; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; use SeQura\Core\BusinessLogic\Domain\Connection\ProxyContracts\ConnectionProxyInterface; use SeQura\Core\BusinessLogic\Domain\Connection\RepositoryContracts\ConnectionDataRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\Connection\RepositoryContracts\CredentialsRepositoryInterface; @@ -139,8 +144,10 @@ use SeQura\Core\Infrastructure\Logger\Logger; use SeQura\Core\Infrastructure\Logger\LoggerConfiguration; use SeQura\Core\Infrastructure\ORM\Exceptions\RepositoryClassException; +use SeQura\Core\Infrastructure\ORM\RepositoryRegistry; use SeQura\Core\Infrastructure\Serializer\Concrete\JsonSerializer; use SeQura\Core\Infrastructure\Serializer\Serializer; +use SeQura\Core\Infrastructure\ServiceRegister; use SeQura\Core\Infrastructure\TaskExecution\Events\QueueItemStateTransitionEventBus; use SeQura\Core\Infrastructure\TaskExecution\Interfaces\TaskRunnerWakeup; use SeQura\Core\Infrastructure\TaskExecution\QueueItem; @@ -445,6 +452,14 @@ protected function setUp(): void TestServiceRegister::getService(StoreContext::class) ); }, + + BannerSettingsRepositoryInterface::class => function () { + return new BannerSettingsRepository( + TestRepositoryRegistry::getRepository(BannerSettings::getClassName()), + TestServiceRegister::getService(StoreContext::class) + ); + }, + PaymentMethodRepositoryInterface::class => function () { return new PaymentMethodRepository( TestRepositoryRegistry::getRepository(PaymentMethod::getClassName()), @@ -481,6 +496,11 @@ protected function setUp(): void TestServiceRegister::getService(DeploymentsService::class) ); }, + BannerSettingsService::class => function () { + return new BannerSettingsService( + TestServiceRegister::getService(BannerSettingsRepositoryInterface::class) + ); + }, ProductServiceInterface::class => function () { return new MockProductService(); }, @@ -495,6 +515,11 @@ protected function setUp(): void TestServiceRegister::getService(WidgetSettingsService::class) ); }, + BannerSettingsController::class => function () { + return new BannerSettingsController( + TestServiceRegister::getService(BannerSettingsService::class) + ); + }, AbstractItemFactory::class => function () { return new ItemFactory(); }, @@ -963,6 +988,7 @@ static function () { MemoryRepository::getClassName() ); TestRepositoryRegistry::registerRepository(WidgetSettings::getClassName(), MemoryRepository::getClassName()); + TestRepositoryRegistry::registerRepository(BannerSettings::getClassName(), MemoryRepository::getClassName()); TestRepositoryRegistry::registerRepository( TransactionLog::getClassName(), MemoryRepositoryWithConditionalDelete::getClassName() From 7787cc27eede8fd7893302d4c463c72a855e89c5 Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Mon, 4 May 2026 14:34:07 +0200 Subject: [PATCH 05/18] Add unit tests LIS-111 --- .../BannerSettingsControllerTest.php | 22 +- .../MockBannerSettingsRepository.php | 34 +++ .../BannerSettingsRepositoryTest.php | 175 +++++++++++ .../Service/BannerSettingsServiceTest.php | 288 ++++++++++++++++++ 4 files changed, 516 insertions(+), 3 deletions(-) create mode 100644 tests/BusinessLogic/Common/MockComponents/MockBannerSettingsRepository.php create mode 100644 tests/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepositoryTest.php create mode 100644 tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php diff --git a/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php b/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php index cb041ec..2c74124 100644 --- a/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php +++ b/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php @@ -2,6 +2,7 @@ namespace SeQura\Core\Tests\BusinessLogic\AdminAPI\BannerSettings; +use Exception; use SeQura\Core\BusinessLogic\AdminAPI\AdminAPI; use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Requests\BannerSettingsRequest; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\Banner; @@ -25,7 +26,12 @@ protected function setUp(): void $this->bannerSettingsRepository = TestServiceRegister::getService(BannerSettingsRepositoryInterface::class); } - public function testGetSettings() + /** + * @return void + * + * @throws Exception + */ + public function testGetSettings(): void { // arrange $settings = new BannerSettings( @@ -71,7 +77,12 @@ public function testGetSettings() ); } - public function testSetSettings() + /** + * @return void + * + * @throws Exception + */ + public function testSetSettings(): void { // arrange $settings = new BannerSettingsRequest( @@ -99,7 +110,12 @@ public function testSetSettings() self::assertEquals($settings->transformToDomainModel(), $savedSettings); } - public function testSetSettingsInvalidURL() + /** + * @return void + * + * @throws Exception + */ + public function testSetSettingsInvalidURL(): void { // arrange $settings = new BannerSettingsRequest( diff --git a/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsRepository.php b/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsRepository.php new file mode 100644 index 0000000..ff34d22 --- /dev/null +++ b/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsRepository.php @@ -0,0 +1,34 @@ +settings = $settings; + } + + public function getBannerSettings(): ?BannerSettings + { + return $this->settings; + } + + public function deleteBannerSettings(): void + { + $this->settings = null; + } +} diff --git a/tests/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepositoryTest.php b/tests/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepositoryTest.php new file mode 100644 index 0000000..0791207 --- /dev/null +++ b/tests/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepositoryTest.php @@ -0,0 +1,175 @@ +repository = TestRepositoryRegistry::getRepository(BannerSettingEntity::getClassName()); + $this->bannerSettingsRepository = new BannerSettingsRepository( + $this->repository, + StoreContext::getInstance() + ); + + TestServiceRegister::registerService(BannerSettingsRepositoryInterface::class, function () { + return $this->bannerSettingsRepository; + }); + } + + /** + * @return void + * + * @throws Exception + */ + public function testGetBannerSettings(): void + { + // arrange + $bannerSettings = new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/image.jpg' + ), + new Banner( + 'PT', + 'displayOnCartPage', + 'https://www.sequra.com/it/faq#shoppers', + 'https://shop/sequra/pt/image.jpg' + ) + ] + ); + + $entity = new BannerSettingEntity(); + $entity->setStoreId('1'); + $entity->setBannerSettings($bannerSettings); + $this->repository->save($entity); + + // act + StoreContext::doWithStore( + '1', + [$this->bannerSettingsRepository, 'getBannerSettings'] + ); + + // assert + /** @var BannerSettingEntity[] $result */ + $result = $this->repository->select(); + + self::assertCount(1, $result); + self::assertEquals($bannerSettings, $result[0]->getBannerSettings()); + } + + /** + * @return void + * + * @throws Exception + */ + public function testSetBannerSettings(): void + { + // arrange + $bannerSettings = new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.com/es/faq#shoppers', + '' + ), + new Banner( + 'PT', + 'displayOnCartPage', + '', + 'https://shop/sequra/pt/image.jpg' + ) + ] + ); + + // act + StoreContext::doWithStore( + '1', + [$this->bannerSettingsRepository, 'setBannerSettings'], + [$bannerSettings] + ); + + // assert + /** @var BannerSettingEntity[] $result */ + $result = $this->repository->select(); + + self::assertCount(1, $result); + self::assertEquals($result[0]->getBannerSettings(), $bannerSettings); + } + + /** + * @throws Exception + */ + public function testDeleteBannerSettings(): void + { + // arrange + $bannerSettings = new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/image.jpg' + ), + new Banner( + 'PT', + 'displayOnCartPage', + 'https://www.sequra.com/it/faq#shoppers', + 'https://shop/sequra/pt/image.jpg' + ) + ] + ); + + $entity = new BannerSettingEntity(); + $entity->setStoreId('1'); + $entity->setBannerSettings($bannerSettings); + $this->repository->save($entity); + + // act + StoreContext::doWithStore( + '1', + [$this->bannerSettingsRepository, 'deleteBannerSettings'] + ); + + // assert + $result = $this->repository->select(); + self::assertCount(0, $result); + } +} diff --git a/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php b/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php new file mode 100644 index 0000000..51b4158 --- /dev/null +++ b/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php @@ -0,0 +1,288 @@ +bannerSettingsRepository = new MockBannerSettingsRepository(); + $this->bannerSettingsService = new BannerSettingsService($this->bannerSettingsRepository); + } + + /** + * @return void + * + * @throws Exception + */ + public function testGetBannerSettingsNoSettings(): void + { + //Arrange + + //Act + $result = $this->bannerSettingsService->getBannerSettings(); + + //Assert + self::assertNull($result); + } + + /** + * @throws Exception + */ + public function testGetBannerSettings(): void + { + //Arrange + $bannerSettings = new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/image.jpg' + ), + new Banner( + 'PT', + 'displayOnCartPage', + 'https://www.sequra.com/it/faq#shoppers', + 'https://shop/sequra/pt/image.jpg' + ) + ] + ); + $this->bannerSettingsRepository->setBannerSettings($bannerSettings); + + //Act + $result = $this->bannerSettingsService->getBannerSettings(); + + //Assert + self::assertNotNull($result); + self::assertCount(2, $result->getBannerConfigs()); + self::assertEquals('PT', $result->getBannerConfigs()[1]->getCountry()); + } + + /** + * @return void + * + * @throws Exception + */ + public function testSetBannerSettingsNoSettingsInDB(): void + { + //Arrange + $bannerSettings = new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/image.jpg' + ), + new Banner( + 'PT', + 'displayOnCartPage', + 'https://www.sequra.com/it/faq#shoppers', + 'https://shop/sequra/pt/image.jpg' + ) + ] + ); + //Act + $this->bannerSettingsService->setBannerSettings($bannerSettings); + + //Assert + $result = $this->bannerSettingsRepository->getBannerSettings(); + self::assertNotNull($result); + self::assertCount(2, $result->getBannerConfigs()); + self::assertEquals('PT', $result->getBannerConfigs()[1]->getCountry()); + } + + /** + * @return void + * + * @throws Exception + */ + public function testSetBannerSettingsSettingsChanged(): void + { + //Arrange + $bannerSettings = new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/image.jpg' + ), + new Banner( + 'PT', + 'displayOnCartPage', + 'https://www.sequra.com/it/faq#shoppers', + 'https://shop/sequra/pt/image.jpg' + ), + new Banner( + 'FR', + 'displayOnHomePage', + 'https://www.sequra.com/fr/faq#shoppers', + 'https://shop/sequra/fr/image.jpg' + ), + + ] + ); + $this->bannerSettingsRepository->setBannerSettings(new BannerSettings( + [ + new Banner( + 'FR', + 'displayOnHomePage', + 'https://www.sequra.com/fr/faq#shoppers', + 'https://shop/sequra/fr/image.jpg' + ) + ] + )); + + //Act + $this->bannerSettingsService->setBannerSettings($bannerSettings); + + //Assert + $result = $this->bannerSettingsRepository->getBannerSettings(); + + self::assertNotNull($result); + self::assertCount(3, $result->getBannerConfigs()); + self::assertEquals('ES', $result->getBannerConfigs()[0]->getCountry()); + self::assertEquals('PT', $result->getBannerConfigs()[1]->getCountry()); + self::assertEquals('FR', $result->getBannerConfigs()[2]->getCountry()); + } + + /** + * @return void + * + * @throws Exception + */ + public function testSetBannerSettingsInvalidURL(): void + { + //Arrange + $bannerSettings = new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'link', + 'https://shop/sequra/es/image.jpg' + ), + new Banner( + 'PT', + 'displayOnCartPage', + 'https://www.sequra.com/it/faq#shoppers', + 'https://shop/sequra/pt/image.jpg' + ) + ] + ); + + //Assert + $this->expectException(InvalidURLException::class); + + //Act + $this->bannerSettingsService->setBannerSettings($bannerSettings); + } + + /** + * @throws Exception + */ + public function testGetBannerDataByCountry(): void + { + //Arrange + $bannerSettings = new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/image.jpg' + ), + new Banner( + 'PT', + 'displayOnCartPage', + 'https://www.sequra.com/it/faq#shoppers', + 'https://shop/sequra/pt/image.jpg' + ), + new Banner( + 'FR', + 'displayOnHomePage', + 'https://www.sequra.com/fr/faq#shoppers', + 'https://shop/sequra/fr/image.jpg' + ), + + ] + ); + $this->bannerSettingsRepository->setBannerSettings($bannerSettings); + + $country = 'FR'; + + //Act + $result = $this->bannerSettingsService->getBannerData($country); + + //Assert + self::assertNotNull($result); + self::assertEquals($country, $result->getCountry()); + } + + /** + * @throws Exception + */ + public function testGetBannerDataByCountryNoData(): void + { + //Arrange + $bannerSettings = new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/image.jpg' + ), + new Banner( + 'FR', + 'displayOnHomePage', + 'https://www.sequra.com/fr/faq#shoppers', + 'https://shop/sequra/fr/image.jpg' + ), + + ] + ); + $this->bannerSettingsRepository->setBannerSettings($bannerSettings); + + $country = 'PT'; + + //Act + $result = $this->bannerSettingsService->getBannerData($country); + + //Assert + self::assertNull($result); + } +} From 9c80b094ebf2049fffb9e55b4c9730a317b00d83 Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Tue, 5 May 2026 16:40:58 +0200 Subject: [PATCH 06/18] Register new topics and create a webhook handlers LIS-111 --- .../BannerSettingsController.php | 4 +- ...nerResponse.php => InvalidURLResponse.php} | 18 +++---- src/BusinessLogic/BootstrapComponent.php | 46 ++++++++++++++++++ .../GetBannerDisplayLocationsHandler.php | 37 +++++++++++++++ .../GetBannerSettingsHandler.php | 46 ++++++++++++++++++ .../SaveBannerSettingsHandler.php | 47 +++++++++++++++++++ .../Handlers/Enums/Topics.php | 15 ++++++ .../SaveBannerSettingsRequest.php | 24 ++++++++++ .../BannerDisplayLocationsResponse.php | 34 ++++++++++++++ .../BannerSettings/BannerSettingsResponse.php | 35 ++++++++++++++ .../BannerSettings/InvalidURLResponse.php | 43 +++++++++++++++++ .../SaveBannerSettingsResponse.php | 14 ++++++ .../Repositories/BannerSettingsRepository.php | 6 +++ .../BannerSettingsRepositoryInterface.php | 7 --- .../Services/BannerSettingsService.php | 10 ++-- .../Banner/BannerServiceInterface.php | 16 +++++++ 16 files changed, 374 insertions(+), 28 deletions(-) rename src/BusinessLogic/AdminAPI/BannerSettings/Responses/{UnsuccessfulBannerResponse.php => InvalidURLResponse.php} (59%) create mode 100644 src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerDisplayLocationsHandler.php create mode 100644 src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerSettingsHandler.php create mode 100644 src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php create mode 100644 src/BusinessLogic/ConfigurationWebhookAPI/Requests/BannerSettings/SaveBannerSettingsRequest.php create mode 100644 src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerDisplayLocationsResponse.php create mode 100644 src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerSettingsResponse.php create mode 100644 src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/InvalidURLResponse.php create mode 100644 src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/SaveBannerSettingsResponse.php create mode 100644 src/BusinessLogic/Domain/Integration/Banner/BannerServiceInterface.php diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php b/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php index 05bcd68..6c40cda 100644 --- a/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php +++ b/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php @@ -5,8 +5,8 @@ use Exception; use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Requests\BannerSettingsRequest; use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Responses\BannerSettingsResponse; +use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Responses\InvalidURLResponse; use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Responses\SuccessfulBannerResponse; -use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Responses\UnsuccessfulBannerResponse; use SeQura\Core\BusinessLogic\AdminAPI\Response\Response; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\InvalidURLException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; @@ -55,7 +55,7 @@ public function setBannerSettings(BannerSettingsRequest $settingsRequest): Respo try { $this->bannerSettingsService->setBannerSettings($settingsRequest->transformToDomainModel()); } catch (InvalidURLException $e) { - return new UnsuccessfulBannerResponse($e->getMessage()); + return new InvalidURLResponse($e->getMessage()); } return new SuccessfulBannerResponse(); diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/Responses/UnsuccessfulBannerResponse.php b/src/BusinessLogic/AdminAPI/BannerSettings/Responses/InvalidURLResponse.php similarity index 59% rename from src/BusinessLogic/AdminAPI/BannerSettings/Responses/UnsuccessfulBannerResponse.php rename to src/BusinessLogic/AdminAPI/BannerSettings/Responses/InvalidURLResponse.php index 905a5de..062851b 100644 --- a/src/BusinessLogic/AdminAPI/BannerSettings/Responses/UnsuccessfulBannerResponse.php +++ b/src/BusinessLogic/AdminAPI/BannerSettings/Responses/InvalidURLResponse.php @@ -5,11 +5,11 @@ use SeQura\Core\BusinessLogic\AdminAPI\Response\Response; /** - * Class UnsuccessfulBannerResponse + * Class InvalidURLResponse * * @package SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Responses */ -class UnsuccessfulBannerResponse extends Response +class InvalidURLResponse extends Response { /** * @var bool @@ -21,19 +21,12 @@ class UnsuccessfulBannerResponse extends Response */ protected $message = ''; - /** - * @var int - */ - protected $statusCode = 400; - /** * @param string $message - * @param int $statusCode */ - public function __construct(string $message, int $statusCode = 400) + public function __construct(string $message) { $this->message = $message; - $this->statusCode = $statusCode; } /** @@ -42,8 +35,9 @@ public function __construct(string $message, int $statusCode = 400) public function toArray(): array { return [ - 'message' => $this->message, - 'errorCode' => $this->statusCode + 'success' => false, + 'error' => $this->message, + 'errorCode' => 'INVALID_URL' ]; } } diff --git a/src/BusinessLogic/BootstrapComponent.php b/src/BusinessLogic/BootstrapComponent.php index 19e1630..3758e4d 100644 --- a/src/BusinessLogic/BootstrapComponent.php +++ b/src/BusinessLogic/BootstrapComponent.php @@ -20,6 +20,9 @@ use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Controller\ConfigurationWebhookController; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\AdvancedSettings\GetAdvancedSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\AdvancedSettings\SaveAdvancedSettingsHandler; +use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\GetBannerDisplayLocationsHandler; +use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\GetBannerSettingsHandler; +use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\SaveBannerSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\Enums\Topics; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\GeneralSettings\GetGeneralSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\GeneralSettings\SaveGeneralSettingsHandler; @@ -66,6 +69,7 @@ use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Services\AdvancedSettingsService; use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; +use SeQura\Core\BusinessLogic\Domain\Integration\Banner\BannerServiceInterface; use SeQura\Core\Infrastructure\Logger\Interfaces\LoggerSettingsProviderInterface; use SeQura\Core\BusinessLogic\Domain\Connection\ProxyContracts\ConnectionProxyInterface; use SeQura\Core\BusinessLogic\Domain\Connection\RepositoryContracts\ConnectionDataRepositoryInterface; @@ -1039,6 +1043,21 @@ protected static function initTopicHandlers(): void SaveAdvancedSettingsHandler::class ); + TopicHandlerRegistry::register( + Topics::GET_BANNER_SETTINGS, + GetBannerSettingsHandler::class + ); + + TopicHandlerRegistry::register( + Topics::SAVE_BANNER_SETTINGS, + SaveBannerSettingsHandler::class + ); + + TopicHandlerRegistry::register( + Topics::GET_BANNER_DISPLAY_LOCATIONS, + GetBannerDisplayLocationsHandler::class + ); + TopicHandlerRegistry::register( Topics::GET_LOG_CONTENT, GetLogContentHandler::class @@ -1162,6 +1181,33 @@ static function () { } ); + ServiceRegister::registerService( + GetBannerSettingsHandler::class, + static function () { + return new GetBannerSettingsHandler( + ServiceRegister::getService(BannerSettingsService::class) + ); + } + ); + + ServiceRegister::registerService( + SaveBannerSettingsHandler::class, + static function () { + return new SaveBannerSettingsHandler( + ServiceRegister::getService(BannerSettingsService::class) + ); + } + ); + + ServiceRegister::registerService( + GetBannerDisplayLocationsHandler::class, + static function () { + return new GetBannerDisplayLocationsHandler( + ServiceRegister::getService(BannerServiceInterface::class) + ); + } + ); + ServiceRegister::registerService( GetLogContentHandler::class, static function () { diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerDisplayLocationsHandler.php b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerDisplayLocationsHandler.php new file mode 100644 index 0000000..bfe1516 --- /dev/null +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerDisplayLocationsHandler.php @@ -0,0 +1,37 @@ +bannerService = $bannerService; + } + + /** + * @inheritDoc + */ + public function handle(array $payload): Response + { + return new BannerDisplayLocationsResponse($this->bannerService->getBannerDisplayLocations()); + } +} diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerSettingsHandler.php b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerSettingsHandler.php new file mode 100644 index 0000000..a8c99ff --- /dev/null +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerSettingsHandler.php @@ -0,0 +1,46 @@ +bannerSettingsService = $bannerSettingsService; + } + + /** + * @param mixed[] $payload + * + * @return Response + */ + public function handle(array $payload): Response + { + $bannerSettings = $this->bannerSettingsService->getBannerSettings(); + + if (!$bannerSettings) { + return new SuccessResponse(); + } + + return new BannerSettingsResponse($bannerSettings); + } +} diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php new file mode 100644 index 0000000..2426eaa --- /dev/null +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php @@ -0,0 +1,47 @@ +bannerSettingsService = $bannerSettingsService; + } + + /** + * @inheritDoc + */ + public function handle(array $payload): Response + { + $request = SaveBannerSettingsRequest::fromPayload($payload); + try { + $this->bannerSettingsService->setBannerSettings($request->transformToDomainModel()); + } catch (InvalidURLException $e) { + return new InvalidURLResponse($e->getMessage()); + } + + return new SaveWidgetSettingsResponse(); + } +} diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/Enums/Topics.php b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/Enums/Topics.php index 771f900..856df18 100644 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/Enums/Topics.php +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/Enums/Topics.php @@ -45,6 +45,18 @@ interface Topics * @var string */ public const SAVE_ADVANCED_SETTINGS = 'save-advanced-settings'; + /** + * @var string + */ + public const GET_BANNER_SETTINGS = 'get-banner-settings'; + /** + * @var string + */ + public const SAVE_BANNER_SETTINGS = 'save-banner-settings'; + /** + * @var string + */ + public const GET_BANNER_DISPLAY_LOCATIONS = 'get-banner-display-locations'; /** * @var string */ @@ -82,6 +94,9 @@ interface Topics self::SAVE_ORDER_STATUS_SETTINGS, self::GET_ADVANCED_SETTINGS, self::SAVE_ADVANCED_SETTINGS, + self::GET_BANNER_SETTINGS, + self::SAVE_BANNER_SETTINGS, + self::GET_BANNER_DISPLAY_LOCATIONS, self::GET_LOG_CONTENT, self::REMOVE_LOG_CONTENT, self::GET_SHOP_CATEGORIES, diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Requests/BannerSettings/SaveBannerSettingsRequest.php b/src/BusinessLogic/ConfigurationWebhookAPI/Requests/BannerSettings/SaveBannerSettingsRequest.php new file mode 100644 index 0000000..c71888a --- /dev/null +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Requests/BannerSettings/SaveBannerSettingsRequest.php @@ -0,0 +1,24 @@ +bannerDisplayLocations = $bannerDisplayLocations; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return $this->bannerDisplayLocations; + } +} diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerSettingsResponse.php b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerSettingsResponse.php new file mode 100644 index 0000000..035bffa --- /dev/null +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerSettingsResponse.php @@ -0,0 +1,35 @@ +settings = $settings; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return !$this->settings ? [] : $this->settings->toArray(); + } +} diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/InvalidURLResponse.php b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/InvalidURLResponse.php new file mode 100644 index 0000000..37f9ee3 --- /dev/null +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/InvalidURLResponse.php @@ -0,0 +1,43 @@ +message = $message; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'success' => false, + 'error' => $this->message, + 'errorCode' => 'INVALID_URL' + ]; + } +} diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/SaveBannerSettingsResponse.php b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/SaveBannerSettingsResponse.php new file mode 100644 index 0000000..21af060 --- /dev/null +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/SaveBannerSettingsResponse.php @@ -0,0 +1,14 @@ +getBannerConfigs() as $bannerConfig) { $this->assertValidUrl($bannerConfig->getLinkUrl()); + $this->assertValidUrl($bannerConfig->getImageUrl()); } $this->bannerSettingsRepository->setBannerSettings($bannerSettings); @@ -65,8 +63,6 @@ public function setBannerSettings(BannerSettings $bannerSettings): void * @param string $country * * @return Banner|null - * - * @throws Exception */ public function getBannerData(string $country): ?Banner { @@ -90,7 +86,7 @@ public function getBannerData(string $country): ?Banner * * @throws InvalidURLException */ - private function assertValidUrl(string $url): void + protected function assertValidUrl(string $url): void { if (mb_strlen($url) > 2048) { throw new InvalidURLException('URL is too long (max 2048 characters)'); diff --git a/src/BusinessLogic/Domain/Integration/Banner/BannerServiceInterface.php b/src/BusinessLogic/Domain/Integration/Banner/BannerServiceInterface.php new file mode 100644 index 0000000..95c8297 --- /dev/null +++ b/src/BusinessLogic/Domain/Integration/Banner/BannerServiceInterface.php @@ -0,0 +1,16 @@ + Date: Tue, 5 May 2026 16:41:09 +0200 Subject: [PATCH 07/18] Add unit tests LIS-111 --- .../BannerSettingsControllerTest.php | 34 ++- tests/BusinessLogic/Common/BaseTestCase.php | 46 ++++ .../MockComponents/MockBannerService.php | 34 +++ .../MockBannerSettingsService.php | 53 +++++ .../ConfigurationWebhookAPITest.php | 216 ++++++++++++++++++ 5 files changed, 379 insertions(+), 4 deletions(-) create mode 100644 tests/BusinessLogic/Common/MockComponents/MockBannerService.php create mode 100644 tests/BusinessLogic/Common/MockComponents/MockBannerSettingsService.php diff --git a/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php b/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php index 2c74124..b1f5c67 100644 --- a/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php +++ b/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php @@ -5,6 +5,8 @@ use Exception; use SeQura\Core\BusinessLogic\AdminAPI\AdminAPI; use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Requests\BannerSettingsRequest; +use SeQura\Core\BusinessLogic\AdminAPI\Response\Response; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\InvalidURLException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\Banner; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\BannerSettings; use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; @@ -12,6 +14,11 @@ use SeQura\Core\Tests\BusinessLogic\Common\BaseTestCase; use SeQura\Core\Tests\Infrastructure\Common\TestServiceRegister; +/**+ + * Class BannerSettingsControllerTest + * + * @package SeQura\Core\Tests\BusinessLogic\AdminAPI\BannerSettings + */ class BannerSettingsControllerTest extends BaseTestCase { /** @@ -19,11 +26,16 @@ class BannerSettingsControllerTest extends BaseTestCase */ private $bannerSettingsRepository; + /** + * @inheritDoc + */ protected function setUp(): void { parent::setUp(); - $this->bannerSettingsRepository = TestServiceRegister::getService(BannerSettingsRepositoryInterface::class); + $this->bannerSettingsRepository = TestServiceRegister::getService( + BannerSettingsRepositoryInterface::class + ); } /** @@ -106,7 +118,13 @@ public function testSetSettings(): void AdminAPI::get()->bannerSettings('store1')->setBannerSettings($settings); // assert - $savedSettings = StoreContext::doWithStore('store1', [$this->bannerSettingsRepository, 'getBannerSettings']); + $savedSettings = StoreContext::doWithStore( + 'store1', + [ + $this->bannerSettingsRepository, + 'getBannerSettings' + ] + ); self::assertEquals($settings->transformToDomainModel(), $savedSettings); } @@ -136,10 +154,18 @@ public function testSetSettingsInvalidURL(): void ); // act - AdminAPI::get()->bannerSettings('store1')->setBannerSettings($settings); + $result = AdminAPI::get()->bannerSettings('store1')->setBannerSettings($settings); // assert - $savedSettings = StoreContext::doWithStore('store1', [$this->bannerSettingsRepository, 'getBannerSettings']); + self::assertFalse($result->isSuccessful()); + self::assertEquals('INVALID_URL', $result->toArray()['errorCode']); + $savedSettings = StoreContext::doWithStore( + 'store1', + [ + $this->bannerSettingsRepository, + 'getBannerSettings' + ] + ); self::assertNull($savedSettings); } } diff --git a/tests/BusinessLogic/Common/BaseTestCase.php b/tests/BusinessLogic/Common/BaseTestCase.php index b27a798..1412023 100644 --- a/tests/BusinessLogic/Common/BaseTestCase.php +++ b/tests/BusinessLogic/Common/BaseTestCase.php @@ -20,6 +20,9 @@ use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Controller\ConfigurationWebhookController; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\AdvancedSettings\GetAdvancedSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\AdvancedSettings\SaveAdvancedSettingsHandler; +use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\GetBannerDisplayLocationsHandler; +use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\GetBannerSettingsHandler; +use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\SaveBannerSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\Enums\Topics; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\GeneralSettings\GetGeneralSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\GeneralSettings\SaveGeneralSettingsHandler; @@ -77,6 +80,7 @@ use SeQura\Core\BusinessLogic\Domain\GeneralSettings\RepositoryContracts\GeneralSettingsRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\GeneralSettings\Services\CategoryService; use SeQura\Core\BusinessLogic\Domain\GeneralSettings\Services\GeneralSettingsService; +use SeQura\Core\BusinessLogic\Domain\Integration\Banner\BannerServiceInterface; use SeQura\Core\BusinessLogic\Domain\Integration\Category\CategoryServiceInterface; use SeQura\Core\BusinessLogic\Domain\Integration\Log\LogServiceInterface; use SeQura\Core\BusinessLogic\Domain\Integration\Order\MerchantDataProviderInterface; @@ -840,6 +844,33 @@ static function () { } ); + TestServiceRegister::registerService( + GetBannerSettingsHandler::class, + static function () { + return new GetBannerSettingsHandler( + TestServiceRegister::getService(BannerSettingsService::class) + ); + } + ); + + TestServiceRegister::registerService( + SaveBannerSettingsHandler::class, + static function () { + return new SaveBannerSettingsHandler( + TestServiceRegister::getService(BannerSettingsService::class) + ); + } + ); + + TestServiceRegister::registerService( + GetBannerDisplayLocationsHandler::class, + static function () { + return new GetBannerDisplayLocationsHandler( + TestServiceRegister::getService(BannerServiceInterface::class) + ); + } + ); + TestServiceRegister::registerService( GetLogContentHandler::class, static function () { @@ -939,6 +970,21 @@ static function () { SaveAdvancedSettingsHandler::class ); + TopicHandlerRegistry::register( + Topics::GET_BANNER_SETTINGS, + GetBannerSettingsHandler::class + ); + + TopicHandlerRegistry::register( + Topics::SAVE_BANNER_SETTINGS, + SaveBannerSettingsHandler::class + ); + + TopicHandlerRegistry::register( + Topics::GET_BANNER_DISPLAY_LOCATIONS, + GetBannerDisplayLocationsHandler::class + ); + TopicHandlerRegistry::register( Topics::GET_LOG_CONTENT, GetLogContentHandler::class diff --git a/tests/BusinessLogic/Common/MockComponents/MockBannerService.php b/tests/BusinessLogic/Common/MockComponents/MockBannerService.php new file mode 100644 index 0000000..8e79d03 --- /dev/null +++ b/tests/BusinessLogic/Common/MockComponents/MockBannerService.php @@ -0,0 +1,34 @@ +bannerDisplayLocations; + } + + /** + * @param array $bannerDisplayLocations + */ + public function setBannerDisplayLocations(array $bannerDisplayLocations): void + { + $this->bannerDisplayLocations = $bannerDisplayLocations; + } +} diff --git a/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsService.php b/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsService.php new file mode 100644 index 0000000..d0b78f8 --- /dev/null +++ b/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsService.php @@ -0,0 +1,53 @@ +bannerSettings; + } + + /** + * @inheritDoc + */ + public function getBannerData(string $country): ?Banner + { + return + new Banner( + $country, + 'displayOnHomePage', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/image.jpg' + ); + } + + /** + * @inheritDoc + */ + public function setBannerSettings(BannerSettings $bannerSettings): void + { + foreach ($bannerSettings->getBannerConfigs() as $bannerConfig) { + $this->assertValidUrl($bannerConfig->getLinkUrl()); + $this->assertValidUrl($bannerConfig->getImageUrl()); + } + + $this->bannerSettings = $bannerSettings; + } +} diff --git a/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php b/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php index 037c58e..4585941 100644 --- a/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php +++ b/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php @@ -3,8 +3,14 @@ namespace SeQura\Core\Tests\BusinessLogic\ConfigurationWebhookAPI; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\ConfigurationWebhookAPI; +use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\BannerSettings\BannerDisplayLocationsResponse; +use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\BannerSettings\BannerSettingsResponse; use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Models\AdvancedSettings; use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Services\AdvancedSettingsService; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\InvalidURLException; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\Banner; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\BannerSettings; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; use SeQura\Core\BusinessLogic\Domain\Connection\Exceptions\InvalidEnvironmentException; use SeQura\Core\BusinessLogic\Domain\Connection\Models\AuthorizationCredentials; use SeQura\Core\BusinessLogic\Domain\Connection\Models\ConnectionData; @@ -24,6 +30,7 @@ use SeQura\Core\BusinessLogic\Domain\GeneralSettings\RepositoryContracts\GeneralSettingsRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\GeneralSettings\Services\CategoryService; use SeQura\Core\BusinessLogic\Domain\GeneralSettings\Services\GeneralSettingsService; +use SeQura\Core\BusinessLogic\Domain\Integration\Banner\BannerServiceInterface; use SeQura\Core\BusinessLogic\Domain\Integration\Category\CategoryServiceInterface; use SeQura\Core\BusinessLogic\Domain\Integration\Log\LogServiceInterface; use SeQura\Core\BusinessLogic\Domain\Integration\Product\ProductServiceInterface; @@ -55,6 +62,9 @@ use SeQura\Core\Tests\BusinessLogic\Common\BaseTestCase; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockAdvancedSettingsRepository; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockAdvancedSettingsService; +use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockBannerService; +use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockBannerSettingsRepository; +use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockBannerSettingsService; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockCategoryService; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockConnectionProxy; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockConnectionService; @@ -177,6 +187,16 @@ class ConfigurationWebhookAPITest extends BaseTestCase */ private $advancedSettingsService; + /** + * @var MockBannerService $bannerService + */ + private $bannerService; + + /** + * @var MockBannerSettingsService $bannerSettingsService + */ + private $bannerSettingsService; + /** * @var MockCredentialsService */ @@ -346,6 +366,18 @@ function () { return $this->advancedSettingsService; }); + $this->bannerService = new MockBannerService(); + + TestServiceRegister::registerService(BannerServiceInterface::class, function () { + return $this->bannerService; + }); + + $this->bannerSettingsService = new MockBannerSettingsService(new MockBannerSettingsRepository()); + + TestServiceRegister::registerService(BannerSettingsService::class, function () { + return $this->bannerSettingsService; + }); + $this->credentialsService = new MockCredentialsService( new MockConnectionProxy(), new MockCredentialsRepository(), @@ -1746,4 +1778,188 @@ public function testGetAdvancedSettingsResponseNoAdvancedSettings(): void self::assertTrue($response->isSuccessful()); self::assertEmpty($response->toArray()); } + + /** + * @return void + * + * @throws InvalidURLException + */ + public function testSaveBannerSettingsResponse(): void + { + //Arrange + $this->bannerSettingsService->setBannerSettings( + new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.es/es/faq#shoppers', + 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png' + ) + ] + ) + ); + + //Act + $response = ConfigurationWebhookAPI::configurationHandler()->handleRequest( + $this->signature, + [ + "topic" => "save-banner-settings", + "bannerConfigs" => [ + [ + 'country' => 'ES', + 'imageUrl' => 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png', + 'linkUrl' => 'https://www.sequra.es/es/faq#shoppers', + 'displayLocation' => 'displayOnHomePage' + ], + [ + 'country' => 'PT', + 'imageUrl' => 'https://shop/img/sequra/pt/banner/Flag_of_Spain.svg.png', + 'linkUrl' => 'https://www.sequra.pt/pt/faq#shoppers', + 'displayLocation' => 'displayOnCartPage' + ], + ] + ] + ); + + //Assert + self::assertTrue($response->isSuccessful()); + self::assertEmpty($response->toArray()); + self::assertCount(2, $this->bannerSettingsService->getBannerSettings()->getBannerConfigs()); + } + + + /** + * @return void + * + * @throws InvalidURLException + */ + public function testSaveBannerSettingsInvalidURLResponse(): void + { + //Arrange + $this->bannerSettingsService->setBannerSettings( + new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.es/es/faq#shoppers', + 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png' + ) + ] + ) + ); + + //Act + $response = ConfigurationWebhookAPI::configurationHandler()->handleRequest( + $this->signature, + [ + "topic" => "save-banner-settings", + "bannerConfigs" => [ + [ + 'country' => 'ES', + 'imageUrl' => 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png', + 'linkUrl' => 'string', + 'displayLocation' => 'displayOnHomePage' + ], + [ + 'country' => 'PT', + 'imageUrl' => 'https://shop/img/sequra/pt/banner/Flag_of_Spain.svg.png', + 'linkUrl' => 'https://www.sequra.pt/pt/faq#shoppers', + 'displayLocation' => 'displayOnCartPage' + ], + ] + ] + ); + + //Assert + self::assertFalse($response->isSuccessful()); + self::assertEquals('INVALID_URL', $response->toArray()['errorCode']); + self::assertCount(1, $this->bannerSettingsService->getBannerSettings()->getBannerConfigs()); + } + + /** + * @return void + * + * @throws InvalidURLException + */ + public function testGetBannerSettingsResponse(): void + { + //Arrange + $this->bannerSettingsService->setBannerSettings( + new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.es/es/faq#shoppers', + 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png' + ) + ] + ) + ); + + //Act + /** @var BannerSettingsResponse $response */ + $response = ConfigurationWebhookAPI::configurationHandler()->handleRequest( + $this->signature, + [ + "topic" => "get-banner-settings" + ] + ); + + //Assert + self::assertTrue($response->isSuccessful()); + self::assertCount(1, $response->toArray()['bannerConfigs']); + } + + /** + * @return void + * + * @throws InvalidURLException + */ + public function testGetBannerSettingsEmptyResponse(): void + { + //Arrange + + //Act + /** @var BannerSettingsResponse $response */ + $response = ConfigurationWebhookAPI::configurationHandler()->handleRequest( + $this->signature, + [ + "topic" => "get-banner-settings" + ] + ); + + //Assert + self::assertTrue($response->isSuccessful()); + self::assertEmpty($response->toArray()); + } + + /** + * @return void + */ + public function testGetBannerDisplayLocations(): void + { + //Arrange + $this->bannerService->setBannerDisplayLocations([ + 'displayOnHomePage', + 'displayOnProductPage', + 'displayOnCartPage', + 'displayOnProductListingPage' + ]); + + //Act + /** @var BannerDisplayLocationsResponse $response */ + $response = ConfigurationWebhookAPI::configurationHandler()->handleRequest( + $this->signature, + [ + "topic" => "get-banner-display-locations" + ] + ); + + //Assert + self::assertTrue($response->isSuccessful()); + self::assertCount(4, $response->toArray()); + } } From f43236372dfb4f180edecc1ea88526986c6d9182 Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Wed, 6 May 2026 12:07:29 +0200 Subject: [PATCH 08/18] Fix error responses in integration webhooks LIS-111 --- .../BannerSettingsController.php | 4 +- .../Responses/InvalidURLResponse.php | 43 ------------------- .../BannerSettings/InvalidURLResponse.php | 3 +- .../Responses/TopicMissingErrorResponse.php | 3 +- .../Responses/UnknownTopicErrorResponse.php | 3 +- .../Exceptions/InvalidURLException.php | 4 ++ .../BannerSettingsControllerTest.php | 6 ++- .../ConfigurationWebhookAPITest.php | 11 ++--- 8 files changed, 20 insertions(+), 57 deletions(-) delete mode 100644 src/BusinessLogic/AdminAPI/BannerSettings/Responses/InvalidURLResponse.php diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php b/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php index 6c40cda..47573fa 100644 --- a/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php +++ b/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php @@ -5,8 +5,8 @@ use Exception; use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Requests\BannerSettingsRequest; use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Responses\BannerSettingsResponse; -use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Responses\InvalidURLResponse; use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Responses\SuccessfulBannerResponse; +use SeQura\Core\BusinessLogic\AdminAPI\Response\ErrorResponse; use SeQura\Core\BusinessLogic\AdminAPI\Response\Response; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\InvalidURLException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; @@ -55,7 +55,7 @@ public function setBannerSettings(BannerSettingsRequest $settingsRequest): Respo try { $this->bannerSettingsService->setBannerSettings($settingsRequest->transformToDomainModel()); } catch (InvalidURLException $e) { - return new InvalidURLResponse($e->getMessage()); + return new ErrorResponse($e); } return new SuccessfulBannerResponse(); diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/Responses/InvalidURLResponse.php b/src/BusinessLogic/AdminAPI/BannerSettings/Responses/InvalidURLResponse.php deleted file mode 100644 index 062851b..0000000 --- a/src/BusinessLogic/AdminAPI/BannerSettings/Responses/InvalidURLResponse.php +++ /dev/null @@ -1,43 +0,0 @@ -message = $message; - } - - /** - * @inheritDoc - */ - public function toArray(): array - { - return [ - 'success' => false, - 'error' => $this->message, - 'errorCode' => 'INVALID_URL' - ]; - } -} diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/InvalidURLResponse.php b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/InvalidURLResponse.php index 37f9ee3..7e673b2 100644 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/InvalidURLResponse.php +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/InvalidURLResponse.php @@ -35,8 +35,7 @@ public function __construct(string $message) public function toArray(): array { return [ - 'success' => false, - 'error' => $this->message, + 'errorMessage' => $this->message, 'errorCode' => 'INVALID_URL' ]; } diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/TopicMissingErrorResponse.php b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/TopicMissingErrorResponse.php index 3ad12ec..5ce23be 100644 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/TopicMissingErrorResponse.php +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/TopicMissingErrorResponse.php @@ -22,8 +22,7 @@ class TopicMissingErrorResponse extends Response public function toArray(): array { return [ - 'success' => false, - 'error' => 'Topic field is required in the webhook payload.', + 'errorMessage' => 'Topic field is required in the webhook payload.', 'errorCode' => 'TOPIC_MISSING' ]; } diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/UnknownTopicErrorResponse.php b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/UnknownTopicErrorResponse.php index 104204d..acddc95 100644 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/UnknownTopicErrorResponse.php +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/UnknownTopicErrorResponse.php @@ -35,8 +35,7 @@ public function __construct(string $topic) public function toArray(): array { return [ - 'success' => false, - 'error' => "Unknown or unsupported topic: {$this->topic}", + 'errorMessage' => "Unknown or unsupported topic: {$this->topic}", 'errorCode' => 'UNKNOWN_TOPIC' ]; } diff --git a/src/BusinessLogic/Domain/BannerSettings/Exceptions/InvalidURLException.php b/src/BusinessLogic/Domain/BannerSettings/Exceptions/InvalidURLException.php index 0833726..50e4742 100644 --- a/src/BusinessLogic/Domain/BannerSettings/Exceptions/InvalidURLException.php +++ b/src/BusinessLogic/Domain/BannerSettings/Exceptions/InvalidURLException.php @@ -11,4 +11,8 @@ */ class InvalidURLException extends BaseException { + /** + * @var int + */ + protected $code = 400; } diff --git a/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php b/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php index b1f5c67..2c749ae 100644 --- a/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php +++ b/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php @@ -158,7 +158,11 @@ public function testSetSettingsInvalidURL(): void // assert self::assertFalse($result->isSuccessful()); - self::assertEquals('INVALID_URL', $result->toArray()['errorCode']); + self::assertEquals([ + 'errorMessage' => 'URL format is invalid', + 'errorCode' => '400' + ], $result->toArray()); + $savedSettings = StoreContext::doWithStore( 'store1', [ diff --git a/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php b/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php index 4585941..8ff4c72 100644 --- a/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php +++ b/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php @@ -421,8 +421,7 @@ public function testTopicMissingResponse(): void //Assert self::assertFalse($response->isSuccessful()); self::assertEquals([ - 'success' => false, - 'error' => 'Topic field is required in the webhook payload.', + 'errorMessage' => 'Topic field is required in the webhook payload.', 'errorCode' => 'TOPIC_MISSING' ], $response->toArray()); } @@ -497,8 +496,7 @@ public function testUnknownTopicError(): void //Assert self::assertFalse($response->isSuccessful()); self::assertEquals([ - 'success' => false, - 'error' => 'Unknown or unsupported topic: get-payment-data', + 'errorMessage' => 'Unknown or unsupported topic: get-payment-data', 'errorCode' => 'UNKNOWN_TOPIC' ], $response->toArray()); } @@ -1874,7 +1872,10 @@ public function testSaveBannerSettingsInvalidURLResponse(): void //Assert self::assertFalse($response->isSuccessful()); - self::assertEquals('INVALID_URL', $response->toArray()['errorCode']); + self::assertEquals([ + 'errorMessage' => 'URL format is invalid', + 'errorCode' => 'INVALID_URL' + ], $response->toArray()); self::assertCount(1, $this->bannerSettingsService->getBannerSettings()->getBannerConfigs()); } From 6e5cca586b77561d93681d9907a6ae3abfa0b3b8 Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Wed, 6 May 2026 16:06:04 +0200 Subject: [PATCH 09/18] Add checkout API endpoint LIS-111 --- composer.lock | 6 +- src/BusinessLogic/BootstrapComponent.php | 10 ++ .../Banners/BannerCheckoutController.php | 42 +++++++ .../Requests/GetBannerForLocationRequest.php | 73 ++++++++++++ .../GetBannerForLocationResponse.php | 44 +++++++ src/BusinessLogic/CheckoutAPI/CheckoutAPI.php | 14 +++ .../Services/BannerSettingsService.php | 5 +- .../CheckoutAPI/Banners/BannersApiTest.php | 109 ++++++++++++++++++ tests/BusinessLogic/Common/BaseTestCase.php | 6 + .../MockBannerSettingsService.php | 16 +-- .../Service/BannerSettingsServiceTest.php | 52 ++++++++- 11 files changed, 360 insertions(+), 17 deletions(-) create mode 100644 src/BusinessLogic/CheckoutAPI/Banners/BannerCheckoutController.php create mode 100644 src/BusinessLogic/CheckoutAPI/Banners/Requests/GetBannerForLocationRequest.php create mode 100644 src/BusinessLogic/CheckoutAPI/Banners/Responses/GetBannerForLocationResponse.php create mode 100644 tests/BusinessLogic/CheckoutAPI/Banners/BannersApiTest.php diff --git a/composer.lock b/composer.lock index d7ef01c..d40d9db 100644 --- a/composer.lock +++ b/composer.lock @@ -1922,7 +1922,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, "platform": { @@ -1931,9 +1931,9 @@ "ext-ctype": "*", "ext-mbstring": "*" }, - "platform-dev": {}, + "platform-dev": [], "platform-overrides": { "php": "7.2" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.2.0" } diff --git a/src/BusinessLogic/BootstrapComponent.php b/src/BusinessLogic/BootstrapComponent.php index 3758e4d..0e75f56 100644 --- a/src/BusinessLogic/BootstrapComponent.php +++ b/src/BusinessLogic/BootstrapComponent.php @@ -14,6 +14,7 @@ use SeQura\Core\BusinessLogic\AdminAPI\PromotionalWidgets\PromotionalWidgetsController; use SeQura\Core\BusinessLogic\AdminAPI\Store\StoreController; use SeQura\Core\BusinessLogic\AdminAPI\TransactionLogs\TransactionLogsController; +use SeQura\Core\BusinessLogic\CheckoutAPI\Banners\BannerCheckoutController; use SeQura\Core\BusinessLogic\CheckoutAPI\PaymentMethods\CachedPaymentMethodsController; use SeQura\Core\BusinessLogic\CheckoutAPI\PromotionalWidgets\PromotionalWidgetsCheckoutController; use SeQura\Core\BusinessLogic\CheckoutAPI\Solicitation\Controller\SolicitationController; @@ -824,6 +825,15 @@ static function () { } ); + ServiceRegister::registerService( + BannerCheckoutController::class, + static function () { + return new BannerCheckoutController( + ServiceRegister::getService(BannerSettingsService::class) + ); + } + ); + ServiceRegister::registerService( DeploymentsController::class, static function () { diff --git a/src/BusinessLogic/CheckoutAPI/Banners/BannerCheckoutController.php b/src/BusinessLogic/CheckoutAPI/Banners/BannerCheckoutController.php new file mode 100644 index 0000000..ecb8f02 --- /dev/null +++ b/src/BusinessLogic/CheckoutAPI/Banners/BannerCheckoutController.php @@ -0,0 +1,42 @@ +bannerSettingsService = $bannerSettingsService; + } + + /** + * Returns banner data + * + * @param GetBannerForLocationRequest $request + * + * @return GetBannerForLocationResponse + */ + public function getBannerForLocation(GetBannerForLocationRequest $request): GetBannerForLocationResponse + { + return new GetBannerForLocationResponse( + $this->bannerSettingsService->getBannerData($request->getCountry(), $request->getDisplayLocation()) + ); + } +} diff --git a/src/BusinessLogic/CheckoutAPI/Banners/Requests/GetBannerForLocationRequest.php b/src/BusinessLogic/CheckoutAPI/Banners/Requests/GetBannerForLocationRequest.php new file mode 100644 index 0000000..b34ddfb --- /dev/null +++ b/src/BusinessLogic/CheckoutAPI/Banners/Requests/GetBannerForLocationRequest.php @@ -0,0 +1,73 @@ +country = $country; + $this->displayLocation = $displayLocation; + } + + /** + * @return string + */ + public function getCountry(): string + { + return $this->country; + } + + /** + * @return string + */ + public function getDisplayLocation(): string + { + return $this->displayLocation; + } + + /** + * @param array $data + * + * @return self + */ + public static function fromArray(array $data): self + { + return new self( + self::getDataValue($data, 'country'), + self::getDataValue($data, 'displayLocation') + ); + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'country' => $this->country, + 'displayLocation' => $this->displayLocation, + ]; + } +} diff --git a/src/BusinessLogic/CheckoutAPI/Banners/Responses/GetBannerForLocationResponse.php b/src/BusinessLogic/CheckoutAPI/Banners/Responses/GetBannerForLocationResponse.php new file mode 100644 index 0000000..ba111c9 --- /dev/null +++ b/src/BusinessLogic/CheckoutAPI/Banners/Responses/GetBannerForLocationResponse.php @@ -0,0 +1,44 @@ +banner = $banner; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + if ($this->banner === null) { + return []; + } + + return [ + 'country' => $this->banner->getCountry(), + 'displayLocation' => $this->banner->getDisplayLocation(), + 'linkUrl' => $this->banner->getLinkUrl(), + 'imageUrl' => $this->banner->getImageUrl(), + ]; + } +} diff --git a/src/BusinessLogic/CheckoutAPI/CheckoutAPI.php b/src/BusinessLogic/CheckoutAPI/CheckoutAPI.php index f135775..b36f2d6 100644 --- a/src/BusinessLogic/CheckoutAPI/CheckoutAPI.php +++ b/src/BusinessLogic/CheckoutAPI/CheckoutAPI.php @@ -5,6 +5,7 @@ use SeQura\Core\BusinessLogic\AdminAPI\Aspects\ErrorHandlingAspect; use SeQura\Core\BusinessLogic\AdminAPI\Aspects\StoreContextAspect; use SeQura\Core\BusinessLogic\Bootstrap\Aspect\Aspects; +use SeQura\Core\BusinessLogic\CheckoutAPI\Banners\BannerCheckoutController; use SeQura\Core\BusinessLogic\CheckoutAPI\PaymentMethods\CachedPaymentMethodsController; use SeQura\Core\BusinessLogic\CheckoutAPI\PromotionalWidgets\PromotionalWidgetsCheckoutController; use SeQura\Core\BusinessLogic\CheckoutAPI\Solicitation\Controller\SolicitationController; @@ -68,4 +69,17 @@ public function promotionalWidgets(string $storeId): object ->andRun(new StoreContextAspect($storeId)) ->beforeEachMethodOfService(PromotionalWidgetsCheckoutController::class); } + + /** + * @param string $storeId + * + * @return object + */ + public function banners(string $storeId): object + { + return Aspects + ::run(new ErrorHandlingAspect()) + ->andRun(new StoreContextAspect($storeId)) + ->beforeEachMethodOfService(BannerCheckoutController::class); + } } diff --git a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php index bfdf3ad..28105e6 100644 --- a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php +++ b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php @@ -61,10 +61,11 @@ public function setBannerSettings(BannerSettings $bannerSettings): void * Returns banner data * * @param string $country + * @param string $displayLocation * * @return Banner|null */ - public function getBannerData(string $country): ?Banner + public function getBannerData(string $country, string $displayLocation): ?Banner { $bannerSettings = $this->getBannerSettings(); @@ -73,7 +74,7 @@ public function getBannerData(string $country): ?Banner } foreach ($bannerSettings->getBannerConfigs() as $bannerConfig) { - if ($bannerConfig->getCountry() === $country) { + if ($bannerConfig->getCountry() === $country && $bannerConfig->getDisplayLocation() === $displayLocation) { return $bannerConfig; } } diff --git a/tests/BusinessLogic/CheckoutAPI/Banners/BannersApiTest.php b/tests/BusinessLogic/CheckoutAPI/Banners/BannersApiTest.php new file mode 100644 index 0000000..0ecf311 --- /dev/null +++ b/tests/BusinessLogic/CheckoutAPI/Banners/BannersApiTest.php @@ -0,0 +1,109 @@ +mockBannerSettingsService = new MockBannerSettingsService( + TestServiceRegister::getService(BannerSettingsRepositoryInterface::class) + ); + + TestServiceRegister::registerService( + BannerSettingsService::class, + function () { + return $this->mockBannerSettingsService; + } + ); + } + + /** + * @return void + * + * @throws InvalidURLException + */ + public function testGetBannersDataSuccess(): void + { + //Arrange + $this->mockBannerSettingsService->setBannerSettings( + new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.es/es/faq#shoppers', + 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png' + ) + ] + ) + ); + + //Act + $response = CheckoutAPI::get()->banners('1') + ->getBannerForLocation(new GetBannerForLocationRequest('ES', 'displayOnHomePage')); + + //Assert + self::assertTrue($response->isSuccessful()); + self::assertNotEmpty($response->toArray()); + } + + /** + * @return void + * + * @throws InvalidURLException + */ + public function testGetBannersNoDataSuccess(): void + { + //Arrange + $this->mockBannerSettingsService->setBannerSettings( + new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.es/es/faq#shoppers', + 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png' + ) + ] + ) + ); + + //Act + $response = CheckoutAPI::get()->banners('1') + ->getBannerForLocation(new GetBannerForLocationRequest('ES', 'displayOnCartPage')); + + //Assert + self::assertTrue($response->isSuccessful()); + self::assertEmpty($response->toArray()); + } +} diff --git a/tests/BusinessLogic/Common/BaseTestCase.php b/tests/BusinessLogic/Common/BaseTestCase.php index 1412023..db27da1 100644 --- a/tests/BusinessLogic/Common/BaseTestCase.php +++ b/tests/BusinessLogic/Common/BaseTestCase.php @@ -15,6 +15,7 @@ use SeQura\Core\BusinessLogic\AdminAPI\PromotionalWidgets\PromotionalWidgetsController; use SeQura\Core\BusinessLogic\AdminAPI\Store\StoreController; use SeQura\Core\BusinessLogic\AdminAPI\TransactionLogs\TransactionLogsController; +use SeQura\Core\BusinessLogic\CheckoutAPI\Banners\BannerCheckoutController; use SeQura\Core\BusinessLogic\CheckoutAPI\PaymentMethods\CachedPaymentMethodsController; use SeQura\Core\BusinessLogic\CheckoutAPI\PromotionalWidgets\PromotionalWidgetsCheckoutController; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Controller\ConfigurationWebhookController; @@ -450,6 +451,11 @@ protected function setUp(): void TestServiceRegister::getService(WidgetValidationService::class) ); }, + BannerCheckoutController::class => function () { + return new BannerCheckoutController( + TestServiceRegister::getService(BannerSettingsService::class) + ); + }, WidgetSettingsRepositoryInterface::class => function () { return new WidgetSettingsRepository( TestRepositoryRegistry::getRepository(WidgetSettings::getClassName()), diff --git a/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsService.php b/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsService.php index d0b78f8..a6dacdd 100644 --- a/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsService.php +++ b/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsService.php @@ -27,15 +27,15 @@ public function getBannerSettings(): ?BannerSettings /** * @inheritDoc */ - public function getBannerData(string $country): ?Banner + public function getBannerData(string $country, string $displayLocation): ?Banner { - return - new Banner( - $country, - 'displayOnHomePage', - 'https://www.sequra.com/es/faq#shoppers', - 'https://shop/sequra/es/image.jpg' - ); + foreach ($this->bannerSettings->getBannerConfigs() as $bannerConfig) { + if ($bannerConfig->getCountry() === $country && $bannerConfig->getDisplayLocation() === $displayLocation) { + return $bannerConfig; + } + } + + return null; } /** diff --git a/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php b/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php index 51b4158..8b169d3 100644 --- a/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php +++ b/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php @@ -214,7 +214,7 @@ public function testSetBannerSettingsInvalidURL(): void /** * @throws Exception */ - public function testGetBannerDataByCountry(): void + public function testGetBannerDataByCountryAndDisplayLocation(): void { //Arrange $bannerSettings = new BannerSettings( @@ -243,19 +243,62 @@ public function testGetBannerDataByCountry(): void $this->bannerSettingsRepository->setBannerSettings($bannerSettings); $country = 'FR'; + $displayLocation = 'displayOnHomePage'; //Act - $result = $this->bannerSettingsService->getBannerData($country); + $result = $this->bannerSettingsService->getBannerData($country, $displayLocation); //Assert self::assertNotNull($result); self::assertEquals($country, $result->getCountry()); + self::assertEquals($displayLocation, $result->getDisplayLocation()); } /** * @throws Exception */ - public function testGetBannerDataByCountryNoData(): void + public function testGetBannerNoDataForDisplayLocation(): void + { + //Arrange + $bannerSettings = new BannerSettings( + [ + new Banner( + 'ES', + 'displayOnHomePage', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/image.jpg' + ), + new Banner( + 'PT', + 'displayOnCartPage', + 'https://www.sequra.com/it/faq#shoppers', + 'https://shop/sequra/pt/image.jpg' + ), + new Banner( + 'FR', + 'displayOnHomePage', + 'https://www.sequra.com/fr/faq#shoppers', + 'https://shop/sequra/fr/image.jpg' + ), + + ] + ); + $this->bannerSettingsRepository->setBannerSettings($bannerSettings); + + $country = 'FR'; + $displayLocation = 'displayOnCartPage'; + + //Act + $result = $this->bannerSettingsService->getBannerData($country, $displayLocation); + + //Assert + self::assertNull($result); + } + + /** + * @throws Exception + */ + public function testGetBannerNoDataForCountry(): void { //Arrange $bannerSettings = new BannerSettings( @@ -278,9 +321,10 @@ public function testGetBannerDataByCountryNoData(): void $this->bannerSettingsRepository->setBannerSettings($bannerSettings); $country = 'PT'; + $displayLocation = 'displayOnCartPage'; //Act - $result = $this->bannerSettingsService->getBannerData($country); + $result = $this->bannerSettingsService->getBannerData($country, $displayLocation); //Assert self::assertNull($result); From 881e3f73ba91a95e9288d329fc1e68e759ca3345 Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Mon, 11 May 2026 15:57:57 +0200 Subject: [PATCH 10/18] Change the logic to save image on integration server LIS-111 --- .../BannerSettingsController.php | 21 +- .../Requests/SaveBannerSettingsRequest.php | 11 +- .../Responses/SuccessfulBannerResponse.php | 21 -- src/BusinessLogic/BootstrapComponent.php | 3 +- .../GetBannerSettingsHandler.php | 8 +- .../SaveBannerSettingsHandler.php | 15 +- .../BannerSettings/InvalidURLResponse.php | 42 --- .../SaveBannerSettingsResponse.php | 14 - .../Entities/BannerSettings.php | 4 +- .../BannerImageRequiredException.php | 14 + .../Exceptions/InvalidURLException.php | 8 +- .../Domain/BannerSettings/Models/Banner.php | 49 +++- .../BannerSettings/Models/BannerSettings.php | 15 +- .../Services/BannerSettingsService.php | 164 ++++++++++- .../Banner/BannerServiceInterface.php | 23 ++ .../BannerSettingsControllerTest.php | 31 +- .../CheckoutAPI/Banners/BannersApiTest.php | 8 +- tests/BusinessLogic/Common/BaseTestCase.php | 7 +- .../MockComponents/MockBannerService.php | 55 +++- .../MockBannerSettingsService.php | 18 +- .../ConfigurationWebhookAPITest.php | 29 +- .../BannerSettingsRepositoryTest.php | 24 +- .../Service/BannerSettingsServiceTest.php | 268 +++++++++++++++--- 23 files changed, 628 insertions(+), 224 deletions(-) delete mode 100644 src/BusinessLogic/AdminAPI/BannerSettings/Responses/SuccessfulBannerResponse.php delete mode 100644 src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/InvalidURLResponse.php delete mode 100644 src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/SaveBannerSettingsResponse.php create mode 100644 src/BusinessLogic/Domain/BannerSettings/Exceptions/BannerImageRequiredException.php diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php b/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php index 47573fa..a19650d 100644 --- a/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php +++ b/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php @@ -5,9 +5,7 @@ use Exception; use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Requests\BannerSettingsRequest; use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Responses\BannerSettingsResponse; -use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Responses\SuccessfulBannerResponse; -use SeQura\Core\BusinessLogic\AdminAPI\Response\ErrorResponse; -use SeQura\Core\BusinessLogic\AdminAPI\Response\Response; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\BannerImageRequiredException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\InvalidURLException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; @@ -46,18 +44,15 @@ public function getBannerSettings(): BannerSettingsResponse * * @param BannerSettingsRequest $settingsRequest * - * @return Response + * @return BannerSettingsResponse * - * @throws Exception + * @throws BannerImageRequiredException + * @throws InvalidURLException */ - public function setBannerSettings(BannerSettingsRequest $settingsRequest): Response + public function setBannerSettings(BannerSettingsRequest $settingsRequest): BannerSettingsResponse { - try { - $this->bannerSettingsService->setBannerSettings($settingsRequest->transformToDomainModel()); - } catch (InvalidURLException $e) { - return new ErrorResponse($e); - } - - return new SuccessfulBannerResponse(); + return new BannerSettingsResponse( + $this->bannerSettingsService->setBannerSettings($settingsRequest->transformToDomainModel()) + ); } } diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/Requests/SaveBannerSettingsRequest.php b/src/BusinessLogic/AdminAPI/BannerSettings/Requests/SaveBannerSettingsRequest.php index cbcc05d..baa6880 100644 --- a/src/BusinessLogic/AdminAPI/BannerSettings/Requests/SaveBannerSettingsRequest.php +++ b/src/BusinessLogic/AdminAPI/BannerSettings/Requests/SaveBannerSettingsRequest.php @@ -13,12 +13,12 @@ trait SaveBannerSettingsRequest { /** - * @var array> + * @var array> */ protected $bannerConfigs; /** - * @param array> $bannerConfigs + * @param array> $bannerConfigs */ public function __construct( array $bannerConfigs = [] @@ -37,9 +37,12 @@ public function transformToDomainModel(): object foreach ($this->bannerConfigs as $bannerConfig) { $arrayOfBannerConfigs[] = new Banner( $bannerConfig['country'] ?? '', - $bannerConfig['displayLocation'] ?? '', $bannerConfig['linkUrl'] ?? '', - $bannerConfig['imageUrl'] ?? '' + '', + $bannerConfig['displayLocation'] ?? '', + isset($bannerConfig['imageBase64']) && $bannerConfig['imageBase64'] !== '' + ? $bannerConfig['imageBase64'] + : null ); } diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/Responses/SuccessfulBannerResponse.php b/src/BusinessLogic/AdminAPI/BannerSettings/Responses/SuccessfulBannerResponse.php deleted file mode 100644 index 71f1eb7..0000000 --- a/src/BusinessLogic/AdminAPI/BannerSettings/Responses/SuccessfulBannerResponse.php +++ /dev/null @@ -1,21 +0,0 @@ -bannerSettingsService->getBannerSettings(); - - if (!$bannerSettings) { - return new SuccessResponse(); - } + $bannerSettings = $this->bannerSettingsService->getBannerSettings() ?? new BannerSettings([]); return new BannerSettingsResponse($bannerSettings); } diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php index 2426eaa..44e0276 100644 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php @@ -5,8 +5,8 @@ use SeQura\Core\BusinessLogic\AdminAPI\Response\Response; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\TopicHandlerInterface; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Requests\BannerSettings\SaveBannerSettingsRequest; -use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\BannerSettings\InvalidURLResponse; -use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\WidgetSettings\SaveWidgetSettingsResponse; +use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\BannerSettings\BannerSettingsResponse; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\BannerImageRequiredException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\InvalidURLException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; @@ -32,16 +32,15 @@ public function __construct(BannerSettingsService $bannerSettingsService) /** * @inheritDoc + * + * @throws BannerImageRequiredException + * @throws InvalidURLException */ public function handle(array $payload): Response { $request = SaveBannerSettingsRequest::fromPayload($payload); - try { - $this->bannerSettingsService->setBannerSettings($request->transformToDomainModel()); - } catch (InvalidURLException $e) { - return new InvalidURLResponse($e->getMessage()); - } + $saved = $this->bannerSettingsService->setBannerSettings($request->transformToDomainModel()); - return new SaveWidgetSettingsResponse(); + return new BannerSettingsResponse($saved); } } diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/InvalidURLResponse.php b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/InvalidURLResponse.php deleted file mode 100644 index 7e673b2..0000000 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/InvalidURLResponse.php +++ /dev/null @@ -1,42 +0,0 @@ -message = $message; - } - - /** - * @inheritDoc - */ - public function toArray(): array - { - return [ - 'errorMessage' => $this->message, - 'errorCode' => 'INVALID_URL' - ]; - } -} diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/SaveBannerSettingsResponse.php b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/SaveBannerSettingsResponse.php deleted file mode 100644 index 21af060..0000000 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/SaveBannerSettingsResponse.php +++ /dev/null @@ -1,14 +0,0 @@ -country = $country; - $this->displayLocation = $displayLocation; $this->linkUrl = $linkUrl; $this->imageUrl = $imageUrl; + $this->displayLocation = $displayLocation; + $this->imageBase64 = $imageBase64; } /** @@ -107,4 +117,33 @@ public function setDisplayLocation(string $displayLocation): void { $this->displayLocation = $displayLocation; } + + /** + * @return string|null + */ + public function getImageBase64(): ?string + { + return $this->imageBase64; + } + + /** + * @param string|null $imageBase64 + */ + public function setImageBase64(?string $imageBase64): void + { + $this->imageBase64 = $imageBase64; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'country' => $this->country, + 'linkUrl' => $this->linkUrl, + 'imageUrl' => $this->imageUrl, + 'displayLocation' => $this->displayLocation, + ]; + } } diff --git a/src/BusinessLogic/Domain/BannerSettings/Models/BannerSettings.php b/src/BusinessLogic/Domain/BannerSettings/Models/BannerSettings.php index e279447..284df39 100644 --- a/src/BusinessLogic/Domain/BannerSettings/Models/BannerSettings.php +++ b/src/BusinessLogic/Domain/BannerSettings/Models/BannerSettings.php @@ -45,17 +45,12 @@ public function setBannerConfigs(array $bannerConfigs): void */ public function toArray(): array { - $bannerSettingsArray = []; - - foreach ($this->bannerConfigs as $bannerConfig) { - $bannerSettingsArray['bannerConfigs'][] = [ - 'country' => $bannerConfig->getCountry(), - 'linkUrl' => $bannerConfig->getLinkUrl(), - 'imageUrl' => $bannerConfig->getImageUrl(), - 'displayLocation' => $bannerConfig->getDisplayLocation() - ]; + if (empty($this->bannerConfigs)) { + return []; } - return $bannerSettingsArray; + return [ + 'bannerConfigs' => Banner::toBatchArray($this->bannerConfigs), + ]; } } diff --git a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php index 28105e6..d76d1ca 100644 --- a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php +++ b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php @@ -2,10 +2,13 @@ namespace SeQura\Core\BusinessLogic\Domain\BannerSettings\Services; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\BannerImageRequiredException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\InvalidURLException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\Banner; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\BannerSettings; use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; +use SeQura\Core\BusinessLogic\Domain\Integration\Banner\BannerServiceInterface; +use SeQura\Core\BusinessLogic\Domain\Translations\Model\TranslatableLabel; /** * Class BannerSettingsService @@ -19,13 +22,21 @@ class BannerSettingsService */ protected $bannerSettingsRepository; + /** + * @var BannerServiceInterface + */ + protected $bannerService; + /** * @param BannerSettingsRepositoryInterface $bannerSettingsRepository + * @param BannerServiceInterface $bannerService */ public function __construct( - BannerSettingsRepositoryInterface $bannerSettingsRepository + BannerSettingsRepositoryInterface $bannerSettingsRepository, + BannerServiceInterface $bannerService ) { $this->bannerSettingsRepository = $bannerSettingsRepository; + $this->bannerService = $bannerService; } /** @@ -43,18 +54,42 @@ public function getBannerSettings(): ?BannerSettings * * @param BannerSettings $bannerSettings * - * @return void + * @return BannerSettings * + * @throws BannerImageRequiredException * @throws InvalidURLException */ - public function setBannerSettings(BannerSettings $bannerSettings): void + public function setBannerSettings(BannerSettings $bannerSettings): BannerSettings { - foreach ($bannerSettings->getBannerConfigs() as $bannerConfig) { - $this->assertValidUrl($bannerConfig->getLinkUrl()); - $this->assertValidUrl($bannerConfig->getImageUrl()); + $incomingBanners = $bannerSettings->getBannerConfigs(); + $existingBannerSettings = $this->getBannerSettings(); + $existingBanners = $existingBannerSettings + ? $existingBannerSettings->getBannerConfigs() + : []; + + $existingBannersByKey = $this->indexByKey($existingBanners); + $incomingBannersByKey = $this->indexByKey($incomingBanners); + + $resolvedBanners = []; + + foreach ($incomingBanners as $banner) { + $this->assertValidUrl($banner->getLinkUrl()); + $this->assertBannerHasImageSource($banner, $existingBannersByKey); + + $resolvedBanners[] = $this->resolveBannerImage($banner, $existingBannersByKey); + } + + foreach (array_diff_key($existingBannersByKey, $incomingBannersByKey) as $bannerToRemove) { + $this->bannerService->deleteBannerImage( + $bannerToRemove->getCountry(), + $bannerToRemove->getDisplayLocation() + ); } - $this->bannerSettingsRepository->setBannerSettings($bannerSettings); + $persisted = new BannerSettings($resolvedBanners); + $this->bannerSettingsRepository->setBannerSettings($persisted); + + return $persisted; } /** @@ -82,6 +117,100 @@ public function getBannerData(string $country, string $displayLocation): ?Banner return null; } + /** + * Verifies whether the banner contains an imageBase64 payload + * or already has a persisted image in storage. + * + * @param Banner $banner + * @param array $existingByKey + * + * @throws BannerImageRequiredException + */ + protected function assertBannerHasImageSource(Banner $banner, array $existingByKey): void + { + if ($this->hasImageBase64($banner) || isset($existingByKey[$this->keyFor($banner)])) { + return; + } + + throw new BannerImageRequiredException( + new TranslatableLabel( + 'A new banner must include an imageBase64.', + 'general.errors.bannerSettings.imageRequired' + ) + ); + } + + /** + * Uploads a new image when a base64 payload is present, otherwise reuses + * the URL of the previously stored banner + * + * @param Banner $banner + * @param array $existingByKey + * + * @return Banner + * + * @throws InvalidURLException + */ + protected function resolveBannerImage(Banner $banner, array $existingByKey): Banner + { + $key = $this->keyFor($banner); + + if ($this->hasImageBase64($banner)) { + $banner->setImageUrl( + $this->bannerService->saveBannerImage( + $banner->getCountry(), + $banner->getDisplayLocation(), + $banner->getImageBase64() + ) + ); + } elseif (isset($existingByKey[$key])) { + $banner->setImageUrl($existingByKey[$key]->getImageUrl()); + } + + $banner->setImageBase64(null); + + $this->assertValidUrl($banner->getImageUrl()); + + return $banner; + } + + /** + * @param Banner $banner + * + * @return bool + */ + protected function hasImageBase64(Banner $banner): bool + { + $base64 = $banner->getImageBase64(); + + return $base64 !== null && $base64 !== ''; + } + + /** + * @param Banner[] $banners + * + * @return array + */ + protected function indexByKey(array $banners): array + { + $indexed = []; + foreach ($banners as $banner) { + $indexed[$this->keyFor($banner)] = $banner; + } + + return $indexed; + } + + /** + * @param Banner $banner + * + * @return string + */ + protected function keyFor(Banner $banner): string + { + return $banner->getCountry() . '|' . $banner->getDisplayLocation(); + } + /** * Validates the URL * @@ -90,16 +219,31 @@ public function getBannerData(string $country, string $displayLocation): ?Banner protected function assertValidUrl(string $url): void { if (mb_strlen($url) > 2048) { - throw new InvalidURLException('URL is too long (max 2048 characters)'); + throw new InvalidURLException( + new TranslatableLabel( + 'URL is too long (max 2048 characters)', + 'general.errors.bannerSettings.urlTooLong' + ) + ); } if (!filter_var($url, FILTER_VALIDATE_URL)) { - throw new InvalidURLException('URL format is invalid'); + throw new InvalidURLException( + new TranslatableLabel( + 'URL format is invalid', + 'general.errors.bannerSettings.invalidUrlFormat' + ) + ); } $scheme = parse_url($url, PHP_URL_SCHEME); if (!in_array($scheme, ['http', 'https'], true)) { - throw new InvalidURLException('URL must use http or https'); + throw new InvalidURLException( + new TranslatableLabel( + 'URL must use http or https', + 'general.errors.bannerSettings.invalidUrlScheme' + ) + ); } } } diff --git a/src/BusinessLogic/Domain/Integration/Banner/BannerServiceInterface.php b/src/BusinessLogic/Domain/Integration/Banner/BannerServiceInterface.php index 95c8297..c348112 100644 --- a/src/BusinessLogic/Domain/Integration/Banner/BannerServiceInterface.php +++ b/src/BusinessLogic/Domain/Integration/Banner/BannerServiceInterface.php @@ -10,7 +10,30 @@ interface BannerServiceInterface { /** + * Returns available banner display locations in integration + * * @return string[] */ public function getBannerDisplayLocations(): array; + + /** + * Persists the banner image on the integration server and returns its public URL. + * + * @param string $country + * @param string $displayLocation + * @param string $imageBase64 Raw Base64-encoded image content. + * + * @return string Public URL of the stored image. + */ + public function saveBannerImage(string $country, string $displayLocation, string $imageBase64): string; + + /** + * Removes the banner image associated with the given country and display location. + * + * @param string $country + * @param string $displayLocation + * + * @return void + */ + public function deleteBannerImage(string $country, string $displayLocation): void; } diff --git a/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php b/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php index 2c749ae..f984ca6 100644 --- a/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php +++ b/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php @@ -5,8 +5,6 @@ use Exception; use SeQura\Core\BusinessLogic\AdminAPI\AdminAPI; use SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Requests\BannerSettingsRequest; -use SeQura\Core\BusinessLogic\AdminAPI\Response\Response; -use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\InvalidURLException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\Banner; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\BannerSettings; use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; @@ -50,15 +48,15 @@ public function testGetSettings(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.com/es/faq#shoppers', - 'https://shop/sequra/es/image.jpg' + 'https://shop/sequra/es/image.jpg', + 'displayOnHomePage' ), new Banner( 'PT', - 'displayOnCartPage', 'https://www.sequra.com/it/faq#shoppers', - 'https://shop/sequra/pt/image.jpg' + 'https://shop/sequra/pt/image.jpg', + 'displayOnCartPage' ) ] ); @@ -103,21 +101,22 @@ public function testSetSettings(): void 'country' => 'ES', 'displayLocation' => 'displayOnHomePage', 'linkUrl' => 'https://www.sequra.com/es/faq#shoppers', - 'imageUrl' => 'https://shop/sequra/es/image.jpg' + 'imageBase64' => 'ES-base64' ], [ 'country' => 'PT', 'displayLocation' => 'displayOnCartPage', 'linkUrl' => 'https://www.sequra.com/it/faq#shoppers', - 'imageUrl' => 'https://shop/sequra/pt/image.jpg' + 'imageBase64' => 'PT-base64' ], ] ); // act - AdminAPI::get()->bannerSettings('store1')->setBannerSettings($settings); + $result = AdminAPI::get()->bannerSettings('store1')->setBannerSettings($settings); // assert + self::assertTrue($result->isSuccessful()); $savedSettings = StoreContext::doWithStore( 'store1', [ @@ -125,7 +124,11 @@ public function testSetSettings(): void 'getBannerSettings' ] ); - self::assertEquals($settings->transformToDomainModel(), $savedSettings); + self::assertNotNull($savedSettings); + self::assertCount(2, $savedSettings->getBannerConfigs()); + self::assertNotSame('', $savedSettings->getBannerConfigs()[0]->getImageUrl()); + self::assertNotSame('', $savedSettings->getBannerConfigs()[1]->getImageUrl()); + self::assertEquals($savedSettings->toArray(), $result->toArray()); } /** @@ -142,13 +145,13 @@ public function testSetSettingsInvalidURL(): void 'country' => 'ES', 'displayLocation' => 'displayOnHomePage', 'linkUrl' => 'https://www.sequra.com/es/faq#shoppers', - 'imageUrl' => 'https://shop/sequra/es/image.jpg' + 'imageBase64' => 'ES-base64' ], [ 'country' => 'PT', 'displayLocation' => 'displayOnCartPage', 'linkUrl' => 'string', - 'imageUrl' => 'https://shop/sequra/pt/image.jpg' + 'imageBase64' => 'PT-base64' ], ] ); @@ -159,8 +162,10 @@ public function testSetSettingsInvalidURL(): void // assert self::assertFalse($result->isSuccessful()); self::assertEquals([ + 'statusCode' => 0, + 'errorCode' => 'general.errors.bannerSettings.invalidUrlFormat', 'errorMessage' => 'URL format is invalid', - 'errorCode' => '400' + 'errorParameters' => [], ], $result->toArray()); $savedSettings = StoreContext::doWithStore( diff --git a/tests/BusinessLogic/CheckoutAPI/Banners/BannersApiTest.php b/tests/BusinessLogic/CheckoutAPI/Banners/BannersApiTest.php index 0ecf311..6dd1250 100644 --- a/tests/BusinessLogic/CheckoutAPI/Banners/BannersApiTest.php +++ b/tests/BusinessLogic/CheckoutAPI/Banners/BannersApiTest.php @@ -60,9 +60,9 @@ public function testGetBannersDataSuccess(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.es/es/faq#shoppers', - 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png' + 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png', + 'displayOnHomePage' ) ] ) @@ -90,9 +90,9 @@ public function testGetBannersNoDataSuccess(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.es/es/faq#shoppers', - 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png' + 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png', + 'displayOnHomePage' ) ] ) diff --git a/tests/BusinessLogic/Common/BaseTestCase.php b/tests/BusinessLogic/Common/BaseTestCase.php index db27da1..d4a2133 100644 --- a/tests/BusinessLogic/Common/BaseTestCase.php +++ b/tests/BusinessLogic/Common/BaseTestCase.php @@ -167,6 +167,7 @@ use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockDeploymentsRepository; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockDeploymentsService; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockIntegrationStoreIntegrationService; +use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockBannerService; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockMerchantDataProvider; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockMiniWidgetMessagesProvider; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockOrderCreation; @@ -508,9 +509,13 @@ protected function setUp(): void }, BannerSettingsService::class => function () { return new BannerSettingsService( - TestServiceRegister::getService(BannerSettingsRepositoryInterface::class) + TestServiceRegister::getService(BannerSettingsRepositoryInterface::class), + TestServiceRegister::getService(BannerServiceInterface::class) ); }, + BannerServiceInterface::class => function () { + return new MockBannerService(); + }, ProductServiceInterface::class => function () { return new MockProductService(); }, diff --git a/tests/BusinessLogic/Common/MockComponents/MockBannerService.php b/tests/BusinessLogic/Common/MockComponents/MockBannerService.php index 8e79d03..7395a25 100644 --- a/tests/BusinessLogic/Common/MockComponents/MockBannerService.php +++ b/tests/BusinessLogic/Common/MockComponents/MockBannerService.php @@ -16,6 +16,16 @@ class MockBannerService implements BannerServiceInterface */ protected $bannerDisplayLocations = []; + /** + * @var array + */ + protected $storedImages = []; + + /** + * @var array + */ + protected $deletedImages = []; + /** * @inheritDoc */ @@ -25,10 +35,53 @@ public function getBannerDisplayLocations(): array } /** - * @param array $bannerDisplayLocations + * @param string[] $bannerDisplayLocations */ public function setBannerDisplayLocations(array $bannerDisplayLocations): void { $this->bannerDisplayLocations = $bannerDisplayLocations; } + + /** + * @inheritDoc + */ + public function saveBannerImage(string $country, string $displayLocation, string $imageBase64): string + { + $key = $this->key($country, $displayLocation); + $this->storedImages[$key] = $imageBase64; + unset($this->deletedImages[$key]); + + return 'https://shop.test/banners/' . $country . '_' . $displayLocation . '.png'; + } + + /** + * @inheritDoc + */ + public function deleteBannerImage(string $country, string $displayLocation): void + { + $key = $this->key($country, $displayLocation); + unset($this->storedImages[$key]); + $this->deletedImages[$key] = true; + } + + /** + * @return array + */ + public function getStoredImages(): array + { + return $this->storedImages; + } + + /** + * @return string[] + */ + public function getDeletedImageKeys(): array + { + return array_keys($this->deletedImages); + } + + private function key(string $country, string $displayLocation): string + { + return $country . '|' . $displayLocation; + } } diff --git a/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsService.php b/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsService.php index a6dacdd..d068f94 100644 --- a/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsService.php +++ b/tests/BusinessLogic/Common/MockComponents/MockBannerSettingsService.php @@ -4,6 +4,7 @@ use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\Banner; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\BannerSettings; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; /** @@ -16,6 +17,14 @@ class MockBannerSettingsService extends BannerSettingsService /** @var BannerSettings */ protected $bannerSettings; + /** + * @param BannerSettingsRepositoryInterface $bannerSettingsRepository + */ + public function __construct(BannerSettingsRepositoryInterface $bannerSettingsRepository) + { + parent::__construct($bannerSettingsRepository, new MockBannerService()); + } + /** * @inheritDoc */ @@ -29,6 +38,10 @@ public function getBannerSettings(): ?BannerSettings */ public function getBannerData(string $country, string $displayLocation): ?Banner { + if ($this->bannerSettings === null) { + return null; + } + foreach ($this->bannerSettings->getBannerConfigs() as $bannerConfig) { if ($bannerConfig->getCountry() === $country && $bannerConfig->getDisplayLocation() === $displayLocation) { return $bannerConfig; @@ -41,13 +54,14 @@ public function getBannerData(string $country, string $displayLocation): ?Banner /** * @inheritDoc */ - public function setBannerSettings(BannerSettings $bannerSettings): void + public function setBannerSettings(BannerSettings $bannerSettings): BannerSettings { foreach ($bannerSettings->getBannerConfigs() as $bannerConfig) { $this->assertValidUrl($bannerConfig->getLinkUrl()); - $this->assertValidUrl($bannerConfig->getImageUrl()); } $this->bannerSettings = $bannerSettings; + + return $bannerSettings; } } diff --git a/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php b/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php index 8ff4c72..ea9628b 100644 --- a/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php +++ b/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php @@ -1790,9 +1790,9 @@ public function testSaveBannerSettingsResponse(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.es/es/faq#shoppers', - 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png' + 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png', + 'displayOnHomePage' ) ] ) @@ -1806,13 +1806,13 @@ public function testSaveBannerSettingsResponse(): void "bannerConfigs" => [ [ 'country' => 'ES', - 'imageUrl' => 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png', + 'imageBase64' => 'ES-base64', 'linkUrl' => 'https://www.sequra.es/es/faq#shoppers', 'displayLocation' => 'displayOnHomePage' ], [ 'country' => 'PT', - 'imageUrl' => 'https://shop/img/sequra/pt/banner/Flag_of_Spain.svg.png', + 'imageBase64' => 'PT-base64', 'linkUrl' => 'https://www.sequra.pt/pt/faq#shoppers', 'displayLocation' => 'displayOnCartPage' ], @@ -1822,7 +1822,10 @@ public function testSaveBannerSettingsResponse(): void //Assert self::assertTrue($response->isSuccessful()); - self::assertEmpty($response->toArray()); + $payload = $response->toArray(); + self::assertCount(2, $payload['bannerConfigs']); + self::assertEquals('ES', $payload['bannerConfigs'][0]['country']); + self::assertEquals('PT', $payload['bannerConfigs'][1]['country']); self::assertCount(2, $this->bannerSettingsService->getBannerSettings()->getBannerConfigs()); } @@ -1840,9 +1843,9 @@ public function testSaveBannerSettingsInvalidURLResponse(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.es/es/faq#shoppers', - 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png' + 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png', + 'displayOnHomePage' ) ] ) @@ -1856,13 +1859,13 @@ public function testSaveBannerSettingsInvalidURLResponse(): void "bannerConfigs" => [ [ 'country' => 'ES', - 'imageUrl' => 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png', + 'imageBase64' => 'ES-base64', 'linkUrl' => 'string', 'displayLocation' => 'displayOnHomePage' ], [ 'country' => 'PT', - 'imageUrl' => 'https://shop/img/sequra/pt/banner/Flag_of_Spain.svg.png', + 'imageBase64' => 'PT-base64', 'linkUrl' => 'https://www.sequra.pt/pt/faq#shoppers', 'displayLocation' => 'displayOnCartPage' ], @@ -1873,8 +1876,10 @@ public function testSaveBannerSettingsInvalidURLResponse(): void //Assert self::assertFalse($response->isSuccessful()); self::assertEquals([ + 'statusCode' => 0, + 'errorCode' => 'general.errors.bannerSettings.invalidUrlFormat', 'errorMessage' => 'URL format is invalid', - 'errorCode' => 'INVALID_URL' + 'errorParameters' => [], ], $response->toArray()); self::assertCount(1, $this->bannerSettingsService->getBannerSettings()->getBannerConfigs()); } @@ -1892,9 +1897,9 @@ public function testGetBannerSettingsResponse(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.es/es/faq#shoppers', - 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png' + 'https://shop/img/sequra/es/banner/Flag_of_Spain.svg.png', + 'displayOnHomePage' ) ] ) diff --git a/tests/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepositoryTest.php b/tests/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepositoryTest.php index 0791207..da4eb8d 100644 --- a/tests/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepositoryTest.php +++ b/tests/BusinessLogic/DataAccess/BannerSettings/Repositories/BannerSettingsRepositoryTest.php @@ -62,15 +62,15 @@ public function testGetBannerSettings(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.com/es/faq#shoppers', - 'https://shop/sequra/es/image.jpg' + 'https://shop/sequra/es/image.jpg', + 'displayOnHomePage' ), new Banner( 'PT', - 'displayOnCartPage', 'https://www.sequra.com/it/faq#shoppers', - 'https://shop/sequra/pt/image.jpg' + 'https://shop/sequra/pt/image.jpg', + 'displayOnCartPage' ) ] ); @@ -106,15 +106,15 @@ public function testSetBannerSettings(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.com/es/faq#shoppers', - '' + '', + 'displayOnHomePage' ), new Banner( 'PT', - 'displayOnCartPage', '', - 'https://shop/sequra/pt/image.jpg' + 'https://shop/sequra/pt/image.jpg', + 'displayOnCartPage' ) ] ); @@ -144,15 +144,15 @@ public function testDeleteBannerSettings(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.com/es/faq#shoppers', - 'https://shop/sequra/es/image.jpg' + 'https://shop/sequra/es/image.jpg', + 'displayOnHomePage' ), new Banner( 'PT', - 'displayOnCartPage', 'https://www.sequra.com/it/faq#shoppers', - 'https://shop/sequra/pt/image.jpg' + 'https://shop/sequra/pt/image.jpg', + 'displayOnCartPage' ) ] ); diff --git a/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php b/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php index 8b169d3..a2f1573 100644 --- a/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php +++ b/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php @@ -3,12 +3,14 @@ namespace SeQura\Core\Tests\BusinessLogic\Domain\BannerSettings\Service; use Exception; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\BannerImageRequiredException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\InvalidURLException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\Banner; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\BannerSettings; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; use SeQura\Core\Infrastructure\ORM\Exceptions\RepositoryClassException; use SeQura\Core\Tests\BusinessLogic\Common\BaseTestCase; +use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockBannerService; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockBannerSettingsRepository; /** @@ -28,6 +30,11 @@ class BannerSettingsServiceTest extends BaseTestCase */ private $bannerSettingsRepository; + /** + * @var MockBannerService $bannerService + */ + private $bannerService; + /** * @return void * @@ -38,7 +45,11 @@ public function setUp(): void parent::setUp(); $this->bannerSettingsRepository = new MockBannerSettingsRepository(); - $this->bannerSettingsService = new BannerSettingsService($this->bannerSettingsRepository); + $this->bannerService = new MockBannerService(); + $this->bannerSettingsService = new BannerSettingsService( + $this->bannerSettingsRepository, + $this->bannerService + ); } /** @@ -67,15 +78,15 @@ public function testGetBannerSettings(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.com/es/faq#shoppers', - 'https://shop/sequra/es/image.jpg' + 'https://shop/sequra/es/image.jpg', + 'displayOnHomePage' ), new Banner( 'PT', - 'displayOnCartPage', 'https://www.sequra.com/it/faq#shoppers', - 'https://shop/sequra/pt/image.jpg' + 'https://shop/sequra/pt/image.jpg', + 'displayOnCartPage' ) ] ); @@ -102,18 +113,21 @@ public function testSetBannerSettingsNoSettingsInDB(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.com/es/faq#shoppers', - 'https://shop/sequra/es/image.jpg' + '', + 'displayOnHomePage', + 'ES-base64' ), new Banner( 'PT', - 'displayOnCartPage', 'https://www.sequra.com/it/faq#shoppers', - 'https://shop/sequra/pt/image.jpg' + '', + 'displayOnCartPage', + 'PT-base64' ) ] ); + //Act $this->bannerSettingsService->setBannerSettings($bannerSettings); @@ -122,6 +136,15 @@ public function testSetBannerSettingsNoSettingsInDB(): void self::assertNotNull($result); self::assertCount(2, $result->getBannerConfigs()); self::assertEquals('PT', $result->getBannerConfigs()[1]->getCountry()); + self::assertEquals( + 'https://shop.test/banners/ES_displayOnHomePage.png', + $result->getBannerConfigs()[0]->getImageUrl() + ); + self::assertEquals( + 'https://shop.test/banners/PT_displayOnCartPage.png', + $result->getBannerConfigs()[1]->getImageUrl() + ); + self::assertNull($result->getBannerConfigs()[0]->getImageBase64()); } /** @@ -129,28 +152,193 @@ public function testSetBannerSettingsNoSettingsInDB(): void * * @throws Exception */ - public function testSetBannerSettingsSettingsChanged(): void + public function testSetBannerSettingsNewBannerWithoutImageBase64Throws(): void { //Arrange $bannerSettings = new BannerSettings( [ new Banner( 'ES', + 'https://www.sequra.com/es/faq#shoppers', + '', + 'displayOnHomePage' + ), + ] + ); + + //Assert + $this->expectException(BannerImageRequiredException::class); + + //Act + $this->bannerSettingsService->setBannerSettings($bannerSettings); + } + + /** + * @return void + * + * @throws Exception + */ + public function testSetBannerSettingsPreservesImageUrlWhenNoBase64Provided(): void + { + //Arrange + $this->bannerSettingsRepository->setBannerSettings(new BannerSettings( + [ + new Banner( + 'FR', + 'https://www.sequra.com/fr/faq#shoppers', + 'https://shop/sequra/fr/existing.jpg', + 'displayOnHomePage' + ) + ] + )); + + $update = new BannerSettings( + [ + new Banner( + 'FR', + 'https://www.sequra.com/fr/updated-link', + '', + 'displayOnHomePage' + ), + ] + ); + + //Act + $this->bannerSettingsService->setBannerSettings($update); + + //Assert + $result = $this->bannerSettingsRepository->getBannerSettings(); + self::assertNotNull($result); + self::assertCount(1, $result->getBannerConfigs()); + self::assertEquals( + 'https://shop/sequra/fr/existing.jpg', + $result->getBannerConfigs()[0]->getImageUrl() + ); + self::assertEquals( + 'https://www.sequra.com/fr/updated-link', + $result->getBannerConfigs()[0]->getLinkUrl() + ); + self::assertEmpty($this->bannerService->getStoredImages()); + } + + /** + * @return void + * + * @throws Exception + */ + public function testSetBannerSettingsReplacesImageWhenBase64Provided(): void + { + //Arrange + $this->bannerSettingsRepository->setBannerSettings(new BannerSettings( + [ + new Banner( + 'FR', + 'https://www.sequra.com/fr/faq#shoppers', + 'https://shop/sequra/fr/old.jpg', + 'displayOnHomePage' + ) + ] + )); + + $update = new BannerSettings( + [ + new Banner( + 'FR', + 'https://www.sequra.com/fr/faq#shoppers', + '', 'displayOnHomePage', + 'FR-new-base64' + ), + ] + ); + + //Act + $this->bannerSettingsService->setBannerSettings($update); + + //Assert + $result = $this->bannerSettingsRepository->getBannerSettings(); + self::assertEquals( + 'https://shop.test/banners/FR_displayOnHomePage.png', + $result->getBannerConfigs()[0]->getImageUrl() + ); + self::assertEquals(['FR|displayOnHomePage' => 'FR-new-base64'], $this->bannerService->getStoredImages()); + } + + /** + * @return void + * + * @throws Exception + */ + public function testSetBannerSettingsDeletesOmittedBanners(): void + { + //Arrange + $this->bannerSettingsRepository->setBannerSettings(new BannerSettings( + [ + new Banner( + 'ES', 'https://www.sequra.com/es/faq#shoppers', - 'https://shop/sequra/es/image.jpg' + 'https://shop/sequra/es/image.jpg', + 'displayOnHomePage' + ), + new Banner( + 'PT', + 'https://www.sequra.com/pt/faq#shoppers', + 'https://shop/sequra/pt/image.jpg', + 'displayOnCartPage' + ), + ] + )); + + $update = new BannerSettings( + [ + new Banner( + 'ES', + 'https://www.sequra.com/es/faq#shoppers', + '', + 'displayOnHomePage' + ), + ] + ); + + //Act + $this->bannerSettingsService->setBannerSettings($update); + + //Assert + $result = $this->bannerSettingsRepository->getBannerSettings(); + self::assertCount(1, $result->getBannerConfigs()); + self::assertEquals('ES', $result->getBannerConfigs()[0]->getCountry()); + self::assertEquals(['PT|displayOnCartPage'], $this->bannerService->getDeletedImageKeys()); + } + + /** + * @return void + * + * @throws Exception + */ + public function testSetBannerSettingsSettingsChanged(): void + { + //Arrange + $bannerSettings = new BannerSettings( + [ + new Banner( + 'ES', + 'https://www.sequra.com/es/faq#shoppers', + '', + 'displayOnHomePage', + 'ES-base64' ), new Banner( 'PT', - 'displayOnCartPage', 'https://www.sequra.com/it/faq#shoppers', - 'https://shop/sequra/pt/image.jpg' + '', + 'displayOnCartPage', + 'PT-base64' ), new Banner( 'FR', - 'displayOnHomePage', 'https://www.sequra.com/fr/faq#shoppers', - 'https://shop/sequra/fr/image.jpg' + '', + 'displayOnHomePage' ), ] @@ -159,9 +347,9 @@ public function testSetBannerSettingsSettingsChanged(): void [ new Banner( 'FR', - 'displayOnHomePage', 'https://www.sequra.com/fr/faq#shoppers', - 'https://shop/sequra/fr/image.jpg' + 'https://shop/sequra/fr/image.jpg', + 'displayOnHomePage' ) ] )); @@ -177,6 +365,10 @@ public function testSetBannerSettingsSettingsChanged(): void self::assertEquals('ES', $result->getBannerConfigs()[0]->getCountry()); self::assertEquals('PT', $result->getBannerConfigs()[1]->getCountry()); self::assertEquals('FR', $result->getBannerConfigs()[2]->getCountry()); + self::assertEquals( + 'https://shop/sequra/fr/image.jpg', + $result->getBannerConfigs()[2]->getImageUrl() + ); } /** @@ -191,15 +383,17 @@ public function testSetBannerSettingsInvalidURL(): void [ new Banner( 'ES', - 'displayOnHomePage', 'link', - 'https://shop/sequra/es/image.jpg' + '', + 'displayOnHomePage', + 'ES-base64' ), new Banner( 'PT', - 'displayOnCartPage', 'https://www.sequra.com/it/faq#shoppers', - 'https://shop/sequra/pt/image.jpg' + '', + 'displayOnCartPage', + 'PT-base64' ) ] ); @@ -221,21 +415,21 @@ public function testGetBannerDataByCountryAndDisplayLocation(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.com/es/faq#shoppers', - 'https://shop/sequra/es/image.jpg' + 'https://shop/sequra/es/image.jpg', + 'displayOnHomePage' ), new Banner( 'PT', - 'displayOnCartPage', 'https://www.sequra.com/it/faq#shoppers', - 'https://shop/sequra/pt/image.jpg' + 'https://shop/sequra/pt/image.jpg', + 'displayOnCartPage' ), new Banner( 'FR', - 'displayOnHomePage', 'https://www.sequra.com/fr/faq#shoppers', - 'https://shop/sequra/fr/image.jpg' + 'https://shop/sequra/fr/image.jpg', + 'displayOnHomePage' ), ] @@ -264,21 +458,21 @@ public function testGetBannerNoDataForDisplayLocation(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.com/es/faq#shoppers', - 'https://shop/sequra/es/image.jpg' + 'https://shop/sequra/es/image.jpg', + 'displayOnHomePage' ), new Banner( 'PT', - 'displayOnCartPage', 'https://www.sequra.com/it/faq#shoppers', - 'https://shop/sequra/pt/image.jpg' + 'https://shop/sequra/pt/image.jpg', + 'displayOnCartPage' ), new Banner( 'FR', - 'displayOnHomePage', 'https://www.sequra.com/fr/faq#shoppers', - 'https://shop/sequra/fr/image.jpg' + 'https://shop/sequra/fr/image.jpg', + 'displayOnHomePage' ), ] @@ -305,15 +499,15 @@ public function testGetBannerNoDataForCountry(): void [ new Banner( 'ES', - 'displayOnHomePage', 'https://www.sequra.com/es/faq#shoppers', - 'https://shop/sequra/es/image.jpg' + 'https://shop/sequra/es/image.jpg', + 'displayOnHomePage' ), new Banner( 'FR', - 'displayOnHomePage', 'https://www.sequra.com/fr/faq#shoppers', - 'https://shop/sequra/fr/image.jpg' + 'https://shop/sequra/fr/image.jpg', + 'displayOnHomePage' ), ] From 415341e20a9d4e85f798aad6ad948aee983c99d4 Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Tue, 12 May 2026 12:49:19 +0200 Subject: [PATCH 11/18] Fetch display locations together with the get banners response LIS-111 --- .../BannerSettingsController.php | 22 +++++- .../Responses/BannerSettingsResponse.php | 18 ++++- src/BusinessLogic/BootstrapComponent.php | 22 ++---- .../GetBannerDisplayLocationsHandler.php | 37 ---------- .../GetBannerSettingsHandler.php | 19 ++++- .../SaveBannerSettingsHandler.php | 19 ++++- .../Handlers/Enums/Topics.php | 5 -- .../BannerDisplayLocationsResponse.php | 34 --------- .../BannerSettings/BannerSettingsResponse.php | 16 +++- .../BannerSettingsControllerTest.php | 66 ++++++++++++++++- tests/BusinessLogic/Common/BaseTestCase.php | 22 ++---- .../ConfigurationWebhookAPITest.php | 74 ++++++++++++------- 12 files changed, 199 insertions(+), 155 deletions(-) delete mode 100644 src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerDisplayLocationsHandler.php delete mode 100644 src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerDisplayLocationsResponse.php diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php b/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php index a19650d..273b989 100644 --- a/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php +++ b/src/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsController.php @@ -8,6 +8,7 @@ use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\BannerImageRequiredException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\InvalidURLException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; +use SeQura\Core\BusinessLogic\Domain\Integration\Banner\BannerServiceInterface; /** * Class BannerSettingsController @@ -21,12 +22,21 @@ class BannerSettingsController */ protected $bannerSettingsService; + /** + * @var BannerServiceInterface + */ + protected $bannerService; + /** * @param BannerSettingsService $bannerSettingsService + * @param BannerServiceInterface $bannerService */ - public function __construct(BannerSettingsService $bannerSettingsService) - { + public function __construct( + BannerSettingsService $bannerSettingsService, + BannerServiceInterface $bannerService + ) { $this->bannerSettingsService = $bannerSettingsService; + $this->bannerService = $bannerService; } /** @@ -36,7 +46,10 @@ public function __construct(BannerSettingsService $bannerSettingsService) */ public function getBannerSettings(): BannerSettingsResponse { - return new BannerSettingsResponse($this->bannerSettingsService->getBannerSettings()); + return new BannerSettingsResponse( + $this->bannerSettingsService->getBannerSettings(), + $this->bannerService->getBannerDisplayLocations() + ); } /** @@ -52,7 +65,8 @@ public function getBannerSettings(): BannerSettingsResponse public function setBannerSettings(BannerSettingsRequest $settingsRequest): BannerSettingsResponse { return new BannerSettingsResponse( - $this->bannerSettingsService->setBannerSettings($settingsRequest->transformToDomainModel()) + $this->bannerSettingsService->setBannerSettings($settingsRequest->transformToDomainModel()), + $this->bannerService->getBannerDisplayLocations() ); } } diff --git a/src/BusinessLogic/AdminAPI/BannerSettings/Responses/BannerSettingsResponse.php b/src/BusinessLogic/AdminAPI/BannerSettings/Responses/BannerSettingsResponse.php index d8a1d94..dbba2ba 100644 --- a/src/BusinessLogic/AdminAPI/BannerSettings/Responses/BannerSettingsResponse.php +++ b/src/BusinessLogic/AdminAPI/BannerSettings/Responses/BannerSettingsResponse.php @@ -13,16 +13,23 @@ class BannerSettingsResponse extends Response { /** - * @var BannerSettings + * @var BannerSettings|null */ protected $bannerSettings; + /** + * @var string[] + */ + protected $displayLocations; + /** * @param BannerSettings|null $bannerSettings + * @param string[] $displayLocations */ - public function __construct(?BannerSettings $bannerSettings) + public function __construct(?BannerSettings $bannerSettings, array $displayLocations) { $this->bannerSettings = $bannerSettings; + $this->displayLocations = $displayLocations; } /** @@ -30,6 +37,11 @@ public function __construct(?BannerSettings $bannerSettings) */ public function toArray(): array { - return !$this->bannerSettings ? [] : $this->bannerSettings->toArray(); + $settingsArray = $this->bannerSettings ? $this->bannerSettings->toArray() : []; + + return [ + 'displayLocations' => $this->displayLocations, + 'bannerConfigs' => $settingsArray['bannerConfigs'] ?? [], + ]; } } diff --git a/src/BusinessLogic/BootstrapComponent.php b/src/BusinessLogic/BootstrapComponent.php index 2768484..36a46f4 100644 --- a/src/BusinessLogic/BootstrapComponent.php +++ b/src/BusinessLogic/BootstrapComponent.php @@ -21,7 +21,6 @@ use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Controller\ConfigurationWebhookController; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\AdvancedSettings\GetAdvancedSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\AdvancedSettings\SaveAdvancedSettingsHandler; -use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\GetBannerDisplayLocationsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\GetBannerSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\SaveBannerSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\Enums\Topics; @@ -766,7 +765,8 @@ static function () { BannerSettingsController::class, static function () { return new BannerSettingsController( - ServiceRegister::getService(BannerSettingsService::class) + ServiceRegister::getService(BannerSettingsService::class), + ServiceRegister::getService(BannerServiceInterface::class) ); } ); @@ -1064,11 +1064,6 @@ protected static function initTopicHandlers(): void SaveBannerSettingsHandler::class ); - TopicHandlerRegistry::register( - Topics::GET_BANNER_DISPLAY_LOCATIONS, - GetBannerDisplayLocationsHandler::class - ); - TopicHandlerRegistry::register( Topics::GET_LOG_CONTENT, GetLogContentHandler::class @@ -1196,7 +1191,8 @@ static function () { GetBannerSettingsHandler::class, static function () { return new GetBannerSettingsHandler( - ServiceRegister::getService(BannerSettingsService::class) + ServiceRegister::getService(BannerSettingsService::class), + ServiceRegister::getService(BannerServiceInterface::class) ); } ); @@ -1205,15 +1201,7 @@ static function () { SaveBannerSettingsHandler::class, static function () { return new SaveBannerSettingsHandler( - ServiceRegister::getService(BannerSettingsService::class) - ); - } - ); - - ServiceRegister::registerService( - GetBannerDisplayLocationsHandler::class, - static function () { - return new GetBannerDisplayLocationsHandler( + ServiceRegister::getService(BannerSettingsService::class), ServiceRegister::getService(BannerServiceInterface::class) ); } diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerDisplayLocationsHandler.php b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerDisplayLocationsHandler.php deleted file mode 100644 index bfe1516..0000000 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerDisplayLocationsHandler.php +++ /dev/null @@ -1,37 +0,0 @@ -bannerService = $bannerService; - } - - /** - * @inheritDoc - */ - public function handle(array $payload): Response - { - return new BannerDisplayLocationsResponse($this->bannerService->getBannerDisplayLocations()); - } -} diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerSettingsHandler.php b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerSettingsHandler.php index 853e66a..b02c1ed 100644 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerSettingsHandler.php +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerSettingsHandler.php @@ -7,6 +7,7 @@ use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\BannerSettings\BannerSettingsResponse; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\BannerSettings; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; +use SeQura\Core\BusinessLogic\Domain\Integration\Banner\BannerServiceInterface; /** * Class GetBannerSettingsHandler @@ -20,12 +21,21 @@ class GetBannerSettingsHandler implements TopicHandlerInterface */ protected $bannerSettingsService; + /** + * @var BannerServiceInterface + */ + protected $bannerService; + /** * @param BannerSettingsService $bannerSettingsService + * @param BannerServiceInterface $bannerService */ - public function __construct(BannerSettingsService $bannerSettingsService) - { + public function __construct( + BannerSettingsService $bannerSettingsService, + BannerServiceInterface $bannerService + ) { $this->bannerSettingsService = $bannerSettingsService; + $this->bannerService = $bannerService; } /** @@ -37,6 +47,9 @@ public function handle(array $payload): Response { $bannerSettings = $this->bannerSettingsService->getBannerSettings() ?? new BannerSettings([]); - return new BannerSettingsResponse($bannerSettings); + return new BannerSettingsResponse( + $bannerSettings, + $this->bannerService->getBannerDisplayLocations() + ); } } diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php index 44e0276..e250468 100644 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php @@ -9,6 +9,7 @@ use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\BannerImageRequiredException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\InvalidURLException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; +use SeQura\Core\BusinessLogic\Domain\Integration\Banner\BannerServiceInterface; /** * Class SaveBannerSettingsHandler @@ -22,12 +23,21 @@ class SaveBannerSettingsHandler implements TopicHandlerInterface */ protected $bannerSettingsService; + /** + * @var BannerServiceInterface + */ + protected $bannerService; + /** * @param BannerSettingsService $bannerSettingsService + * @param BannerServiceInterface $bannerService */ - public function __construct(BannerSettingsService $bannerSettingsService) - { + public function __construct( + BannerSettingsService $bannerSettingsService, + BannerServiceInterface $bannerService + ) { $this->bannerSettingsService = $bannerSettingsService; + $this->bannerService = $bannerService; } /** @@ -41,6 +51,9 @@ public function handle(array $payload): Response $request = SaveBannerSettingsRequest::fromPayload($payload); $saved = $this->bannerSettingsService->setBannerSettings($request->transformToDomainModel()); - return new BannerSettingsResponse($saved); + return new BannerSettingsResponse( + $saved, + $this->bannerService->getBannerDisplayLocations() + ); } } diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/Enums/Topics.php b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/Enums/Topics.php index 856df18..91debd3 100644 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/Enums/Topics.php +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/Enums/Topics.php @@ -53,10 +53,6 @@ interface Topics * @var string */ public const SAVE_BANNER_SETTINGS = 'save-banner-settings'; - /** - * @var string - */ - public const GET_BANNER_DISPLAY_LOCATIONS = 'get-banner-display-locations'; /** * @var string */ @@ -96,7 +92,6 @@ interface Topics self::SAVE_ADVANCED_SETTINGS, self::GET_BANNER_SETTINGS, self::SAVE_BANNER_SETTINGS, - self::GET_BANNER_DISPLAY_LOCATIONS, self::GET_LOG_CONTENT, self::REMOVE_LOG_CONTENT, self::GET_SHOP_CATEGORIES, diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerDisplayLocationsResponse.php b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerDisplayLocationsResponse.php deleted file mode 100644 index 43d6614..0000000 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerDisplayLocationsResponse.php +++ /dev/null @@ -1,34 +0,0 @@ -bannerDisplayLocations = $bannerDisplayLocations; - } - - /** - * @inheritDoc - */ - public function toArray(): array - { - return $this->bannerDisplayLocations; - } -} diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerSettingsResponse.php b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerSettingsResponse.php index 035bffa..397af76 100644 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerSettingsResponse.php +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerSettingsResponse.php @@ -17,12 +17,19 @@ class BannerSettingsResponse extends Response */ protected $settings; + /** + * @var string[] + */ + protected $displayLocations; + /** * @param BannerSettings $settings + * @param string[] $displayLocations */ - public function __construct(BannerSettings $settings) + public function __construct(BannerSettings $settings, array $displayLocations) { $this->settings = $settings; + $this->displayLocations = $displayLocations; } /** @@ -30,6 +37,11 @@ public function __construct(BannerSettings $settings) */ public function toArray(): array { - return !$this->settings ? [] : $this->settings->toArray(); + $settingsArray = $this->settings->toArray(); + + return [ + 'displayLocations' => $this->displayLocations, + 'bannerConfigs' => $settingsArray['bannerConfigs'] ?? [], + ]; } } diff --git a/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php b/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php index f984ca6..a79160a 100644 --- a/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php +++ b/tests/BusinessLogic/AdminAPI/BannerSettings/BannerSettingsControllerTest.php @@ -8,8 +8,10 @@ use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\Banner; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\BannerSettings; use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; +use SeQura\Core\BusinessLogic\Domain\Integration\Banner\BannerServiceInterface; use SeQura\Core\BusinessLogic\Domain\Multistore\StoreContext; use SeQura\Core\Tests\BusinessLogic\Common\BaseTestCase; +use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockBannerService; use SeQura\Core\Tests\Infrastructure\Common\TestServiceRegister; /**+ @@ -24,6 +26,11 @@ class BannerSettingsControllerTest extends BaseTestCase */ private $bannerSettingsRepository; + /** + * @var MockBannerService + */ + private $bannerService; + /** * @inheritDoc */ @@ -34,6 +41,17 @@ protected function setUp(): void $this->bannerSettingsRepository = TestServiceRegister::getService( BannerSettingsRepositoryInterface::class ); + + $this->bannerService = new MockBannerService(); + $this->bannerService->setBannerDisplayLocations([ + 'displayOnHomePage', + 'displayOnProductPage', + 'displayOnCartPage', + 'displayOnProductListingPage', + ]); + TestServiceRegister::registerService(BannerServiceInterface::class, function () { + return $this->bannerService; + }); } /** @@ -68,6 +86,12 @@ public function testGetSettings(): void // assert self::assertEquals( [ + 'displayLocations' => [ + 'displayOnHomePage', + 'displayOnProductPage', + 'displayOnCartPage', + 'displayOnProductListingPage', + ], 'bannerConfigs' => [ [ 'country' => $settings->getBannerConfigs()[0]->getCountry(), @@ -87,6 +111,31 @@ public function testGetSettings(): void ); } + /** + * @return void + * + * @throws Exception + */ + public function testGetSettingsEmpty(): void + { + // act + $result = AdminAPI::get()->bannerSettings('store1')->getBannerSettings(); + + // assert + self::assertEquals( + [ + 'displayLocations' => [ + 'displayOnHomePage', + 'displayOnProductPage', + 'displayOnCartPage', + 'displayOnProductListingPage', + ], + 'bannerConfigs' => [], + ], + $result->toArray() + ); + } + /** * @return void * @@ -117,6 +166,20 @@ public function testSetSettings(): void // assert self::assertTrue($result->isSuccessful()); + $payload = $result->toArray(); + self::assertEquals( + [ + 'displayOnHomePage', + 'displayOnProductPage', + 'displayOnCartPage', + 'displayOnProductListingPage', + ], + $payload['displayLocations'] + ); + self::assertCount(2, $payload['bannerConfigs']); + self::assertNotSame('', $payload['bannerConfigs'][0]['imageUrl']); + self::assertNotSame('', $payload['bannerConfigs'][1]['imageUrl']); + $savedSettings = StoreContext::doWithStore( 'store1', [ @@ -126,9 +189,6 @@ public function testSetSettings(): void ); self::assertNotNull($savedSettings); self::assertCount(2, $savedSettings->getBannerConfigs()); - self::assertNotSame('', $savedSettings->getBannerConfigs()[0]->getImageUrl()); - self::assertNotSame('', $savedSettings->getBannerConfigs()[1]->getImageUrl()); - self::assertEquals($savedSettings->toArray(), $result->toArray()); } /** diff --git a/tests/BusinessLogic/Common/BaseTestCase.php b/tests/BusinessLogic/Common/BaseTestCase.php index d4a2133..7a1baf6 100644 --- a/tests/BusinessLogic/Common/BaseTestCase.php +++ b/tests/BusinessLogic/Common/BaseTestCase.php @@ -21,7 +21,6 @@ use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Controller\ConfigurationWebhookController; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\AdvancedSettings\GetAdvancedSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\AdvancedSettings\SaveAdvancedSettingsHandler; -use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\GetBannerDisplayLocationsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\GetBannerSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\SaveBannerSettingsHandler; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\Enums\Topics; @@ -532,7 +531,8 @@ protected function setUp(): void }, BannerSettingsController::class => function () { return new BannerSettingsController( - TestServiceRegister::getService(BannerSettingsService::class) + TestServiceRegister::getService(BannerSettingsService::class), + TestServiceRegister::getService(BannerServiceInterface::class) ); }, AbstractItemFactory::class => function () { @@ -859,7 +859,8 @@ static function () { GetBannerSettingsHandler::class, static function () { return new GetBannerSettingsHandler( - TestServiceRegister::getService(BannerSettingsService::class) + TestServiceRegister::getService(BannerSettingsService::class), + TestServiceRegister::getService(BannerServiceInterface::class) ); } ); @@ -868,15 +869,7 @@ static function () { SaveBannerSettingsHandler::class, static function () { return new SaveBannerSettingsHandler( - TestServiceRegister::getService(BannerSettingsService::class) - ); - } - ); - - TestServiceRegister::registerService( - GetBannerDisplayLocationsHandler::class, - static function () { - return new GetBannerDisplayLocationsHandler( + TestServiceRegister::getService(BannerSettingsService::class), TestServiceRegister::getService(BannerServiceInterface::class) ); } @@ -991,11 +984,6 @@ static function () { SaveBannerSettingsHandler::class ); - TopicHandlerRegistry::register( - Topics::GET_BANNER_DISPLAY_LOCATIONS, - GetBannerDisplayLocationsHandler::class - ); - TopicHandlerRegistry::register( Topics::GET_LOG_CONTENT, GetLogContentHandler::class diff --git a/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php b/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php index ea9628b..019ec57 100644 --- a/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php +++ b/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php @@ -3,7 +3,6 @@ namespace SeQura\Core\Tests\BusinessLogic\ConfigurationWebhookAPI; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\ConfigurationWebhookAPI; -use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\BannerSettings\BannerDisplayLocationsResponse; use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\BannerSettings\BannerSettingsResponse; use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Models\AdvancedSettings; use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Services\AdvancedSettingsService; @@ -1785,6 +1784,12 @@ public function testGetAdvancedSettingsResponseNoAdvancedSettings(): void public function testSaveBannerSettingsResponse(): void { //Arrange + $this->bannerService->setBannerDisplayLocations([ + 'displayOnHomePage', + 'displayOnProductPage', + 'displayOnCartPage', + 'displayOnProductListingPage', + ]); $this->bannerSettingsService->setBannerSettings( new BannerSettings( [ @@ -1823,6 +1828,15 @@ public function testSaveBannerSettingsResponse(): void //Assert self::assertTrue($response->isSuccessful()); $payload = $response->toArray(); + self::assertEquals( + [ + 'displayOnHomePage', + 'displayOnProductPage', + 'displayOnCartPage', + 'displayOnProductListingPage', + ], + $payload['displayLocations'] + ); self::assertCount(2, $payload['bannerConfigs']); self::assertEquals('ES', $payload['bannerConfigs'][0]['country']); self::assertEquals('PT', $payload['bannerConfigs'][1]['country']); @@ -1892,6 +1906,12 @@ public function testSaveBannerSettingsInvalidURLResponse(): void public function testGetBannerSettingsResponse(): void { //Arrange + $this->bannerService->setBannerDisplayLocations([ + 'displayOnHomePage', + 'displayOnProductPage', + 'displayOnCartPage', + 'displayOnProductListingPage', + ]); $this->bannerSettingsService->setBannerSettings( new BannerSettings( [ @@ -1916,7 +1936,17 @@ public function testGetBannerSettingsResponse(): void //Assert self::assertTrue($response->isSuccessful()); - self::assertCount(1, $response->toArray()['bannerConfigs']); + $payload = $response->toArray(); + self::assertEquals( + [ + 'displayOnHomePage', + 'displayOnProductPage', + 'displayOnCartPage', + 'displayOnProductListingPage', + ], + $payload['displayLocations'] + ); + self::assertCount(1, $payload['bannerConfigs']); } /** @@ -1925,47 +1955,37 @@ public function testGetBannerSettingsResponse(): void * @throws InvalidURLException */ public function testGetBannerSettingsEmptyResponse(): void - { - //Arrange - - //Act - /** @var BannerSettingsResponse $response */ - $response = ConfigurationWebhookAPI::configurationHandler()->handleRequest( - $this->signature, - [ - "topic" => "get-banner-settings" - ] - ); - - //Assert - self::assertTrue($response->isSuccessful()); - self::assertEmpty($response->toArray()); - } - - /** - * @return void - */ - public function testGetBannerDisplayLocations(): void { //Arrange $this->bannerService->setBannerDisplayLocations([ 'displayOnHomePage', 'displayOnProductPage', 'displayOnCartPage', - 'displayOnProductListingPage' + 'displayOnProductListingPage', ]); //Act - /** @var BannerDisplayLocationsResponse $response */ + /** @var BannerSettingsResponse $response */ $response = ConfigurationWebhookAPI::configurationHandler()->handleRequest( $this->signature, [ - "topic" => "get-banner-display-locations" + "topic" => "get-banner-settings" ] ); //Assert self::assertTrue($response->isSuccessful()); - self::assertCount(4, $response->toArray()); + self::assertEquals( + [ + 'displayLocations' => [ + 'displayOnHomePage', + 'displayOnProductPage', + 'displayOnCartPage', + 'displayOnProductListingPage', + ], + 'bannerConfigs' => [], + ], + $response->toArray() + ); } } From f1f7ff4cf2d602d5b461864907a93fe1dbfcbda8 Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Tue, 12 May 2026 13:24:21 +0200 Subject: [PATCH 12/18] Remove banner settings and uploaded images LIS-111 --- src/BusinessLogic/BootstrapComponent.php | 3 +- .../Services/BannerSettingsService.php | 41 +++++++++ .../Disconnect/Services/DisconnectService.php | 12 ++- .../DisconnectionControllerApiTest.php | 4 +- .../Services/DisconnectServiceTest.php | 90 ++++++++++++++++++- 5 files changed, 146 insertions(+), 4 deletions(-) diff --git a/src/BusinessLogic/BootstrapComponent.php b/src/BusinessLogic/BootstrapComponent.php index 36a46f4..1e9c271 100644 --- a/src/BusinessLogic/BootstrapComponent.php +++ b/src/BusinessLogic/BootstrapComponent.php @@ -509,7 +509,8 @@ static function () { ServiceRegister::getService(StatisticalDataRepositoryInterface::class), ServiceRegister::getService(TransactionLogRepositoryInterface::class), ServiceRegister::getService(StoreIntegrationService::class), - ServiceRegister::getService(AdvancedSettingsRepositoryInterface::class) + ServiceRegister::getService(AdvancedSettingsRepositoryInterface::class), + ServiceRegister::getService(BannerSettingsService::class) ); } ); diff --git a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php index d76d1ca..d8faf04 100644 --- a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php +++ b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php @@ -92,6 +92,47 @@ public function setBannerSettings(BannerSettings $bannerSettings): BannerSetting return $persisted; } + /** + * Removes banner images currently uploaded to the integration server + * + * @return void + */ + public function deleteUploadedBannerImages(): void + { + $bannerSettings = $this->getBannerSettings(); + if ($bannerSettings === null) { + return; + } + + foreach ($bannerSettings->getBannerConfigs() as $banner) { + $this->bannerService->deleteBannerImage( + $banner->getCountry(), + $banner->getDisplayLocation() + ); + } + } + + /** + * Deletes the banner settings + * + * @return void + */ + public function deleteBannerSettings(): void + { + $this->bannerSettingsRepository->deleteBannerSettings(); + } + + /** + * Removes both the uploaded banner images and banner settings. + * + * @return void + */ + public function clearBannerSettings(): void + { + $this->deleteUploadedBannerImages(); + $this->deleteBannerSettings(); + } + /** * Returns banner data * diff --git a/src/BusinessLogic/Domain/Disconnect/Services/DisconnectService.php b/src/BusinessLogic/Domain/Disconnect/Services/DisconnectService.php index 74e959a..a455f39 100644 --- a/src/BusinessLogic/Domain/Disconnect/Services/DisconnectService.php +++ b/src/BusinessLogic/Domain/Disconnect/Services/DisconnectService.php @@ -3,6 +3,7 @@ namespace SeQura\Core\BusinessLogic\Domain\Disconnect\Services; use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\RepositoryContracts\AdvancedSettingsRepositoryInterface; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; use SeQura\Core\BusinessLogic\Domain\Connection\RepositoryContracts\ConnectionDataRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\Connection\RepositoryContracts\CredentialsRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\CountryConfiguration\RepositoryContracts\CountryConfigurationRepositoryInterface; @@ -102,6 +103,11 @@ class DisconnectService */ protected $advancedSettingsRepository; + /** + * @var BannerSettingsService $bannerSettingsService + */ + protected $bannerSettingsService; + /** * @param DisconnectServiceInterface $integrationDisconnectService * @param SendReportRepositoryInterface $sendReportRepository @@ -118,6 +124,7 @@ class DisconnectService * @param TransactionLogRepositoryInterface $transactionLogRepository * @param StoreIntegrationService $storeIntegrationService * @param AdvancedSettingsRepositoryInterface $advancedSettingsRepository + * @param BannerSettingsService $bannerSettingsService */ public function __construct( DisconnectServiceInterface $integrationDisconnectService, @@ -134,7 +141,8 @@ public function __construct( StatisticalDataRepositoryInterface $statisticalDataRepository, TransactionLogRepositoryInterface $transactionLogRepository, StoreIntegrationService $storeIntegrationService, - AdvancedSettingsRepositoryInterface $advancedSettingsRepository + AdvancedSettingsRepositoryInterface $advancedSettingsRepository, + BannerSettingsService $bannerSettingsService ) { $this->integrationDisconnectService = $integrationDisconnectService; $this->sendReportRepository = $sendReportRepository; @@ -151,6 +159,7 @@ public function __construct( $this->transactionLogRepository = $transactionLogRepository; $this->storeIntegrationService = $storeIntegrationService; $this->advancedSettingsRepository = $advancedSettingsRepository; + $this->bannerSettingsService = $bannerSettingsService; } /** @@ -186,6 +195,7 @@ public function disconnect(string $deploymentId, bool $isFullDisconnect): void $this->orderStatusSettingsRepository->deleteOrderStatusMapping(); $this->paymentMethodRepository->deleteAllPaymentMethods(); $this->widgetSettingsRepository->deleteWidgetSettings(); + $this->bannerSettingsService->clearBannerSettings(); $this->sendReportRepository->deleteSendReportForContext(StoreContext::getInstance()->getStoreId()); $this->statisticalDataRepository->deleteStatisticalData(); $this->transactionLogRepository->deleteAllTransactionLogs(); diff --git a/tests/BusinessLogic/AdminAPI/Disconnection/DisconnectionControllerApiTest.php b/tests/BusinessLogic/AdminAPI/Disconnection/DisconnectionControllerApiTest.php index 62a4410..6b3628b 100644 --- a/tests/BusinessLogic/AdminAPI/Disconnection/DisconnectionControllerApiTest.php +++ b/tests/BusinessLogic/AdminAPI/Disconnection/DisconnectionControllerApiTest.php @@ -5,6 +5,7 @@ use SeQura\Core\BusinessLogic\AdminAPI\AdminAPI; use SeQura\Core\BusinessLogic\AdminAPI\Disconnect\Requests\DisconnectRequest; use SeQura\Core\BusinessLogic\AdminAPI\Disconnect\Responses\DisconnectResponse; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; use SeQura\Core\BusinessLogic\Domain\Connection\RepositoryContracts\ConnectionDataRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\Connection\RepositoryContracts\CredentialsRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\CountryConfiguration\RepositoryContracts\CountryConfigurationRepositoryInterface; @@ -57,7 +58,8 @@ protected function setUp(): void ServiceRegister::getService(StatisticalDataRepositoryInterface::class), ServiceRegister::getService(TransactionLogRepositoryInterface::class), ServiceRegister::getService(StoreIntegrationService::class), - new MockAdvancedSettingsRepository() + new MockAdvancedSettingsRepository(), + ServiceRegister::getService(BannerSettingsService::class) ); TestServiceRegister::registerService(DisconnectService::class, function () { diff --git a/tests/BusinessLogic/Domain/Disconnect/Services/DisconnectServiceTest.php b/tests/BusinessLogic/Domain/Disconnect/Services/DisconnectServiceTest.php index c2a3e87..874f6c5 100644 --- a/tests/BusinessLogic/Domain/Disconnect/Services/DisconnectServiceTest.php +++ b/tests/BusinessLogic/Domain/Disconnect/Services/DisconnectServiceTest.php @@ -6,6 +6,9 @@ use Exception; use SeQura\Core\BusinessLogic\DataAccess\TransactionLog\Entities\TransactionLog; use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Models\AdvancedSettings; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\Banner; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\BannerSettings; +use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; use SeQura\Core\BusinessLogic\Domain\Connection\Exceptions\InvalidEnvironmentException; use SeQura\Core\BusinessLogic\Domain\Connection\Models\AuthorizationCredentials; use SeQura\Core\BusinessLogic\Domain\Connection\Models\ConnectionData; @@ -25,6 +28,7 @@ use SeQura\Core\BusinessLogic\Domain\Order\RepositoryContracts\SeQuraOrderRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\OrderStatusSettings\Models\OrderStatusMapping; use SeQura\Core\BusinessLogic\Domain\OrderStatusSettings\RepositoryContracts\OrderStatusSettingsRepositoryInterface; +use SeQura\Core\BusinessLogic\Domain\PaymentMethod\Exceptions\PaymentMethodNotFoundException; use SeQura\Core\BusinessLogic\Domain\PaymentMethod\Models\SeQuraCost; use SeQura\Core\BusinessLogic\Domain\PaymentMethod\Models\SeQuraPaymentMethod; use SeQura\Core\BusinessLogic\Domain\PaymentMethod\RepositoryContracts\PaymentMethodRepositoryInterface; @@ -37,6 +41,8 @@ use SeQura\Core\BusinessLogic\TransactionLog\RepositoryContracts\TransactionLogRepositoryInterface; use SeQura\Core\Tests\BusinessLogic\Common\BaseTestCase; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockAdvancedSettingsRepository; +use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockBannerService; +use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockBannerSettingsRepository; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockConnectionDataRepository; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockCountryConfigurationRepository; use SeQura\Core\Tests\BusinessLogic\Common\MockComponents\MockCredentialsRepository; @@ -137,6 +143,21 @@ class DisconnectServiceTest extends BaseTestCase */ private $advancedSettingsRepository; + /** + * @var MockBannerSettingsRepository $bannerSettingsRepository + */ + private $bannerSettingsRepository; + + /** + * @var MockBannerService $bannerService + */ + private $bannerService; + + /** + * @var BannerSettingsService $bannerSettingsService + */ + private $bannerSettingsService; + /** * @var DisconnectService $service */ @@ -166,6 +187,12 @@ protected function setUp(): void new MockStoreInfoService() ); $this->advancedSettingsRepository = new MockAdvancedSettingsRepository(); + $this->bannerSettingsRepository = new MockBannerSettingsRepository(); + $this->bannerService = new MockBannerService(); + $this->bannerSettingsService = new BannerSettingsService( + $this->bannerSettingsRepository, + $this->bannerService + ); $this->service = new DisconnectService( $this->integrationDisconnectService, @@ -182,7 +209,8 @@ protected function setUp(): void $this->statisticalDataRepository, $this->transactionLogRepository, $this->storeIntegrationService, - $this->advancedSettingsRepository + $this->advancedSettingsRepository, + $this->bannerSettingsService ); } @@ -509,4 +537,64 @@ public function testDisconnectIntegrationDeleted(): void //Assert self::assertTrue($this->storeIntegrationService->isDeleted()); } + + /** + * @return void + * + * @throws PaymentMethodNotFoundException + */ + public function testDisconnectFullClearsBannerSettingsAndImages(): void + { + //Arrange + $this->bannerSettingsRepository->setBannerSettings(new BannerSettings([ + new Banner( + 'ES', + 'https://www.sequra.es/es/faq#shoppers', + 'https://shop.test/banners/ES_displayOnHomePage.png', + 'displayOnHomePage' + ), + new Banner( + 'PT', + 'https://www.sequra.pt/pt/faq#shoppers', + 'https://shop.test/banners/PT_displayOnCartPage.png', + 'displayOnCartPage' + ), + ])); + + //Act + $this->service->disconnect('sequra', true); + + //Assert + self::assertNull($this->bannerSettingsRepository->getBannerSettings()); + self::assertEquals( + ['ES|displayOnHomePage', 'PT|displayOnCartPage'], + $this->bannerService->getDeletedImageKeys() + ); + } + + /** + * @return void + * + * @throws PaymentMethodNotFoundException + */ + public function testDisconnectNotFullPreservesBannerSettings(): void + { + //Arrange + $existing = new BannerSettings([ + new Banner( + 'ES', + 'https://www.sequra.es/es/faq#shoppers', + 'https://shop.test/banners/ES_displayOnHomePage.png', + 'displayOnHomePage' + ), + ]); + $this->bannerSettingsRepository->setBannerSettings($existing); + + //Act + $this->service->disconnect('sequra', false); + + //Assert + self::assertNotNull($this->bannerSettingsRepository->getBannerSettings()); + self::assertEmpty($this->bannerService->getDeletedImageKeys()); + } } From 12ca9c7a8857011b68edd76720a1eebcae09f71b Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Tue, 12 May 2026 14:20:46 +0200 Subject: [PATCH 13/18] Add banner capability LIS-111 --- .../StoreIntegration/Models/Capability.php | 19 +++++++++++++++++++ .../Models/CapabilityModelTest.php | 17 +++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/BusinessLogic/Domain/StoreIntegration/Models/Capability.php b/src/BusinessLogic/Domain/StoreIntegration/Models/Capability.php index 5488ce6..0b3e48d 100644 --- a/src/BusinessLogic/Domain/StoreIntegration/Models/Capability.php +++ b/src/BusinessLogic/Domain/StoreIntegration/Models/Capability.php @@ -21,6 +21,11 @@ class Capability */ private const WIDGET = 'widget'; + /** + * Banner capability string constant. + */ + private const BANNER = 'banner'; + /** * Order status capability string constant. */ @@ -84,6 +89,16 @@ public static function widget(): self return new self(self::WIDGET); } + /** + * Called for banner capability. + * + * @return Capability + */ + public static function banner(): self + { + return new self(self::BANNER); + } + /** * Called for order status capability. * @@ -171,6 +186,10 @@ public static function parse(string $capability): self return self::widget(); } + if ($capability === self::BANNER) { + return self::banner(); + } + if ($capability === self::ORDER_STATUS) { return self::orderStatus(); } diff --git a/tests/BusinessLogic/Domain/StoreIntegration/Models/CapabilityModelTest.php b/tests/BusinessLogic/Domain/StoreIntegration/Models/CapabilityModelTest.php index b7e7e90..a9179d7 100644 --- a/tests/BusinessLogic/Domain/StoreIntegration/Models/CapabilityModelTest.php +++ b/tests/BusinessLogic/Domain/StoreIntegration/Models/CapabilityModelTest.php @@ -62,6 +62,23 @@ public function testWidgetCapability(): void self::assertEquals(Capability::widget(), $capability); } + /** + * @return void + * + * @throws InvalidCapabilityException + */ + public function testBannerCapability(): void + { + // arrange + + // act + $capability = Capability::parse('banner'); + + // assert + self::assertEquals('banner', $capability->getCapability()); + self::assertEquals(Capability::banner(), $capability); + } + /** * @return void * From 1fdec158041d0734091c9902598da2c0c0e58281 Mon Sep 17 00:00:00 2001 From: Tamara Vukovic Date: Tue, 12 May 2026 14:56:46 +0200 Subject: [PATCH 14/18] Add error log when image cannot be deleted from integration system LIS-111 --- .../Services/BannerSettingsService.php | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php index d8faf04..eb77e73 100644 --- a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php +++ b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php @@ -9,6 +9,9 @@ use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; use SeQura\Core\BusinessLogic\Domain\Integration\Banner\BannerServiceInterface; use SeQura\Core\BusinessLogic\Domain\Translations\Model\TranslatableLabel; +use SeQura\Core\Infrastructure\Logger\LogContextData; +use SeQura\Core\Infrastructure\Logger\Logger; +use Throwable; /** * Class BannerSettingsService @@ -93,7 +96,7 @@ public function setBannerSettings(BannerSettings $bannerSettings): BannerSetting } /** - * Removes banner images currently uploaded to the integration server + * Removes banner images currently uploaded to the integration server. * * @return void */ @@ -105,10 +108,23 @@ public function deleteUploadedBannerImages(): void } foreach ($bannerSettings->getBannerConfigs() as $banner) { - $this->bannerService->deleteBannerImage( - $banner->getCountry(), - $banner->getDisplayLocation() - ); + try { + $this->bannerService->deleteBannerImage( + $banner->getCountry(), + $banner->getDisplayLocation() + ); + } catch (Throwable $e) { + Logger::logError( + 'Failed to delete uploaded banner image.', + 'Core', + [ + new LogContextData('country', $banner->getCountry()), + new LogContextData('displayLocation', $banner->getDisplayLocation()), + new LogContextData('message', $e->getMessage()), + new LogContextData('type', get_class($e)), + ] + ); + } } } From 4e10721cc0d8c36f227f116f599ed717d3daefde Mon Sep 17 00:00:00 2001 From: Boljanovic Date: Mon, 18 May 2026 15:47:43 +0200 Subject: [PATCH 15/18] Add selling countries to banner response ISSUE: LIS-111 --- composer.lock | 160 +++++++++++------- src/BusinessLogic/BootstrapComponent.php | 3 +- .../GetBannerSettingsHandler.php | 23 ++- .../BannerSettings/BannerSettingsResponse.php | 10 +- tests/BusinessLogic/Common/BaseTestCase.php | 3 +- .../ConfigurationWebhookAPITest.php | 8 + 6 files changed, 141 insertions(+), 66 deletions(-) diff --git a/composer.lock b/composer.lock index d40d9db..6d81f44 100644 --- a/composer.lock +++ b/composer.lock @@ -549,16 +549,11 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.28", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "fcf8b71aeab4e1a1131d1783cef97b23a51b87a9" - }, + "version": "1.12.33", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/fcf8b71aeab4e1a1131d1783cef97b23a51b87a9", - "reference": "fcf8b71aeab4e1a1131d1783cef97b23a51b87a9", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/37982d6fc7cbb746dda7773530cda557cdf119e1", + "reference": "37982d6fc7cbb746dda7773530cda557cdf119e1", "shasum": "" }, "require": { @@ -603,7 +598,7 @@ "type": "github" } ], - "time": "2025-07-17T17:15:39+00:00" + "time": "2026-02-28T20:30:03+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1056,16 +1051,16 @@ }, { "name": "sebastian/comparator", - "version": "3.0.5", + "version": "3.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770" + "reference": "bc7d8ac2fe1cce229bff9b5fd4efe65918a1ff52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dc7ceb4a24aede938c7af2a9ed1de09609ca770", - "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/bc7d8ac2fe1cce229bff9b5fd4efe65918a1ff52", + "reference": "bc7d8ac2fe1cce229bff9b5fd4efe65918a1ff52", "shasum": "" }, "require": { @@ -1118,15 +1113,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.7" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" } ], - "time": "2022-09-14T12:31:48+00:00" + "time": "2026-01-24T09:20:25+00:00" }, { "name": "sebastian/diff", @@ -1259,16 +1266,16 @@ }, { "name": "sebastian/exporter", - "version": "3.1.6", + "version": "3.1.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "1939bc8fd1d39adcfa88c5b35335910869214c56" + "reference": "64cfeaa341951ceb2019d7b98232399d57bb2296" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/1939bc8fd1d39adcfa88c5b35335910869214c56", - "reference": "1939bc8fd1d39adcfa88c5b35335910869214c56", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/64cfeaa341951ceb2019d7b98232399d57bb2296", + "reference": "64cfeaa341951ceb2019d7b98232399d57bb2296", "shasum": "" }, "require": { @@ -1324,28 +1331,40 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.6" + "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" } ], - "time": "2024-03-02T06:21:38+00:00" + "time": "2025-09-24T05:55:14+00:00" }, { "name": "sebastian/global-state", - "version": "3.0.5", + "version": "3.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "91c7c47047a971f02de57ed6f040087ef110c5d9" + "reference": "800689427e3e8cf57a8fe38fcd1d4344c9b2f046" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/91c7c47047a971f02de57ed6f040087ef110c5d9", - "reference": "91c7c47047a971f02de57ed6f040087ef110c5d9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/800689427e3e8cf57a8fe38fcd1d4344c9b2f046", + "reference": "800689427e3e8cf57a8fe38fcd1d4344c9b2f046", "shasum": "" }, "require": { @@ -1388,15 +1407,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.6" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", + "type": "tidelift" } ], - "time": "2024-03-02T06:13:16+00:00" + "time": "2025-08-10T05:40:12+00:00" }, { "name": "sebastian/object-enumerator", @@ -1512,16 +1543,16 @@ }, { "name": "sebastian/recursion-context", - "version": "3.0.2", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c" + "reference": "8fe7e75986a9d24b4cceae847314035df7703a5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/9bfd3c6f1f08c026f542032dfb42813544f7d64c", - "reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/8fe7e75986a9d24b4cceae847314035df7703a5a", + "reference": "8fe7e75986a9d24b4cceae847314035df7703a5a", "shasum": "" }, "require": { @@ -1563,15 +1594,27 @@ "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.2" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2024-03-01T14:07:30+00:00" + "time": "2025-08-10T05:25:53+00:00" }, { "name": "sebastian/resource-operations", @@ -1729,16 +1772,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.13.2", + "version": "3.13.5", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "5b5e3821314f947dd040c70f7992a64eac89025c" + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/5b5e3821314f947dd040c70f7992a64eac89025c", - "reference": "5b5e3821314f947dd040c70f7992a64eac89025c", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4", + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4", "shasum": "" }, "require": { @@ -1755,11 +1798,6 @@ "bin/phpcs" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -1809,20 +1847,20 @@ "type": "thanks_dev" } ], - "time": "2025-06-17T22:17:01+00:00" + "time": "2025-11-04T16:30:35+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -1851,7 +1889,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -1859,32 +1897,32 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" }, { "name": "webmozart/assert", - "version": "1.11.0", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + "reference": "9be6926d8b485f55b9229203f962b51ed377ba68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68", + "reference": "9be6926d8b485f55b9229203f962b51ed377ba68", "shasum": "" }, "require": { "ext-ctype": "*", + "ext-date": "*", + "ext-filter": "*", "php": "^7.2 || ^8.0" }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" + "suggest": { + "ext-intl": "", + "ext-simplexml": "", + "ext-spl": "" }, "type": "library", "extra": { @@ -1915,9 +1953,9 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" + "source": "https://github.com/webmozarts/assert/tree/1.12.1" }, - "time": "2022-06-03T18:03:27+00:00" + "time": "2025-10-29T15:56:20+00:00" } ], "aliases": [], diff --git a/src/BusinessLogic/BootstrapComponent.php b/src/BusinessLogic/BootstrapComponent.php index 1e9c271..6b70f56 100644 --- a/src/BusinessLogic/BootstrapComponent.php +++ b/src/BusinessLogic/BootstrapComponent.php @@ -1193,7 +1193,8 @@ static function () { static function () { return new GetBannerSettingsHandler( ServiceRegister::getService(BannerSettingsService::class), - ServiceRegister::getService(BannerServiceInterface::class) + ServiceRegister::getService(BannerServiceInterface::class), + ServiceRegister::getService(CountryConfigurationService::class) ); } ); diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerSettingsHandler.php b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerSettingsHandler.php index b02c1ed..60bdc95 100644 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerSettingsHandler.php +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/GetBannerSettingsHandler.php @@ -7,6 +7,9 @@ use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\BannerSettings\BannerSettingsResponse; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Models\BannerSettings; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; +use SeQura\Core\BusinessLogic\Domain\CountryConfiguration\Exceptions\FailedToRetrieveSellingCountriesException; +use SeQura\Core\BusinessLogic\Domain\CountryConfiguration\Models\CountryConfiguration; +use SeQura\Core\BusinessLogic\Domain\CountryConfiguration\Services\CountryConfigurationService; use SeQura\Core\BusinessLogic\Domain\Integration\Banner\BannerServiceInterface; /** @@ -26,30 +29,46 @@ class GetBannerSettingsHandler implements TopicHandlerInterface */ protected $bannerService; + /** + * @var CountryConfigurationService + */ + protected $countryConfigurationService; + /** * @param BannerSettingsService $bannerSettingsService * @param BannerServiceInterface $bannerService + * @param CountryConfigurationService $countryConfigurationService */ public function __construct( BannerSettingsService $bannerSettingsService, - BannerServiceInterface $bannerService + BannerServiceInterface $bannerService, + CountryConfigurationService $countryConfigurationService ) { $this->bannerSettingsService = $bannerSettingsService; $this->bannerService = $bannerService; + $this->countryConfigurationService = $countryConfigurationService; } /** * @param mixed[] $payload * * @return Response + * + * @throws FailedToRetrieveSellingCountriesException */ public function handle(array $payload): Response { $bannerSettings = $this->bannerSettingsService->getBannerSettings() ?? new BannerSettings([]); + $countryConfigurations = $this->countryConfigurationService->getCountryConfiguration() ?? []; + $sellingCountries = array_map(function (CountryConfiguration $countyConfiguration) { + return $countyConfiguration->getCountryCode(); + }, $countryConfigurations); + return new BannerSettingsResponse( $bannerSettings, - $this->bannerService->getBannerDisplayLocations() + $this->bannerService->getBannerDisplayLocations(), + $sellingCountries ); } } diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerSettingsResponse.php b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerSettingsResponse.php index 397af76..fc81819 100644 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerSettingsResponse.php +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Responses/BannerSettings/BannerSettingsResponse.php @@ -22,14 +22,21 @@ class BannerSettingsResponse extends Response */ protected $displayLocations; + /** + * @var string[] + */ + protected $sellingCountries; + /** * @param BannerSettings $settings * @param string[] $displayLocations + * @param string[] $sellingCountries */ - public function __construct(BannerSettings $settings, array $displayLocations) + public function __construct(BannerSettings $settings, array $displayLocations, array $sellingCountries = []) { $this->settings = $settings; $this->displayLocations = $displayLocations; + $this->sellingCountries = $sellingCountries; } /** @@ -41,6 +48,7 @@ public function toArray(): array return [ 'displayLocations' => $this->displayLocations, + 'sellingCountries' => $this->sellingCountries, 'bannerConfigs' => $settingsArray['bannerConfigs'] ?? [], ]; } diff --git a/tests/BusinessLogic/Common/BaseTestCase.php b/tests/BusinessLogic/Common/BaseTestCase.php index 7a1baf6..0504840 100644 --- a/tests/BusinessLogic/Common/BaseTestCase.php +++ b/tests/BusinessLogic/Common/BaseTestCase.php @@ -860,7 +860,8 @@ static function () { static function () { return new GetBannerSettingsHandler( TestServiceRegister::getService(BannerSettingsService::class), - TestServiceRegister::getService(BannerServiceInterface::class) + TestServiceRegister::getService(BannerServiceInterface::class), + TestServiceRegister::getService(CountryConfigurationService::class) ); } ); diff --git a/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php b/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php index 019ec57..28ab7ce 100644 --- a/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php +++ b/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php @@ -1924,6 +1924,12 @@ public function testGetBannerSettingsResponse(): void ] ) ); + $this->countryConfigurationService->saveCountryConfiguration([ + new CountryConfiguration('ES', 'merchant1'), + new CountryConfiguration('FR', 'merchant2'), + new CountryConfiguration('IT', 'merchant3'), + new CountryConfiguration('PT', 'merchant4'), + ]); //Act /** @var BannerSettingsResponse $response */ @@ -1946,6 +1952,7 @@ public function testGetBannerSettingsResponse(): void ], $payload['displayLocations'] ); + self::assertEquals(['ES', 'FR', 'IT', 'PT'], $payload['sellingCountries']); self::assertCount(1, $payload['bannerConfigs']); } @@ -1983,6 +1990,7 @@ public function testGetBannerSettingsEmptyResponse(): void 'displayOnCartPage', 'displayOnProductListingPage', ], + 'sellingCountries' => [], 'bannerConfigs' => [], ], $response->toArray() From d74da925e21840d45bebab2b390caf262cebee2d Mon Sep 17 00:00:00 2001 From: Boljanovic Date: Mon, 18 May 2026 17:12:08 +0200 Subject: [PATCH 16/18] Add selling countries to save banner response ISSUE: LIS-111 --- src/BusinessLogic/BootstrapComponent.php | 3 ++- .../SaveBannerSettingsHandler.php | 22 +++++++++++++++++-- tests/BusinessLogic/Common/BaseTestCase.php | 3 ++- .../ConfigurationWebhookAPITest.php | 7 ++++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/BusinessLogic/BootstrapComponent.php b/src/BusinessLogic/BootstrapComponent.php index 6b70f56..384670d 100644 --- a/src/BusinessLogic/BootstrapComponent.php +++ b/src/BusinessLogic/BootstrapComponent.php @@ -1204,7 +1204,8 @@ static function () { static function () { return new SaveBannerSettingsHandler( ServiceRegister::getService(BannerSettingsService::class), - ServiceRegister::getService(BannerServiceInterface::class) + ServiceRegister::getService(BannerServiceInterface::class), + ServiceRegister::getService(CountryConfigurationService::class) ); } ); diff --git a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php index e250468..7e29e8b 100644 --- a/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php +++ b/src/BusinessLogic/ConfigurationWebhookAPI/Handlers/BannerSettings/SaveBannerSettingsHandler.php @@ -9,6 +9,9 @@ use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\BannerImageRequiredException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Exceptions\InvalidURLException; use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; +use SeQura\Core\BusinessLogic\Domain\CountryConfiguration\Exceptions\FailedToRetrieveSellingCountriesException; +use SeQura\Core\BusinessLogic\Domain\CountryConfiguration\Models\CountryConfiguration; +use SeQura\Core\BusinessLogic\Domain\CountryConfiguration\Services\CountryConfigurationService; use SeQura\Core\BusinessLogic\Domain\Integration\Banner\BannerServiceInterface; /** @@ -28,16 +31,24 @@ class SaveBannerSettingsHandler implements TopicHandlerInterface */ protected $bannerService; + /** + * @var CountryConfigurationService + */ + protected $countryConfigurationService; + /** * @param BannerSettingsService $bannerSettingsService * @param BannerServiceInterface $bannerService + * @param CountryConfigurationService $countryConfigurationService */ public function __construct( BannerSettingsService $bannerSettingsService, - BannerServiceInterface $bannerService + BannerServiceInterface $bannerService, + CountryConfigurationService $countryConfigurationService ) { $this->bannerSettingsService = $bannerSettingsService; $this->bannerService = $bannerService; + $this->countryConfigurationService = $countryConfigurationService; } /** @@ -45,15 +56,22 @@ public function __construct( * * @throws BannerImageRequiredException * @throws InvalidURLException + * @throws FailedToRetrieveSellingCountriesException */ public function handle(array $payload): Response { $request = SaveBannerSettingsRequest::fromPayload($payload); $saved = $this->bannerSettingsService->setBannerSettings($request->transformToDomainModel()); + $countryConfigurations = $this->countryConfigurationService->getCountryConfiguration() ?? []; + $sellingCountries = array_map(function (CountryConfiguration $countryConfiguration) { + return $countryConfiguration->getCountryCode(); + }, $countryConfigurations); + return new BannerSettingsResponse( $saved, - $this->bannerService->getBannerDisplayLocations() + $this->bannerService->getBannerDisplayLocations(), + $sellingCountries ); } } diff --git a/tests/BusinessLogic/Common/BaseTestCase.php b/tests/BusinessLogic/Common/BaseTestCase.php index 0504840..dd6baa0 100644 --- a/tests/BusinessLogic/Common/BaseTestCase.php +++ b/tests/BusinessLogic/Common/BaseTestCase.php @@ -871,7 +871,8 @@ static function () { static function () { return new SaveBannerSettingsHandler( TestServiceRegister::getService(BannerSettingsService::class), - TestServiceRegister::getService(BannerServiceInterface::class) + TestServiceRegister::getService(BannerServiceInterface::class), + TestServiceRegister::getService(CountryConfigurationService::class) ); } ); diff --git a/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php b/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php index 28ab7ce..4024db6 100644 --- a/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php +++ b/tests/BusinessLogic/ConfigurationWebhookAPI/ConfigurationWebhookAPITest.php @@ -1802,6 +1802,12 @@ public function testSaveBannerSettingsResponse(): void ] ) ); + $this->countryConfigurationService->saveCountryConfiguration([ + new CountryConfiguration('ES', 'merchant1'), + new CountryConfiguration('FR', 'merchant2'), + new CountryConfiguration('IT', 'merchant3'), + new CountryConfiguration('PT', 'merchant4'), + ]); //Act $response = ConfigurationWebhookAPI::configurationHandler()->handleRequest( @@ -1837,6 +1843,7 @@ public function testSaveBannerSettingsResponse(): void ], $payload['displayLocations'] ); + self::assertEquals(['ES', 'FR', 'IT', 'PT'], $payload['sellingCountries']); self::assertCount(2, $payload['bannerConfigs']); self::assertEquals('ES', $payload['bannerConfigs'][0]['country']); self::assertEquals('PT', $payload['bannerConfigs'][1]['country']); From ddd0be400faa3ede958e83afb6341f86dee299f0 Mon Sep 17 00:00:00 2001 From: Boljanovic Date: Mon, 18 May 2026 17:54:26 +0200 Subject: [PATCH 17/18] Update banner image when display location is changed ISSUE: LIS-111 --- .../Services/BannerSettingsService.php | 184 +++++++++++++----- .../Banner/BannerServiceInterface.php | 18 ++ .../MockComponents/MockBannerService.php | 38 ++++ .../Service/BannerSettingsServiceTest.php | 142 ++++++++++++++ 4 files changed, 329 insertions(+), 53 deletions(-) diff --git a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php index eb77e73..20eee57 100644 --- a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php +++ b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php @@ -64,30 +64,12 @@ public function getBannerSettings(): ?BannerSettings */ public function setBannerSettings(BannerSettings $bannerSettings): BannerSettings { + $existingBanners = $this->getExistingBanners(); + $existingByCountry = $this->indexByCountry($existingBanners); $incomingBanners = $bannerSettings->getBannerConfigs(); - $existingBannerSettings = $this->getBannerSettings(); - $existingBanners = $existingBannerSettings - ? $existingBannerSettings->getBannerConfigs() - : []; - - $existingBannersByKey = $this->indexByKey($existingBanners); - $incomingBannersByKey = $this->indexByKey($incomingBanners); - - $resolvedBanners = []; - foreach ($incomingBanners as $banner) { - $this->assertValidUrl($banner->getLinkUrl()); - $this->assertBannerHasImageSource($banner, $existingBannersByKey); - - $resolvedBanners[] = $this->resolveBannerImage($banner, $existingBannersByKey); - } - - foreach (array_diff_key($existingBannersByKey, $incomingBannersByKey) as $bannerToRemove) { - $this->bannerService->deleteBannerImage( - $bannerToRemove->getCountry(), - $bannerToRemove->getDisplayLocation() - ); - } + $resolvedBanners = $this->resolveIncomingBanners($incomingBanners, $existingByCountry); + $this->deleteRemovedBanners($existingBanners, $this->indexByCountry($incomingBanners)); $persisted = new BannerSettings($resolvedBanners); $this->bannerSettingsRepository->setBannerSettings($persisted); @@ -174,18 +156,68 @@ public function getBannerData(string $country, string $displayLocation): ?Banner return null; } + /** + * @return Banner[] + */ + protected function getExistingBanners(): array + { + $existingBannerSettings = $this->getBannerSettings(); + + return $existingBannerSettings ? $existingBannerSettings->getBannerConfigs() : []; + } + + /** + * @param Banner[] $incomingBanners + * @param array $existingByCountry + * + * @return Banner[] + * + * @throws BannerImageRequiredException + * @throws InvalidURLException + */ + protected function resolveIncomingBanners(array $incomingBanners, array $existingByCountry): array + { + $resolved = []; + foreach ($incomingBanners as $banner) { + $this->assertValidUrl($banner->getLinkUrl()); + $this->assertBannerHasImageSource($banner, $existingByCountry); + + $resolved[] = $this->resolveBannerImage($banner, $existingByCountry); + } + + return $resolved; + } + + /** + * Deletes images for countries that are no longer present in the incoming set. + * + * @param Banner[] $existingBanners + * @param array $incomingByCountry + */ + protected function deleteRemovedBanners(array $existingBanners, array $incomingByCountry): void + { + foreach ($existingBanners as $banner) { + if (!isset($incomingByCountry[$banner->getCountry()])) { + $this->bannerService->deleteBannerImage( + $banner->getCountry(), + $banner->getDisplayLocation() + ); + } + } + } + /** * Verifies whether the banner contains an imageBase64 payload - * or already has a persisted image in storage. + * or already has a persisted image in storage for the country. * * @param Banner $banner - * @param array $existingByKey + * @param array $existingByCountry * * @throws BannerImageRequiredException */ - protected function assertBannerHasImageSource(Banner $banner, array $existingByKey): void + protected function assertBannerHasImageSource(Banner $banner, array $existingByCountry): void { - if ($this->hasImageBase64($banner) || isset($existingByKey[$this->keyFor($banner)])) { + if ($this->hasImageBase64($banner) || isset($existingByCountry[$banner->getCountry()])) { return; } @@ -198,39 +230,95 @@ protected function assertBannerHasImageSource(Banner $banner, array $existingByK } /** - * Uploads a new image when a base64 payload is present, otherwise reuses - * the URL of the previously stored banner + * Resolves the image URL for an incoming banner: + * - If a new imageBase64 is supplied, uploads it (deleting the previous + * image first when the display location has changed). + * - Otherwise reuses the previous URL if the display location is + * unchanged, or asks the integration to relocate the image when the + * display location has changed. * * @param Banner $banner - * @param array $existingByKey + * @param array $existingByCountry * * @return Banner * * @throws InvalidURLException */ - protected function resolveBannerImage(Banner $banner, array $existingByKey): Banner + protected function resolveBannerImage(Banner $banner, array $existingByCountry): Banner { - $key = $this->keyFor($banner); + $existing = $existingByCountry[$banner->getCountry()] ?? null; if ($this->hasImageBase64($banner)) { - $banner->setImageUrl( - $this->bannerService->saveBannerImage( - $banner->getCountry(), - $banner->getDisplayLocation(), - $banner->getImageBase64() - ) - ); - } elseif (isset($existingByKey[$key])) { - $banner->setImageUrl($existingByKey[$key]->getImageUrl()); + $this->uploadBannerImage($banner, $existing); + } elseif ($existing !== null) { + $banner->setImageUrl($this->reuseOrRelocateImageUrl($banner, $existing)); } $banner->setImageBase64(null); - $this->assertValidUrl($banner->getImageUrl()); return $banner; } + /** + * Uploads the banner image, deleting the previously stored one when the + * display location has changed. + * + * @param Banner $banner + * @param Banner|null $existing + */ + protected function uploadBannerImage(Banner $banner, ?Banner $existing): void + { + $this->deleteImageIfLocationChanged($banner, $existing); + + $banner->setImageUrl( + $this->bannerService->saveBannerImage( + $banner->getCountry(), + $banner->getDisplayLocation(), + $banner->getImageBase64() + ) + ); + } + + /** + * Returns the existing image URL when the display location is unchanged, + * otherwise asks the integration to relocate the image and returns the + * new URL. + * + * @param Banner $banner + * @param Banner $existing + * + * @return string + */ + protected function reuseOrRelocateImageUrl(Banner $banner, Banner $existing): string + { + if ($existing->getDisplayLocation() === $banner->getDisplayLocation()) { + return $existing->getImageUrl(); + } + + return $this->bannerService->changeBannerImageDisplayLocation( + $banner->getCountry(), + $existing->getDisplayLocation(), + $banner->getDisplayLocation() + ); + } + + /** + * @param Banner $banner + * @param Banner|null $existing + */ + protected function deleteImageIfLocationChanged(Banner $banner, ?Banner $existing): void + { + if ($existing === null || $existing->getDisplayLocation() === $banner->getDisplayLocation()) { + return; + } + + $this->bannerService->deleteBannerImage( + $existing->getCountry(), + $existing->getDisplayLocation() + ); + } + /** * @param Banner $banner * @@ -248,26 +336,16 @@ protected function hasImageBase64(Banner $banner): bool * * @return array */ - protected function indexByKey(array $banners): array + protected function indexByCountry(array $banners): array { $indexed = []; foreach ($banners as $banner) { - $indexed[$this->keyFor($banner)] = $banner; + $indexed[$banner->getCountry()] = $banner; } return $indexed; } - /** - * @param Banner $banner - * - * @return string - */ - protected function keyFor(Banner $banner): string - { - return $banner->getCountry() . '|' . $banner->getDisplayLocation(); - } - /** * Validates the URL * diff --git a/src/BusinessLogic/Domain/Integration/Banner/BannerServiceInterface.php b/src/BusinessLogic/Domain/Integration/Banner/BannerServiceInterface.php index c348112..e961786 100644 --- a/src/BusinessLogic/Domain/Integration/Banner/BannerServiceInterface.php +++ b/src/BusinessLogic/Domain/Integration/Banner/BannerServiceInterface.php @@ -36,4 +36,22 @@ public function saveBannerImage(string $country, string $displayLocation, string * @return void */ public function deleteBannerImage(string $country, string $displayLocation): void; + + /** + * Notifies the integration that the banner image for the given country + * is moving from one display location to another. + * The integration is responsible for relocating the underlying image + * and returning the public URL at the new location. + * + * @param string $country + * @param string $oldDisplayLocation + * @param string $newDisplayLocation + * + * @return string Public URL of the image at the new display location. + */ + public function changeBannerImageDisplayLocation( + string $country, + string $oldDisplayLocation, + string $newDisplayLocation + ): string; } diff --git a/tests/BusinessLogic/Common/MockComponents/MockBannerService.php b/tests/BusinessLogic/Common/MockComponents/MockBannerService.php index 7395a25..996327b 100644 --- a/tests/BusinessLogic/Common/MockComponents/MockBannerService.php +++ b/tests/BusinessLogic/Common/MockComponents/MockBannerService.php @@ -26,6 +26,11 @@ class MockBannerService implements BannerServiceInterface */ protected $deletedImages = []; + /** + * @var array + */ + protected $movedImages = []; + /** * @inheritDoc */ @@ -64,6 +69,39 @@ public function deleteBannerImage(string $country, string $displayLocation): voi $this->deletedImages[$key] = true; } + /** + * @inheritDoc + */ + public function changeBannerImageDisplayLocation( + string $country, + string $oldDisplayLocation, + string $newDisplayLocation + ): string { + $oldKey = $this->key($country, $oldDisplayLocation); + $newKey = $this->key($country, $newDisplayLocation); + + if (isset($this->storedImages[$oldKey])) { + $this->storedImages[$newKey] = $this->storedImages[$oldKey]; + unset($this->storedImages[$oldKey]); + } + + $this->movedImages[$newKey] = [ + 'country' => $country, + 'from' => $oldDisplayLocation, + 'to' => $newDisplayLocation, + ]; + + return 'https://shop.test/banners/' . $country . '_' . $newDisplayLocation . '.png'; + } + + /** + * @return array + */ + public function getMovedImages(): array + { + return $this->movedImages; + } + /** * @return array */ diff --git a/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php b/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php index a2f1573..6abe3a4 100644 --- a/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php +++ b/tests/BusinessLogic/Domain/BannerSettings/Service/BannerSettingsServiceTest.php @@ -264,6 +264,148 @@ public function testSetBannerSettingsReplacesImageWhenBase64Provided(): void self::assertEquals(['FR|displayOnHomePage' => 'FR-new-base64'], $this->bannerService->getStoredImages()); } + /** + * @return void + * + * @throws Exception + */ + public function testSetBannerSettingsRelocatesImageWhenDisplayLocationChangesWithoutBase64(): void + { + //Arrange + $this->bannerSettingsRepository->setBannerSettings(new BannerSettings( + [ + new Banner( + 'ES', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/existing.jpg', + 'displayOnHomePage' + ) + ] + )); + + $update = new BannerSettings( + [ + new Banner( + 'ES', + 'https://www.sequra.com/es/faq#shoppers', + '', + 'displayOnCartPage' + ), + ] + ); + + //Act + $this->bannerSettingsService->setBannerSettings($update); + + //Assert + $result = $this->bannerSettingsRepository->getBannerSettings(); + self::assertNotNull($result); + self::assertCount(1, $result->getBannerConfigs()); + self::assertEquals('displayOnCartPage', $result->getBannerConfigs()[0]->getDisplayLocation()); + self::assertEquals( + 'https://shop.test/banners/ES_displayOnCartPage.png', + $result->getBannerConfigs()[0]->getImageUrl() + ); + self::assertEquals( + [ + 'ES|displayOnCartPage' => [ + 'country' => 'ES', + 'from' => 'displayOnHomePage', + 'to' => 'displayOnCartPage', + ], + ], + $this->bannerService->getMovedImages() + ); + self::assertEmpty($this->bannerService->getDeletedImageKeys()); + } + + /** + * @return void + * + * @throws Exception + */ + public function testSetBannerSettingsKeepsImageUrlWhenDisplayLocationUnchanged(): void + { + //Arrange + $this->bannerSettingsRepository->setBannerSettings(new BannerSettings( + [ + new Banner( + 'ES', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/existing.jpg', + 'displayOnHomePage' + ) + ] + )); + + $update = new BannerSettings( + [ + new Banner( + 'ES', + 'https://www.sequra.com/es/updated-link', + '', + 'displayOnHomePage' + ), + ] + ); + + //Act + $this->bannerSettingsService->setBannerSettings($update); + + //Assert + $result = $this->bannerSettingsRepository->getBannerSettings(); + self::assertEquals( + 'https://shop/sequra/es/existing.jpg', + $result->getBannerConfigs()[0]->getImageUrl() + ); + self::assertEmpty($this->bannerService->getMovedImages()); + } + + /** + * @return void + * + * @throws Exception + */ + public function testSetBannerSettingsDisplayLocationChangeWithBase64DeletesOldImage(): void + { + //Arrange + $this->bannerSettingsRepository->setBannerSettings(new BannerSettings( + [ + new Banner( + 'ES', + 'https://www.sequra.com/es/faq#shoppers', + 'https://shop/sequra/es/old.jpg', + 'displayOnHomePage' + ) + ] + )); + + $update = new BannerSettings( + [ + new Banner( + 'ES', + 'https://www.sequra.com/es/faq#shoppers', + '', + 'displayOnCartPage', + 'ES-new-base64' + ), + ] + ); + + //Act + $this->bannerSettingsService->setBannerSettings($update); + + //Assert + $result = $this->bannerSettingsRepository->getBannerSettings(); + self::assertEquals('displayOnCartPage', $result->getBannerConfigs()[0]->getDisplayLocation()); + self::assertEquals( + 'https://shop.test/banners/ES_displayOnCartPage.png', + $result->getBannerConfigs()[0]->getImageUrl() + ); + self::assertEquals(['ES|displayOnCartPage' => 'ES-new-base64'], $this->bannerService->getStoredImages()); + self::assertEquals(['ES|displayOnHomePage'], $this->bannerService->getDeletedImageKeys()); + } + /** * @return void * From c1b9ca8961811b595a7fae0936c58b3c3ac3be79 Mon Sep 17 00:00:00 2001 From: Boljanovic Date: Tue, 19 May 2026 14:35:06 +0200 Subject: [PATCH 18/18] Fix code sniffer issues ISSUE: LIS-111 --- .github/workflows/pipeline.yml | 4 ++-- run-tests.sh | 3 +++ .../BannerSettings/Services/BannerSettingsService.php | 4 ++-- .../Domain/Connection/Services/ConnectionService.php | 3 +++ .../StoreIntegration/Services/StoreIntegrationService.php | 6 ++++++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 5d6cd27..64c5ff8 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -16,10 +16,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Cache Composer dependencies - uses: actions/cache@v4 + uses: actions/cache@v5 id: cache-composer with: path: | diff --git a/run-tests.sh b/run-tests.sh index 5865ad0..4924ff1 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -20,6 +20,9 @@ echo -e "\e[32mUnit tests: PHP 8.3\e[39m" echo -e "\e[32mUnit tests: PHP 8.4\e[39m" /usr/bin/php8.4 ./vendor/bin/phpunit --configuration ./phpunit.xml +echo -e "\e[32mUnit tests: PHP 8.5\e[39m" +/usr/bin/php8.5 ./vendor/bin/phpunit --configuration ./phpunit.xml + echo -e "\e[32mPHP_CodeSniffer\e[39m" vendor/bin/phpcs --standard=.phpcs.xml.dist --warning-severity=0 . diff --git a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php index 20eee57..2dee14b 100644 --- a/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php +++ b/src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php @@ -103,7 +103,7 @@ public function deleteUploadedBannerImages(): void new LogContextData('country', $banner->getCountry()), new LogContextData('displayLocation', $banner->getDisplayLocation()), new LogContextData('message', $e->getMessage()), - new LogContextData('type', get_class($e)), + new LogContextData('type', \get_class($e)), ] ); } @@ -372,7 +372,7 @@ protected function assertValidUrl(string $url): void } $scheme = parse_url($url, PHP_URL_SCHEME); - if (!in_array($scheme, ['http', 'https'], true)) { + if (!\in_array($scheme, ['http', 'https'], true)) { throw new InvalidURLException( new TranslatableLabel( 'URL must use http or https', diff --git a/src/BusinessLogic/Domain/Connection/Services/ConnectionService.php b/src/BusinessLogic/Domain/Connection/Services/ConnectionService.php index 77c9783..786b85e 100644 --- a/src/BusinessLogic/Domain/Connection/Services/ConnectionService.php +++ b/src/BusinessLogic/Domain/Connection/Services/ConnectionService.php @@ -12,6 +12,7 @@ use SeQura\Core\BusinessLogic\Domain\PaymentMethod\Exceptions\PaymentMethodNotFoundException; use SeQura\Core\BusinessLogic\Domain\StoreIntegration\Exceptions\CapabilitiesEmptyException; use SeQura\Core\BusinessLogic\Domain\StoreIntegration\Services\StoreIntegrationService; +use SeQura\Core\BusinessLogic\Domain\URL\Exceptions\InvalidUrlException; use SeQura\Core\Infrastructure\Http\Exceptions\HttpRequestException; /** @@ -192,6 +193,7 @@ public function getConnectionDataByMerchantId(string $merchantId): ConnectionDat * @return void * * @throws CapabilitiesEmptyException + * @throws InvalidUrlException */ public function reRegisterWebhooks(ConnectionData $connectionData): void { @@ -205,6 +207,7 @@ public function reRegisterWebhooks(ConnectionData $connectionData): void * @return void * * @throws CapabilitiesEmptyException + * @throws InvalidUrlException */ protected function registerWebhooks(ConnectionData $connectionData): void { diff --git a/src/BusinessLogic/Domain/StoreIntegration/Services/StoreIntegrationService.php b/src/BusinessLogic/Domain/StoreIntegration/Services/StoreIntegrationService.php index 4fa990f..581eb51 100644 --- a/src/BusinessLogic/Domain/StoreIntegration/Services/StoreIntegrationService.php +++ b/src/BusinessLogic/Domain/StoreIntegration/Services/StoreIntegrationService.php @@ -14,6 +14,7 @@ use SeQura\Core\BusinessLogic\Domain\StoreIntegration\Models\CreateStoreIntegrationRequest; use SeQura\Core\BusinessLogic\Domain\StoreIntegration\Models\DeleteStoreIntegrationRequest; use SeQura\Core\BusinessLogic\Domain\StoreIntegration\ProxyContracts\StoreIntegrationsProxyInterface; +use SeQura\Core\BusinessLogic\Domain\URL\Exceptions\InvalidUrlException; use SeQura\Core\BusinessLogic\Domain\URL\Model\Query; use SeQura\Core\BusinessLogic\Domain\URL\Model\URL; use SeQura\Core\BusinessLogic\Webhook\Exceptions\InvalidSignatureException; @@ -71,6 +72,7 @@ public function __construct( * @return void * * @throws CapabilitiesEmptyException + * @throws InvalidUrlException */ public function createStoreIntegration(ConnectionData $connectionData): void { @@ -87,6 +89,8 @@ public function createStoreIntegration(ConnectionData $connectionData): void * @param ConnectionData $connectionData * * @return void + * + * @throws InvalidUrlException */ public function deleteStoreIntegration(ConnectionData $connectionData): void { @@ -119,6 +123,8 @@ protected function getSupportedCapabilities(): array * @param string $signature * * @return URL + * + * @throws InvalidUrlException */ protected function buildWebhookUrl(URL $webhookUrl, string $signature): URL {