typoscript variable in plugin settings? - typo3

I am using a custom plugin and I need to add the page title as one of the plugin's settings variables:
plugin.tx_fsearch {
settings {
resultsPath = search-results/brand/{field:title}/make/{field:title}
resultsPath.insertData = 1
}
}
However this is outputting the word 'Array' instead of the path I need.
Does anyone know how I might be able to make this work?

There is no stdWrap available for settings in extbase extensions, no matter if using TEXT cObj or insertData!
As a workaround, you can fix that yourself by doing something like EXT:news does here https://github.com/georgringer/news/blob/master/Classes/Controller/NewsController.php#L495
public function injectConfigurationManager(
\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
) {
$this->configurationManager = $configurationManager;
$typoScriptService = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Service\TypoScriptService::class);
$typoScriptArray = $typoScriptService->convertPlainArrayToTypoScriptArray($originalSettings);
$stdWrapProperties = GeneralUtility::trimExplode(',', $originalSettings['useStdWrap'], true);
foreach ($stdWrapProperties as $key) {
if (is_array($typoScriptArray[$key . '.'])) {
$originalSettings[$key] = $this->configurationManager->getContentObject()->stdWrap(
$originalSettings[$key],
$typoScriptArray[$key . '.']
);
}
}
}
$this->settings = $originalSettings;
}
Or you skip the TS part and call the stdWrap directly in your controller.

Try TEXT object
plugin.tx_fsearch {
settings {
resultsPath = TEXT
resultsPath.value = search-results/brand/{field.title}/make/{field.title}
}
}

Related

How to use DataProcessors with TYPO3 plugins

