Skip to content

Add banner upload functionality to the shop home screen#59

Open
AleksandarBoljanovic wants to merge 21 commits into
masterfrom
LIS-111
Open

Add banner upload functionality to the shop home screen#59
AleksandarBoljanovic wants to merge 21 commits into
masterfrom
LIS-111

Conversation

@AleksandarBoljanovic
Copy link
Copy Markdown
Collaborator

What is the goal?

  • Add the functionality to upload a banner for the shop's home page to the integration-core, and ensure this new configuration can be received via the configuration webhook sent by the merchant portal.

References

How is it being implemented?

  • Added new Checkout API controller (BannerCheckoutController) with getBannerForLocation endpoint, request and response - used by the storefront to fetch the banner to render for a given country/display location
  • Registered new Configuration Webhook topics (get-banner-settings, save-banner-settings)
  • Added the BannerSettings domain context: Banner and BannerSettings models, BannerSettings entity with EntityConfiguration, BannerSettingsRepositoryInterface + repository, and BannerSettingsService orchestrating fetch/save/delete and display-location-aware image updates
  • Added new integration interface (BannerServiceInterface) as the platform extension point - exposes display locations, image upload/delete, and country lookup so each e-commerce platform supplies its own implementation
  • Added a BANNER capability to Capability and surfaced it via StoreIntegrationService so platforms can advertise banner support
  • Hooked into connection lifecycle: ConnectionService triggers banner-settings provisioning on connect, DisconnectService cleans up persisted settings and uploaded images on disconnect (with an error log if image deletion on the integration side fails)
  • Wired everything in BootstrapComponent (repository, service, controllers, webhook handlers)
  • Added unit tests

How is it tested?

  • Unit tests

Comment thread src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php Outdated
Comment thread src/BusinessLogic/Domain/BannerSettings/Services/BannerSettingsService.php Outdated
Comment thread src/BusinessLogic/ConfigurationWebhookAPI/Responses/UnknownTopicErrorResponse.php Outdated
Comment thread src/BusinessLogic/ConfigurationWebhookAPI/Responses/TopicMissingErrorResponse.php Outdated
Comment thread src/BusinessLogic/DataAccess/BannerSettings/Entities/BannerSettings.php Outdated
Comment thread src/BusinessLogic/DataAccess/BannerSettings/Entities/BannerSettings.php Outdated
Comment thread src/BusinessLogic/DataAccess/BannerSettings/Entities/BannerSettings.php Outdated
Copy link
Copy Markdown
Member

@m1k3lm m1k3lm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the banner-upload feature end-to-end. Overall well-organized and follows existing patterns (DTOs, entity with IndexMap, bootstrap registration, topic handlers, BannerServiceInterface as a minimal integration extension point). Tests are comprehensive (~668-line service test, +265-line webhook test). Comments below cover correctness, design, and a couple of doc-vs-behavior mismatches — none are hard blockers, but I'd want the save-atomicity ordering, required-field validation in SaveBannerSettingsRequest, and the PR description fixed before merge.

Risks summary

Risk Severity
Orphan remote images on partial save failure Medium
Partial-disconnect leaves banner state Low (likely intentional, worth a comment)
Unvalidated image size / required fields Low–Medium
Cross-namespace trait reuse (Webhook uses AdminAPI trait) Low (style)
Response shape divergence between Admin / Webhook Low (UX)
InvalidURLException vs existing InvalidUrlException Low (style)

Notes that don't fit on a line

  • PR description vs. behavior: the description says "ConnectionService triggers banner-settings provisioning on connect", but the actual ConnectionService.php change is two @throws docblock additions. Provisioning is indirect (BANNER capability advertised via createStoreIntegration, merchant portal then sends save-banner-settings). Please update the description.
  • PHP 8.5 in run-tests.sh but not in the GH workflow matrix: if 8.5 support is intended, mirror it in CI; otherwise consider keeping it local.
  • actions/cache@v5 and dev-dep bumps (phpstan 1.12.33, phpcs 3.13.5, webmozart/assert 1.12.1 which now requires ext-date/ext-filter): worth a quick sanity check against the lowest supported PHP (7.2) target.

isset($bannerConfig['imageBase64']) && $bannerConfig['imageBase64'] !== ''
? $bannerConfig['imageBase64']
: null
);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required fields (country, linkUrl, displayLocation) silently default to '' when missing. The empty linkUrl happens to be caught later by assertValidUrl (filter_var('', FILTER_VALIDATE_URL) fails), but a missing country slips through to the persistence layer and the remote saveBannerImage/deleteBannerImage calls. Validate required fields explicitly with a clear error here rather than relying on downstream side effects.

*
* @package SeQura\Core\BusinessLogic\AdminAPI\BannerSettings\Requests
*/
trait SaveBannerSettingsRequest
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cross-namespace trait reuse. This trait lives under AdminAPI\BannerSettings\Requests but is used by ConfigurationWebhookAPI\Requests\BannerSettings\SaveBannerSettingsRequest. The webhook reaching into the Admin namespace for shared code is a leaky abstraction — moving the shared transformation into a common namespace (or extracting a small request-to-domain transformer) would be cleaner.

{
if (empty($this->bannerConfigs)) {
return [];
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning [] when empty instead of ['bannerConfigs' => []] forces every caller to defensively use $settingsArray['bannerConfigs'] ?? [] (see both Admin and Webhook BannerSettingsResponse). Returning the consistent shape unconditionally would remove that special case at every call site.

/**
* @var string|null
*/
protected $imageBase64;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The imageBase64 field is purely transient input — it's scrubbed back to null in BannerSettingsService::resolveBannerImage (line 257) before persistence, and toArray deliberately omits it. It works, but mixing input-only and persisted fields in the same DTO is a smell. Consider splitting into BannerInput (carries base64) and Banner (persisted shape).

Comment thread src/BusinessLogic/Domain/Disconnect/Services/DisconnectService.php
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants