I have to show in my single page: the single and the list of News with the same categories of single new. I have two plugins in my backend page and have tried to assign the categories of single to the list for typoscript, but i could not do it.
This is the code, i used page.x for debug and catch values:
page.100 = TEXT
page.100.data = GP:tx_ttnews|tt_news
page.100.wrap = The single tt_news id is: |
page.100.data = GP:tx_ttnews|cat
page.100.wrap = The category of single is: |
page.110 = TEXT
page.110
{
value = { register:newsCategoryUid }
insertData = 1
wrap = - Categories: |
}
plugin.tt_news
{
categorySelection = { register:newsCategoryUid }
#show only selected categories
categoryMode = 1
}
It's not fully visible what you're trying. I think the best way should to put the cat value inside a temp object. Do you have the plugins inserted by TypoScript or as Content Element? You are using tt_news not news by georg ringer right?
temp.tx_news_catId = TEXT
temp.tx_news_catId.data = GP:tx_ttnews|cat
temp.tx_news_catId.intval = 1
page.110 < temp.tx_news_catId
page.110.wrap = Category: |
plugin.tt_news
{
categorySelection < temp.tx_news_catId
# you need to use data not categorySelection = {...} <- that should
# only work on constants
# but only works if categorySelection capabilities
#categorySelection.data = register:newsCategoryUid
#show only selected categories
categoryMode = 1
}
(Untested TypoScript)
hope this helps you a little bit
PS: Have you checked whether categorySelection has stdWrap capabilities?
I don't really get what you want to do, maybe this helps a bit:
If you want to show in the detail action articles with the same category as the current one, you can use a snippet like this one:
Add this to the Detail.html which will pass the first category uid to the TypoScript object lib.tx_news.relatedByFirstCategory.
<f:if condition="{newsItem.firstCategory}">
<f:cObject typoscriptObjectPath="lib.tx_news.relatedByFirstCategory">{newsItem.firstCategory.uid}</f:cObject>
</f:if>
and the TS:
lib.tx_news.relatedByFirstCategory = USER
lib.tx_news.relatedByFirstCategory {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
extensionName = News
pluginName = Pi1
vendorName = GeorgRinger
switchableControllerActions {
News {
1 = list
}
}
settings < plugin.tx_news.settings
settings {
relatedView = 1
detailPid = 31
useStdWrap := addToList(categories)
categories.current = 1
categoryConjunction = or
overrideFlexformSettingsIfEmpty := addToList(detailPid)
startingpoint = 78
}
}
I have taken this from the manual.
Related
I have a menu (HMENU with special = updated) that gives me the latest sub and sub-sub pages from 3 categories.
The page structure looks like this in the backend:
In addition to the title, I would like to output the name of the respective category (the parent level-1 page).
This is my TypoScript attempt:
lib.myMenu = HMENU
lib.myMenu {
special = updated
special{
value.field = 10,11,12
beginAtLevel = 1
limit = 99
}
1 = TMENU
1{
NO{
doNotLinkIt = 1
stdWrap.cObject = COA
stdWrap.cObject {
10 = TEXT
10{
wrap = <h3>|</h3>
field = seo_title // title
typolink.parameter.field = uid
}
20 = HMENU
20{
wrap = <div class="category attempt-1">|</div>
special = rootline
special.range = 1|1
special.value.field = uid # does not work
1 = TMENU
1.NO.allWrap = |
}
30 = TEXT
30{
wrap = <div class="category attempt-2">|</div>
data = leveltitle : 1 # does not work as expected
}
}
}
}
}
Unfortunately it does not work, because …
special = rootline does not support special.value.
data = leveltitle : 1 uses the ID of the current page, instead of the TMENU item ID.
Does anyone have another approach how I can get the title of the respective category using TypoScript?
Edit: Background information / what this is needed for
With this menu I intend to replace the news module ext:news of an existing project. Instead of news records, pages are now used and this menu creates the list view. Of course a TypoScript page browser will be added.
I would not rebuild the complete menu item generation (NO.doNotLinkIt = 1).
Just use NO.after.cObject = COA.
leveltitle : 1 is correct if you want to have the title for the current page.
The same if you show a rootline menu: it is generated for the current page.
If you want the levelfield for another page you need to build it by yourself.
In typoscript you might use a userfunction. (there is a core function for getting the rootline for a given page id)
If you generate your menu with FLUID you might use a viewhelper. (You might get inspired from this option of viewhelper menu.directory or this option of VH page.breadCrumb in ext:vhs.)
Edit:
you might store the needed information directly in the pagesrecord.
add a new field to the record (or use any unused).
then make sure that each category page contains some page TS_config:
TCADefaults.pages.<yourfield> = CategoryName
With this configuration each new page below will get this value set automatically.
Of course you need to set these values for all existing pages by hand or by some manual queries.
And if the editors are to be prevented from changing this value you need to remove the field from the edit form with this TSConfig on the top-page:
TCEForm.pages.<yourfield>.hide= 1
I have found a pure TypoScript solution that may not be very elegant, but it works:
lib.myMenu = HMENU
lib.myMenu {
special = updated
special{
value.field = 10,11,12
beginAtLevel = 1
limit = 99
}
1 = TMENU
1{
NO{
doNotLinkIt = 1
stdWrap.cObject = COA
stdWrap.cObject {
10 = TEXT
10{
wrap = <h3>|</h3>
field = seo_title // title
typolink.parameter.field = uid
}
20 = HMENU
20{
wrap = <div class="category">|</div>
special = list
special.value.field = pid
1 = TMENU
1{
NO{
doNotLinkIt = 1
stdWrap.override{
# Overwrite it if we are not yet at the category level
if{
# The ID of the page parent to the categories ("Website") is 1618
equals = 1618
value.field = pid
negate = 1
}
cObject = HMENU
cObject{
special = list
special.value.field = pid
1 = TMENU
1.NO.doNotLinkIt = 1
}
}
}
}
}
}
}
}
}
If the menu is to go over further levels, the override must of course be nested even deeper.
Edit – Improvements:
RECORDS instead of HMENU: Bernd Wilke suggested in the comments to use CONTENT instead of HMENU to generate the category title. This caused problems in my tests when sysfolders (as subpages of the categories) were used to structure the items. This could be related to the bug/feature #20933 (Enable working with SysFolders in CONTENT). But RECORDS might be comparable. I tried it and was able to improve the render times a little bit (see table below).
lib.myMenu.1.NO.stdWrap.cObject.20 = RECORDS
lib.myMenu.1.NO.stdWrap.cObject.20{
stdWrap.wrap = <div class="category">|</div>
source.field = pid
tables = pages
conf.pages = TEXT
conf.pages {
field = seo_title // title
stdWrap.override{
# Overwrite it if we are not yet at the category level
if{
# The ID of the page parent to the categories ("Website") is 1618
equals = 1618
value.field = pid
negate = 1
}
cObject = RECORDS
cObject{
source.field = pid
tables = pages
conf.pages = TEXT
conf.pages.field = seo_title // title
}
}
}
}
CONTENT instead of HMENU: if no sysfolders are needed (as of TYPO3 10.4 sysfolders should also work)
lib.myMenu.1.NO.stdWrap.cObject.20 = CONTENT
lib.myMenu.1.NO.stdWrap.cObject.20{
stdWrap.wrap = <div class="category">|</div>
table = pages
select {
uidInList.field = pid
pidInList = 0
selectFields = uid, pid, seo_title, title
}
renderObj = TEXT
renderObj {
field = seo_title // title
stdWrap.override{
# Overwrite it if we are not yet at the category level
if{
# The ID of the page parent to the categories ("Website") is 1618
equals = 1618
value.field = pid
negate = 1
}
cObject = CONTENT
cObject{
table = pages
select {
uidInList.field = pid
pidInList = 0
selectFields = uid, pid, seo_title, title
}
renderObj = TEXT
renderObj.field = seo_title // title
}
}
}
}
userFunc instead of HMENU: Bernd Wilke suggested in his answer to use a userfunction. Even if this is not a pure TypoScript solution, I would have liked to test it to be able to compare the performance. The method getRootLine() has unfortunately been marked as deprecated. Since I'm not an extension developer, it's not clear to me yet how to read the category via a userFunc and if this is actually more effective. If I still come across a solution regarding this, it will be added here.
Rendertime: I have test-implemented the menu in the live site (in the existing template) and compared the website render times with and without the output of the categories to see how much the nested menu affects the performance. The values are average values from 10 measurements. I also limited the output to 20 items, which should be a more realistic value per page later on:
mode
20 items
100 items
without category
99 ms
218 ms
categories via HMENU
133 ms
353 ms
categories via RECORDS
132 ms
331 ms
categories via CONTENT
121 ms
255 ms
categories via userFunc
TBD
TBD
You should neither use a separate HMENU nor a userFunc but a simple LOAD_REGISTER within the menu items of the parent level. This generates register entries, that can be added, changed or restored while looping through the different levels of the HMENU structure.
So you don't need the custom code of a PHP function and you won't get the performance penalty of a nested HMENU.
Basically it's shown in the official documentation, but with a CSS class instead of a title. But of course you could hand over other information from the parent to its children the same way.
Here is the example:
10 = COA
10 {
### left menu table column
10 = LOAD_REGISTER
10 {
ulClass = col-left
}
### right menu table column
20 = LOAD_REGISTER
20 {
ulClass = col-right
}
30 = HMENU
30 {
special = list
special.value = 1
1 = TMENU
# ...
3 = TMENU
3 {
stdWrap {
preCObject = COA
preCObject {
10 = RESTORE_REGISTER
}
dataWrap = <ul class="{register:ulClass}">|</ul>
}
wrap =
SPC = 1
SPC {
allStdWrap {
replacement {
10 {
search = ---
replace =
}
}
dataWrap = </ul>|<ul class="{register:ulClass}">
}
}
}
}
}
And here the link to the full documentation page:
https://docs.typo3.org/m/typo3/reference-typoscript/master/en-us/UsingSetting/Register.html
I want to pass a variable (uid of category) in Fluid to a TypoScript :
<f:cObject typoscriptObjectPath="lib.testFluid" data="{setting.myvar}/>
Then i want to use the var to get all content elements in folder with pid 942 and the category {setting.myvar}
lib.testFluid = COA
lib.testFluid = CONTENT
lib.testFluid {
table = tt_content
select {
pidInList = 942
where = selected_categories = |
}
}
This does not work, it creates an MySql syntax error. I also tried using current = 1 instead of the where clause without success. I looked at post TYPO3: pass variable to typoscript via cObject? and I can recreate it but it does not work with my script. (TYPO3 8)
If i use
...
where = selected_categories = 13
....
the scrip will succesfully display all CE with category 13. How do i make it work with a var?
could you try this:
<f:cObject typoscriptObjectPath="lib.testFluid" data="{myvar: setting.myvar}/>
lib.testFluid = CONTENT
lib.testFluid {
table = tt_content
select {
pidInList = 942
where.data = field:myvar
where.intval = 1
where.wrap = selected_categories=|
}
}
hard to test for me but it might work ...
I had to solve it once with markers. I couldn't find another simpler way. I give you a very general solution which you may adapt to your needs. For example you could set the pid value via a typoscript setting which is more elegant than to put it in the snippet code. Please try:
<f:cObject typoscriptObjectPath="lib.testFluid" data="{category: setting.myvar, catPid: 942}" currrentValueKey="category" />
The related TypoScript snippet:
lib.testFluid = COA
lib.testFluid {
10 = LOAD_REGISTER
10 {
category.cObject = TEXT
category.cObject.value.current = 1
catPid.cObject = TEXT
catPid.cObject.value.dataWrap = { field: catPid }
}
20 = CONTENT
20 {
table = tt_content
select {
pidInList.cObject = TEXT
pidInList.cObject.dataWrap = {REGISTER:catPid}
where = selected_categories=###category###
markers {
category.data = REGISTER:category
}
}
}
30 = RESTORE_REGISTER
}
I want to get the categories of a single new but the Typoscript code:
page.100.data = GP:tx_ttnews|cat
Does not work, the return show cat = 0 in the page.
I need this value for set it in a list tt_news in its categorySelection
Is the category really in the URL? That is not the case for a single news. You only have the news uid and need to do the join yourself.
Try something like that
[globalVar = GP:tx_ttnews|tt_news > 0]
lib.categoryTitle = COA
lib.categoryTitle {
20 = RECORDS
20 {
source.data = register:newsCategoryUid
tables = tt_news_cat
conf.tt_news_cat = TEXT
conf.tt_news_cat.field = title
conf.tt_news_cat.noTrimWrap = || - |
}
}
I have a user function that return a list of categories (f.e. 20, 19) and I want to set in tt_news categorySelection as indicate the code
plugin.tt_news {
categorySelection = user_ttNewsCategoriesByUID
categoryMode = 2
}
Before of this I have the user function and works correctly
page.105 = USER
page.105 {
includeLibs = EXT:tt_news/Categorias.php
userFunc = user_ttNewsInCat
}
I am looking but I have not found something. How can I set the return of function in categorySelection
Since categorySelection is stdWrap enabled (see reference), you should be able to make use of it like this:
plugin.tt_news {
categorySelection >
categorySelection.cObject = USER
categorySelection.cObject.userFunc = user_ttNewsCategoriesByUID
categoryMode = 2
}
I found the answer and works correctly in this way
includeLibs.userCategories = EXT:tt_news/Categorias.php
temp.catuid = USER
temp.catuid.preUserFunc = user_ttNewsInCat
plugin.tt_news {
categorySelection < temp.catuid
categoryMode = 2
}
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