Access dynamic object property in Typo3 Fluid template - typo3

I have an object in a Typo3 Fluid template and want to access a property on it, but the name of the property is in a variable someProperty:
<f:if condition="searchObject.{someProperty}">
Found!
</f:if>
Because this does not work: Is there a built in way to access a property by variable?

You can give a chance to fedex Fluid viewhelper collection and its v:var.get viewhelper.
Or check the other viewhelpers in here. If you do not find a suitable one, you can write your own for this functionality based on some example here.
UPDATE:
Since this is an old question to TYPO3 6.2 it is the time to update it to the current standards. (See also the answer of Claus Due:
For the current LTS: TYPO3 9.5, you can use simple:
{searchObject.{someProperty}}

In Fluid standalone and TYPO3v8 and upward:
{array.{variableContainingKey}}.

The point notation actually is the correct way to access a property. What do you mean by dynamic? Can be null? Have you tried the following?
<f:if condition="<f:count>{searchObject.someProperty}</f:count>">
Found!
</f:if>
Or maybe just:
<f:if condition="{searchObject.someProperty}">
Found!
</f:if>

Related

Display full name of logged in TYPO3 frontend user in Fluid

The task is pretty simple: I want to display the full name (first- and lastname) of the current TYPO3 frontend user in Fluid. But somehow, TYPO3 (version 9.5) or Fluid seems to cache data, so a logged in frontend user sometimes sees the name of other another logged user.
Current implementation:
TypoScript:
lib.username = USER_INT
lib.username.userFunc = Vendor\Extension\UserFunc\Username->getUsername
This is a USER_INT, so the output should always be uncached.
Fluid Layout - Default.html:
<f:render partial="Header" section="Top" />
Fluid Partial - Header.html:
<f:section name="Top">
<img src="logo.png">
<f:render partial="Navigation" />
</f:section>
Fluid Partial - Navigation.html
<f:security.ifAuthenticated>
<f:then>
<p>Logged in as: <f:cObject typoscriptObjectPath="lib.username" /></p>
</f:then>
<f:else>
<p>Not logged in</p>
<f:else>
</f:security.ifAuthenticated>
Why does the result of the cObject get cached? Should'nt this always be calculated per request, because lib.username is a USER_INT? I also tried to add a f:cache.disable ViewHelper to the template with no success.
In order to resolve the problem I refactored it to fetch the full name of the fe_user using a JavaScript XHR request to a simple PSR-15 middleware. Is this really the only suitable solution or am I missing something?
Update 17.12.2020
This all works fine. I just spotted a typo in my userFunc, which resulted in the unexpected behavior.
This happens because TYPO3 cache works with frontend user groups, not frontend users. So you will see results cached for the list of user's groups rather than the current user.
Use <v:render.uncache> ... </v:render.uncache> from EXT:vhs to render that part of code uncached. Alternatively you can modify TYPO3 caching to use the current user but this may decrease cache performance and seriously increase amount of cached items.
Beware, that there is a caching problem even with USER_INT and COA_Int see https://forge.typo3.org/issues/37988
You could use only TypoScript for that like:
lib.username = COA_INT
lib.username {
10 = TEXT
10.data = TSFE:fe_user|user|first_name
10.wrap = |
20 = TEXT
20.data = TSFE:fe_user|user|lastname_name
}
Why use TypoScript? It is very limited on what it can bring back. I just finished a tutorial where you can use a ViewHelper to add an ExtBase variable which assigns the whole user object in the FrontEnd and you can use it wherever you want with all it's relations, even the image, which is difficult to get via TypoScript.
TYPO3 tutorial
Best regards
share edit delete flag

fluid template: render image only if it exists

How can I use f:if to see if an image exists on the server before trying to render it?
I have tried the following without success:
<f:if condition="fileadmin/bilder/Header/{data.title}.jpg">
<f:then>
<f:variable name="imageUri" value="fileadmin/bilder/Header/{data.title}.jpg" />
</f:then>
<f:else>
<f:variable name="imageUri" value="fileadmin/bilder/Header/default.jpg" />
</f:else>
</f:if>
{data.title} works correkt. The Problem is that my condition is wrong. It never goes to the else. Probably my condition is interpret as a string und not as an source.
Description here doesn´t help because my Image is on the server.
Render image in fluid template if it exists?
First of all, why would you have a hardcoded path to a file in fileadmin in a template? That's very uncommon, most of the time you have some kind of relation through TYPO3 (e.g. through the media field in the pages table or something like that).
If this is still something you need, you'd have to write a FileExistsViewHelper that checks if the file exists before using it. Here's the documentation on how to write a custom view helper: https://docs.typo3.org/m/typo3/book-extbasefluid/master/en-us/8-Fluid/8-developing-a-custom-viewhelper.html
You'd need to register your filename as an argument with registerArgument and then prepend the path to the TYPO3 installation (to make it an absolute path) and check for this file with file_exists.
Extend from \TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper and implement the verdict method.
Your template above just creates a string (as you already guessed).

How to disable automated encoding of special characters in fluid partials (TYPO3)

Should be simple enough. I'm trying to add an input field to a fluid partial in the extension "yag" (yet another gallery).
Input: <f:form.textfield id="live-filter" name="test" />
Output: <input id="live-filter" type="text" name="test" />
Somehow the code get's filtered along the way, but I don't know why.
TYPO3 v. 6.2
YAG v. 3.2.1
Edit: A wild guess would be some output filtering in TYPO3 itself, but where? I didn't set anything by purpose.
You need to traverse the path upwards to check if there is any fluid tag wrapped around it, that does escaping. In general, all tags do escaping.
Also check the code around <f:render partial....
It could also be that the TypoScript code that does calls the fluid template, has a .htmlspecialchars = 1 set.
Since TYPO3 8 there is another pitfall: Custom Viewhelpers do htmlspecialchars on the output unless told otherwise. The solution is:
<?php
namespace Vendor\ArTest\ViewHelpers;
class YourViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper{
/**
* As this ViewHelper renders HTML, the output must not be escaped.
*
* #var bool
*/
protected $escapeOutput = false;
As of TYPO3 ver. 9.5 and up to ver. 10.4 you could also wrap the output in the Fluid template into <f:format.htmlentitiesDecode> Tags like this:
<f:format.htmlentitiesDecode>
<f:form.textfield id="live-filter" name="test" />
</f:format.htmlentitiesDecode>
Further information on this can be found in the TYPO3 View Helper Reference.

Dynamicly change TYPO3 fluid Layout by typeNum

I am using the extension fluidpages and want to switch the layout by the typeNum.
is it possible to change the f:layout by by an condition?
This wont work:
<f:layout name="{f:if(condition: '{typeNum} == 666', then: 'PageAjax', else: 'Page')}"/>
Suggested approach:
<f:layout name="Page/{typeNum}"/>
Required files:
Resources/Private/Layouts/Page/0.html
Resources/Private/Layouts/Page/666.html
Please note: this only works if the {typeNum} variable is guaranteed to exist - if it does not, you will face a "template file not found" error with an empty filename. To avoid this, you can use the VHS extension's v:var.convert ViewHelper to ensure a proper value:
<f:layout name="Page/{typeNum -> v:var.convert(type: 'integer')}"/>
I got the same problem recently, and found the solution after a few researchings.
The problem is, you can not use nested fluid like <f:if>, <f:cObject> or others in <f:layout>. Otherwise, you will get a fatal error in the cache file, saying call to a member function getViewHelper() on a non-object. And when you look at the cache file, you will find it's because $self is not defined.
Therefore, my solution is, searching public function getLayoutName( in \TYPO3\CMS\Fluid\Core\Compiler\TemplateCompiler, and adding \$self = \$this; before \$currentVariableContainer = \$renderingContext->getTemplateVariableContainer();, just like generateCodeForSection()
I have now added the Condition in the Layout template. I get the typeNum from typoscript.
<f:if condition="{f:cObject(typoscriptObjectPath:'plugin.nc_template.settings.pageLayout')} == 'Default'">
<p>Default Template</p>
</f:if>
<f:if condition="{f:cObject(typoscriptObjectPath:'plugin.nc_template.settings.pageLayout')} == 'Ajax'">
<p>Ajax Template</p>
</f:if>
I found an example on the fedext Page, but could not get this to run:
https://fedext.net/blog/archive.html?tx_news_pi1[news]=55&tx_news_pi1[%40widget_0][currentPage]=8&cHash=f9c3165598a28d2aa98fd30ef115bb75
Can´t you use an if-statement instead?
IMHO this is easier to read - and if you need to add more arguments which depends on typeNum, it would stay readable.
<f:if condition="{typeNum} == 666">
<f:then>
<f:layout name="PageAjax">
</f:then>
<f:else>
<f:layout name="Page">
</f:else>
</f:if>

The value must be of type 'xx' error by restricted access

I have a product database extension. Based on Extbase + Fluid.
Everything working like it should be, but I have a Problem with restricted Access.
There are some products only for a certain group of users. When I set a group, and somebody uses a direkt link to this product, the login site should come in case of no login.
It is working for sites, but with products I get the:
"The value must be of type "xx", but was of type "NULL". " error
I also using realUrl.
the enable404forInvalidAlias is set for my extension, so a non-existing product call leads to the 404 page, but unfortunetly I couldn't handle till now the restricted access question.
Version is: 4.5.22
Solution should be work without major update.
UPDATE:
In my showAction the product defined with = NULL default value.
I have already a condition in my fluid template like this:
<f:if condition="{product}">
...
</f:if>
The error message coming from this line:
Tx_Extbase_MVC_Exception_InvalidArgumentValue thrown in file
\typo3\sysext\extbase\Classes\MVC\Controller\Argument.php
in line 389.
I made some debug and the whole showAction runs through.
You can change the action in a way so that it allows for no-instances of your product and check for the existance within fluid:
public function showAction(Tx_YourExt_Domain_Model_Product $product = NULL) ..
in Fluid:
<f:if condition="{product}">
<f:then> <!-- show your product --> </f:then>
<f:else>
<!-- show a login form, e.g. something you have in typoscript -->
</f:else>
</f:if>
Downside of this is, that you can't handle proper 404's easily.
There's an ifAuthenticated viewhelper as well and in combination with the above it should be straight forward to handle proper 404's as well. I'm not sure which TYPO3 version this has been introduced though.