TYPO3: Special tt_contenttype. Modify content before output - typo3

Can I create a "special" type of tt_content, so text is beeing processed in some custom ways before outputtet?
In my case I would like to add ###MY_MARKER### somewhere in header and/or bodytext and have it replaced by the right words for the given page.
eg:
When visiting this page: mypage.com/?marker=test
Header in tt_content: "Welcome to ###MY_MARKER##, enjoy
Output in browser: "Welcome to TEST, enjoy"
I CAN do it by making a custom plugin. Question is more if I can reuse normal tt_contant for the same purpose

Yes, you can easily extend the tt_content by adding your own TCA configuration to the typo3conf/extTables.php file:
t3lib_div::loadTCA('tt_content');
$TCA['tt_content']['columns']['CType']['config']['items']['user_my_type'] = array(
0 => 'My custom content',
1 => 'user_my_type',
2 => 'i/tt_content.gif',
);
$TCA['tt_content']['ctrl']['typeicon_classes']['user_my_type'] = 'mimetypes-x-content-text';
$TCA['tt_content']['ctrl']['typeicons']['user_my_type'] = 'tt_content.gif';
/* In the following either copy, insert and modify configuration from some other
content elemenet (you can find it in the ADMIN TOOLS -> Configuration - $TCA)... */
$TCA['tt_content']['types']['user_my_type']['showitem'] = '';
/* ...or assign it some other configuration so that it's exactly the same
as some other content type and stays the same after some update of TYPO3: */
$TCA['tt_content']['types']['user_my_type']['showitem'] = $TCA['tt_content']['types']['text']['showitem'];
After that, just set in your Typoscript template how the element is supposed to be rendered:
tt_content.user_my_type = COA
tt_content.user_my_type {
10 = TEMPLATE
10 {
template = TEXT
template.field = header
marks {
MY_MARKER = TEXT
MY_MARKER.value = TEST
}
}
20 = TEMPLATE
20 {
template = TEXT
template {
field = bodytext
required = 1
parseFunc = < lib.parseFunc_RTE
}
marks < tt_content.user_my_type.10.marks
}
}
NOTES
The Typoscript rendering is just a simplified example. You might want to add other standard configuration like in other elements, e.g. the one that adds edit icons for frontend display.
The marker in my example can be populated by the value of a GET paramater in the URL as you wanted but this would have nasty security implications. You would certainly need very good validation of that input.

Related

Typo3 Typoscript additionalHeaders header location using variable

I try to redirect a link which is coming, but before part of the link should be replaced.
tmp.getSlug = TEXT
tmp.getSlug.data = getIndpEnv : TYPO3_REQUEST_URL
tmp.getSlug.replacement {
10 {
search = myLinkPart
replace = myNewLinkPart
}
}
config.additionalHeaders.10 {
header = Location: {tmp.getSlug}
}
So from: www.myUrl.de/test/myLinkPart/test2/
To: www.myUrl.de/test/myNewLinkPart/test2/
It must be inside Typoscript because of other conditions.
Does anybody has an idea?
you are mixing different objects in a non functional way.
First you define tmp.getSlug as a typoscript object. Then you try to use it as a data variable.
Additional everything beyond tmp. is not available at rendering time. (it just is available when the typoscript is scanned.)
If you want to use the evaluation of tmp.getSlug you need to assign it to a permanent object and then store it in a register so you can access it afterwards.
Additional you need a flexible object to compose the Location header, which by default just contains a string.
Either a text object where you can use data (which must be evaluated and stored in a register before) or a COA to compose the static and the dynamic string.
This might be a solution:
tmp.getSlug = TEXT
tmp.getSlug.data = getIndpEnv : TYPO3_REQUEST_URL
tmp.getSlug.replacement {
10 {
search = myLinkPart
replace = myNewLinkPart
}
}
config.additionalHeaders.10 {
header.cObject = COA
header.cObject {
10 = TEXT
10.value = Location:
20 < tmp.getSlug
}
}

TYPO3 11 call stdWrap from Extbase

