Typo3: display content from first sub-page using typoscript - typo3

This is what I want to do: on a given page, I want to display all content elements of the first child page of a given page. I cannot simply use a shortcut page, because I need to display other content elements after the ones from the sub-page. How can I do this?
Here is a snippet of how I think I could do it, but I don't know how to build the select. Is there a better way?
# save current content
tmp.pagecontent < page.10.subparts.main-content
# clear the content of the main column
page.10.subparts.main-content >
# build a new object for this column as content-object-array
page.10.subparts.main-content = COA
page.10.subparts.main-content {
10 = CONTENT
10.table = tt_content
10.select {
# what should I put here?
}
# re-insert the normal pagecontent to the page
20 < tmp.pagecontent

Just add answer for other people.
First : specify the first sub page of current page.
Second : get content elements that you want of that sub page.
temp.content = COA
temp.content {
10 = CONTENT
10 {
table = pages
select {
pidInList.field = uid
orderBy = sorting ASC
max = 1
begin = 0
}
renderObj = COA
renderObj {
10 = CONTENT
10 {
table = tt_content
select {
languageField = sys_language_uid
pidInList.field = uid
orderBy = sorting
#where = colPos = 10
}
stdWrap.wrap = |
}
}
}
}

I finally succeed! Not sure though it is the best way. What do you think about it? Should I put the second select into userFunc too?
fileadmin/userfunc/mailArchive.php
<?php
class user_mailArchive {
function getFirstChild($content, $conf) {
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
'uid', // SELECT ...
'pages', // FROM ...
'pid='.intval($conf['pid']), // WHERE...
'', // GROUP BY...
'sorting', // ORDER BY...
'1' // LIMIT ...
);
$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
if ($row) {
return $row['uid'];
}
else {
return '';
}
}
}
TS template
# fill the content of the main-column to a tmp.object
tmp.pagecontent < page.10.subparts.main-content
# clear the content of the main column
page.10.subparts.main-content >
includeLibs.mailArchive= fileadmin/userfunc/mailArchive.php
# build a new object for this column as content-object-array
page.10.subparts.main-content = COA
page.10.subparts.main-content {
10 = CONTENT
10 {
table = tt_content
select {
pidInList.cObject = USER
pidInList.cObject {
userFunc = user_mailArchive->getFirstChild
# parent page ID
pid = 139
}
orderBy = sorting
}
}
# re-insert the normal pagecontent to the page
20 < tmp.pagecontent
}

Related

TYPO3 - simpler way, rendering content from colPos into Fluidtemplate?

