Double opt-in for EXT:form

Extension key

form_consent

Package name

eliashaeussler/typo3-form-consent

Version

3.1

Language

en

Author

Elias Häußler & contributors

License

This extension documentation is published under the CC BY-NC-SA 4.0 (Creative Commons) license.


An extension for TYPO3 CMS that adds double opt-in functionality to EXT:form. It allows the dynamic adaptation of the entire double opt-in process using various events. In addition, the extension integrates seamlessly into TYPO3, for example to delete expired consents in compliance with the GDPR.


Introduction

A quick overview about the main features provided by this extension.

Installation

Instructions on how to install this extension and which TYPO3 and PHP versions are currently supported.

Configuration

Learn how to configure the extension in various ways. This includes extension configuration, site sets, TypoScript configuration and form finisher configuration.

Usage

This section describes all possible usages of this extension. Learn how to use the consent finisher, validation plugin and other optional features.

Developer corner

A quick overview about all relevant classes provided by this extension.

Migration

Required migration steps when upgrading the extension to a new major version.

Introduction

What does it do?

The extension provides a Consent finisher for forms created with EXT:form. With this finisher, a complete double opt-in process can be triggered. Several parts of this process can be customized by a various set of events. Additionally, it provides a dashboard widget and a garbage collection task for expired consents.

