Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow record sliding in page.resources.fal with traits #825

Merged
merged 4 commits into from
Aug 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions Classes/Traits/SlideViewHelperTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php
namespace FluidTYPO3\Vhs\Traits;

/*
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
*
* For the full copyright and license information, please read the
* LICENSE.md file that was distributed with this source code.
*/

use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
* Class SlideViewHelperTrait
*
* Trait implemented by ViewHelpers that wants some kind of
* records to be optionally looked up and/or collected from
* the current page and pages up the rootline. ViewHelpers must
* implement the getSlideRecordsFromPage method which looks up
* resources for a single page.
*
* Has the following main responsibilities:
* - register arguments common for sliding
* - method to get records with sliding according
* to the ViewHelper arguments
*/
trait SlideViewHelperTrait {

/**
* Default initialisation of arguments - will be used
* if the implementing ViewHelper does not itself define
* this method.
*
* @return void
*/
public function initializeArguments() {
$this->registerSlideArguments();
}

/**
* Register the "limit", "slide", "slideCollect" and "slideCollectReverse"
* arguments which are consumed by getSlideRecords.
* Should be used inside registerArguments().
*
* @return void
* @api
*/
protected function registerSlideArguments() {
$this->registerArgument('limit', 'integer', 'Optional limit to the total number of records to render');
$this->registerArgument('slide', 'integer', 'Enables Record Sliding - amount of levels which shall get walked up the rootline, including the current page. For infinite sliding (till the rootpage) set to -1. Only the first PID which has at minimum one record is used', FALSE, 0);
$this->registerArgument('slideCollect', 'integer', 'If TRUE, content is collected up the root line. If FALSE, only the first PID which has content is used. If greater than zero, this value overrides $slide.', FALSE, 0);
$this->registerArgument('slideCollectReverse', 'boolean', 'Normally when collecting records the elements from the actual page get shown on the top and those from the parent pages below those. You can invert this behaviour (actual page elements at bottom) by setting this flag))', FALSE, 0);
}

/**
* @return \FluidTYPO3\Vhs\Service\PageSelectService
*/
protected function getPageSelectService() {
$objectManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
return $objectManager->get('FluidTYPO3\\Vhs\\Service\\PageSelectService');
}

/**
* Get a number of records from a page for sliding
*
* @param integer $pageUid PID to get the records from
* @param integer $limit number of records to get at maximum
*/
abstract protected function getSlideRecordsFromPage($pageUid, $limit);

/**
* Get records, optionally sliding up the page rootline
*
* @param integer $pageUid
* @param integer $limit
* @return array
* @api
*/
protected function getSlideRecords($pageUid, $limit = NULL) {
if (NULL === $limit && FALSE === empty($this->arguments['limit'])) {
$limit = (integer) $this->arguments['limit'];
}

$slide = (integer) $this->arguments['slide'];
$slideCollectReverse = (boolean) $this->arguments['slideCollectReverse'];
$slideCollect = (integer) $this->arguments['slideCollect'];

if (0 < $slideCollect) {
$slide = $slideCollect;
}

// find out which storage page UIDs to read from, respecting slide depth
$storagePageUids = array();
if (0 === $slide) {
$storagePageUids[] = $pageUid;
} else {
$reverse = FALSE;
if (TRUE === $slideCollectReverse && 0 !== $slideCollect) {
$reverse = TRUE;
}
$rootLine = $this->getPageSelectService()->getRootLine($pageUid, NULL, $reverse);
if (-1 !== $slide) {
if (TRUE === $reverse) {
$rootLine = array_slice($rootLine, - $slide);
} else {
$rootLine = array_slice($rootLine, 0, $slide);
}
}
foreach ($rootLine as $page) {
$storagePageUids[] = (integer) $page['uid'];
}
}
// select records, respecting slide and slideCollect.
$records = array();
do {
$storagePageUid = array_shift($storagePageUids);
$limitRemaining = NULL;
if (NULL !== $limit) {
$limitRemaining = $limit - count($records);
if (0 >= $limitRemaining) {
break;
}
}
$recordsFromPageUid = $this->getSlideRecordsFromPage($storagePageUid, $limitRemaining);
if (0 < count($recordsFromPageUid)) {
$records = array_merge($records, $recordsFromPageUid);
if (0 === $slideCollect) {
// stop collecting because argument said so and we've gotten at least one record now.
break;
}
}
} while (0 < count($storagePageUids));

return $records;
}

}
74 changes: 11 additions & 63 deletions Classes/ViewHelpers/Content/AbstractContentViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* LICENSE.md file that was distributed with this source code.
*/