The official TYPO3 Documentation explains how to create (or copy) and use a lib.dynamicContent to render columns into a Fluidtemplate.
I do not understand exactly whats going on in this example.
The TypoScript there is:
lib.dynamicContent = COA
lib.dynamicContent {
10 = LOAD_REGISTER
10.colPos.cObject = TEXT
10.colPos.cObject {
field = colPos
ifEmpty.cObject = TEXT
ifEmpty.cObject {
value.current = 1
ifEmpty = 0
}
}
20 = CONTENT
20 {
table = tt_content
select {
orderBy = sorting
where = colPos={register:colPos}
where.insertData = 1
}
}
90 = RESTORE_REGISTER
}
I use this snippet in a ton of TYPO3 projects and often had asked myself whats going on there.
I have changed this by experimenting a bit and ended with:
lib {
dynamicContent = COA
dynamicContent {
10 = CONTENT
10 {
table = tt_content
select {
orderBy = sorting
where {
data = field:colPos
wrap = colPos=|
}
}
}
}
}
That seems to do "exactly the same" thing - it outputs my content when called via cObject ViewHelper.
Can somebody explain if or why this is the worse way to render Content?
Here's the link to the lib.dynamicContent-doc: https://docs.typo3.org/c/typo3/cms-fluid-styled-content/master/en-us/Installation/InsertingContentPageTemplate/Index.html#based-on-the-fluidtemplate-content-object-cobj
Here you go!
you can try this,
# Clear out any constants in this reserved room!
styles.content >
# get content
styles.content.get = CONTENT
styles.content.get {
table = tt_content
select.orderBy = sorting
select.where = colPos=0
}
# Left Column
styles.content.getLeft < styles.content.get
styles.content.getLeft.select.where = colPos=1
# Right content
styles.content.getRight < styles.content.get
styles.content.getRight.select.where = colPos=2
Also, you can use variable in the fluid page object, check this out:
lib.pageTemplate = FLUIDTEMPLATE
lib.pageTemplate {
variables {
content = CONTENT
content {
table = tt_content
select.orderBy = sorting
select.where = colPos=0
}
contentRight = CONTENT
contentRight {
table = tt_content
slide = -1
select.orderBy = sorting
select.where = colPos=2
}
}
}
You can find out more here:
Adding the page content to a fluid template
Typo3 7.6 typoscript problems with markers
Hope this make sense, Cheer...!
You should look at this snippet together with some information about the Fluid view helper <f:cObject> which can be found here: https://docs.typo3.org/other/typo3/view-helper-reference/9.5/en-us/typo3/fluid/latest/CObject.html
As you can see there are the parameters data, currentValueKey and table that will be handed over to the typoscriptObjectPath, which is why the snippet makes perfect sense. The reason is, that it's a bit hard to put the different options into the where clause of the CONTENT object. So it increases readability and those registers can be easily extended.
So the register in this example is used to put in either the value of the data field colPos or if that is empty it will take the current value from the currentValueKey and if that is empty too it will fall back to a value of 0 to make sure the query won't produce an exception.
lib.dynamicContent = COA
lib.dynamicContent {
10 = LOAD_REGISTER
10.colPos.cObject = TEXT
10.colPos.cObject {
field = colPos
ifEmpty.cObject = TEXT
ifEmpty.cObject {
value.current = 1
ifEmpty = 0
}
}
20 = CONTENT
20 {
table = tt_content
select {
orderBy = sorting
where = colPos={register:colPos}
where.insertData = 1
}
}
90 = RESTORE_REGISTER
}
We used a modified version of that snippet to sneak in some more parameter values for the CONTENT object.
So we can hand over a data field pageUid, if that is not set we will use the uid of the current page. This will be overriden if the current or the target page is configured to show content from another page and finally we can trigger a slide with another data field.
lib.dynamicContent = COA
lib.dynamicContent {
5 = LOAD_REGISTER
5 {
colPos.cObject = TEXT
colPos.cObject {
field = colPos
ifEmpty.cObject = TEXT
ifEmpty.cObject {
value.current = 1
ifEmpty = 0
}
}
pageUid.cObject = TEXT
pageUid.cObject {
field = pageUid
ifEmpty.data = TSFE:id
}
contentFromPid.cObject = TEXT
contentFromPid.cObject {
data = DB:pages:{register:pageUid}:content_from_pid
data.insertData = 1
}
}
20 = CONTENT
20 {
table = tt_content
slide = -1
slide.if.isTrue.field = slide
select {
includeRecordsWithoutDefaultTranslation = 1
orderBy = sorting
where = {#colPos}={register:colPos}
where.insertData = 1
pidInList.data = register:pageUid
pidInList.override.data = register:contentFromPid
}
}
90 = RESTORE_REGISTER
}
This enables us to make use of the <f:cObject> view helper while triggering additional parameters just by handing over some more values within the data array.

TYPO3 content on one page order by position in pagetree

I'm showing all content from the subpages on one page:
lib.allPid = COA
lib.allPid {
10 = HMENU
10 {
#entryLevel = 1
special = directory
special.value = 115
1 = TMENU
1 {
expAll = 1
NO.doNotShowLink = 1
NO.allStdWrap.field = uid
NO.allStdWrap.wrap = |,
}
2 < .1
}
}
lib.allContent = CONTENT
lib.allContent {
table = tt_content
select {
pidInList.cObject < lib.allPid
where = colPos = 0
orderBy = pid DESC
}
}
Here the content is ordere by pid DESC. But I'd like to order the content from the subpages by their position in the pagetree. So that the user can define his own ordering.
I tried:
lib.allContent = CONTENT
lib.allContent {
table = tt_content
select {
pidInList.cObject < lib.allPid
leftjoin = pages ON (tt_content.pid = pages.pid)
where = tt_content.colPos = 0
orderBy = pages.sorting ASC
}
}
Didn't work...
Does anyone know how to do this? Thanks in advance!
You are on a good way, but you made the join wrong.
In your code it is tt_content.pid = pages.pid, and this one is wrong. The pid value in tt_content is the uid from the pages.
You need to change your script so:
lib.allContent = CONTENT
lib.allContent {
table = tt_content
select {
pidInList.cObject < lib.allPid
leftjoin = pages ON (tt_content.pid = pages.uid)
where = tt_content.colPos = 0
orderBy = pages.sorting ASC
}
}
I tested it, and it worked on a test instance.

How to get page categories in Typoscript (and use with tx_news)

I would like to read out a page's system categories for further use with tx_news (to display news that have the same categories as the page - as tx_news is using system categories).
I was looking for a native solution, hopefully via getText, something like:
plugin.tx_news.settings.categories.data = page:categories
but that doesn't seem to exist yet
Also, I tried to simplify the query by using sys_category_records_mm, which contains all the information needed for that case, but TYPO3 complains that "there is no entry in the $TCA array":
lib.categoryUid = CONTENT
lib.categoryUid {
wrap = kategorien:|
table = sys_category_record_mm
select {
selectFields = uid
where = uid_foreign = {TSFE:id}
where.insertData = 1
}
renderObj = TEXT
renderObj {
field = uid
wrap = |,
}
}
So that would be nice, but it's not allowed.
Here's a solution that works in my setup. The editor chooses categories for the page, and gets all news items that belong to the category.
temp.categoryUid = CONTENT
temp.categoryUid {
table = pages
select {
// dontCheckPid doesn't exist for CONTENT objects, so make it recursive from root page (or pidInList.data = leveluid:-2
pidInList = {$pidRoot}
recursive = 99
selectFields = sys_category.uid as catUid
join = sys_category_record_mm ON pages.uid = sys_category_record_mm.uid_foreign JOIN sys_category ON sys_category.uid = sys_category_record_mm.uid_local
where = sys_category_record_mm.tablenames = 'pages' AND sys_category_record_mm.uid_foreign = {TSFE:id}
where.insertData = 1
// not necessary for this use case
// orderBy = sys_category.sorting
}
renderObj = TEXT
renderObj {
field = catUid
// Hack: if there are no cats selected for a page, all news are displayed
// so I just pass a catUid that's quite unlikely
wrap = 999999,|,
}
}
lib.newstest = USER
lib.newstest {
userFunc = tx_extbase_core_bootstrap->run
extensionName = News
pluginName = Pi1
switchableControllerActions {
News {
1 = list
}
}
settings < plugin.tx_news.settings
settings {
limit = 5
orderBy = datetime
orderDirection = desc
detailPid = {$pidNachrichtenDetail}
overrideFlexformSettingsIfEmpty := addToList(detailPid)
startingpoint = {$pidNachrichtenRecords}
// for use in my fluid template
// pluginTitle = {$llAktuell}
// latest = 0
// recordType = aktuell
// https://forge.typo3.org/issues/52978
useStdWrap = categories
categories.override.cObject < temp.categoryUid
categoryConjunction = or
}
view =< plugin.tx_news.view
}
What is unclear to me still is if recursive = 1 in the select has no setback. Actually, I don't want to check for the current page's parent uid at all, but WHERE pages.pid IN ({current pid}) is always inserted automatically. Therefore the recursive = 1.
I found this example (in German) and modified it to display the category UIDs.
The following TypoScript will display the UIDs of all categories for the current page seperated by a comma.
10 = CONTENT
10 {
table = pages
select {
uidInList.field = uid
pidInList = 1 # UID or list of UIDs, where your categories are saved
selectFields = sys_category.uid as catUid
join = sys_category_record_mm ON pages.uid = sys_category_record_mm.uid_foreign JOIN sys_category ON sys_category.uid = sys_category_record_mm.uid_local
where = sys_category_record_mm.tablenames = 'pages' AND sys_category_record_mm.uid_foreign = {field:uid}
where.insertData = 1
orderBy = sys_category.sorting
}
renderObj = TEXT
renderObj {
field = catUid
wrap = |,
}
# HACK
# If category is empty, the mechanism below won't work
# As long as I don't know how to query if this is empty or not,
# just add an imaginary extra category!
wrap = 12345,|
}
Unfortunately you have to set pidInList manually to a list of UIDs, where your categories are stored.
Looking for the cat-id of a page:
I did it this way:
lib.cat = CONTENT
lib.cat {
wrap = |
table = sys_category
select {
pidInList = 1
selectFields = sys_category.uid, sys_category.title
max = 1
join = sys_category_record_mm ON(sys_category_record_mm.uid_local = sys_category.uid)
where = sys_category_record_mm.tablenames='pages'
andWhere.dataWrap = sys_category_record_mm.uid_foreign = {TSFE:id}
}
renderObj = COA
renderObj {
10 = TEXT
10 {
field = uid
wrap = class="category|
}
20 = TEXT
20 {
field = title
case = lower
stdWrap.noTrimWrap = | |"|
}
}
}

fallback for FILES in typoscript

I'm using typoscript go get the first file out of a page. This works and is out of the documentation. But the documentation doesn't tell something about a fallback if no files are found.
lib.files = FILES
lib.files {
references {
table = pages
fieldName = media
}
file =
begin = 0
maxItems = 1
renderObj = TEXT
renderObj {
value = URL: {file:current:publicUrl}
insertData = 1
}
}
A naive .if.isNull failed at the first attpent. Is there a possibilty to define a fallback if the FILES-Object is empty?
Mh,
try to make a second object and check there if lib.files is filled with data.
__
UNTESTED
lib.files = FILES
lib.files {
references {
table = pages
fieldName = media
}
file =
begin = 0
maxItems = 1
renderObj = TEXT
renderObj {
value = URL: {file:current:publicUrl}
insertData = 1
}
}
lib.fileFallback = COA
lib.fileFallback {
10 < lib.files
20 = TEXT
20 {
value = Do something
stdWrap.if.isFalse.cObject < lib.fileFallback.10
}
}
I am using this technique often to slide through pages for slideshow objects.
Let me know, if it is working.
You should check the TypoScript Reference stdWrap.ifEmpty.
In your case the code should look like this
lib.files {
# ....
stdWrap.ifEmpty.cObject = IMAGE
stdWrap.ifEmpty.cObject{
file = fileadmin/.../my_image.png
}
# ....
}
You can use every cObject you want.
Check out Content Objects (cObject)

typo3 css_styled content edit source

I have the following problem:
I am using typo3 4.7.7 and I am adding custom columns in the Backend. I am able to do taht by place a configuration array in the /typo3conf/extTables.php
$TCA["tt_content"]["columns"]["colPos"]["config"]["items"] = array (
"3" => array ("Border,"3"),
"2" => array ("Right","2"),
"1" => array ("Left","1"),
"0" => array ("Normal","0"),
"5" => array ("Central","5"),
"6" => array ("Border","6"),
"4" => array ("Footer","4")
);
Then set:
mod.SHARED.colPos_list=0,1,2,3,4,5,6
in the TSconfig.
It is working, I enjoy my new columns :), but there is a problem. I want to be able to use the css_styled_content to map my new columns to my html template. This is not possible, because the "get" constants of css_styled_content are hard coded and I am not able to use something like "content.getFooter". At the moment the only way I can get my content is like this:
...
page.10 = CONTENT
page.10.table = tt_content
page.10.select {
orderBy = sorting
where = colPos = 4
}
page.10.renderObj = COA
page.10.renderObj {
10 = TEXT
10.field = header
20 = TEXT
20.field = bodytext
}
...
This is a lot of code, so I was wondering if there is a way to "make" CSC recognize my new columns, so that I would be able to use "content.getMYCUSTOM_COLUMN_NAME".
P.S. I do not want to use templavoila and I found something in the source of CSC under /static/setup.txt :
# Clear out any constants in this reserved room!
styles.content >
# get content
styles.content.get = CONTENT
styles.content.get {
table = tt_content
select.orderBy = sorting
select.where = colPos=0
select.languageField = sys_language_uid
}
# get content, left
styles.content.getLeft < styles.content.get
styles.content.getLeft.select.where = colPos=1
# get content, right
styles.content.getRight < styles.content.get
styles.content.getRight.select.where = colPos=2
# get content, margin
styles.content.getBorder < styles.content.get
styles.content.getBorder.select.where = colPos=3
# get news
styles.content.getNews < styles.content.get
styles.content.getNews.select.pidInList = {$styles.content.getNews.newsPid}
# Edit page object:
styles.content.editPanelPage = COA
styles.content.editPanelPage {
10 = EDITPANEL
10 {
allow = toolbar,move,hide
label.data = LLL:EXT:css_styled_content/pi1/locallang.xml:eIcon.page
label.wrap = | <b>%s</b>
}
}
I then tried to add:
# get content, footer
styles.content.getFooter < styles.content.get
styles.content.getFooter.select.where = colPos=4
But it did not work.
you are on the right track. try to create your own Content Object:
temp.footer < styles.content.get
temp.footer.select.where = colPos=4
page = PAGE
page.100 < temp.footer