TYPO3 TCA pages types add Tab - typo3

I want to add an existing tab to special pagetype.
For example tab "social media" to pagetype 254 (folder).
So i used mergeRecursiveWithOverrule like this, but then i redefine all.
Can i only add a single tab?
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule(
$GLOBALS['TCA']['pages'],
[
'types' => [
254 => [
'showitem' => '
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general, --palette--;;standard, --palette--;;titleonly, ,
--div--;LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.tabs.socialmedia, --palette--;;opengraph, --palette--;;twittercards,
,...
,
'
]
],
],
);
Thanks

ExtensionManagementUtility::addToAllTCAtypes() is what you are looking for, especially the third parameter.
Parameters of addToAllTCAtypes():
Name of the table to which the fields should be added.
Comma-separated string of fields, the same syntax used in the showitem property of types in TCA.
Optional: record types of the table where the fields should be
added, see types in TCA for details.
Optional: position ('before' or 'after') in relation to an existing
field.
Docs: Extension Development -> Extending the TCA array -> Customization Examples

Related

Localize records and update with DataHandler

It is possible to localize records by using the "localize" command of the DataHandler
$cmd[self::TABLE_NAME] = [
uid_of_the_original_record => [
'localize' => language_uid,
]
];
$this->dataHandler->start([], $cmd);
$this->dataHandler->process_cmdmap();
This correctly adds a translated record to the DB, but with the copied strings of the original record. How is it possible to edit the properties of the localized record? By using the update command afterwards? If so, how do I get the uid of the added localization?
You can actually create localizations using the data map instead:
$data[self::TABLE_NAME] = [
'NEW123' => [
'sys_language_uid' => <language-uid>,
'l10n_parent' => <original-record-uid>, // Optionally also l10n_source
// Other fields
],
];
$this->dataHandler->start($data, []);
$this->dataHandler->process_datamap();
This way you can directly set other fields when creating a localization.
Currently it's not possible to run localize and put the translated content in there at the same time.
There are two options I can see:
Get all translated elements (by the original UID you have) and set the translated content in each of them afterwards
Hook into processCmdmap_postProcess or processCmdmap_afterFinish and put the translated content into it
I had the same issue with an importer and used option 1.

How to use/link sys_category field in custom model in TYPO3

I am developing an extension in which I am uploading files and for each file upload I need to have one or more categories associated with it.
I have built a custom category model and it shows fine at the backend when creating a record, but I want to show/link the sys_category records instead of my own custom categories.
How do I link that field in my custom model?
If anyone else stumbles upon this, I found the solution from the documentation thanks to #larry-pete.
Simply add these lines to your ext_tables.php file in your extension folder.
// Add an extra categories selection field to the pages table
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable(
'ext_key',
'your_table_name',
'categories',
array(
// Set a custom label
'label' => 'LLL:EXT:ext_key/Resources/Private/Language/locallang.xlf:additional_categories',
// This field should not be an exclude-field
'exclude' => FALSE,
// Override generic configuration, e.g. sort by title rather than by sorting
'fieldConfiguration' => array(
'foreign_table_where' => ' AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.title ASC',
),
// string (keyword), see TCA reference for details
'l10n_mode' => 'exclude',
// list of keywords, see TCA reference for details
'l10n_display' => 'hideDiff',
)
);
Hope it helps someone.

How to create inline-records (IRRE) using DataHandler in TYPO3?

