Markus Michalski FAQ

ALTCHA: Extensibility and Compatibility

ALTCHA spam protection for Sylius - registering custom protection targets via service tag, decorating interfaces and the backward compatibility promise under semantic versioning

Deutsche Version

Back to overview

ALTCHA: Extensibility and Compatibility

Live Demo: Try this and other plugins live — no installation, no risk: demo.markus-michalski.net

Custom targets

Register a new target from a plugin. Prefer instantiating Mmd\SyliusAltchaPlugin\Target\ProtectionTarget as a service over implementing ProtectionTargetInterface yourself - the interface may gain methods in a minor release, while the ProtectionTarget constructor only ever gains optional parameters at the end. Use named arguments and a translation key as the label. The constructor takes $code, $label, $formTypes, $routes, $events, $enabledByDefault and $requiresProof; only $code and $label are required:

services:
    App\Altcha\OrderFormTarget:
        class: Mmd\SyliusAltchaPlugin\Target\ProtectionTarget
        arguments:
            $code: order_form
            $label: app.altcha.target.order_form
            $events: ['app.order_form.pre_submit']
        tags: ['mmd_sylius_altcha.protection_target']

The tag is what puts the target in the admin list; a service implementing ProtectionTargetInterface only gets it automatically when autoconfiguration is on.

A target names how it is enforced: a form type, a route name, or a rejectable event of your plugin. The event needs getRequest(): Request and reject(?string $reason); an optional getSource(): BackedEnum returning registration or admin exempts those entry points. Codes starting with custom_ are reserved for operator-defined forms added through the admin.

The widget has to be placed in the form's template before the target is ticked, see Storefront Integration.

Decorate, don't subclass

Extend behaviour by decorating the public interfaces (SubmissionGuardInterface, RateLimiterInterface, ReplayGuardInterface, AltchaVerifierInterface, DisposableEmailGuardInterface, GibberishGuardInterface, ...) rather than subclassing.

Backward Compatibility

Covered by semantic versioning:

Not covered: constructors other than ProtectionTarget's, protected members of every class, other public methods, and any class or interface marked @internal. The persistence side is out as well: the interfaces ChannelSettingsRepositoryInterface, DynamicTargetSourceInterface and DisposableDomainOverrideRepositoryInterface are marked @internal, and the entities ChannelSettings and DisposableDomainOverride count as other classes. The bundled disposable-domain snapshot is content, not an API - its path, format and the domains in it may change at any time, including in a patch release.