How to get the rootpage Id in a itemproc function? - typo3

I got an extension which uses itemproc functions to configure the plugins.
/Configuration/FlexForms/Config.xml:
<T3DataStructure>
<meta type="array">
<langChildren>0</langChildren>
<langDisable>1</langDisable>
</meta>
<sheets>
<sDEF>
<ROOT>
<TCEforms>
<sheetTitle>Allgemein</sheetTitle>
</TCEforms>
<type>array</type>
<el>
:
<settings.auswahlKategorie>
<TCEforms>
<label>Anzuzeigende Kategorie wählen:</label>
<config>
<type>select</type>
<itemsProcFunc>Company\myextension\UserFunc\ItemsProcFunc->getCategoryList</itemsProcFunc>
</config>
</TCEforms>
</settings.auswahlKategorie>
:
</el>
</ROOT>
</sDEF>
</sheets>
</T3DataStructure>
in function definition
/**
* Generiert die Liste der Kategorien.
*
* Wird für den Aufbau der "FlexForm" benötigt.
*
* #param string_array $config TYPO3 config array.
* #return string_array Angepasstes TYPO3 - Config array.
*/
public function getCategoryList($config) {
:
they assume the root page could be accessed with:
$pageId = $config['flexParentDatabaseRow']['pid'];
to access the typoscript configuration:
$conf = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('Company\\myextension\\Services\\Config');
$conf->setConfFromTsSetup($pageId);
but there is no value $config['flexParentDatabaseRow']['pid'] and so the typoscript from page 0 is fetched, where no typoscript exist.
how can I provide a correct root-page Id (without modifying the sources from the external company)?

I'm pretty sure what they meant is that you have to add the configuration to your flexform config.
Should be something like this:
<config>
<type>select</type>
<itemsProcFunc>Company\myextension\UserFunc\ItemsProcFunc->getCategoryList</itemsProcFunc>
<flexParentDatabaseRow>
<pid>1</pid>
</flexParentDatabaseRow>
</config>
Not sure this is the correct way, but I'm pretty sure that $config refers to that very config section of the flexform or TCA setup if TCA is used.

The problem was the installed compatibility6 extension.
This issue gave the hint:
The breaking change no 70132 ("FormEngine custom functions") in the
TYPO3 core 7.6 suggests using 'flexParentDatabaseRow' instead of 'row'
for retrieving the full parent database row in a userFunc /
itemsProcFunc.
There is no setting I need to do. The values are set when the data is received.

Related

TYPO3: Default setting in TCA overwritten when settable via Flexforms in Extbase Extension

I added the possibility to set a detailPid in my Extension via flexforms:
<ROOT>
<type>array</type>
<el>
<settings.detailPid>
<TCEforms>
<label>
LLL:EXT:events/Resources/Private/Language/locallang_db.xlf:flexforms.overview.detailPid
</label>
<config>
<type>group</type>
<internal_type>db</internal_type>
<allowed>pages</allowed>
<size>1</size>
<maxitems>1</maxitems>
<show_thumbs>1</show_thumbs>
<wizards>
<suggest>
<type>suggest</type>
</suggest>
</wizards>
</config>
</TCEforms>
</settings.detailPid>
</el>
</ROOT>
I want to set the default detailPid via TS in my setup.ts:
plugin.tx_events_eventdetail {
settings {
listPid = {$plugin.tx_events_eventdetail.settings.listPid}
detailPid = {$plugin.tx_events_eventdetail.settings.detailPid}
}
}
My problem is, that if I don't configure a detailPid in my plugin, the default value from my TS is not used. The settings.detailPid in my Controller or in the FLUID-Template is empty. Is there a way to just fix that?
I already looked around and found out, that the news-extension has the same behavior.
Thanks for any help and suggestions!
At least the extensions tt_address and news have a configuration which allow a fallback to TS if flexform is empty. If you need that, you can copy the code and use that in your extension.
There is no configuration available in the core for that.
You can rename your flexforms detailPid path to something like settings.flexform.detailPid then in your controller you may merge the settings from TS with those from the Flexform so that only non empty values will take affect.
ArrayUtility::arrayMergeRecursiveOverrule($this->settings, $this-settings['flexform'])
https://api.typo3.org/typo3cms/current/html/class_t_y_p_o3_1_1_c_m_s_1_1_extbase_1_1_utility_1_1_array_utility.html#af4008bc539411e9114ed53b1b007735b

TYPO3 FlexForm: how to disable field in inline element?

I have a TYPO3 plugin with a FlexForm. In the FlexForm I added relations to a foreign table. I now need to disable some of the fields of the foreign table. I can't do this via user rights since it's a question of context, not rights.
My FlexForm looks like this:
<settings.moreinfo>
<TCEforms>
<label>my label</label>
<config>
<type>inline</type>
<foreign_table>tx_foo_domain_model_bar</foreign_table>
<foreign_field>content_uid</foreign_field>
<foreign_sortby>sorting</foreign_sortby>
<maxitems>50</maxitems>
</config>
</TCEforms>
</settings.moreinfo>
I thought about TCEFORM, but have no idea how to address the field:
TCEFORM.tt_content.pi_flexform.foobar.general {
settings\.moreinfo {
# maybe here?
}
}
Is there any possibility to disable a field via TSconfig or PHP?
in general you could disable flexform fields. the manual states the possibility:
Other properties also apply to flex form fields, in this case the full property path including the data structure key has to be set:
TCEFORM.[tableName].[fieldName].[dataStructureKey].[flexSheet].[flexFieldName].[propertyName].
The [dataStructKey] represents the key of a FlexForm in
$GLOBALS['TCA'][<tableName>]['columns'][<field>]['config']['ds']. This
key will be split into up to two parts. By default the first part will
be used as identifier of the FlexForm in TSconfig. The second part
will override the identifier if it is not empty, list or *.
For example the identifier of the key my_ext_pi1,list will be my_ext_pi1
and of the key *,my_CType it will be my_CType. See section Pointing to
a data structure of the TCA reference for details.
Some properties apply to whole FlexForm sheets, their property path is
TCEFORM.[tableName].[fieldName].[dataStructureKey].[flexSheet].[propertyName].
it could be problematic if you use . inside of identifiers.
This answer to a different question inspired me to the solution which finally solved my problem!
foreign_types was the solution I was looking for:
<settings.moreinfo>
<TCEforms>
<label>my label</label>
<config>
<type>inline</type>
<foreign_table>tx_foo_domain_model_bar</foreign_table>
<foreign_field>content_uid</foreign_field>
<foreign_sortby>sorting</foreign_sortby>
<maxitems>50</maxitems>
<foreign_types type="array">
<numIndex index="1" type="array">
<showitem>
title, link, --div--;LLL:EXT:cms/locallang_ttc.xlf:tabs.access, hidden;;1, starttime, endtime
</showitem>
</numIndex>
</foreign_types>
</config>
</TCEforms>
</settings.moreinfo>

Get sys_categories from tt_content flexform settings

Let's say I have a FE Plugin with the option to set some sys_category references via the following flexform field:
<settings.categories>
<TCEforms>
<label>Some Label</label>
<config>
<type>select</type>
<foreign_table>sys_category</foreign_table>
<foreign_table_where> AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.sorting ASC</foreign_table_where>
<MM>sys_category_record_mm</MM>
<MM_opposite_field>items</MM_opposite_field>
<MM_match_fields>
<tablenames>tt_content</tablenames>
<fieldname>categories</fieldname>
</MM_match_fields>
<maxitems>9999</maxitems>
<renderMode>tree</renderMode>
<size>10</size>
<treeConfig>
<appearance>
<expandAll>1</expandAll>
<showHeader>1</showHeader>
</appearance>
<parentField>parent</parentField>
</treeConfig>
</config>
</TCEforms>
</settings.categories>
Now I want to get all category Objects referenced in the flexform in the controller of the plugin. What's the best approach to do so? Should’nt there already be a suitable repository function somewhere? Thank you for your help!
There is no dedicated API for that, however normally you wouldn't need the mm-relation. Removing that and having it like
<settings.categories>
<TCEforms>
<label>LLL:EXT:news/Resources/Private/Language/locallang_be.xlf:flexforms_general.categories</label>
<config>
<type>select</type>
<renderMode>tree</renderMode>
<renderType>selectTree</renderType>
<treeConfig>
<dataProvider>GeorgRinger\News\TreeProvider\DatabaseTreeDataProvider</dataProvider>
<parentField>parent</parentField>
<appearance>
<maxLevels>99</maxLevels>
<expandAll>TRUE</expandAll>
<showHeader>TRUE</showHeader>
<width>600</width>
</appearance>
</treeConfig>
<foreign_table>sys_category</foreign_table>
<foreign_table_where>AND (sys_category.sys_language_uid = 0 OR sys_category.l10n_parent = 0) ORDER BY sys_category.sorting</foreign_table_where>
<size>15</size>
<minitems>0</minitems>
<maxitems>99</maxitems>
</config>
</TCEforms>
</settings.categories>
it is much easier to retrieve the categories. You can also take a look at the CategoryRepository I am using for the news extension https://github.com/georgringer/news/blob/master/Classes/Domain/Repository/CategoryRepository.php

Render multitype link field via fluid - TYPO3

What is the best way to render link field in TYPO3 fluid template?
Link field is defined via flexform as:
<field_link type="array">
<TCEforms type="array">
<config type="array">
<type>input</type>
<eval>trim</eval>
<wizards type="array">
<link type="array">
<type>popup</type>
<title>Link</title>
<icon>link_popup.gif</icon>
<script>
browse_links.php ? mode = wizard & amp;
act = page
</script>
<params type="array">
<blindLinkOptions>file,spec,email,folder</blindLinkOptions>
</params>
<JSopenParams>height=300,width=500,status=0,menubar=0,scrollbars=1</JSopenParams>
</link>
</wizards>
</config>
<label>link</label>
</TCEforms>
</field_link>
Fluid comes with viewhelpers such as link.email, link.external, link.page but my link field could be either page id or external link or email or link to sys_file record. How do you handle that in your projects without making multiple if statemens in fluid template? (custom viewhelper?, typoscript object)?
You can also use the f:link.page to generate links external urls or files, that does not matter as internally typolink is used.
If you are using the wizards like in your example, you should use the f:link.typolink viewhelper which supports all attributes.
Link for email works perfect
here my flexform:
<settings.link>
<TCEforms>
<label>Link</label>
<config>
<type>input</type>
<size>30</size>
<eval>trim</eval>
<softref>typolink,typolink_tag,images,url</softref>
<wizards>
<_PADDING>2</_PADDING>
<link>
<type>popup</type>
<title>Link</title>
<module>
<name>wizard_element_browser</name>
<urlParameters>
<mode>wizard</mode>
</urlParameters>
</module>
<icon>link_popup.gif</icon>
<script>browse_links.php?mode=wizard</script>
<params>
<blindLinkOptions>file,folder,url,spec</blindLinkOptions>
</params>
<JSopenParams>height=500,width=500,status=0,menubar=0,scrollbars=1</JSopenParams>
</link>
</wizards>
</config>
</TCEforms>
</settings.link>
Output:
Liunk

TCA (flexform) multi select

I work on an extension and for a plugin I want to select specific records. For that I created a flexform with a TCA select configuration:
<T3DataStructure>
<meta>
<langDisable>1</langDisable>
</meta>
<sheets>
<sDEF>
<ROOT>
<TCEforms>
<sheetTitle>TEST</sheetTitle>
</TCEforms>
<type>array</type>
<el>
<settings.selection>
<TCEforms>
<exclude>1</exclude>
<label>Selection</label>
<config>
<type>select</type>
<foreign_table>tx_mycollection_domain_model_mycollection</foreign_table>
<renderType>selectCheckBox</renderType>
<size>5</size>
<minItems>3</minItems>
<maxItems>999</maxItems>
<foreign_table_where>AND tx_mycollection_domain_model_mycollection.sys_language_uid=###REC_FIELD_sys_language_uid###</foreign_table_where>
</config>
</TCEforms>
</settings.selection>
</el>
</ROOT>
</sDEF>
</sheets>
</T3DataStructure>
It looks fine, in the backend I have checkboxes to select the records. But when I save the plugin only the first checkbox is checked/saved.
Is there something wrong in the configuration or what could be the reason that I can not save multible values?
<minItems>3</minItems>
<maxItems>999</maxItems>
From the documentation here:
https://docs.typo3.org/typo3cms/TCAReference/Reference/Columns/Select/Index.html#properties
These needs to be specified as all lower case, so changing them to:
<minitems>3</minitems>
<maxitems>999</maxitems>
Should resolve your issue. It is saving only 1 right now, since maxitems by default is set to 1.