In our case we have a table A which contains IRRE records using table B. Inside a backend module we import an XML file to import those records for table B.
All records/data for table A is available.
All data for table B is available, except the new uids/identifiers.
Based on https://docs.typo3.org/typo3cms/CoreApiReference/6.2/ApiOverview/Typo3CoreEngine/Database/ I have to set the identifier NEWxxxx for all new created records.
I'm importing a large number of records at once. Can I generate those identifiers in a loop and process all records at once or do I have to run the whole datamap-handling record by record ?
Besides the identifier, is there any field i have to set on the parent record which contains the IRRE record ?
No translations/workspaces/other relations are involved.
Thanks for your help.
The DataHandler in TYPO3 is using the following array structure to create new or update existing records - this is valid up to and including TYPO3 CMS 8:
$dataMap = ['<table-name>' => [
'<record-uid>' => ['<field-name>' => '<field-value>']
];
Existing records use the integer value of the record's uid field, e.g. 123, new records use some random but unique identifier that are prefixed with NEW, e.g. NEWa2b3c4f8 created by uniqid('NEW', true) - since TYPO3 CMS 7 StringUtility::getUniqueId('NEW') can and should be used for that.
Generic Example
Let's assume the following records shall be created:
a new content element in table tt_content
two new inline file references for table sys_file_reference for field tt_content.image
referencing to existing sys_file record with uid 123
referencing to existing sys_file record with uid 234
// generating unique identifiers for records to be created
$ttContentId = 'NEW58d5079c8741c822627844'; // StringUtility::getUniqueId('NEW')
$fileRefId1st = 'NEW58d506f3cd0c4159344142'; // StringUtility::getUniqueId('NEW')
$fileRefId2nd = 'NEW58d50714c1226092562338'; // StringUtility::getUniqueId('NEW')
Preparing data-map
Hava a close look to tt_content.image, this is actually defining the (new) inline references, defined by a comma separated values of new records or existing records - this could either be NEWabc,NEWdef, 123,234,345 or NEWabc,123,NEWdef, mixing new and existing record references.
$dataMap = [
'tt_content' => [
'NEW58d5079c8741c822627844' => [
'title' => 'My new content element',
'bodytext' => 'Look at the following images...',
'CType' => 'textpic',
// $fileRefId1st & $fileRefId2nd, the sorting order is defined by this as well
'image' => 'NEW58d506f3cd0c4159344142,NEW58d50714c1226092562338',
],
],
'sys_file_reference' => [
'NEW58d506f3cd0c4159344142' => [
'uid_local' => 123,
'title' => 'Image #123',
],
'NEW58d50714c1226092562338' => [
'uid_local' => 234,
'title' => 'Image #234',
],
]
];
Preparing command-map
// the command-maps is similar to the data-map to copy, localize, move records
// however, it's not required in this scenario and thus stays empty
$commandMap = [];
Executing DataHandler
$dataHandler = new \TYPO3\CMS\Core\DataHandling\DataHandler();
$dataHandler->start($dataMap, $commandMap);
$dataHandler->process_datamap();
// $dataHandler->process_cmdmap(); // if $commandMap should be processed as well
If you need the uid of the created records, this can be resolved from the internal DataHandler record mapping. For example, the following code resolves the new uid of the created tt_content record:
// fetching the actual record ID, e.g. results in 333
$ttContentId = $dataHandler->substNEWwithIDs['NEW58d5079c8741c822627844'];
Notes
Defining the references happens in the example above directly for the field tt_content.image, which can contain NEW... ids as well as existing integer ids. The behaviour for the is the same for all reference types in TYPO3:
TCA type inline, for all variants (plain, foreign_field, MM)
TCA type select, for all variants (plain, MM)
TCA type group, for all variants (plain, MM)
Passing data through DataHandler ensures that log entries are created, and the in most cases modifications can be reverted using TYPO3's history/rollback module.
Besides that, it's possible to execute mass actions - the invocation of DataHandler is not limited to just on aggregate (the tt_content record in the example above). However, the NEW... ids have to be unique and must not be re-used during mass-executions to avoid side-effects.
Transformed to table_a & table_b scenario
Transforming this to the table_a and table_b scenario of the initial question, the $dataMap might look like the following. Of course you have to determine which references to table_b are bound to table_a.
$dataMap = [
// existing records of table_a, thus using the real ids
'table_a' => [
'11' => [ 'reference_field' => 'NEWb1,NEWb2' ],
'22' => [ 'reference_field' => 'NEWb3,NEWb4' ],
'33' => [ 'reference_field' => 'NEWb5,NEWb6' ],
],
// new records to be references for table_b, thus using NEW... ids
'table_b' => [
'NEWb1' => [ ... field values of this particular table_b record ... ],
'NEWb2' => [ ... field values of this particular table_b record ... ],
'NEWb3' => [ ... field values of this particular table_b record ... ],
'NEWb4' => [ ... field values of this particular table_b record ... ],
'NEWb5' => [ ... field values of this particular table_b record ... ],
'NEWb6' => [ ... field values of this particular table_b record ... ],
],
];
Notes on identifiers
Identifiers like NEWb1 are kept simple intentionally - usually those identifiers are composed by prefix NEW and a (pseudo-)random hexadecimal string abdc....
The TYPO3 core is using $id = StringUtility::getUniqueId('NEW') to create those unique identifiers. However, that also can be achieved using $id = 'NEW' . bin2hex(random_bytes(10); - identifiers just have to be unique for this particular process.

How to use TCA Placeholder from parent records

Can anyone give me a hint how to use the TCA placeholder stuff correctly?
I got the example about sys_file_reference here, but it doesn't work if I adapt it onto my TCA table configuration
My config looks something like this:
tx_epproducts_domain_model_product => [
ctrl ...
columns => [
parent => [
label => ...
config => [
type => select
foreign_table => tx_epproducts_domain_model_product
foreign_table_where => AND tx_epproducts_domain_model_product.uid != ###THIS_UID###
]
],
name => [
label => ...
config => [
type => input
placeholder => __row|parent|name
mode => useOrOverridePlaceholder
]
]
]
]
I thought I had to write __row to reference the current record, then parent to reference the parent record by the value inside the current records parent field and then the field where the placeholder text is located, but this isn't working at all.
I even don't get the checkbox to override the value like in the sys_file_reference inline relations
EDIT:
I forgot to mention that I want to use this in columnsOverrides section of another type of the record.
Sadly, this configuration is not fixable, yet. The configuration works for the columns section but fails to work in the columnsOverrides section of the type. This probably has to do with this bug/feature: https://forge.typo3.org/issues/76671
Long story short: placholder configuration is possible, but not via columnsOverrides in another record type configuration.

Typo3 foreign_table & foreign_table_where in TCA

I am struggling with the following problem.
I have two database tables, "Books" and "Category". I am getting all the data from "books"-table via Sysfolder in Backends List-view for editing, sorting and controlling them.
What I would like to get, is that there would be in that list view also the name of the category where the book belongs.
In "Books"-table there is a field foreign-key "category_id" which defines that for which category the Book belongs. I have tried via this "category_id" to get the name of the Category in List-view of the Books.
When I define in TCA['books'] that category_id like:
'category_id' => array (
'exclude' => 0,
'label' => 'Cat name',
'config' => array (
'type' => 'select',
'foreign_table' => 'category',
'foreign_table_where' => 'AND category.id=###REC_FIELD_category_id###',
'eval' => 'int',
'checkbox' => '0',
'default' => 0
)
),
it connects the Books and Categories using category_id (in Books-table) and uid (in Category-table).
Not like I would like, that it would connect them using category_id(in Books-table) and id(in Category-table). This id is a id of the category and can be different that uid.
Am I doing something wrong or does Typo3 somehow automatically makes this "connection" to foreign tables uid. ? Is there some way to get it like I would like?
I'm afraid it's not possible to specify different foreign key. So unless somebody proves me wrong, here is a workaround that I would use.
itemsProcFunc of the select type allows you to completely override the items in the menu and thus create a different relation.
Create an extra class that will be loaded in the backend only and that will have the method that will be called in the itemsProcFunc:
yourMethod($PA, $fobj)
Make the method to load all the categories you want to have in the SELECT box and set them in the $PA['items'] by completely overriding it so that it is an array of arrays where the 0 key is element title and 1 key is the category ID that you want. See items in select.
$PA['items'] = array(array($title, $id, ''));
Include the class in the ext_tables.php:
if(TYPO3_MODE == 'BE') require_once(t3lib_extMgm::extPath($_EXTKEY).'class.YOUR_CLASS.php');
Set the config for the category field in the books table:
'itemsProcFunc' => 'tx_YOUR_CLASS->yourMethod',
In addition to the great answer of cascaval:
#cascaval: Do you mind pointing to the select.items in the Typo3TCA in the select links? The current links aren't straight forward.
http://docs.typo3.org/typo3cms/TCAReference/singlehtml/#columns-select-properties-items
(no permission to comment to your answer, so had to answer myself just for this link ... weird)