The legacy dca aka old dca format is used in Contao 2 and Contao 3. This page describe how this format is mapped into the DcGeneral Container.
For a full dca example and mapping description, see the DCA mapping reference chapter.
You can access the basic section with this snippet:
use DcGeneral\DataDefinition\Section\BasicSectionInterface;
$basicSection = $container->getSection(BasicSectionInterface::NAME);
/** @var BasicSectionInterface $basicSection */
Warning
$GLOBALS['TL_DCA']['tl_example'] = array
(
// List
'list' => array
(
'sorting' => array
(
'mode' => 6,
)
)
);
|
-> used as mode ($basicSection->getMode())
|
You can access the data provider section with this snippet:
use DcGeneral\DataDefinition\Section\DataProviderSectionInterface;
$dataProviderSection = $container->getSection(DataProviderSectionInterface::NAME);
/** @var DataProviderSectionInterface $dataProviderSection */
$GLOBALS['TL_DCA']['tl_example'] = array
(
// Config
'config' => array
(
'ptable' => 'tl_parent',
'ctable' => array('tl_child1', 'tl_child2')
)
);
|
-> create a data provider information called tl_example, of type ContaoDataProviderInformation, with DcGeneral\Data\DefaultDriver as driver class, with table name tl_example as source Retrieve it like the following: $parentDriver = $dataProviderSection->getInformation( $container->getBasicSection()->getDataProvider() ); -> create a data provider information called tl_parent, of type ContaoDataProviderInformation, with DcGeneral\Data\DefaultDriver as driver class, with table name tl_parent as source $parentDriver = $dataProviderSection->getInformation( $container->getBasicSection()->getParentDataProvider() ); -> get's ignored in DCGeneral as we refuse to destroy the data without the users notice. This is only used to restrict backend modules to certain tables and prune unparented data- sets in Contao and considered harmful by the developers of DCGeneral. |
$GLOBALS['TL_DCA']['tl_example'] = array
(
// DcGeneral config
'dca_config' => array
(
'data_provider' => array
(
array(
'factory' => 'DcGeneral\DataDefinition\
DataProviderInformation\
ContaoDataProviderInformationFactory',
'type' => 'DcGeneral\DataDefinition\
DataProviderInformation\
ContaoDataProviderInformation',
'class' => 'DcGeneral\Data\DefaultDriver',
'source' => 'tl_table_name',
...
),
'root' => array(
...
),
'parent' => array(
...
),
'default' => array(
...
),
'default' => 'tl_table_name'
)
)
);
|
-> create a data provider information called tl_table_name (See comment for "source" key) -> (optional) the information type factory class name -> (optional) the information type class name. This is ignored by the ExtendedLegacyDcaDataDefinitionBuilder when a factory is defined but the factory might non the less use it. -> (optional) the driver class name, note that this is only inter- preted by the default DataProviderPopulator and other popula- tors might ignore it. -> (required) the source (table) name. NOTE: This will also get used as the name for the information. -> Any optional data that can be interpreted by any registered builder or factory. -> (required in (parented) tree mode) Root elements for tree view will get fetched from this provider. $dataProviderSection->getInformation( $basicSection()->getRootDataProvider() ); -> (required in parented list and parented tree mode) This defines the parent element the root elements (when in tree mode) or the current elements (when in list mode must be children of. $dataProviderSection->getInformation( $basicSection()->getParentDataProvider() ); -> (required) The current data provider, this is the data we really work on. $dataProviderSection->getInformation( $basicSection()->getDataProvider() ); -> Any of the named keys (root, parent, current) can be aliased to each other. In this example default is an alias of the parent and there- fore both will use the same driver. |
Normally the DcGeneral support multiple views on the container. The legacy dca will be mapped into backend view, which is the default for the Contao backend editing.
You can access the backend view section with this snippet:
use DcGeneral\DataDefinition\Section\BackendViewSectionInterface;
$backendViewSection = $container->getSection(BackendViewSectionInterface::NAME);
/** @var BackendViewSectionInterface $backendViewSection */
There is no special mapping from DCA parts into the backend view. The backend view will be filled with a listing, a panel layout and operations.
The listing contain all informations how to list the models.
You can access the listing options of the backend view section with this snippet:
use DcGeneral\DataDefinition\Section\BackendViewSectionInterface;
use DcGeneral\DataDefinition\Section\View\ListingConfigInterface;
$backendViewSection = $container->getSection(BackendViewSectionInterface::NAME);
/** @var BackendViewSectionInterface $backendViewSection */
$listingConfig = $backendViewSection->getListingConfig();
/** @var ListingConfigInterface $listingConfig */
$GLOBALS['TL_DCA']['tl_example'] = array
(
// List
'list' => array
(
'sorting' => array
(
'flag' => 6,
'fields' => array(
'published DESC', 'title', 'author'
),
'headerFields' => array(
'title', 'headline', 'author'
),
'icon' => 'path/to/icon.png',
'disableGrouping' => true,
'child_record_callback' => array(
'<class name>', '<method name>'
)
'child_record_class' => 'css_class_name'
),
'label' => array
(
'fields' => array('title', 'alias'),
'format' => '%s [%s]',
'maxCharacters' => 255,
'group_callback' => array(
'<class name>', '<method name>'
)
'label_callback' => array()
'<class name>', '<method name>'
)
)
);
|
-> (optional) define the default sorting and grouping mode $listingConfig->getGroupingMode() $listingConfig->getSortingMode() -> (optional) define the initial default sorting fields $listingConfig->getDefaultSortingFields() -> (required in parented view) define the fields of the parent element which are shown above the item list $listingConfig->getHeaderPropertyNames() -> (optional) path to an icon that is used as tree root icon $listingConfig->getRootIcon() -> (deprecated) define whether items are grouped or not, this enforce $listingConfig->getGroupingMode() to be ListingConfigInterface::GROUP_NONE when false -> (deprecated) use an event listener instead, the dispatched event depends on the view, for details, see the Callbacks chapter. -> (optional) used as item container css class $listingConfig->getItemCssClass() -> (required) this part is converted into an LabelFormatter` $listingConfig->getLabelFormatter() -> (required) used for ListItemFormatter::$propertyNames -> (optional) used for ListItemFormatter::$format -> (optional) used for ListItemFormatter::$maxLength -> (deprecated) use an event listener instead, the dispatched event depends on the view, for details, see the Callbacks chapter. -> (deprecated) use an event listener instead, the dispatched event depends on the view, for details, see the Callbacks chapter. |
You can access the panel layout of the backend view section with this snippet:
use DcGeneral\DataDefinition\Section\BackendViewSectionInterface;
use DcGeneral\DataDefinition\Section\View\PanelLayoutInterface;
$backendViewSection = $container->getSection(BackendViewSectionInterface::NAME);
/** @var BackendViewSectionInterface $backendViewSection */
$panelLayout = $backendViewSection->getPanelLayout();
/** @var PanelLayoutInterface $panelLayout */
$GLOBALS['TL_DCA']['tl_example'] = array
(
// List
'list' => array
(
'sorting' => array
(
'panelLayout' => 'filter;search,limit'
)
)
);
|
-> (optional) will be parsed and used as panel layout array. $panelLayout->getRows() will return array(array('filter'), array('search', 'limit')) |
Global operations are mapped as container scoped commands.
To see how the operations are mapped, see the Operation mapping chapter.
You can access the global operations defined in backend view section with this snippet:
use DcGeneral\DataDefinition\Section\BackendViewSectionInterface;
use DcGeneral\DataDefinition\Section\View\OperationCollectionInterface;
$backendViewSection = $container->getSection(BackendViewSectionInterface::NAME);
/** @var BackendViewSectionInterface $backendViewSection */
$globalOperations = $backendViewSection->getGlobalOperations();
/** @var OperationCollectionInterface $globalOperations */
Model operations are mapped as model scoped commands.
To see how the operations are mapped, see the Operation mapping chapter.
You can access the item operations defined in backend view section with this snippet:
use DcGeneral\DataDefinition\Section\BackendViewSectionInterface;
use DcGeneral\DataDefinition\Section\View\OperationCollectionInterface;
$backendViewSection = $container->getSection(BackendViewSectionInterface::NAME);
/** @var BackendViewSectionInterface $backendViewSection */
$itemOperations = $backendViewSection->getItemOperations();
/** @var OperationCollectionInterface $itemOperations */
In DcGeneral all operations are used as Commands (fka Operations).
'all' => array
(
'parameters' => array(),
'href' => 'act=select',
'label' => &$GLOBALS['TL_LANG']['MSC']['all'],
'description' => &$GLOBALS['TL_LANG']['MSC']['all'],
'icon' => 'delete.gif',
'class' => 'header_edit_all',
'attributes' => 'onclick="Backend.getScrollOffset()"',
'<extra data>' => <mixed>,
'button_callback' => array('<class name>', '<method name>')
)
|
-> (optional) used as operation's command name $operation->getName() -> (optional) used as operation's command parameters $operation->getParameters() -> (deprecated) the query string is parsed and used as command parameters, if the query contain a parameter named act, the value is used as command name -> (optional) used as operation label (human readable name) $operation->getLabel() -> (optional) used as operation description (tooltip) $operation->getDescription() -> (optional) will be added to extra data $operation->getExtra()['icon'] -> (optional) will be added to extra data $operation->getExtra()['class'] -> (optional) will be added to extra data $operation->getExtra()['attributes'] -> (optional) all extra data will be mapped into the operations extra data array. The usage depends on the view $operation->getExtra() -> (deprecated) use an event listener instead, the dispatched event depends on the view, for details, see the Callbacks chapter. |
Palettes define the arrangement of properties in the view. The PalettesSectionInterface itself is a subclass of PaletteCollectionInterface.
You can access the palettes defined in backend view section with this snippet:
use DcGeneral\DataDefinition\Section\PalettesSectionInterface;
$palettesSection = $container->getSection(PalettesSectionInterface::NAME);
/** @var PalettesSectionInterface $palettesSection */
$GLOBALS['TL_DCA']['tl_example'] = array
(
// Palettes
'palettes' => array
(
'__selector__' => array('protected'),
'default' => '{title_legend},title,alias,author;...'
),
// Subpalettes
'subpalettes' => array
(
'protected' => 'groups'
)
);
|
-> (deprecated) define selectors is not required,
the selector list will be used to generate the
corresponding palette conditions.
-> (deprecated) will be parsed into legends from
the {*_legend} parts and property collections
from the fields list.
-> (deprecated) the generated palettes will be extended
with the subpalette properties, each subpalette property
gain a corresponding property condition.
|
See the Palettes document for details about the new palettes system.
Properties formally known as fields, define certain meta informations of model’s properties. Every model property, that is not defined here, is ignored by DcGeneral.
These meta informations can have different effects on the properties value (like transformation), the load and store process (similar to triggers) and the view (like display formation).
You can access the properties section with this snippet:
use DcGeneral\DataDefinition\Section\PropertiesSectionInterface;
$propertiesSection = $container->getSection(PropertiesSectionInterface::NAME);
/** @var PropertiesSectionInterface $propertiesSection */
You can access a single property from the properties section with this snippet:
use DcGeneral\DataDefinition\Section\Palette\PropertyInterface;
$titleProperty = $propertiesSection->getProperty('title');
/** @var PropertyInterface $titleProperty */
$GLOBALS['TL_DCA']['tl_example'] = array
(
// Fields
'fields' => array
(
'title' => array
(
'label' => &$GLOBALS['TL_LANG']['...']['title'],
'description' => &$GLOBALS['TL_LANG']['...']['description'],
'default' => 'default value',
'exclude' => true,
'search' => true,
'sorting' => true,
'filter' => true,
'flag' => 12,
'length' => 3,
'inputType' => 'text',
'options' => array('a', 'b', 'c'),
'options_callback' => array(...),
'foreignKey' => 'tl_other_table.name',
'reference' => &$GLOBALS['TL_LANG']['...']['title'],
'explanation' => &$GLOBALS['TL_LANG']['...']['title'],
'input_field_callback' => array(...),
'wizard' => array('<class name>', '<method name>'),
'relation' => array('type'=>'hasOne', 'load'=>'eager'),
'load_callback' => array
(
array('<class name>', '<method name>')
),
'save_callback' => array
(
array('<class name>', '<method name>')
),
'eval' => array(
...
),
'sql' => "varchar(255) NOT NULL default ''"
)
)
);
|
-> (required) used as property name. $property->getName() -> (required) used as property label. if it is an array, only the first item is used as label. $property->getLabel() -> (optional) used as property description. if label is an array, the second item is used as description. $property->getDescription() -> (optional) used as property default value. $property->getDefaultValue() -> (optional) define if this property can be excluded from an editors view. $property->isExcluded() -> (optional) define if this property is searchable $property->isSearchable() -> (optional) define if this property is sortable $property->isSortable() -> (optional) define if this property is filterable $property->isFilterable() -> (deprecated) define the sort and group mode $property->getGroupingMode() $property->getSortingMode() -> (optional) define the count of signs used for grouping $property->getGroupingLength() -> (optional) define the input type (widget type) of this property. How the widget type is interpreted depends on the view. $property->getWidgetType() -> (optional) The valid values of this property, formally used by selectable input types. $property->getOptions() -> (deprecated) define a callback that produce the valid values of this property. for details, see the Callbacks chapter. -> (deprecated) define a foreign key that are used as valid values of this property. -> (deprecated) language array with translations for the valid values. -> (optional) the explanation of the property, is used in property overview. $property->getExplanation() -> (deprecated) define a callback that produce the widget html code, if this is used depends on the view. for details, see the Callbacks chapter. -> (deprecated) define a callback that produce the wizard html code, if this is used depends on the view. for details, see the Callbacks chapter. -> (ignored) the relations are only used by the Contao models (don't confuse with the DcGeneral models!) -> (deprecated) define a callback that is called after loading the data from the model. for details, see the Callbacks chapter. -> (deprecated) define a callback that is called before saving the data to the model. for details, see the Callbacks chapter. -> (optional) any additional configuration data, if this data is used depends on the view, widget type and event listeners. $property->getExtra() -> (*ignored*) the sql is used by Contao's DcaExtractor |
Callbacks are still supported for compatibility reason, but the complete DcGeneral is fully event driven and all callbacks are only triggered through a legacy callback event listener. For full functionality, you should use custom event listeners.
To find out the responsible event, have a look into the DcGeneral\DataDefinition\Builder\Event namespace.
The dataContainer parts is only necessary for contao to know which data container driver should be used. This must be General.
The dynamic ptable can be solved over the Parent-child condition mapping.
TODO add an example
Defining the child tables is not necessary at all, but can be done by a parent-child condition.
TODO add an example
TODO
TODO
TODO
DcGeneral does not do any sql updated, so there is no need to parse this informations.
$GLOBALS['TL_DCA']['tl_example'] = array
(
// Config
'config' => array
(
'label' => &$GLOBALS['TL_LANG']['tl_example']['headline'],
'dataContainer' => 'General',
'ptable' => 'tl_parent',
'dynamicPtable' => true, // require 'ptable'=>''
'ctable' => array('tl_child1', 'tl_child2'),
'validFileTypes' => 'jpg,png,gif',
'uploadScript' => '',
'closed' => true,
'notEditable' => true,
'notDeletable' => true,
'switchToEdit' => true,
'enableVersioning' => true,
'doNotCopyRecords' => true,
'doNotDeleteRecords' => true,
'onload_callback' => array
(
array('<class name>', '<method name>')
),
'onsubmit_callback' => array
(
array('<class name>', '<method name>')
),
'ondelete_callback' => array
(
array('<class name>', '<method name>')
),
'oncut_callback' => array
(
array('<class name>', '<method name>')
),
'oncopy_callback' => array
(
array('<class name>', '<method name>')
),
'sql' => array
(
'keys' => array
(
'id' => 'primary',
'pid' => 'index',
'alias' => 'index'
)
)
),
// DcGeneral config
'dca_config' => array
(
'callback' => 'DcGeneral\Callbacks\ContaoStyleCallbacks',
'controller' => 'DcGeneral\Controller\DefaultController',
'view' => 'DcGeneral\View\DefaultView',
'data_provider' => array
(
'default' => array
(
'type' => '...\ContaoDataProviderInformation',
'factory' => '...\ContaoDataProviderInformationFactory',
'class' => 'DcGeneral\Data\DefaultDriver',
'source' => 'tl_example'
),
'parent' => array
(
'type' => '...\ContaoDataProviderInformation',
'factory' => '...\ContaoDataProviderInformationFactory',
'class' => 'DcGeneral\Data\DefaultDriver',
'source' => 'tl_parent'
)
),
'rootEntries' => array(
'tl_example' => array(
'setOn' => array
(
array(
'property' => 'id',
'value' => 0
),
),
'filter' => array
(
array
(
'property' => 'id',
'value' => 0,
'operation' => '='
)
)
)
),
'childCondition' => array(
array(
'from' => 'tl_parent',
'to' => 'tl_example',
'setOn' => array
(
array(
'from_field' => 'id',
'to_field' => 'pid'
),
),
'filter' => array
(
array
(
'remote' => 'id',
'local' => 'pid',
'operation' => '='
)
)
)
)
),
// List
'list' => array
(
'sorting' => array
(
'mode' => 6,
'flag' => 6,
'panelLayout' => 'filter;search,limit',
'fields' => array('published DESC', 'title', 'author'),
'headerFields' => array('title', 'headline', 'author'),
'icon' => 'path/to/icon.png',
'root' => 6,
'filter' => array(array('status=?', 'active')),
'disableGrouping' => true,
'paste_button_callback' => array('<class name>', '<method name>'),
'child_record_callback' => array('<class name>', '<method name>'),
'child_record_class' => 'css_class_name'
),
'label' => array
(
'fields' => array('title', 'inColumn'),
'format' => '%s <span style="color:#b3b3b3">[%s]</span>',
'maxCharacters' => 255,
'group_callback' => array('<class name>', '<method name>'),
'label_callback' => array('<class name>', '<method name>')
),
'global_operations' => array
(
'all' => array
(
'label' => &$GLOBALS['TL_LANG']['MSC']['all'],
'href' => 'act=select',
'class' => 'header_edit_all',
'attributes' => 'onclick="Backend.getScrollOffset()"',
'button_callback' => array('<class name>', '<method name>')
)
),
'operations' => array
(
'delete' => array
(
'label' => &$GLOBALS['TL_LANG']['tl_example']['delete'],
'href' => 'act=delete',
'icon' => 'delete.gif',
'attributes' => 'onclick="Backend.getScrollOffset()"',
'button_callback' => array('<class name>', '<method name>')
),
)
),
// Palettes
'palettes' => array
(
'__selector__' => array('protected'),
'default' => '{title_legend},title,alias,author;...'
),
// Subpalettes
'subpalettes' => array
(
'protected' => 'groups'
),
// Fields
'fields' => array
(
'title' => array
(
'label' => &$GLOBALS['TL_LANG']['tl_example']['title'],
'default' => 'default value',
'exclude' => true,
'search' => true,
'sorting' => true,
'filter' => true,
'flag' => 12,
'length' => 3,
'inputType' => 'text',
'options' => array('a', 'b', 'c'),
'options_callback' => array('<class name>', '<method name>'),
'foreignKey' => 'tl_other_table.name',
'reference' => &$GLOBALS['TL_LANG']['tl_example']['title'],
'explanation' => &$GLOBALS['TL_LANG']['tl_example']['title'],
'input_field_callback' => array('<class name>', '<method name>'),
'wizard' => array('<class name>', '<method name>'),
'relation' => array('type'=>'hasOne', 'load'=>'eager'),
'load_callback' => array
(
array('<class name>', '<method name>')
),
'save_callback' => array
(
array('<class name>', '<method name>')
),
'eval' => array(
'helpwizard' => true,
'mandatory' => true,
'maxlength' => 255,
'minlength' => 255,
'fallback' => true,
'rgxp' => 'friendly',
'cols' => 12,
'rows' => 6,
'wrap' => 'hard',
'multiple' => true,
'size' => 6,
'style' => 'border:2px',
'rte' => 'tinyFlash',
'submitOnChange' => true,
'nospace' => true,
'allowHtml' => true,
'preserveTags' => true,
'decodeEntities' => true,
'doNotSaveEmpty' => true,
'alwaysSave' => true,
'spaceToUnderscore' => true,
'unique' => true,
'encrypt' => true,
'trailingSlash' => true,
'files' => true,
'filesOnly' => true,
'extensions' => 'jpg,png,gif',
'path' => 'path/inside/of/contao',
'fieldType' => 'checkbox',
'includeBlankOption' => true,
'blankOptionLabel' => '- none selected -',
'chosen' => true,
'findInSet' => true,
'datepicker' => true,
'colorpicker' => true,
'feEditable' => true,
'feGroup' => 'contact',
'feViewable' => true,
'doNotCopy' => true,
'hideInput' => true,
'doNotShow' => true,
'isBoolean' => true,
'disabled' => true,
'readonly' => true,
),
'sql' => 'varchar(255) NOT NULL default '''
)
)
);
|
-> Data provider mapping -> Listing mapping -> *ignored* -> Data provider mapping -> *ignored* -> *ignored* -> *ignored* -> *ignored* -> -> -> -> -> -> -> *ignored* -> ^ ^ ^ -> ^ ^ ^ -> ^ ^ ^ -> ^ ^ ^ -> ^ ^ ^ -> *ignored* ^ ^ ^ ^ ^ ^ ^ ^ -> -> Deprecated DcGeneral config -> Deprecated DcGeneral config -> Deprecated DcGeneral config -> Data provider mapping ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ -> Root entries mapping ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ -> Parent-child condition mapping ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ -> Backend view mapping -> Basic config mapping -> Listing mapping -> Panel layout mapping -> Listing mapping ^ ^ -> -> -> Listing mapping -> -> Listing mapping ^ -> Listing mapping ^ ^ ^ ^ ^ ^ -> Global operations mapping -> Operation mapping ^ ^ ^ ^ ^ ^ ^ -> Model operations mapping -> Operation mapping ^ ^ ^ ^ ^ ^ ^ -> Palettes mapping ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ -> Properties (fka fields) mapping ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ -> *ignored* |