How do you call the ContentObjectRenderer method stdWrap from Extbase?
The setup from a pi_base plugin is:
plugin.tx_myextension {
standard = TEXT
standard.value = Sorry, no data could be fetched!
}
In TYPO3 extensions without Extbase you have the $conf array with the keys
'standard' =>
'TEXT' (string)
and the key
'standard.' =>
'value' (array) =>
'Sorry, no data could be fetched!'.
Then you call the method by:
$out =
$cObj->stdWrap(
$conf['standard'],
$conf['standard.']
);
This will render the desired text 'Sorry, no data could be fetched!' into $out.
But in Extbase you do not have the $conf array in this way. Exbase delivers the $this->settings to store the settings part of the setup.
plugin.tx_myextension {
settings {
standard = TEXT
standard.value = Sorry, no data could be fetched!
}
}
The standard setup is internally stored by Extbase as a 2-dimensional array with this data:
'standard'
=> 'value' (Array)
=> 'Sorry, no data could be fetched!'
and
'standard'
=> '_typoScriptNodeValue' (Array)
=> 'TEXT'
I have tried it this way ($conf = $this->settings):
$out =
$cObj->stdWrap(
'',
$conf['standard']
);
And I have tried this:
$out =
$cObj->stdWrap(
$conf['standard']['_typoScriptNodeValue'],
$conf['standard']
);
But the result is an empty string only.
What is the recommended way to accomplish the stdWrap rendering with Extbase?
Basically $cObj->stdWrap only supports stdWrap instructions - however, you were using a cObject instruction (with TEXT).
Let's assume your settings look like this in TypoScript:
plugin.tx_myextension {
settings {
standard {
# cObject is a stdWrap function
# (that was the missing piece)
cObject = TEXT
cObject.value = Sorry, no data could be fetched!
}
}
}
Inside an Extbase controller $this->settings holds all data of the TypoScript path plugin.tx_myextension.settings as shown in the example before - and, the structure has been converted to be a "plain array".
Thus, inside a controller action things would look like this:
public function myAction()
{
// consider using dependency-injection instead
$typoScriptService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\TypoScript\TypoScriptService::class);
// converting "plain array" back to TypoScript array
$typoScriptArray = $typoScriptService->convertPlainArrayToTypoScriptArray($this->settings['standard']);
// invoking stdWrap instruction
$cObj = $this->configurationManager->getContentObject();
$out = $cObj->stdWrap('', $typoScriptArray);
// ...
}
Additional considerations:
in Extbase, plugin settings from TypoScript and potential FlexForm settings for a specific plugin are merged
→ make sure, to keep scopes separated before "executing" it as instruction
→ otherwise editors might be able to trigger stdWrap functions via FlexForm
→ that would be an "injection" and a security vulnerability
e.g. use plugin.tx_myextension.instructions dedicated to be used in e.g. stdWrap, instead of putting everything to plugin.tx_myextension.settings
in general consider moving view-related aspects to a corresponding view or Fluid template, e.g using f:cObject view helper there
Maybe a look into the News extension can help. IMO it's a proper, flexible way without much overhead.
// 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 . '.']
);
}
}
}
// start override
if (isset($tsSettings['settings']['overrideFlexformSettingsIfEmpty'])) {
$typoScriptUtility = GeneralUtility::makeInstance(TypoScript::class);
$originalSettings = $typoScriptUtility->override($originalSettings, $tsSettings);
}
// ...
$this->settings = $originalSettings;
snippet taken from https://github.com/georgringer/news/blob/main/Classes/Controller/NewsController.php#L658-L688

TYPO3: configure available types for tx_news content element relation

Is it possible to configure which content element types are available for the content elements relation in tx_news records?
I have a backend layout which allows only gridelements in tt_content. The regular content elements are only allowed within a grid elements container.
Currently I face the problem, that in news records it's only possible to add grid elements:
I'd like to allow only some specific content elements in news records.
Update:
The above mentioned restriction is done via TSConfig for the BackendLayout:
mod.web_layout.BackendLayouts {
1 {
title = Standardseite
config {
backend_layout {
colCount = 1
rowCount = 1
rows {
1 {
columns {
1 {
name = Content
colPos = 0
allowed = gridelements_pi1
}
}
}
}
}
}
}
}
When I remove the line allowed = gridelements_pi1, all content element types are available again.
But regardless of the allowed setting for backend layouts I'd like to have just a small subset of content element types available for news records.
Sometimes the solution can be so simple and obvious! Thx for hint, Georg Ringer!
Just override the settings for the news sys folder:
[45 in tree.rootLineIds]
# this changes the allowed CTypes. Add more as a comma separated list
mod.web_layout.BackendLayouts.1.config.backend_layout.rows.1.columns.1.allowed = textmedia
# this sets the default CType to prevent an error with INVALID VALUE ("text")
TCAdefaults.tt_content.CType = textmedia
[global]
By the way, an even better solution would be to use TCEFORM.tt_content.CType.removeItem = ..., but this would require to update the list each time you add a new CType.

