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
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:
- The interfaces (
ProtectionTargetInterface,SubmissionGuardInterface,RateLimiterInterface,ReplayGuardInterface,AltchaVerifierInterface,ChallengeGeneratorInterface,SecretCipherInterface,AltchaSettingsProviderInterface,DisposableEmailGuardInterface,DisposableDomainListInterface,GibberishGuardInterface,GibberishScorerInterface) together with the types they expose:Rejection(its cases are thereasonof a Shop API rejection; new cases may be added in a minor release),VerificationResult,AltchaSettings, andAltchaOrg\Altcha\Challenge(a third-party type - a major bump ofaltcha-org/altchais a major bump of this plugin). - The
ProtectionTargetvalue object, including its constructor - parameter order and names are fixed, only optional parameters are added at the end. - The duck-typed event contract consumed from other plugins (
getRequest(): Request,reject(?string), optionalgetSource(): BackedEnum) and the service tagmmd_sylius_altcha.protection_target. - The public methods of
ProtectionTargetRegistry(all,find,findByFormType,findByRoute,staticTargets,reset),ProtectionResolver(isProtected,isChannelEnabled),FormToken(issue,ageInSeconds) andChannelSettingsFactory(createForChannel,generateEncryptedSecret), reachable through the public service ids (mmd_sylius_altcha.target_registry,.protection_resolver,.form_token,.channel_settings_factory,.secret_cipher). - The Twig function and hook names, the route names, the target codes (stored per channel), the translation keys, and the console command names.
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 interfacesChannelSettingsRepositoryInterface,DynamicTargetSourceInterfaceandDisposableDomainOverrideRepositoryInterfaceare marked@internal, and the entitiesChannelSettingsandDisposableDomainOverridecount 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.