use FluidTYPO3\Vhs\Service\PageSelectService;
use FluidTYPO3\Vhs\Traits\SlideViewHelperTrait;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;

Expand All @@ -25,6 +25,8 @@
*/
abstract class AbstractContentViewHelper extends AbstractViewHelper {

use SlideViewHelperTrait;

/**
* @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
*/
Expand All @@ -35,10 +37,6 @@ abstract class AbstractContentViewHelper extends AbstractViewHelper {
*/
protected $configurationManager;

/**
* @var \FluidTYPO3\Vhs\Service\PageSelectService
*/
protected $pageSelect;

/**
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
Expand All @@ -49,77 +47,33 @@ public function injectConfigurationManager(ConfigurationManagerInterface $config
$this->contentObject = $configurationManager->getContentObject();
}

/**
* @param \FluidTYPO3\Vhs\Service\PageSelectService $pageSelect
* @return void
*/
public function injectPageSelectService(PageSelectService $pageSelect) {
$this->pageSelect = $pageSelect;
}

/**
* Initialize
*/
public function initializeArguments() {
$this->registerArgument('column', 'integer', 'Name of the column to render', FALSE, 0);
$this->registerArgument('limit', 'integer', 'Optional limit to the number of content elements to render');
$this->registerArgument('order', 'string', 'Optional sort field of content elements - RAND() supported', FALSE, 'sorting');
$this->registerArgument('order', 'string', 'Optional sort field of content elements - RAND() supported. Note that when sliding is enabled, the sorting will be applied to records on a per-page basis and not to the total set of collected records.', FALSE, 'sorting');
$this->registerArgument('sortDirection', 'string', 'Optional sort direction of content elements', FALSE, 'ASC');
$this->registerArgument('pageUid', 'integer', 'If set, selects only content from this page UID', FALSE, 0);
$this->registerArgument('contentUids', 'array', 'If used, replaces all conditions with an "uid IN (1,2,3)" style condition using the UID values from this array');
$this->registerArgument('sectionIndexOnly', 'boolean', 'If TRUE, only renders/gets content that is marked as "include in section index"', FALSE, FALSE);
$this->registerArgument('slide', 'integer', 'Enables Content Sliding - amount of levels which shall get walked up the rootline. For infinite sliding (till the rootpage) set to -1)', FALSE, 0);
$this->registerArgument('slideCollect', 'integer', 'If TRUE, content is collected up the root line. If FALSE, only the first PID which has content is used. If greater than zero, this value overrides $slide', FALSE, 0);
$this->registerArgument('slideCollectReverse', 'boolean', 'Normally when collecting content elements the elements from the actual page get shown on the top and those from the parent pages below those. You can invert this behaviour (actual page elements at bottom) by setting this flag))', FALSE, 0);
$this->registerArgument('loadRegister', 'array', 'List of LOAD_REGISTER variable');
$this->registerArgument('render', 'boolean', 'Optional returning variable as original table rows', FALSE, TRUE);
$this->registerArgument('hideUntranslated', 'boolean', 'If FALSE, will NOT include elements which have NOT been translated, if current language is NOT the default language. Default is to show untranslated elements but never display the original if there is a translated version', FALSE, FALSE);
$this->registerSlideArguments();
}

/**
* Get content records based on column and pid
*
* @param integer $limit
* @param string $order
* @return array
*/
protected function getContentRecords($limit = NULL, $order = NULL) {
protected function getContentRecords() {
$limit = $this->arguments['limit'];

$pageUid = $this->getPageUid();
$slide = (integer) $this->arguments['slide'];
$slideCollectReverse = (boolean) $this->arguments['slideCollectReverse'];
$slideCollect = (integer) $this->arguments['slideCollect'];
if (0 < $slideCollect) {
// $slideCollect overrides $slide to automatically start sliding if
// collection is enabled.
$slide = $slideCollect;
}

// find out which storage page UIDs to read from, respecting slide depth
$storagePageUids = array();
if (0 === $slide) {
$storagePageUids[] = $pageUid;
} else {
$rootLine = $this->pageSelect->getRootLine($pageUid, NULL, $slideCollectReverse);
if (-1 !== $slide) {
$rootLine = array_slice($rootLine, 0, $slide);
}
foreach ($rootLine as $page) {
$storagePageUids[] = (integer) $page['uid'];
}
}
// select content elements, respecting slide and slideCollect.
$contentRecords = array();
do {
$storagePageUid = array_shift($storagePageUids);
$contentFromPageUid = $this->getContentRecordsFromPage($storagePageUid, $limit, $order);
if (0 < count($contentFromPageUid)) {
$contentRecords = array_merge($contentRecords, $contentFromPageUid);
if (0 === $slideCollect) {
// stop collecting because argument said so and we've gotten at least one record now.
break;
}
}
} while (0 < count($storagePageUids));
$contentRecords = $this->getSlideRecords($pageUid, $limit);

if (TRUE === (boolean) $this->arguments['render']) {
$contentRecords = $this->getRenderedRecords($contentRecords);
Expand All @@ -131,17 +85,11 @@ protected function getContentRecords($limit = NULL, $order = NULL) {
/**
* @param integer $pageUid
* @param integer $limit
* @param string $order
* @return array[]
*/
protected function getContentRecordsFromPage($pageUid, $limit, $order) {
protected function getSlideRecordsFromPage($pageUid, $limit) {
$column = (integer) $this->arguments['column'];
if (NULL === $limit && FALSE === empty($this->arguments['limit'])) {
$limit = (integer) $this->arguments['limit'];
}
if (NULL === $order && FALSE === empty($this->arguments['order'])) {
$order = $this->arguments['order'];
}
$order = $this->arguments['order'];
if (FALSE === empty($order)) {
$sortDirection = strtoupper(trim($this->arguments['sortDirection']));
if ('ASC' !== $sortDirection && 'DESC' !== $sortDirection) {
Expand Down
20 changes: 3 additions & 17 deletions Classes/ViewHelpers/Content/Random/GetViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* LICENSE.md file that was distributed with this source code.
*/

use FluidTYPO3\Vhs\ViewHelpers\Content\AbstractContentViewHelper;
use FluidTYPO3\Vhs\ViewHelpers\Content\Random\RenderViewHelper;

/**
* ViewHelper for fetching a random content element in Fluid page templates
Expand All @@ -17,28 +17,14 @@
* @package Vhs
* @subpackage ViewHelpers\Content\Random
*/
class GetViewHelper extends AbstractContentViewHelper {
class GetViewHelper extends RenderViewHelper {

/**
* Initialize ViewHelper arguments
*/
public function initializeArguments() {
parent::initializeArguments();
$this->overrideArgument('limit', 'integer', 'Optional limit to the number of content elements to render', FALSE, 1);
}

/**
* Render method
*
* @return mixed
*/
public function render() {
if ('BE' === TYPO3_MODE) {
return '';
}
$limit = (integer) $this->arguments['limit'];
$contentRecords = $this->getContentRecords($limit, 'RAND()');
return $contentRecords;
$this->overrideArgument('render', 'boolean', 'Optional returning variable as original table rows', FALSE, FALSE);
}

}
35 changes: 31 additions & 4 deletions Classes/ViewHelpers/Content/Random/RenderViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,51 @@
* LICENSE.md file that was distributed with this source code.
*/

use FluidTYPO3\Vhs\ViewHelpers\Content\AbstractContentViewHelper;

/**
* ViewHelper for rendering a random content element in Fluid page templates
*
* @author Björn Fromme, <fromme@dreipunktnull.com>, dreipunktnull
* @package Vhs
* @subpackage ViewHelpers\Content\Random
*/
class RenderViewHelper extends GetViewHelper {
class RenderViewHelper extends AbstractContentViewHelper {

/**
* Initialize ViewHelper arguments
*/
public function initializeArguments() {
parent::initializeArguments();
$this->overrideArgument('limit', 'integer', 'Optional limit to the number of content elements to render', FALSE, 1);
}

/**
* Render method
*
* @return mixed
*/
public function render() {
$contentRecords = (array) parent::render();
$html = implode(LF, $contentRecords);
return $html;
if ('BE' === TYPO3_MODE) {
return '';
}
// Remove limit for getContentRecords()
$limit = $this->arguments['limit'];
$this->arguments['limit'] = NULL;
// Just using getContentRecords with a limit of 1 would not support
// using slideCollect as collecting would stop as soon as one record
// was found. As a potential optimization, $render could be overrided
// so all the content records that end up unused do not get rendered.
$contentRecords = $this->getContentRecords();
if (FALSE === empty($contentRecords)) {
shuffle($contentRecords);
$contentRecords = array_slice($contentRecords, 0, $limit);
if (TRUE === (boolean) $this->arguments['render']) {
$contentRecords = implode(LF, $contentRecords);
}
}
return $contentRecords;
}


}
Loading