Typo3 - Custom email newsletters with direct_mail

Im building a newsletter and the start is like this:
DEAR ###USER_gender### ###USER_first_name### ###USER_last_name###
which outpouts
DEAR ###USER_gender### JOHN DOE
and I was hoping it would replace the gender mark with "Miss" and "Sir", depending on the value. How could I do this?
Extra fields have to be added to the field list (see docu). But I'm not sure whether this automatically works with non-string fields. Maybe using a hook is your solution or using another extension which adds a new field to tt_address.
Another solution is to nest marker:
###GENDER_###USER_gender######
and then warp you content in a new template object:
10 = TEMPLATE
10 {
template < yourAlreadyProcessedContent
marks {
GENDER_m = TEXT
GENDER_m.value = Sir
}
}
It's a bit unusual, but sometimes it's very useful.
(Personally I use it to replace version numbers in tt_content records.)
Edit:
Example for Dbugger:
Download the Introduction Package and install it. After that add to the Welcome page a new template record with the following steup:
temp.mainTemplate = TEMPLATE
temp.mainTemplate {
template = TEXT
template.value = (
Foo
###CONTENT###
###CONTENT###
Bar
)
subparts {
CONTENT < styles.content.get
}
}
page = PAGE
page {
typeNum = 0
10 = TEMPLATE
10 {
template < temp.mainTemplate
marks {
TEST = TEXT
TEST.value = ok
}
}
Now include CSS Styled Contnet and enable the following options:
clear constants, clear setup, rootlevel
The output should look like that:
Foo
Congratulations ...
Bar
If you add ###TEST### to the the tt_content record on the welcome page it will be replaced with ok.
This should work with direct mail, too.
Edit:
I'm sorry, this only works which normal extension which are use in the rendering process.
a little bit late, but here's the best solution for the salutation in direct_mail & tt_address .. works perfect for me. The personalized marker is just ###USER_salutation###,
https://blog.webentwickler.at/individuelle-marker-in-direct-mail/

TYPO3 / TypoScript: How to make a fallback?

I want to output a string to the rendered HTML by using two fallbacks.
My typoscript is defined at the top level page (root page of my website) and is passed to all pages at lower levels.
Structure:
Homepage
Page at level 1
Page at level 2
Regular output of the file:
The string comes from a TemplaVoila field (Page / Edit / Extended / MyField): field_copyright_name
To output it to the desired point in the HTML output a templaVoila mapping exists (Type: Typoscript Object Path), named: lib.copyright_name
The following typoscript does the job:
lib.hint_copyright_name = COA
lib.hint_copyright_name.10 = TEXT
lib.hint_copyright_name.10 {
setCurrent.dataWrap = {field:field_copyright_name}
current = 1
}
This works for all pages at all levels where the field (in page properties) is not empty.
The first fallback:
If the field is empty (in properties of that page, e.g. at level 2) typoscript should get the value from the pages above (at level 1, and if it is empty too, it should get it from homepage). No clue how to do it. Can you help?
The second fallback
If the first fallback still returns an empty string (because the field was empty at all levels) it should do a fallback to a default value "Copyright by me".
To enable this fallback without "first fallback" is easy:
switchdefault_copyright_name = TEXT
switchdefault_copyright_name {
setCurrent.dataWrap = {field:field_copyright_name}
current = 1
override = "Copyright by me"
override.if.isFalse.field = field_copyright_name
}
lib.hint_copyright_name = COA
lib.hint_copyright_name.10 < switchdefault_copyright_name
But how to integrate the "first fallback"?
EDIT:
I tried:
setCurrent.data = {levelfield:-1, field_copyright_name, slide}
or
setCurrent.data = levelfield:-1, field_copyright_name, slide
or
setCurrent.dataWrap = {levelfield:-1, field_copyright_name, slide}
or
setCurrent.dataWrap = levelfield:-1, field_copyright_name, slide
but without success - no output.
Just found this : http://lists.typo3.org/pipermail/typo3-english/2006-October/032764.html
It's supposed to make youre slide thing to work.
Just set : Installation > all configuration > addRootLineFields
Didn't tried it, but seems like the solution