The way to add a DataProcessor to a PAGE or a FLUIDTEMPLATE is often shown. How can it be assigned to a TYPO3 plugin?
For a PAGE you can do it like this:
page {
10 {
dataProcessing {
1558428437 = BK2K\BootstrapPackage\DataProcessing\ConstantsProcessor
1558428437 {
as = myconstants
key = settings.constants
}
}
}
}
But can you do something like this:
config.tx_extbase {
dataProcessing {
1558428437 = BK2K\BootstrapPackage\DataProcessing\ConstantsProcessor
1558428437 {
as = myconstants
key = settings.constants
}
}
Many thanks!
No, this is not possible since data processors is a feature of the FLUIDTEMPLATE content object alone.
In this case you can invoke the ConstantsProcessor manually in your controller action. You can get the current ContentObjectRenderer via $this->configurationManager->getContentObject(). The $processorConfiguration is the same as in TypoScript but as array:
$constantsProcessor = GeneralUtility::makeInstance(ConstantsProcessor::class);
$data = $constantsProcessor->process(
$this->configurationManager->getContentObject(),
[],
[
'key' => 'settings.constants',
'as' => 'myconstants',
],
[]
);
// Use $data['myconstants']
That's currently not possible.
This would definitely be a feature that would make live of Integrators much easier.

TYPO3: Render a plugin via Typoscript or ViewHelper and change settings

I would like to load a plugin dynamically according to some data. First I tried to do it with Typoscript, but after some research I figured out, that it is not possible to change the settings of the plugin (see old forum entry).
I need to change settings.simplepoll.uid according to the passed data:
This is the Typoscript I tried:
lib.loadSimplepoll = USER
lib.loadSimplepoll {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
extensionName = Simplepoll
pluginName = Polllisting
vendorName = Pixelink
switchableControllerActions {
SimplePoll {
1 = list
}
}
settings < plugin.tx_simplepoll.settings
settings {
simplepoll {
uid.current = 1
}
}
}
The call in the template looks like that:
<f:cObject typoscriptObjectPath="lib.loadSimplepoll">{newsItem.simplepoll}</f:cObject>
After figuring out, that changing the settings is not possible, I tried a viewhelper:
<?php
namespace Vendor\Extension\ViewHelpers;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class LoadSimplepollViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper
{
/**
* #param int $uid Uid of poll
* #return string
*/
public function render($uid) {
$cObj = GeneralUtility::makeInstance('TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer');
$configurationManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Configuration\\ConfigurationManager');
$simplepollTs = $configurationManager->getConfiguration(
\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
'simplepoll',
'Polllisting'
);
$ttContentConfig = array(
'tables' => 'tt_content',
'source' => 1030,
'dontCheckPid' => 1
);
// returning this works perfectly!
// but I need to change the "settings.simplepoll.uid"
$data = $cObj->RECORDS($ttContentConfig);
$cObj->start($data, 'tx_simplepoll_domain_model_simplepoll');
$renderObjName = '<tt_content.list.20.simplepoll_polllisting';
$renderObjConf = $GLOBALS['TSFE']->tmpl->setup['tt_content.']['list.']['20.']['simplepoll_polllisting.'];
$renderObjConf['persistence']['storagePid'] = 394; // This does not work!
$renderObjConf['settings'] = $simplepollTs;
$renderObjConf['settings']['simplepoll']['uid'] = $uid;
return $cObj->cObjGetSingle($renderObjName, $renderObjConf);
}
}
The viehelper is called like this:
{vh:LoadSimplepoll(uid: '{newsItem.simplepoll}')}
Now I am able to change the uid of the poll with this line:
$renderObjConf['settings']['simplepoll']['uid'] = $uid;
My problem is now, that it loads the poll, but not the answers. I tracked this down to the fact, that the plugin somehow does not know the Record Storage Page anymore. The line $renderObjConf['persistence']['storagePid'] = 394; does not help.
How can I tell the plugin the Storage Pid?
Or is there another/better way to load a plugin with changing data?
Why shouldn't it be possible to modify settings.simplepoll.uid in typoscript?
because the extension simplepoll does not handle any stdWrap functionality to its typoscript settings.
Have a look into the code:
this special setting is used here:
$simplePoll = $this->simplePollRepository->findByUid($this->settings['simplepoll']['uid']);
no stdWrap, just plain usage.
compare it to ext:news:
before any settings is used it is processed. A dedicated join of typoscript settings with the settings in the plugin. And if necessary there is a stdWrap possible: here
$this->originalSettings = $originalSettings;
// Use stdWrap for given defined settings
if (isset($originalSettings['useStdWrap']) && !empty($originalSettings['useStdWrap'])) {
$typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
$typoScriptArray = $typoScriptService->convertPlainArrayToTypoScriptArray($originalSettings);
$stdWrapProperties = GeneralUtility::trimExplode(',', $originalSettings['useStdWrap'], true);
foreach ($stdWrapProperties as $key) {
if (is_array($typoScriptArray[$key . '.'])) {
$originalSettings[$key] = $this->configurationManager->getContentObject()->stdWrap(
$typoScriptArray[$key],
$typoScriptArray[$key . '.']
);
}
}
}
As you can see:
extbase does not support you with typoscript stdWrap functionality.
You (and every extension author) need to do it by hand. But that was so even before extbase.
In this way: as you can not configure your value you only can trick TYPO3 (and the plugin):
if you have a small number of uids you can have one variant for each uid
lib.loadSimplepoll123 < lib.loadSimplepoll
lib.loadSimplepoll123.settings.simplepoll.uid = 123
lib.loadSimplepoll234 < lib.loadSimplepoll
lib.loadSimplepoll234.settings.simplepoll.uid = 234
lib.loadSimplepoll345 < lib.loadSimplepoll
lib.loadSimplepoll345.settings.simplepoll.uid = 345
lib.loadSimplepoll456 < lib.loadSimplepoll
lib.loadSimplepoll456.settings.simplepoll.uid = 456
and call it like
<f:cObject typoscriptObjectPath="lib.loadSimplepoll{newsItem.simplepoll}" />
or you build a pull request implementing the stdWrap functionality and send it to the extension author.
Why shouldn't it be possible to modify settings.simplepoll.uid in typoscript?
you just need the correct construction to modify it.
For a single value you can use current, but use it properly. It is a stdWrap function which needs to be evaluated.
If there is no stdWrap evaluation by default it might work with a cObject of type TEXT
settings.simplepoll.uid.cObject = TEXT
settings.simplepoll.uid.cObject.current = 1
or to indicate a stdWrap you need to use stdWrap literally:
settings.simplepoll.uid.stdWrap.current = 1
another variant of data transfer are named parameters. Just build an associative array as data parameter and access the values individual:
fluid:
<f:cObject typoscriptObjectPath="lib.arraytest" data="{a:'abc',b:'xyz'}" >
inside text
</f:cObject>
and the typoscript:
lib.arraytest = COA
lib.arraytest {
10 = TEXT
10.field = a
10.wrap = /|/
20 = TEXT
20.field = b
20.wrap = \|\
}
which results in an output of /abc/\xyz\. Be aware: the inner text of the f:cobject tag will be lost as the data parameter has priority about inner children.
In the meantime I got the Viewhelpter to work:
Viewhelper:
<?php
namespace Vendor\Extension\ViewHelpers;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class LoadSimplepollViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper
{
/**
* #return void
*/
public function initializeArguments()
{
parent::initializeArguments();
$this->registerArgument('simplepollUid', 'int', 'Uid of simplepoll', false);
}
/**
* #return string
*/
public function render()
{
$configurationManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Configuration\\ConfigurationManager');
$simplepollTs = $configurationManager->getConfiguration(
\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
'simplepoll',
'Polllisting');
$cObj = GeneralUtility::makeInstance('TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer');
$renderObjName = '<tt_content.list.20.simplepoll_polllisting';
$renderObjConf = $GLOBALS['TSFE']->tmpl->setup['tt_content.']['list.']['20.']['simplepoll_polllisting.'];
$renderObjConf['settings'] = $simplepollTs;
$renderObjConf['settings']['simplepoll']['uid'] = (int)$this->arguments['simplepollUid'];
return $cObj->cObjGetSingle($renderObjName, $renderObjConf);
}
}
Call the viewhelper in the template (don't forget to register the namespace):
{vh:LoadSimplepoll(simplepollUid: '{newsItem.ipgSimplepoll}')}
That's it.

How to choose the template dynamically with fluidpages

I was using fluidpages for template building, and would like to choose the template dynamically based on a field in the fe_users table. For example, most people will see the EXT:default template by default, while some will see EXT:advanced template instead, as they are marked as special.
I tried
plugin.tx_template {
view {
templateRootPaths {
0 = EXT:default/Resources/Private/Templates/
10 {
data = TSFE:fe_user|user|template
wrap = EXT: | /Resources/Private/Templates/
}
}
}
}
But it seems the TS is not parsed and is used directly by fluid, therefore failed.
Any idea or hint is appreciated!
Actually this may be possible. But i can't see an obvious way on how to override the chosen template in the page properties.
To my knowledge, you are required to select a template in the page record.
If you find a possibility to override that one, you could use a TS Setup like this:
EXT:template_package/Configuration/TypoScript/constants.txt:
plugin.tx_templatepackage {
view {
templateRootPaths.default = EXT:template_package/Resources/Private/Templates/
partialRootPaths.default = EXT:template_package/Resources/Private/Partials/
layoutRootPaths.default = EXT:template_package/Resources/Private/Layouts/
}
}
EXT:template_package/Configuration/TypoScript/setup.txt:
plugin.tx_templatepackage {
view {
templateRootPaths.default = {$plugin.tx_templatepackage.view.templateRootPaths.default}
partialRootPaths.default = {$plugin.tx_templatepackage.view.partialRootPaths.default}
layoutRootPaths.default = {$plugin.tx_templatepackage.view.layoutRootPaths.default}
}
}
Above part will setup your global paths.
After that, you'll define your sub packages for templates.
EXT:template_package/Configuration/TypoScript/Basic/setup.txt
plugin.tx_templatepackage {
view {
templateRootPaths.10 = {$plugin.tx_templatepackage.view.templateRootPaths.0}Basic/
partialRootPaths.10 = {$plugin.tx_templatepackage.view.partialRootPaths.0}Basic/
layoutRootPaths.10 = {$plugin.tx_templatepackage.view.layoutRootPaths.0}Basic/
}
}
And
EXT:template_package/Configuration/TypoScript/Advanced/setup.txt
plugin.tx_templatepackage {
view {
templateRootPaths.20 = {$plugin.tx_templatepackage.view.templateRootPaths.0}Advanced/
partialRootPaths.20 = {$plugin.tx_templatepackage.view.partialRootPaths.0}Advanced/
layoutRootPaths.20 = {$plugin.tx_templatepackage.view.layoutRootPaths.0}Advanced/
}
}
Of course you should make them available within TYPO3:
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile($_EXTKEY, 'Configuration/TypoScript', 'Template Package: Base');
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile($_EXTKEY, 'Configuration/TypoScript/Basic', 'Template Package: Basic');
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile($_EXTKEY, 'Configuration/TypoScript/Advanced', 'Template Package: Advanced');
After all of that, you could override a value — IDK which one — via:
[usergroup = group1-uid]
// override option, which defines the default template
[usergroup = group2-uid]
// override option, which defines the default template
Sorry I can't help you out any further. I tried to dig deeper into EXT:flux and EXT:fluidpages. But i can't see that option.

Flexforms in extension without plugin

I have a extbase extension which inserts a content element over PageTSconfig:
NewContentElementWizard.ts:
mod.wizards.newContentElement.wizardItems.common {
elements {
tz_linkrow {
iconIdentifier = content-textpic
title = LLL:EXT:myext/Resources/Private/Language/locallang_db_new_content_el.xlf:wizards.newContentElement.myext_title
description = LLL:EXT:myext/Resources/Private/Language/locallang_db_new_content_el.xlf:wizards.newContentElement.myext_description
tt_content_defValues {
CType = myext_linkrow
}
}
}
show := addToList(linkrow)
}
Is there a possibility to use a flexform?
How can i insert it`?
Try this...
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue(
$_EXTKEY,
'FILE:EXT:pf_spacer/Configuration/FlexForms/flexform_ds.xml',
'tz_linkrow'
);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('tt_content', 'pi_flexform', 'myext_linkrow', 'replace:rowDescription');

Set templavoila template with typoscript

Is it possible to set a page's templavoila template with typoscript?
I have solved it with:
includeLibs.lang = fileadmin/user_tvtest.php
page.1 = USER_INT
page.1.userFunc = user_tvtest->main
page.10 = USER_INT
page.10.userFunc = tx_templavoila_pi1->main_page
page.10.disableExplosivePreview = 1
and in fileadmin/user_tvtest.php:
class user_tvtest
{
function main($content, $conf)
{
if (is_mobile())
{
$GLOBALS['TSFE']->page['tx_templavoila_to'] = 7;
//$GLOBALS['TSFE']->page['tx_templavoila_ds'] = 7;
}
}
}
http://daschmi.de/templavoila-template-domainbezogen-umschalten-gleicher-seitenbaum/
Look how the page is configured by TemplaVoila:
page = PAGE
page.typeNum = 0
page.10 = USER
page.10.userFunc = tx_templavoila_pi1->main_page
page.shortcutIcon = {$faviconPath}
They call the main_page function of class tx_templavoila_pi1 via page.userFunc:
/**
* Main function for rendering of Page Templates of TemplaVoila
*
* #param string Standard content input. Ignore.
* #param array TypoScript array for the plugin.
* #return string HTML content for the Page Template elements.
*/
function main_page($content,$conf) {
$this->initVars($conf);
// Current page record which we MIGHT manipulate a little:
$pageRecord = $GLOBALS['TSFE']->page;
// Find DS and Template in root line IF there is no Data Structure set for the current page:
if (!$pageRecord['tx_templavoila_ds']) {
foreach($GLOBALS['TSFE']->tmpl->rootLine as $pRec) {
if ($pageRecord['uid'] != $pRec['uid']) {
if ($pRec['tx_templavoila_next_ds']) { // If there is a next-level DS:
$pageRecord['tx_templavoila_ds'] = $pRec['tx_templavoila_next_ds'];
$pageRecord['tx_templavoila_to'] = $pRec['tx_templavoila_next_to'];
} elseif ($pRec['tx_templavoila_ds']) { // Otherwise try the NORMAL DS:
$pageRecord['tx_templavoila_ds'] = $pRec['tx_templavoila_ds'];
$pageRecord['tx_templavoila_to'] = $pRec['tx_templavoila_to'];
}
} else break;
}
}
// "Show content from this page instead" support. Note: using current DS/TO!
if ($pageRecord['content_from_pid']) {
$ds = $pageRecord['tx_templavoila_ds'];
$to = $pageRecord['tx_templavoila_to'];
$pageRecord = $GLOBALS['TSFE']->sys_page->getPage($pageRecord['content_from_pid']);
$pageRecord['tx_templavoila_ds'] = $ds;
$pageRecord['tx_templavoila_to'] = $to;
}
return $this->renderElement($pageRecord, 'pages');
}
This function checks the current page or search trough the rootline (TSFE) for the configured page template. The script does not check any TypoScript settings at all so I suppose thats not supported by TemplaVoila right now.
It should not be too hard extending this class with a custom function that will check some TypoScript settings.