How can I use multiple overrides based on the layout?
Single use currently works like this:
tt_content.image.20.1 {
file.width.override {
override = 200c
override.if {
equals.field = layout
value = 1
}
}
}
But I need a different width override for different layout values.
I think I need to do something like this incorrect code:
#does not work
tt_content.image.20.1.file.width = CASE
tt_content.image.20.1.file.width {
key.field = layout
1 = TEXT
1.value = 200c
2 = TEXT
2.value = 400c
}
if an attribute must be enhanced you (nearly) always can use .cObject to enhance it [1].
so you might use something like this:
tt_content.image.20.1 {
file.width.override {
override.cObject = CASE
override.cObject {
key.field = layout
1 = TEXT
1.value = 200c
2 = TEXT
2.value = 400c
}
}
}
[1] this belongs to typoscript used by the core. extensions like plugins, userfuncs may handle their typoscript on their own way not conform to core functionality like .stdWrap
Related
I tried this, in my extension's setup.typoscript. but is not work for me.
plugin.tx_blog {
view {
layoutRootPaths = EXT:solution/Resources/Private/Extensions/Blog/Layouts/
partialRootPaths = EXT:solution/Resources/Private/Extensions/Blog/Partials/
templateRootPaths = EXT:solution/Resources/Private/Extensions/Blog/Templates/
}
}
all the "RootPaths" are arrays so change it to somting like this
plugin.tx_blog {
view {
layoutRootPaths.200 = EXT:solution/Resources/Private/Extensions/Blog/Layouts/
partialRootPaths.200 = EXT:solution/Resources/Private/Extensions/Blog/Partials/
templateRootPaths.200 = EXT:solution/Resources/Private/Extensions/Blog/Templates/
}
the "200" in the examle is the position if Fluid is looking for a Resource (like a template) it will check every provided path in numerical order.
use the Typoscript Object Browser (in the Template Module) to check the configured RootPaths
The standard setup of that extension is a bit uncommon.
The easiest was to override the paths for fluid files is to use the constant editor. There you have fields where you can enter your own paths.
If you want to do it in the setup, you can look in the TypoScript setup of the extension that looks like shown below.
page = PAGE
page {
typeNum = 0
10 = FLUIDTEMPLATE
10 {
templateName = BlogList
templateRootPaths {
0 = EXT:blog/Resources/Private/Templates/Page/
1 = {$page.fluidtemplate.templateRootPath}
}
partialRootPaths {
0 = EXT:blog/Resources/Private/Partials/Page/
1 = {$page.fluidtemplate.partialRootPath}
}
layoutRootPaths {
0 = EXT:blog/Resources/Private/Layouts/Page/
1 = {$page.fluidtemplate.layoutRootPath}
}
...
So in a short block the the paths would look like this:
page.10.templateRootPaths {
0 = EXT:blog/Resources/Private/Templates/Page/
1 = {$page.fluidtemplate.templateRootPath}
}
page.10.partialRootPaths {
0 = EXT:blog/Resources/Private/Partials/Page/
1 = {$page.fluidtemplate.partialRootPath}
}
page.10.layoutRootPaths {
0 = EXT:blog/Resources/Private/Layouts/Page/
1 = {$page.fluidtemplate.layoutRootPath}
}
In the lines starting with 1 you can enter your own path if you never want to use the constants. For this you never have to enter it in the original TypoScript template, but just copy the block above in your own TypoScript and adjust the paths. If your TypoScript is loaded after that of the blog, it's overwriting the original values.
Take care that there exist different setups, one in each folder inside https://github.com/TYPO3GmbH/blog/tree/master/Configuration/TypoScript. So depending on the template you chose the setup must be different. But I hope you're able to adapt the way to go now.
This is very similar to my question Counter for mask elements in a TYPO3 column
I need to pass a variable (in my case, the value of cObj:parentRecordNumber which is the counter for the current item in it's column) to the template.
In the main page template:
<f:cObject typoscriptObjectPath="lib.content.pageteasers" />
In typoscript:
lib.content {
pageteasers < styles.content.get
pageteasers {
select {
where = colPos=2
max = 8
}
// this passes the variable elementCounter to the fluid template of the rendered mask content element:
renderObj.mask_teaser {
variables {
elementCounter = TEXT
elementCounter.value = {cObj:parentRecordNumber}
elementCounter.insertData = 1
}
}
// this should pass the same value to a rendered tx_news plugin:
variables {
elementCounter = TEXT
elementCounter.value = {cObj:parentRecordNumber}
elementCounter.insertData = 1
}
// it doesn't. what about these trial & error:
renderObj.list < .variables
renderObj.plugin.tx_news < .variables
renderObj.list.20.news_pi1 < .variables
renderObj.news_pi1 < .variables
// none of these seem to work either
}
}
And then in the rendered CE template (News/List.html)
<f:debug title="" inline="1">{_all}</f:debug>
I don't manage to see the above variable in here. What is the correct way to pass the variable from TS to the news fluid template?
PS Another try was using the Good Old Register
pageteasers < styles.content.get
pageteasers {
select {
where = colPos=2
max = 8
}
append = LOAD_REGISTER
append {
elementCounter = TEXT
elementCounter.value = {cObj:parentRecordNumber}
elementCounter.insertData = 1
}
}
And in the template:
{v:variable.register.get(name: 'elementCounter')}
but that is NULL
Your try via register could work. But you have to care, where you are doing what...
Registers
LOAD_REGISTER is of type string/stdWrap and not a cObject per definition. If you wanna use content based on a cObject, you can declare this via the stdWrap-property (as shown in the examples):
1 = LOAD_REGISTER
1.param.cObject = TEXT
1.param.cObject.stdWrap.data = GP:the_id
So, in your case it should like:
elementCounter.cObject = TEXT
elementCounter.cObject.data = cObj:parentRecordNumber
Appending at the right place
You are trying to use append directly as a property of pageteasers (which is a copy of styles.content.get which is of type CONTENT.
CONTENT does not have an append-property. In addition, you would put the register in front of the entire content, not the individual content elements.
=> It's needed as part of the renderObj, so it's rendered per CE.
The renderObj of CONTENT is of type CASE, which also has no stdWrap-properties directly. But it has a property stdWrap with stdWrap-properties...
Conclusion
So, you can end up with this snippet:
lib.content {
pageteasers {
renderObj {
stdWrap {
append = LOAD_REGISTER
append {
elementCounter.cObject = TEXT
elementCounter.cObject.data = cObj:parentRecordNumber
}
}
}
}
}
I have the following config
page = PAGE
page {
typeNum = 0
10 = FLUIDTEMPLATE
10 {
templateRootPath = EXT:folder/Resources/Private/Website/Templates/
partialRootPath = EXT:folder/Resources/Private/Website/Partials/
layoutRootPath = EXT:folder/Resources/Private/Website/Layout/
file.stdWrap.cObject = CASE
file.stdWrap.cObject {
key.data = levelfield:-1, backend_layout_next_level, slide
key.override.field = backend_layout
default = TEXT
default.value = whatever.html
1 < .default
2 = TEXT
2.value = whatever-else.html
}
}
Somehow the 'backend_layout_next_level' is not working; it is not sliding down the tree. As a result I have to set a backend_layout for each page which is not what one should expect.
Is there a way of knowing/debugging/finding out what's causing this? I thought it might be something related to a curly brace being in the wrong place (too early, too late or just plain wrong) inside my typoscript. Therefor I looked inside the Typoscript Template Analyzer and found some errors which I've fixed, but the problem still persists.
Thanks already!
Best regards
You use have to give the full path to the file as a value in the .file property or you should use .templateName instead and only provide the name (case sensitive!!!) of the template file without suffix.
#see https://docs.typo3.org/typo3cms/TyposcriptReference/ContentObjects/Fluidtemplate/Index.html
Note that in your current setting, the uid of the template record must be 1 or 2.
And you can try to use levelfield: -2 instead of levelfield: -1.
TBH I never understood this #^$#% CASE syntax... Therefore definitely prefer common condition which works perfect, you must to add custom condition like I showed in other post, so you can use it like:
page {
typeNum = 0
10 = FLUIDTEMPLATE
10 {
templateRootPath = EXT:folder/Resources/Private/Website/Templates/
partialRootPath = EXT:folder/Resources/Private/Website/Partials/
layoutRootPath = EXT:folder/Resources/Private/Website/Layout/
file = whatever.html
}
}
[userFunc = user_beLayout(2)]
page.10.file = whatever-else.html
[userFunc = user_beLayout(3)]
page.10.file = yet-other.html
[userFunc = user_beLayout(4)]
page.10.file = etc.html
[end]
Edit - to satisfy some comments
Note: When I say that I don't understand CASE syntax, that doesn't mean that I don't know it... especially that I studied it in details not once, here's the conclusion...
About performance:
Custom conditions solution is faster than using CASE and slide combination as it doesn't involve additional DB queries (slide does), it iterates $GLOBALS['TSFE']->page array, which is already collected, and stops further checks ASAP, so it's cheaper than slide which makes additional queries if it finds slide in TS (doesn't matter if it's required or not) - (examine the code for slide mechanics), so actually conditions are performance-saver not killer :)
Yet more
Using conditions blocks you can change behavior of multiple elements at once (instead writing separate CASE for each) i.e.:
[userFunc = user_beLayout(2)]
page.10.file = whatever-else.html
lib.genericMenu >
config.absRefPrefix = /layout-specific-abs/
// etc...
[end]
Using CASE syntax you'll need to repeat all these checks for each element... (where's DRY?)
Finally
Both solutions are ... usable especially when using with cached pages, (difference between them will be about teens or maybe in drastic situation hundred milliseconds -conditions will be faster), for uncached pages most probably it will be good idea to set be_layout directly for each pages record in both cases.
It is quite some time ago, you probably resolved your issue but here is a working approach:
page = PAGE
page {
10 = FLUIDTEMPLATE
10 {
# select different html files for layouts - ref: backend_layout
file.stdWrap.cObject = TEXT
file.stdWrap.cObject {
data = levelfield:-2,backend_layout_next_level,slide
override.field = backend_layout
split {
token = pagets__
1.current = 1
1.wrap = |
}
wrap = EXT:folder/Resources/Private/Templates/|.html
}
layoutRootPath = EXT:folder/Resources/Private/Layouts/
partialRootPath = EXT:folder/Resources/Private/Partials/
}
}
or you can pass it as a variable:
page = PAGE
page {
10 = FLUIDTEMPLATE
10 {
file = EXT:folder/Resources/Private/Templates/Main.html
layoutRootPath = EXT:folder/Resources/Private/Layouts/
partialRootPath = EXT:folder/Resources/Private/Partials/
variables {
# BE_Layout
BE_Layout = COA
BE_Layout {
stdWrap.cObject = TEXT
stdWrap.cObject {
data = levelfield:-2,backend_layout_next_level,slide
override.field = backend_layout
split {
token = pagets__
1.current = 1
1.wrap = |
}
wrap = |.html
}
}
}
}
i want to add the language id in a typolink
so far
LOGO = COA
LOGO {
10 = TEXT
10 {
value = logo
typolink {
parameter = 116
additionalParams = &L={$config.sys_language_uid}
}
}
}
if L=4 it's working
but if i use L={$config.sys_language_uid} it gets ignored altogether
same with L=GP:L
and L=GPvar:L
what would be the proper syntax here
working if i do something like
additionalParams = COA
additionalParams {
10 = TEXT
10.data = GP : L
10.intval = 1
10.wrap = &L=|
}
You do not need to do that on your own. With the following global TypoScript configuration the parameter L will added to every link:
config.linkVars = L(int)
So, if you use HMENU.special = language this will be managed on the switch automatically, too:)
http://docs.typo3.org/typo3cms/TyposcriptReference/Setup/Config/Index.html
I do not know about {$config.sys_language_uid}, but your code will output it as plain text. In order to use variables like {GP:L}, you got to dataWrap it or insert "insertData" after the value.
10 = TEXT
10 {
value = logo
typolink {
parameter = 116
additionalParams.dataWrap = &L={GP:L}
}
}
OR (the best way I'd say):
10 = TEXT
10 {
value = logo
typolink {
parameter = 116
additionalParams.cObject = TEXT
additionalParams.cObject {
wrap = &L=|
data = GP:L
}
}
}
Using {TSFE:sys_language_uid} might be a better option if you are querying the database.
There is no need to make a cObject or COA
additionalParams = type=0&L={GP:L}
additionalParams.insertData = 1
You can do this kind of URL using addQueryString = 1. https://docs.typo3.org/typo3cms/TyposcriptReference/Functions/Typolink/Index.html#addquerystring
I am very new to Typo3/TypoScript and I wondered if and how it is possible to give the result of a sql-statement in TypoScript to a php function.
I've managed the userFunc so far, but i'm getting confused with the rest.
Here is my try:
temp.pidList = CONTENT
temp.pidList {
table = tx_eepcollect_sessions
#table = tt_content
select {
pidInList < plugin.tx_eepcollect_pi1.pid_list
where {
stdWrap.cObject = TEXT
stdWrap.cObject {
data = global : _COOKIE | tx_eepcollect_pi1
wrap = ses_id='|'
}
}
}
renderObj = COA
renderObj {
10 = TEXT
10.field = ses_data
#30 = TEXT
#30.data = debug:data
}
}
includeLibs.user_idList = fileadmin/services/user_IdList.php
temp.ListOfIds = USER
temp.ListOfIds.userFunc = user_IdList->get_IdList
#temp.pidList = TEXT
#temp.pidList = {"1275":{"id":"1275","tx_eepcollect_pi1":{"prozess":"add","pid":"1275","ctrl":"1360858765"},"cHash":"e90b62584f3f0e4f71bf1100faf39d83"}}
temp.ListOfIds.userFunc.jsonList < temp.pidList
temp.mainContent = COA_INT
temp.mainContent.10 = TEXT
temp.mainContent.10.stdWrap.cObject < temp.ListOfIds
The output is an array of a lot of stuff, but not the result of the database-query.
TypoScript is not a programming language, so it is not executed in any meaning. You should think about TS as set of instructions for the Core.
So, following line:
temp.ListOfIds.userFunc.jsonList < temp.pidList
will not put result of temp.pidList into temp.ListOfIds.userFunc.jsonList, as you would expect from a programming language - it will simply copy set of instructions, so at the end you'll have following structure:
temp.ListOfIds = USER
temp.ListOfIds.userFunc = user_IdList->get_IdList
temp.ListOfIds.userFunc.jsonList = CONTENT
temp.ListOfIds.userFunc.jsonList.table = tx_eepcollect_sessions
[...]
And since jsonList is your custom property you need to bring stdWrap to it by following method:
TypoScript
temp.ListOfIds.userFunc.jsonList.cObject < temp.pidList
PHP
$jsonList = $this->cObj->stdWrap($conf['jsonList'], $conf['jsonList.']);
I assume, that you call it from a method get_IdList of class user_IdList with two params: $content and $conf.
As an additional measerue, you can make it as extension with a kickstarter or extension builder, so it'll be easier for you to work with configuration.
Another thing is, that your code have potential SQL injection vulnerability here:
where {
stdWrap.cObject = TEXT
stdWrap.cObject {
data = global : _COOKIE | tx_eepcollect_pi1
wrap = ses_id='|'
}
}
So, you may consider reading about markers