4.2.3 Provider features

FluidTYPO3 File contexts, Providers

The Provider class features all revolve around class methods which you can override as needed. These methods can be divided up into four specific groups of methods with similar responsibilities:

Integration Templates Records Components
trigger() getTemplatePathAndFilename() preProcessRecord() getForm()
getExtensionKey() setTemplatePathAndFilename() postProcessRecord() setForm()
getTableName() getTemplateVariables() postProcessDataStructure() getGrid()
setTableName() getTemplateVariables() preProcessCommand() setGrid()
getFieldName() getConfigurationSectionName() postProcessCommand() getPreview()
setFieldName() setConfigurationSectionName() clearCacheCommand()
getPriority() getFlexFormValues()

Common for many of these methods is that they accept a record as argument. This allows you to first analyse the record in your method before manipulating it or returning values based on it. For example, fluidcontent uses this behavior to return different template paths for different values in the Fluid content type field. Another way to utilise this could for example be to match the record type as configured by TCA, before returning a Form component instance - allowing you to return a different Form for each type your record can have.

Areas of responsibility

The methods in the Integration column are used by TYPO3 when detecting Providers and asking your Provider whether or not it should process the current record (in frontend or backend). The getters and setters in this category retrieve and configure the matching conditions - which table, field and priority your Provider has - and the trigger() method is implemented in the base class as a simple method to get the table name and field name and analyse the record passed as argument to see if it matches.

The Templates group of methods are all concerned with resolving template filenames, getting a set of predefined variables, returning the name of the Configuration section. If for example your template file contains multiple Configuration sections, the getConfigurationSectionName method receives a record as argument which means you can change the section name based on one or more properties of the record.

The Records group deals specifically with processing records (and commands executed on records, like copy or delete). These methods can be overridden to make your Provider perform custom operations for example before and after your record is saved. Note that the postProcessDataStructure is a low-level part of the Provider - normally you should not need to override this particular method since what it does, is convert your Form instance to a TCEforms array. The only use case for overriding this field, is to manually return the TCEforms array and/or perform manual modifications to an existing data structure (including ones which were generated by other Providers). In almost all cases the right one to override to affect the Form, is the getForm method.

The final group Components deals directly with returning instances of Form and Grid classes, and preview content (which currently only applies to records from the TYPO3 content element table, tt_content). In implementations which store these types of configuration in template files, these methods try to read this data from templates - but a custom Provider is free to return these instances directly. If for example your Provider returns both a Form and Grid instance, your template files no longer are required to contain a flux:form tag or f:section named Configuration. Indeed, your Provider no longer needs to return a template filename if it returns these instances directly (if your Provider is used in a Flux-enabled controller, not returning a template filename simply causes the controller to attempt to render the template file that is associated with the current action).

Loading/detecting Providers

Providers are always used in one of two possible ways:

  1. Detection using a record, table name, field name and priority
  2. Manually creating instances (and if necessary, setting their table and field name)

The Providers you find in for example flux and fluidcontent are registered using Flux's Core class - which means they can be detected automatically when Flux detects a record being saved, moved and so on. These Providers are registered with a default priority which means that any Provider you yourself register with a higher priority, will be used instead of the existing one.

Using NULL as value of any of the matching properties (tableName, fieldName, contentObjectType etc) means your Provider is a general, but lower priority match for records from the associated DB table. And that means, if another Provider class has a more specific match (for example, if it uses a matching fieldName that is not NULL) then it gets resolved first and your Provider get resolved after it.

Some areas of Flux are able to ask multiple Providers for components - which means for example when getting a TCEforms structure this structure may be processed by multiple Providers - so be careful when you register multiple Providers for the same field. In some cases it is preferable to first unregister the old Provider class name before registering your own. Unregistering a Provider happens by class name and both removes and prevents the unregistered class name from being used.

A Flux-enabled controller can also choose to create the Provider only when rendering in the frontend. Doing this means you can use all the template related features (including the data transformation feature which is configured through the Form instance), but naturally none of the backend-related features. The standard approach is to simply register your Provider to be used along with your plugin's list_type.

Small note about Providers attached to the tt_content table: since it is likely that multiple Providers will already be used with this table, it is best practice to check for the proper list_type or CType value of the record before you let your Provider class perform operations on records. Doing this will avoid having your Provider's code called unintentionally.
Jump to...