Markus Michalski FAQ

Marketplace Redirect: Technical

Technical details of Marketplace Redirect: decision logic, how the cart block is switched off, plugin structure, tables and the product form.

Deutsche Version

Back to overview

Marketplace Redirect: Technical

This documentation always describes the latest published version.

Decision logic

graph TD
    A["Product page or API request"] --> B{"Channel known?"}
    B -->|"No"| C["Normal cart button"]
    B -->|"Yes"| D{"Channel switched on?"}
    D -->|"No"| C
    D -->|"Yes"| E{"Product has a link?"}
    E -->|"No"| C
    E -->|"Yes"| F{"Reference valid?"}
    F -->|"No"| G["Warning in the log, normal button"]
    F -->|"Yes"| H["Build URL: external button or JSON"]

The provider remembers the result per request for each product and channel, because the hook renderer and the button template look up the same product. A database error (for example a missing table) and a stored reference that is no longer valid count as "no redirect" and are logged as a warning.

Switching off the cart block

The decorated renderer MarketplaceRedirectHookableRenderer switches off the add_to_cart hookable of the hook sylius_shop.product.show.content.info.summary: if the product has a redirect, it renders the hookable empty. A condition on the hookable is ruled out because hook conditions only exist in newer twig-hooks versions (Sylius 2.3) and the condition language offers no way to check whether a product has a link. The renderer has the same interface in every twig-hooks version, and no Sylius template is touched.

Plugin structure

src/
β”œβ”€β”€ Api/                      # Shop API provider, Admin API processor and IRI filter
β”‚   └── Resource/             # Read model ProductMarketplaceRedirect
β”œβ”€β”€ Command/                  # mmd:marketplace-redirect:setup
β”œβ”€β”€ DependencyInjection/      # Bundle extension, empty Configuration
β”œβ”€β”€ Entity/                   # ChannelSettings, ProductMarketplaceLink
β”œβ”€β”€ Enum/                     # MarketplaceType
β”œβ”€β”€ Form/                     # Product form extension, types, form model
β”œβ”€β”€ Hook/                     # Decorated hook renderer
β”œβ”€β”€ Menu/                     # Admin menu (group MMKreativ Plugins)
β”œβ”€β”€ Migrations/               # Two Doctrine migrations
β”œβ”€β”€ Model/                    # Redirect value object, interface for the form data
β”œβ”€β”€ Provider/                 # Redirect per product
β”œβ”€β”€ Repository/               # Repository of the links
β”œβ”€β”€ Settings/                 # Repository of the channel settings
β”œβ”€β”€ Twig/                     # Twig functions
β”œβ”€β”€ Url/                      # URL builder per marketplace and resolver
β”œβ”€β”€ Validator/                # Constraint ValidMarketplaceReference
└── MmdSyliusMarketplaceRedirectPlugin.php   # Bundle class
assets/                       # empty placeholders (admin, shop), no JavaScript
config/                       # Services, routes, grid, Twig hooks
templates/                    # Shop button with embedded logo, admin card, title row
translations/                 # messages, validators, flashes (de_DE, en_US)

Tables

Table Entity Content
mmd_sylius_marketplace_redirect_link ProductMarketplaceLink Type, reference, optional Amazon domain and the product (unique, deleted with the product)
mmd_sylius_marketplace_redirect_channel_settings ChannelSettings Channel code (unique) and the "enabled" switch
graph LR
    A["sylius_product"] -->|"1 to 0..1"| B["mmd_sylius_marketplace_redirect_link"]
    C["Channel code"] -->|"1 to 0..1"| D["mmd_sylius_marketplace_redirect_channel_settings"]

The link is a separate entity with a unique join column because Product is a mapped superclass that a plugin cannot extend. The channel is stored as a code, not as a relation: the entry survives re-creating the channel and does not depend on the channel mapped superclass.

The migrations live in the namespace Mmd\SyliusMarketplaceRedirectPlugin\Migrations and run after those of the Sylius core. The namespace is deliberately not the skeleton default DoctrineMigrations, which would collide with the host's namespace.

Admin menu

The menu entry sits in the group "MMKreativ Plugins" (code mmd_plugins), which several independently installed MMKreativ plugins share. If the route is missing because the host has not imported it, the entry is left out and the group stays as long as other plugins fill it.

Product form

A form extension on the admin product type (Sylius\Bundle\AdminBundle\Form\Type\ProductType) adds an unmapped marketplaceLink subform and syncs it with the link entity by hand. Sylius validates product forms in the group sylius, so the subform sets Default explicitly. If the migration has not run yet, the form stays usable but the card is ineffective: on an existing product what is entered is discarded, and a new product with a marketplace chosen cannot be created.

The classes involved are ProductTypeExtension, MarketplaceLinkType (block prefix mmd_sylius_marketplace_redirect_link) and ChannelSettingsFormType for the channel settings.

Frontend

The plugin ships no JavaScript and no Stimulus controllers. The shop button and the admin card consist of Twig and CSS.