Features

  • Custom Consent form finisher for EXT:form
  • Stores all submitted form data as JSON in database
  • Hash-based validation system (using TYPO3's HMAC functionality)
  • Plugin to approve or dismiss a consent
  • Possibility to invoke finishers on consent approval or dismissal
  • Several events for better customization
  • Scheduler task for expired consents
  • Dashboard widget for approved, non-approved and dismissed consents
  • Compatible with TYPO3 12.4 LTS and 13.4 LTS

Support

There are several ways to get support for this extension:

Security Policy

Please read our security policy if you discover a security vulnerability in this extension.

License

This extension is licensed under GNU General Public License 2.0 (or later).

Installation

Requirements

  • PHP 8.1 - 8.4
  • TYPO3 12.4 LTS - 13.4 LTS

Installation

Require the extension via Composer (recommended):

composer require eliashaeussler/typo3-form-consent
Copied!

Or download it from the TYPO3 extension repository.

Initial setup

Once installed, make sure to add the site set eliashaeussler/typo3-form-consent as dependency to your site (TYPO3 >= 13.1) or include the TypoScript setup at EXT:form_consent/Configuration/TypoScript in your root template.

Version matrix

Extension versions TYPO3 versions PHP versions
since 3.1.2 12.4 LTS - 13.4 LTS 8.1 - 8.4
3.1.0 - 3.1.1 12.4 LTS - 13.4 LTS 8.1 - 8.3
3.0.x 11.5 LTS - 13.3 8.1 - 8.3
2.2.0 - 2.3.1 11.5 LTS - 13.1 8.1 - 8.3
2.1.0 11.5 LTS - 13.0 8.1 - 8.3
1.1.0 - 2.0.0 11.5 LTS - 12.4 LTS 8.1 - 8.3
1.0.0 11.5 LTS - 12.4 LTS 8.1 - 8.2
0.3.0 - 0.7.1 10.4 LTS - 11.5 LTS 7.4 - 8.1
0.2.x 10.4 LTS - 11.5 LTS 7.2 - 8.1
0.1.x 10.4 LTS - 11.5 LTS 7.2 - 8.0

Form finisher configuration

The consent finisher can be configured with the following options:

subject

subject
Type
string or LLL reference
Required
true
Default
LLL:EXT:warming/Resources/Private/Language/locallang.xlf:consentMail.subject

Mail subject of the consent mail sent to the form submitter.

recipientAddress

recipientAddress
Type
string
Required
true

Email address of the consent mail recipient. Can be a placeholder to an existing form element.

recipientName

recipientName
Type
string
Required
false

Name of the consent mail recipient. May contain placeholders to one or more existing form elements.

senderAddress

senderAddress
Type
string
Required
false
Default
System default sender e-mail address

Email address of the consent mail sender. Can be a placeholder to an existing form element.

senderName

senderName
Type
string
Required
false
Default
System default sender name

Name of the consent mail sender. May contain placeholders to one or more existing form elements.

replyToAddress

replyToAddress
Type
string
Required
false

Email address of the Reply-To mail recipient. Can be a placeholder to an existing form element.

replyToName

replyToName
Type
string
Required
false

Name of the Reply-To mail recipient. May contain placeholders to one or more existing form elements.

approvalPeriod

approvalPeriod
Type
integer
Required
false
Default
86400 (= 1 day)

Duration in seconds where consent mails can be approved. In fact, this results in a concrete datetime value for the valid_until database field of the current consent.

confirmationPid

confirmationPid
Type
integer
Required
true

ID of the page where consent confirmation is validated. This page should contain the validation plugin that handles consent approval and dismissal. The appropriate links in the consent mail are generated for this page.

storagePid

storagePid
Type
integer
Required
false
Default
0 (falls back to plugin.tx_formconsent.persistence.storagePid)

Page ID where to store new consents. This is typically a folder in the page tree that exclusively contains form consents.

requireApproveVerification

requireApproveVerification
Type
boolean
Required
false
Default
false

Enable or disable an additional required verification step for consent approval. If enabled, users must verify their consent approval by additionally clicking on a link on the consent validation page. This is especially useful to avoid that automatic mail link scanners accidentally approving a consent.

requireDismissVerification

requireDismissVerification
Type
boolean
Required
false
Default
false

Enable or disable an additional required verification step for consent dismissal. If enabled, users must verify their consent dismissal by additionally clicking on a link on the consent validation page. This is especially useful to avoid that automatic mail link scanners accidentally approving a consent.

templateRootPaths

templateRootPaths
Type
array
Required
false

Additional paths to template roots used to render Fluid templates for the consent mail.

partialRootPaths

partialRootPaths
Type
array
Required
false

Additional paths to template partials used to render Fluid partials for the consent mail.

layoutRootPaths

layoutRootPaths
Type
array
Required
false

Additional paths to template layouts used to render Fluid layouts for the consent mail.

SiteSet configuration

The extension ships with a site set called eliashaeussler/typo3-form-consent. It can be used as drop-in replacement for TypoScript in TYPO3 v13.1 or later.

The following settings are available for the site set:

Settings

view.templateRootPath

view.templateRootPath
Type
string
Path
plugin.tx_formconsent

Additional path to template root used in Frontend context. Within this path, Fluid templates of the consent mail sent by the consent finisher as well as templates of the validation plugin can be overwritten.

view.partialRootPath

view.partialRootPath
Type
string
Path
plugin.tx_formconsent

Additional path to template partials used in Frontend context. Within this path, Fluid partials of the consent mail sent by the consent finisher as well as templates of the validation plugin can be overwritten.

view.layoutRootPath

view.layoutRootPath
Type
string
Path
plugin.tx_formconsent

Additional path to template layouts used in Frontend context. Within this path, Fluid layouts of the consent mail sent by the consent finisher as well as templates of the validation plugin can be overwritten.

persistence.storagePid

persistence.storagePid
Type
integer
Path
plugin.tx_formconsent

Page ID where to store new consents created by the consent finisher.

TypoScript configuration

The following global TypoScript configuration is available:

Constants

view.templateRootPath

view.templateRootPath
Type
string
Path
plugin.tx_formconsent

Additional path to template root used in Frontend context. Within this path, Fluid templates of the consent mail sent by the consent finisher as well as templates of the validation plugin can be overwritten.

view.partialRootPath

view.partialRootPath
Type
string
Path
plugin.tx_formconsent

Additional path to template partials used in Frontend context. Within this path, Fluid partials of the consent mail sent by the consent finisher as well as templates of the validation plugin can be overwritten.

view.layoutRootPath

view.layoutRootPath
Type
string
Path
plugin.tx_formconsent

Additional path to template layouts used in Frontend context. Within this path, Fluid layouts of the consent mail sent by the consent finisher as well as templates of the validation plugin can be overwritten.

persistence.storagePid

persistence.storagePid
Type
integer
Path
plugin.tx_formconsent

Page ID where to store new consents created by the consent finisher.

Extension configuration

The extension currently provides the following configuration options:

excludedElements

excludedElements
Type
string (comma-separated list)
Path
persistence.excludedElements
Default
Honeypot

Contains all form element types that should be excluded from persistence. When configured, the consent finisher automatically excludes all form elements matching the configured type from being persisted.

Validation plugin

A plugin is required for approval or dismissal of the consent. The associated page containing the plugin must then be specified in the finisher configuration.

New content element wizard

Scheduler task

Consents are considered "expired" if they were originally submitted with a configured approval period (read more in the consent finisher configuration) and time between consent submit and allowed approval time has passed. If consents are expired, they are not deleted by default, but remain active in the database, even though they can no longer be approved or dismissed.

For TYPO3 installations having EXT:scheduler installed, this extension provides a convenient way to remove expired consents. It adds the consent table tx_formconsent_domain_model_consent to the list of tables for which table garbage collection is supported. For the expireField option, the consent field valid_until is configured.

Scheduler garbage collection task

Dashboard widget

This extension provides a dashboard widget for installations having EXT:dashboard installed. The widget shows all currently approved, non-approved and dismissed consents as doughnut chart.

Dashboard widget with approved, non-approved and dismissed consents

Configuration API

In order to access the extension configuration, a slim PHP API exists. Each configuration option is accessible by an appropriate class method.

class Configuration
Fully qualified name
\EliasHaeussler\Typo3FormConsent\Configuration\Configuration

API to access all available extension configuration options.

getExcludedElementsFromPersistence ( )

Get all form element types that are excluded from persistence.

returntype

list<string>

Events

Some PSR-14 events are dispatched while consents are generated or modified. This allows to step in the consent lifecycle and perform several actions, based on the actual event.

The following events are currently dispatched:

ApproveConsentEvent

This event is dispatched if a consent was approved by the user. This is especially useful when running additional actions that provide a concrete response to be rendered. The response can be attached to the dispatched event and will be handled by the dispatching controller.

DismissConsentEvent

This event is dispatched if a consent was dismissed by the user. This is especially useful when running additional actions that provide a concrete response to be rendered. The response can be attached to the dispatched event and will be handled by the dispatching controller.

GenerateHashEvent

When the HashService generates a new consent validation hash, it dispatches this event. It can be used to either attach a ready-to-use validation hash or modify the hash components used to internally generate the final hash.

ModifyConsentEvent

This event is dispatched after a new consent was generated, which is not yet persisted. It allows to modify the consent while having access to the current FinisherContext. This allows to cancel the whole consent process by calling $event->getFinisherContext()->cancel().

ModifyConsentMailEvent

Once the consent is persisted, the consent mail is sent to the user. It can be modified by listening to this event, which provides the mail as an instance of FluidEmail along with the current FormRuntime.

JSON type

The extension provides a custom type to persist arbitrary form values as JSON data to the database. This allows to dynamically persist values in a relatively easy and maintainable way, since the provided type implements TYPO3 core API. The resulting values are actually JSON-encoded strings.

class JsonType
Fully qualified name
\EliasHaeussler\Typo3FormConsent\Type\JsonType

Type implementing TYPO3's \TYPO3\CMS\Core\Type\TypeInterface that accepts and stores JSON-encoded strings.

static fromArray ( $data)

Create a new JSON type from the given array.

param array $data

Array to persist, will be JSON-encoded

returntype

EliasHaeussler\Typo3FormConsent\Type\JsonType

toArray ( )

Return current JSON-encoded string as parsed array.

returntype

array

Type transformers

Type transformers describe a way how specific data can be modified so that persistence of its value into the database is assured. All returned types are JSON types.

interface TypeTransformer
Fully qualified name
\EliasHaeussler\Typo3FormConsent\Type\Transformer\TypeTransformer

Interface used to transform a given value to a persistable JSON type.

transform ( $formRuntime)

Transform a specific form value from the given form runtime to a persistable JSON type.

param TYPO3\CMS\Form\Domain\Runtime\FormRuntime $formRuntime

Form runtime from which to extract values

returntype

EliasHaeussler\Typo3FormConsent\Type\JsonType

The extension ships with two type transformers:

  • \EliasHaeussler\Typo3FormConsent\Type\Transformer\FormRequestTypeTransformer: Used to transform the current form request parameters to JSON type in order to allow resubmission of the given form
  • \EliasHaeussler\Typo3FormConsent\Type\Transformer\FormValuesTypeTransformer: Used to transform all submitted form values to JSON type in order to store them next to the generated form consent

Migration

This page lists all notable changes and required migrations when upgrading to a new major version of this extension.

Version 2.0.0

Finisher context in event

  • \EliasHaeussler\Typo3FormConsent\Event\ModifyConsentEvent no longer explicitly provides the current \TYPO3\CMS\Form\Domain\Runtime\FormRuntime instance via the getFormRuntime() method. Use getFinisherContext()->getFormRuntime() instead.
  • \EliasHaeussler\Typo3FormConsent\Domain\Factory\ConsentFactory::createFromForm no longer expects a \TYPO3\CMS\Form\Domain\Runtime\FormRuntime as second parameter. Pass the current \TYPO3\CMS\Form\Domain\Finishers\FinisherContext instead.

Version 1.0.0

Version 0.7.0

Global form settings

  • Form settings for Frontend requests ( plugin.tx_form) are no longer included globally.
  • Make sure to add the static TypoScript setup at EXT:form_consent/Configuration/TypoScript to your root template.

Version 0.4.0

Post-consent dismissal finishers

  • Custom finishers can now be executed after consent was dismissed.
  • Event listener was renamed. Change references to \EliasHaeussler\Typo3FormConsent\Event\Listener\InvokeFinishersListener. Adapt your service configuration, if needed.
  • Listener method was renamed. Use onConsentApprove($event) instead of __invoke($event).
  • Event listener identifier formConsentInvokeFinishersOnApproveListener changed. Change references to formConsentInvokeFinishersOnConsentApproveListener.

Version 0.3.0

Post-consent approval finishers

  • Custom finishers can now be executed after consent was approved.
  • Database field tx_formconsent_domain_model_consent.original_request_parameters was added. A manual migration is required. Database field should contain an JSON-encoded string of the parsed body sent with the original form submit request.
  • Database field tx_formconsent_domain_model_consent.original_content_element_uid was added. A manual migration is required. Database field should contain the content element UID of the original form plugin.
  • Post-approval finishers can now be defined as described here: Invoke finishers on consent approval or dismissal. A manual migration is required. Create form variants and configure the post-approval finishers.

Codebase

  • Minimum PHP version was raised to PHP 7.4. Upgrade your codebase to support at least PHP 7.4.
  • Several classes were marked as final. If you still need to extend or override them, consider refactoring your code or submit an issue.

Contributing

Thanks for considering contributing to this extension! Since it is an open source product, its successful further development depends largely on improving and optimizing it together.

The development of this extension follows the official TYPO3 coding standards. To ensure the stability and cleanliness of the code, various code quality tools are used and most components are covered with test cases. In addition, we use DDEV for local development. Make sure to set it up as described below. For continuous integration, we use GitHub Actions.

Create an issue first

Before you start working on the extension, please create an issue on GitHub: https://github.com/eliashaeussler/typo3-form-consent/issues

Also, please check if there is already an issue on the topic you want to address.

Contribution workflow

Preparation

Clone the repository first:

git clone https://github.com/eliashaeussler/typo3-form-consent.git
cd typo3-form-consent
Copied!

Now start DDEV:

ddev start
Copied!

You can access the DDEV site at https://typo3-ext-form-consent.ddev.site/.

Analyze code

# All analyzers
ddev cgl analyze

# Specific analyzers
ddev cgl analyze:dependencies
Copied!

Check code quality

# All linters
ddev cgl lint

# Specific linters
ddev cgl lint:composer
ddev cgl lint:editorconfig
ddev cgl lint:php
ddev cgl lint:typoscript

# Fix all CGL issues
ddev cgl fix

# Fix specific CGL issues
ddev cgl fix:composer
ddev cgl fix:editorconfig
ddev cgl fix:php
ddev cgl fix:typoscript

# All static code analyzers
ddev cgl sca

# Specific static code analyzers
ddev cgl sca:php
Copied!

Run tests

# All tests
ddev test

# Specific tests
ddev test acceptance
ddev test functional
ddev test unit

# All tests with code coverage
ddev test coverage

# Specific tests with code coverage
ddev test coverage:acceptance
ddev test coverage:functional
ddev test coverage:unit

# Merge code coverage of all test suites
ddev test coverage:merge
Copied!

Code coverage reports are written to .Build/coverage. You can open the last merged HTML report like follows:

open .Build/coverage/html/_merged/index.html
Copied!

Reports of acceptance tests are written to .Build/log/acceptance-reports. You can open the last HTML report like follows:

open .Build/log/acceptance-reports/records.html
Copied!

Build documentation

# Rebuild and open documentation
composer docs

# Build documentation (from cache)
composer docs:build

# Open rendered documentation
composer docs:open
Copied!

The built docs will be stored in .Build/docs.

Pull Request

Once you have finished your work, please submit a pull request and describe what you've done: https://github.com/eliashaeussler/typo3-form-consent/pulls

Ideally, your PR references an issue describing the problem you're trying to solve. All described code quality tools are automatically executed on each pull request for all currently supported PHP versions and TYPO3 versions.

Sitemap