In short words this kind of logic isn't possible in Fluid - reason is simple -it's template engine.
You need to create your own extension and create a ViewHelper in it, which will take the collection of News will check if it has required settings (falMedia
existing in this case) and will return limited array which you can iterate. Indeed, reusing f:for
will be fastest solution.
I'm afraid, that's only way.
Here's the sample (compare it to original f:for
viewhelper):
<?php
namespace TYPO3\CMS\Fluid\ViewHelpers;
class ForNewsWithMediaViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
/**
* Iterates through elements of $each and renders child nodes
*
* @param array $each The array or \TYPO3\CMS\Extbase\Persistence\ObjectStorage to iterated over
* @param string $as The name of the iteration variable
* @param string $key The name of the variable to store the current array key
* @param boolean $reverse If enabled, the iterator will start with the last element and proceed reversely
* @param string $iteration The name of the variable to store iteration information (index, cycle, isFirst, isLast, isEven, isOdd)
* @param int $limit Limit of the news items to show
* @return string Rendered string
* @api
*/
public function render($each, $as, $key = '', $reverse = FALSE, $iteration = NULL, $limit = NULL) {
return self::renderStatic($this->arguments, $this->buildRenderChildrenClosure(), $this->renderingContext, $limit);
}
/**
* @param array $arguments
* @param \Closure $renderChildrenClosure
* @param \TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface $renderingContext
* @param int $limit Limit of the news items to show
* @return string
* @throws \TYPO3\CMS\Fluid\Core\ViewHelper\Exception
*/
static public function renderStatic(array $arguments, \Closure $renderChildrenClosure, \TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface $renderingContext, $limit = NULL) {
$templateVariableContainer = $renderingContext->getTemplateVariableContainer();
if ($arguments['each'] === NULL) {
return '';
}
if (is_object($arguments['each']) && !$arguments['each'] instanceof \Traversable) {
throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('ForViewHelper only supports arrays and objects implementing \Traversable interface', 1248728393);
}
if ($arguments['reverse'] === TRUE) {
// array_reverse only supports arrays
if (is_object($arguments['each'])) {
$arguments['each'] = iterator_to_array($arguments['each']);
}
$arguments['each'] = array_reverse($arguments['each']);
}
$iterationData = array(
'index' => 0,
'cycle' => 1,
'total' => count($arguments['each'])
);
$limitCycle = 1;
$output = '';
/**
* @type $singleElement Tx_News_Domain_Model_News
*/
foreach ($arguments['each'] as $keyValue => $singleElement) {
if (is_null($singleElement->getFalMedia())
|| !is_null($limit) && $limitCycle > $limit
) {
continue;
}
$limitCycle++;
$templateVariableContainer->add($arguments['as'], $singleElement);
if ($arguments['key'] !== '') {
$templateVariableContainer->add($arguments['key'], $keyValue);
}
if ($arguments['iteration'] !== NULL) {
$iterationData['isFirst'] = $iterationData['cycle'] === 1;
$iterationData['isLast'] = $iterationData['cycle'] === $iterationData['total'];
$iterationData['isEven'] = $iterationData['cycle'] % 2 === 0;
$iterationData['isOdd'] = !$iterationData['isEven'];
$templateVariableContainer->add($arguments['iteration'], $iterationData);
$iterationData['index']++;
$iterationData['cycle']++;
}
$output .= $renderChildrenClosure();
$templateVariableContainer->remove($arguments['as']);
if ($arguments['key'] !== '') {
$templateVariableContainer->remove($arguments['key']);
}
if ($arguments['iteration'] !== NULL) {
$templateVariableContainer->remove($arguments['iteration']);
}
}
return $output;
}
}
So you can use it in your view as:
<f:forNewsWithMedia each="{news}" as="newsItem" iteration="iterator" limit="4">
<f:render partial="List/TeaserItem" arguments="{newsItem: newsItem,settings:settings,iterator:iterator, contentObjectData:contentObjectData}" />
</f:forNewsWithMedia>