Ok, the headline is bit confusing, but i didnt know, how to describe my problem in a short version. Here we go: I get a list of image-urls from the resources of one page, it works like this:
lib.slider = FILES
lib.slider {
references {
data = levelmedia:-1, slide
}
renderObj = TEXT
renderObj {
data = file:current:publicUrl
wrap = {image :'|'}
}
}
Now i want to make an image-container from each of the images. I'm not very good in typoscript so i have no idea, how to do that. I had the idea of making an array out of it and using the f:for-Viewhelper but I dont know how to get an array from this or how to access the images from html.
As an alternative to your own findings, you can modify the renderObj to be an IMAGE cObject, like the following - that way you can define dimensions of your images as well.
lib.slider = FILES
lib.slider {
...
renderObj = IMAGE
renderObj {
file {
import.data = file:current:originalUid // file:current:uid
maxW = 150
}
}
}
See the FILES documentation and IMAGE documentation for further examples.
Ok, I found a solution myself, ich just changed the wrapper to <img src="|" /> and got what i wanted
Related
I want to built a content element with fields for text and images (I'm using the Mask extension for this) and use parts of the contents of it on further pages, for example as teasers.
Is it basically possible to put out only parts of a specific record, e.g. only the text and can an anybody give me a hint or an example how to?
Thank you for your help!
Michael
What you are rendering is your selection. In mask you already use only a subselection of all available fields in a tt_content record. It s very complicated for an editor if you use fields in your rendering, that can't be edited.
Assume you have CE (content element) of type A with some fields which all are filled with data, then you change the type to B which has other fields. As you have not emptied the fields from type A you still can access them and render it in the frontend.
if you want to render teaser you use only those fields you think what gives you the teaser information.
In general records are handled complete.
you can define your own viewhelper which provide you with restricted data or you use typoscript where you do the rendering in typoscript and you have no access to individual fields.
e.g. you could use a CONTENT object, selecting data from CEs in another page:
temp.teaser = CONTENT
temp.teaser {
table = tt_content
select {
// assuming context of a page, like in a menu
pidInList.field = uid
orderBy = sorting
max = 1
}
renderObj = COA
renderObj {
10 = TEXT
10.field = header
10.wrap = <div class="head">|</div>
20 = TEXT
20.field = bodytext
20.wrap = <div class="content">|</div>
20.crop = 100 | ... | 1
wrap = <div class="teaser">|</div>
}
}
tldr: How do I render a TypoScript COA Object with a GIFBUILDER image from inside a CommandController?
I'm currently developing an eCommerce platform for which I need to periodically import an excel file that holds the product catalog. After a product is created from a row of data in the excel file, a directory is searched for product images related to that item, and they are linked as FileReferences to the product. I've written an ImportCommandController that takes care of that.
This all works like a charm, with the only glaring problem being the performance of the image manipulation. The first call to a product list pages takes a good 30 seconds, the first request of a single view. I periodically need to recreate the whole catalog from scratch, and the source product images are huge files, I have no influence on that.
The product images of that catalog are being generated by a TypoScript that takes care of fitting these images inside a square white background, returning the IMG_RESOURCE url. I call that TypoScript from inside a Fluid template with the cObject ViewHelper.
I've been trying to call this bit of TypoScript from the ImportCommandController->importAction, so that the import cronjob would take care of creating these scaled images beforehand, with the same filename hash, so they're already processed when they're called by the single view. But I can't manage to do that.
The TypoScript in question ist this:
plugin.tx_productfinder_products {
// Productfinder-Produktbilder
// Bilder quadratisch auf weissen Hintergrund einpassen
productimage = COA
productimage {
// Daten der FileReference im Regsiter ablegen
10 = FILES
10 {
references.data = current
renderObj = COA
renderObj {
10 = LOAD_REGISTER
10 {
param = TEXT
param.data = file:current.uid
}
}
}
20 = IMG_RESOURCE
20 {
file = GIFBUILDER
file {
XY = 960,960
format = jpg
quality = 95
backColor = #ffffff
20 = IMAGE
20 {
offset = 960-[20.w]/2,960-[20.h]/2
file {
import.data = current
treatIdAsReference = 1
maxW = 960
maxH = 960
}
}
// // Text aus Daten der FileReference als Wasserzeichen ins Bild rendern
// 30 = TEXT
// 30 {
// //text.data = register:param
// text.data = current
// fontColor= #dddddd
// fontSize = 12
// offset = 20,[20.h]-20
// align = left
// antiAlias = 1
// }
}
}
}
}
And I call these from inside the Fluid template like so:
<img class="img-responsive" src="{f:cObject(typoscriptObjectPath:'plugin.tx_productfinder_products.productpreviewimage', data:'{image.uid}')}">
What have I tried so far? Pretty much everything.
I've first tried to call the ContentObjectRenderer directly,
/** #var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $cObj */
$contentObject = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer');
$contentObject->setCurrentVal($image->getUid());
$content = $contentObject->cObjGetSingle($this->settings['productimagetest'], $this->settings['productimagetest.']);
resulting in these weird errors.
Oops, an error occurred: PHP Warning: imagejpeg(typo3temp/GB/csm_8000424600_cbbd127be3_9cb1d3c8cc.jpg): failed to open stream: No such file or directory in /html/typo3/typo3_src-7.6.16/typo3/sysext/core/Classes/Imaging/GraphicalFunctions.php line 2912
It seems that the TYPO3 Configuration regarding the Grapics Processing isn't initialized in the same way as it is for the Frontend.
Next, I tried instanciate a StandaloneFluidView to render the whole SingleItem template per item, but I cant figure that out because the Request and Context are missing and so the partials being referenced in the template aren't being rendered.
Then I tired to just create the FrontendUrls per single item and request them from the CommandController,
/** #var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $cObj */
$contentObject = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer');
$test = $contentObject->typolink_URL(array(
'parameter' => 671,
'additionalParams' =>
'&tx_productfinder_products[product]='.$product->getUid().
'&tx_productfinder_products[action]=show'.
'&tx_productfinder_products[controller]=Product',
'returnLast' => 'url'
));
$this->outputLine(print_r($test,true));
but the URLs generated in this way are missing the cHash.
Can anybody offer help or a different approach to this?
Since these images are generated just once for the frontend output and are then available anyway, I don't see the advantage of generating them beforehand. The white square could be easily generated with CSS, so to me this does not even look like a use case for the GIFBUILDER.
That being said there's still something you could do: Since you are in the PHP context already, why don't you instanciate the GIFBUILDER directly or use even pure IM/GM commands instead of going for an IMG_RESOURCE which is actually meant to be output in the frontend?
I know this is an old question, but I had the same issue and had to invest some time to debug it, so maybe this this answer is useful for someone else in the future.
The CLI uses a different working directory than the frontend, therefore the relative path to typo3temp/ directory used in the GifBuilder class cannot be resolved, which results in the above mentioned warning.
To fix the relative path resolution, you have to change your working directory to the frontend one, this can be achieved by:
class AcmeCommand extends Command
{
protected static $cwdBackup;
protected function execute(InputInterface $input, OutputInterface $output)
{
if (Environment::isCli()) {
static::$cwdBackup = getcwd();
chdir(Environment::getPublicPath());
}
//
if (Environment::isCli()) {
chdir(static::$cwdBackup);
}
}
}
I have a TYPO3 TypoScript html template and want to show in a single page (called: "competitions"), a list of all competitions with their image and title and this should be links for each of them ('competition'). I have thought to make a page ('competitions') and subpages ('single cmpetition'). I'm not using Fluid actually. How can i get and display those in main page? Or is another way to achieve this ?
depending on your data structure (is the relevant info you want to show stored in the pages record or do you want access tt_content records inside that pages) it is more or less easy.
you always can access the informations with typoscript, but those constructs may get complicated. that means: developing the TS may take some time and the following rendering might also get complex and might take some time.
the easiest way: all information in pages records:
temp.competitions = CONTENT
temp.competitions {
table = pages
select {
pidInList = this
orderBy = sorting
}
renderObj = COA
renderObj {
wrap = <div class="teaser">|</div>
10 = TEXT
10.field = title
10.wrap = <h3>|</h3>
20 = TEXT
20.field = abstract
20.wrap = <div class="abstract">|</div>
30 = IMAGE
:
}
}
It might be a simple solution to that but I am not able to figure it out.
I implement a typo3 6.2.12 website using the bootstrap_package extension. There I have a page with child pages within the page tree. On each child page a comment function should be attached at the end of the main page content. For the comment functionality I use the pw_comments extension, as it is very flexible.
The pw_comments manual shows a possible the integration as follows:
lib.content = COA
lib.content {
10 < styles.content.get
# List comments
20 < lib.pwCommentsIndex
# Write new comment
30 < lib.pwCommentsNew
}
Actually very simple and straightforward.
The bootstrap package extension handles the content as follows (inside base.ts):
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
}
}
20 < styles.content.get
20.select.where = colPos={register:colPos}
20.select.where.insertData = 1
20.select.pidInList.data = register:pageUid
90 = RESTORE_REGISTER
}
lib.dynamicContentSlide =< lib.dynamicContent
lib.dynamicContentSlide.20.slide = -1
And at that point I have no clue how to integrate pw_comments. In the setup of the plugin I tried this:
[PIDupinRootline = 54]
lib.dynamicContent = COA
lib.dynamicContent {
# List comments
30 < lib.pwCommentsIndex
# Write new comment
31 < lib.pwCommentsNew
}
[end]
The goal of the above is: Attach pw_comments to the main column output to each child page of parent page with uid 54.
Actually it is working but due to the inheritance with lib.dynamicContentSlide =< lib.dynamicContent the comments get also attached each of the 3 footer columns which is not desired behavior.
I could use the plugin extension which is available for pw_comments but that would mean that the editor has always to add that plugin to new child pages when creating them.
I could "hack" the fluid content template files and add a <f:cObject /> tag and call the plugin lib, but I think that solution is odd and .. well .. a hack.
So is there any way how I could attach that plugin to these child pages in a typo script way? I guess it is just a lack of syntax knowledge and yes, typo3 is not my every day job.
Hope anybody can give me a hand on this issue. Thanks so much in advance!
You simple need to replace the reference by a real copy before you add your TypoScript.
lib.dynamicContentSlide < lib.dynamicContent
# your TS goes here
Just repeat all lines with an reference to lib.dynamicContent with a copy operator instead, before you add your modifications to the actual content definition.
I'm new to TYPO3 and Fluid and trying to display the page content using a Fluid template similar to the following one:
<div id="content">
<f:format.html>{content}</f:format.html>
</div>
The page data is entered via the backend using a two-column layout (colPos=0, colPos=1).
I am now trying to display the content of the first column (colPos=0) inside the div.
At the moment, my TYPO-Script looks like the following:
page = PAGE
page {
# ...
5 = FLUIDTEMPLATE
5 {
file = fileadmin/templates/default.html
# ...
variables {
pageTitle = TEXT
pageTitle.data = page:title
content = CONTENT
content {
table = tt_content
select {
where=colPos=0
}
renderObj = COA
renderObj {
10 = TEXT
10.field = bodytext
}
}
}
}
It works this way, but I cannot get rid of the feeling that my 5.variables.content is way too complicated.
I saw some solutions using content < styles.content.get as an alternative but using this causes my resulting div to be empty.
Are there any more elegant ways (i.e. shorter in this context) to achieve what I am doing?
On your question which approach is more elegant
(I don't use fluid, but I think it's general Typoscript):
If you want to use css_styled_content, but with more flexibility and transparence than the shortcuts "get", "getLeft" etc., use this:
content < styles.content.get
content.select.where = colPos = 0
No need to specify content = CONTENT in that case.
In the way you wrote it above, you would probably need to add:
10.parseFunc = < lib.parseFunc_RTE
to your renderObj, as else, automatically linked e-Mail addresses etc. won't be rendered in the content.
If you want full control over the markup, your original approach using the CONTENT object is superior to css_styled_content. But you will have to cover each field the editors are supposed to use.
I always use this article: http://www.typo3wizard.com/en/articles/explaining-the-content-object.html
With css_styled_content on the other hand, you get parsing for all fields for free - but also you get all the markup it will write for you.
It might be helpful to look at csc's static template in /typo3/sysext/css_styled_content/static/setup.txt to see what it does.
i dont use fluid, just plain TS for my projects, but i hope ill help.
In backend the cols are like this if u have not "touched" em:
| col1(Left) | col0(Normal) | col2(Right) | col3(Border) |
What i do is this for "normal" layout:
page.10 = TEMPLATE
page.10 {
subparts{
LEFT-CONTENT < styles.content.getLeft
CONTENT < styles.content.get
RIGHT-CONTENT < styles.content.getRight
}
marks {
DESCRIPTION < styles.content.getBorder
}
If u need something more u can use something like this to generate some content that is not on that page and can use it to display it on all pages.
subparts{
LEFT-CONTENT < styles.content.getLeft
LEFT-CONTENT {
select.pidInList = 50
select.where = colPos=0
select.orderBy = sorting
wrap = <div class="col100">|</div>
}
page.5.variables.content < styles.content.get
Of course you must have the CSS styled content extension installed (default) and the static template "CSS Styled content" included in your TypoScript Template (Tab: Includes).
Alternative solution: https://fluidtypo3.org/viewhelpers/vhs/development/Content/RenderViewHelper.html (along with get and random get/render counterparts).