What's the best way to site specific configuration in a multisite TYPO3 installation? - typo3

We have a TYPO3 9.5 installation with a bunch of different websites in it.
We want to store some custom configurations for each site (eg. show phone number in footer yes/no and something like this) and give the editors the possibility to change this in a simple way in the backend.
It would be nice if we can store these properties on the rootpage of each site but be able to overwrite (some) properties on sub pages if needed.
Similar to the page properties that fluidtypo3/flux brings.
Is there a possibility to achieve this with TYPO3 core and a custom extension? Eg. by extending the page table or adding custom table?

You need to differ between a site configuration and regular pages!
The site configuration is valid for the full site, so for every page
A page can be different on a page level
Both use cases are valid, so let's explain in detail
Extending the site configuration
The site configuration can easily be extended by creating the file <site-extension>/Configuration/SiteConfiguration/Overrides/sites.php
<?php
defined('TYPO3_MODE') || die('Access denied.');
call_user_func(
function ($table) {
$GLOBALS['SiteConfiguration'][$table]['columns']['trackingCode'] = [
'label' => 'Label',
'config' => [
'type' => 'input',
'eval' => 'trim',
'placeholder' => 'GTM-123456',
],
];
$GLOBALS['SiteConfiguration'][$table]['types']['0']['showitem'] .= ',--div--;Extra,trackingCode';
},
'site'
);
The value of the new field trackingCode can then be easily fetched, e.g. by TS with data = site:trackingCode. As an alternative you can also use the SiteProcessor to get access to the site configuration in a FLUIDTEMPLATE.
Extending pages
Create the file <site-extension>/Configuration/TCA/Overrides/pages.php
<?php
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns(
'pages',
[
'trackingCode' => [
'exclude' => true,
'label' => 'A label',
'config' => [
'type' => 'input',
]
],
]
);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes(
'pages',
'--div--;Extra, trackingCode'
);
and `ext_tables.sql``
CREATE TABLE pages (
trackingCode text NOT NULL
);
and you get access to the field with TypoScript and within FLUIDTEMPLATE with {data.trackingCode}.
Using slide
By adding trackingCode to the comma separated list in [FE][addRootLineFields] (use the Install Tool > Settings > Configure Installation-Wide Options it is possible to override the value for all subpages.
The following TypoScript will get up the rootline and return the 1st value set.
lib.code = TEXT
lib.code.data = levelfield:-1,trackingCode, slide

Related

TYPO3: Using ###PAGE_TSCONFIG_ID### with addRecord in TCA

The problem at hand has to do with the TCA and its addRecord option, which should save new records to a specific pid configured by ###PAGE_TSCONFIG_ID###. (TYPO3 8.7.24, php 7.2)
The websites extension has a tx_rwfm_domain_model_websitecategory and a tx_rwfm_domain_model_website table, related via a m:m table. The idea is to create website categories and then collect websites, which are assigned to a category. In the BE, the categories (pid=24) as well as the websites (pid=12) have their own folder in the site tree. websitecategory has a multiSelectField to easily select websites and assign them to the category in question. And also "website" has a multiSelectField for categories to easily assign a website to multiple categories.
So far everything is working fine.
Now I bump into this scenario:
I want to add websites to the categories, so I open the websitecategory folder page in list view.
I now realise that the website I want to add has not yet been created.
Instead of closing the websitecategory page, I click on "addRecord" next the multiSelectField of websites (m:m connection)
A new window opens to create the new website, "save and close" brings me back to the websitecategory page, where I can see that the new website was added to the selection list.
The point is: The new website has to be created in its own folder page (pid=12) and NOT on the websitecategory page (pid=24). To do so, there is the property ###PAGE_TSCONFIG_ID###, which I try to configure like this:
// TCA of websitecategory
return [
[...],
'columns' => [
'websites' => [
'config' => [
'type' => 'select',
'renderType' => 'selectMultipleSideBySide',
'enableMultiSelectFilterTextfield' => true,
'foreign_table' => 'tx_rwfm_domain_model_website',
'foreign_table_where' => 'AND tx_rwfm_domain_model_website.sys_language_uid IN (-1,0) ORDER BY tx_rwfm_domain_model_website.title ASC',
'MM' => 'tx_rwfm_domain_model_website_websitecategory_mm',
'MM_opposite_field' => 'categories',
'fieldControl' => [
'editPopup' => [...],
'addRecord' => [
'disabled' => false,
'options' => [
'setValue' => 'prepend',
'title' => 'Create a new website record',
'table' => 'tx_rwfm_domain_model_website',
'pid' => '###PAGE_TSCONFIG_ID###',
],
],
]
]
]
[...]
]
Following the documentation https://docs.typo3.org/typo3cms/TSconfigReference/8.7/PageTsconfig/TCEform/Index.html?highlight=page_tsconfig_id I add this to my page TSconfig:
// TSconfig
TCEFORM {
tx_rwfm_domain_model_website {
pid.PAGE_TSCONFIG_ID = 12
}
tx_rwfm_domain_model_websitecategory {
pid.PAGE_TSCONFIG_ID = 28
}
}
Unfortunately, this does not work. Instead, TYPO3 tries to add it to [root_level] 0, where the table is not allowed.
However, if I replace ###PAGE_TSCONFIG_ID### in TCA -> addRecord with the hard-coded value of the pid, 12, the website is indeed saved on the proper page folder with pid 12.
How do I have to configue TSconfig to make the saving process work propertly?
Using pid as a table reference before the constant PAGE_TSCONFIG_ID is most likely the wrong field you want to address. So this:
TCEFORM {
tx_rwfm_domain_model_website {
pid.PAGE_TSCONFIG_ID = 12
}
tx_rwfm_domain_model_websitecategory {
pid.PAGE_TSCONFIG_ID = 28
}
}
should become this:
TCEFORM {
tx_rwfm_domain_model_website {
[field_of_related_table].PAGE_TSCONFIG_ID = 12
}
tx_rwfm_domain_model_websitecategory {
[field_of_related_table].PAGE_TSCONFIG_ID = 28
}
}
as far as I read the source code, this only applies to values defined in foreign_table_where.
After fooling around quite some time (actually years!), it finally has become clear to me, that the field you need to assign the PID_TSCONFIG_ID to has to be the one, that acts as the pivot to the m:m relation. Or: the opposite field. The even more confusing thing about that is, that, by definition, the opposite field must only be defined on one side of the relationship. So for the "other side" you need to look at the related table's name and use that one.
In the above example that would mean, that categories has to be used instead of pid:
// TSconfig
TCEFORM {
tx_rwfm_domain_model_website {
categories.PAGE_TSCONFIG_ID = 12
}
tx_rwfm_domain_model_websitecategory {
websites.PAGE_TSCONFIG_ID = 28
}
}
That way, records get saved to their given page ids. Thanks, TYPO3, for providing such a mysterious documentation on that topic! :-(
Will try to improve the docu in that aspect ASAP.

TCA Icon overlay in typo3 backend

I’m working on an extension where I synchronise some data to another database and I wanted to show this in the backend using a TCA icon overlay. Sadly I could not find out how to do this. I thought about using ‘ctrl’=>‘typeicon_classes’ (using the state field of my table to choose an icon), this works for the default (non synchronised element) but I cannot figure out how to set an overlay. Any idea on how to do this?
My TCA configuration looks like this:
'ctrl' => [
...
'typeicon_column' => 'state',
'typeicon_classes' => [
'new' => 'mimetypes-x-content-login',
'synced' => 'mimetypes-x-content-login-overlay-approved',
]
],
The "synced" part does not work as expected. What I would expect is to either add the overlay at the end of the icon or by adding it with a whitespace but both did not work.
Any help is appreciated.
PS: I really just need this in the TYPO3 backend, the obvious solution for frontend is to use fluid or PHP but I don't think this suits the TYPO3 Backend list.
You need to register your icon files.
Given your icon files are named content_login.svg and content_login_overlay_approved.svg located in directory /Resources/Public/Icons/ you can register these in ext_localconf.php as following:
if (TYPO3_MODE === 'BE') {
$icons = [
'mimetypes-x-content-login' => 'content_login.svg',
'mimetypes-x-content-login-overlay-approved' => 'content_login_overlay_approved.svg',
];
$iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
foreach ($icons as $identifier => $path) {
$iconRegistry->registerIcon(
$identifier,
\TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
['source' => 'EXT:YOUREXTENSIONNANME/Resources/Public/Icons/' . $path]
);
}
}
Adapt yourextensionname

How to use TYPO3 Link wizard in extension

In an extension, I would like to be able to modify an existing link. The corresponding field in the database is one which may contain several links (e.g. tt_content.bodytext).
I want to reuse as much already existing functionality as possible. So I would like to use the already existing link wizard.
What I did find was the existing route rteckeditor_wizard_browse_links which uses rte_ckeditor/Classes/Controller/BrowseLinksController.php.
I use this in my view helper:
$parameters = [
'table' => $table,
'fieldName' => $field,
'pid' => $pid,
'uid' => $uid,
'recordType' => $recordType;
];
$urlParameters = [
'contentsLanguage' => 'en',
// 'route'
// 'token*
'P' => $parameters,
'curUrl' => [
'url' => $url
// todo: add anchor text etc. ...
],
'editorId' => 'cke_1'
];
$route = 'rteckeditor_wizard_browse_links';
return (string)$uriBuilder->buildUriFromRoute($route, $urlParameters);
This does opens the link wizard correctly. But it is intertwined with the ckeditor.
When I press "Set link" nothing happens and I get the following JavaScript error (visible if Console is open in Browser):
RteLinkBrowser.js?bust=8d6016d70f0f490d5e7d24262f0ec96230f399d9:77 Uncaught TypeError: Cannot read property 'document' of null
at Object.LinkBrowser.finalizeFunction (RteLinkBrowser.js?bust=8d6016d70f0f490d5e7d24262f0ec96230f399d9:77)
at HTMLFormElement.UrlLinkHandler.link (UrlLinkHandler.js?bust=8d6016d70f0f490d5e7d24262f0ec96230f399d9:40)
at HTMLFormElement.dispatch (jquery.min-16985e7a97b69d2a9c29e484ac3b581a.js:2)
at HTMLFormElement.y.handle (jquery.min-16985e7a97b69d2a9c29e484ac3b581a.js:2)
LinkBrowser.finalizeFunction # RteLinkBrowser.js?bust=8d6016d70f0f490d5e7d24262f0ec96230f399d9:77
UrlLinkHandler.link # UrlLinkHandler.js?bust=8d6016d70f0f490d5e7d24262f0ec96230f399d9:40
dispatch # jquery.min-16985e7a97b69d2a9c29e484ac3b581a.js:2
y.handle # jquery.min-16985e7a97b69d2a9c29e484ac3b581a.js:2
The corresponding line in RteLinkBrowser.js is:
var linkElement = RteLinkBrowser.CKEditor.document.createElement('a');
The Link Wizard expects the ckeditor window to be open and uses things in the DOM that are not there.
Is there some way to directly open the link wizard for a specific link within a text field?
Or alternatively open the text field with ckeditor and have the specific link preselected.
I don't have an answer, but at least here is a work-around / alternative:
Don't open Link wizard directly, open field in editor
As an alternative, consider not using the link wizard but using the route 'record_edit' to open the edit dialog for a specific RTE field. If you double-click on a link in that, the link wizard will open.
The following example was taken from linkvalidator in the core and modified. It opens an editor dialog for the field tt_content.bodytext for the record with uid $uid.
$requestUri = GeneralUtility::getIndpEnv('REQUEST_URI') .
'&id=' . $pageid;
$uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
$url = (string)$uriBuilder->buildUriFromRoute('record_edit', [
'edit' => [
'tt_content' => [
$uid => 'edit'
]
],
'columnsOnly' => 'bodytext',
'returnUrl' => $requestUri
]);
Update: For TYPO3 9, a ViewHelper exists for opening the field with FormEngine in the Backend. This has the same result.
https://docs.typo3.org/other/typo3/view-helper-reference/9.5/en-us/typo3/backend/latest/Link/EditRecord.html

Adding new checkbox field to tx_news_domain_model_media

I am trying to add a new checkbox field 'showinhome' to the table 'tx_news_domain_model_media' same to the field 'showinpreview' here is my TCA Configuration in Configuration/TCA/Overrides/tx_news_domain_model_media.php
$temporaryColumns = [
'showinhome' => [
'exclude' => 1,
'label' => 'Show in Home',
'config' => [
'type' => 'check',
'default' => 0,
],
],
];
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns(
'tx_news_domain_model_media',
$temporaryColumns
);
$GLOBALS['TCA']['tx_news_domain_model_media']['ctrl']['label_alt'] .= ', showinhome';
$GLOBALS['TCA']['tx_news_domain_model_media']['interface']['showRecordFieldList'] .= ', showinhome';
$GLOBALS['TCA']['tx_news_domain_model_media']['palettes']['newsPalette']['showitem'] .= 'showinhome,';
The field is not displayed, can someone help me please?
You have mixed up some stuff here.
First: tx_news can use either the own media model or the native FAL relations. I personally always use the native FAL relation.
If you want to add this field to the media table, then there is no newsPalette there. You can use the below code to add the new field:
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('tx_news_domain_model_media', $temporaryColumns);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('tx_news_domain_model_media', implode(',', array_keys($temporaryColumns)));
If you using the normal FAL relation then the showinpreview field is added to the sys_file_reference table's TCA configuration and not to the tx_news_domain_model_media table.
If you want to add this field to the file, then you need to add it to the sys_file_reference field the same way tx_news does it (I guess that you already copied the code from it's override file)
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('sys_file_reference', $temporaryColumns);
// add special news palette
$GLOBALS['TCA']['sys_file_reference']['palettes']['newsPalette']['showitem'] .= ', showinhome';
Last but not least: you have to specify tx_news as a dependency in your extension, otherwise TYPO3 does not know that your extension has to be loaded after tx_news. If you change the dependency after you installed your extension you probably need to uninstall and install it again in the extension manager.

How to add custom wizards in typo3 7 TCA?

When I try to add the wizard named wizard_geo_selector in TCA ,there arised an error "module not registered".Please tell me how to register the wizard properly in the TCA.?
In TYPO3 Version 7.6 new wizards are added like this:
Inside your extension create the directory Configuration/Backend/
In the new directory create a file Routes.php, it will be found automatically, no mentioning in ext_localconf.php or ext_tables.php is required. If you still need Ajax you can add the file AjaxRoutes.php in the same folder.
Content for Routes.php:
return array(
'my_wizard_element' => array(
'path' => '/wizard/tx_geoselecotor/geo_selector_wizard',
'target' => \Path\To\your\class\WizardGeoSelector::class . '::WizardAction'
),
);
Content for AjaxRoutes.php
<?php
/**
* Definitions for routes provided by EXT:backend
* Contains all AJAX-based routes for entry points
*
* Currently the "access" property is only used so no token creation + validation is made
* but will be extended further.
*/
return array('my_ajax_element' => array(
'path' => 'tx_geoselecotor/my_ajax_route',
'target' => \Path\To\your\class\MyAjaxController::class .'::myAjaxFunction'
));
If you're unsure about the notation you can compare with existing entries in the Global Variables in the Backend:
Navigate to System -> Configuration -> Backend Routes
The route of the paths is handled different, for Ajax it's always "ajax" prepended, so you've never to add it to the path, else it's twice in the route. For the common route there is no change concerning the defined string.
Now the wizard can be used and even it never has to be defined in ext_tables.php it has to be mentioned there from any table-field in the configuration-area (module[name]):
'table_field_for_wizard' => array(
'label' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xml:table_name.tx_myextension_wizard',
'config' => array (
'type' => 'user',
'userFunc' => 'Path/to/class/without/wizard->renderForm',
'wizards' => array(
'my_wizard' => array(
'type' => 'popup',
'title' => 'MyTitle',
'JSopenParams' => 'height=700,width=780,status=0,menubar=0,scrollbars=1',
'icon' => 'EXT:' . $_EXTKEY . '/Resources/Public/img/link_popup.gif',
'module' => array(
'name' => 'my_wizard_element',
'urlParameters' => array(
'mode' => 'wizard',
'ajax' => '0',
'any' => '... parameters you need'
),
),
),
'_VALIGN' => 'middle',
'_PADDING' => '4',
),
# Optional
#'softref'=>'something',
),
),
In the userFunc Path/to/class/without/wizard->renderForm you've to create a button which is linking to the wizard and onClick the wizard will open with the route you defined in Routes.php and the optional urlParameters.
Currently I never found this whole item explained in the core-documentation.
Edit:
Details about routing can be found here: Routing
The rendering process can be found here: Rendering / NodeFactory
You should probably read also the outer context of the linked paragraph.
Edit 2:
An example extension can be found here, some things never work 100% but the wizard is working. The extension is for TYPO3 Version 7:
https://github.com/DavidBruchmann/imagemap_wizard
Ricky's answer doesn't really work anymore, since addModulePath ist deprecated since version 7.
Also, just registering the module like this still give's you said error.
The only thing that keeps the wizard going again is this:
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModule('wizard','pbsurvey_answers',"",\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY).'wizard/');
But when you add this, the module appears as a new point in your TYPO3 backend.
IN TCA add the wizard like follows:
'module' => array(
'name' => 'wizard_geo_selector',
),
In ext_tables.php register the wizard.
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModulePath(
'wizard_geo_selector',
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY) . 'Modules/Wizards/Yourwizardname/'
);
Keep in mind this is deprecated since Typo3 7 and removed in Typo3 8.So you can use this method upto Typo3 7.For Typo3 8 do use the method specified by David below.