Created
February 27, 2019 07:28
-
-
Save a-r-m-i-n/4d777d49cce13ec7204662300713c7e6 to your computer and use it in GitHub Desktop.
TYPO3 Fluid Widget to achieve a Glossary navigation.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Vendor\Package\ViewHelpers\Widget\Controller; | |
/** | |
* This view helper uses the technology of paginate widget but works with arrays | |
* and the assigned objects don't need the QueryResultInterface. | |
* | |
* @author Armin Vieweg <[email protected]> | |
* @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later | |
*/ | |
class GlossaryController extends \TYPO3\CMS\Fluid\Core\Widget\AbstractWidgetController | |
{ | |
/** | |
* @var array | |
*/ | |
protected $configuration = array( | |
'insertAbove' => false, | |
'insertBelow' => true, | |
'showAllLink' => true | |
); | |
/** | |
* @var array | |
*/ | |
protected $objects; | |
/** | |
* @var string | |
*/ | |
protected $currentLetter = ''; | |
/** | |
* @var array | |
*/ | |
protected $usedLetters = array(); | |
/** | |
* Initialize Action of the widget controller | |
* | |
* @return void | |
*/ | |
public function initializeAction() | |
{ | |
$this->objects = $this->widgetConfiguration['objects']; | |
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule( | |
$this->configuration, | |
$this->widgetConfiguration['configuration'], | |
true | |
); | |
} | |
/** | |
* Returns all visible objects within a range, depending on itemsPerPage and the currentPage. | |
* | |
* @param \TYPO3\CMS\Extbase\Persistence\Generic\QueryResult|array $objects the list of objects | |
* @return array<mixed> the list of visible objects | |
*/ | |
public function getVisibleObjects($objects) | |
{ | |
$visibleObjects = array(); | |
/** @var $object \PwTeaserTeam\PwTeaser\Domain\Model\Page */ | |
foreach ($objects as $object) { | |
// CAUTION Here you need to adjust the getter! | |
$firstLetterNavTitle = $this->getFirstLetter($object->getNavTitle()); | |
if ($firstLetterNavTitle) { | |
$this->usedLetters[$firstLetterNavTitle] = $firstLetterNavTitle; | |
if ($firstLetterNavTitle === strtolower($this->currentLetter) || $this->currentLetter === 'all') { | |
$visibleObjects[] = $object; | |
} | |
} else { | |
$firstLetter = $this->getFirstLetter($object->getTitle()); | |
$this->usedLetters[$firstLetter] = $firstLetter; | |
if ($firstLetter === strtolower($this->currentLetter) || $this->currentLetter === 'all') { | |
$visibleObjects[] = $object; | |
} | |
} | |
} | |
if (empty($visibleObjects)) { | |
$GLOBALS['TSFE']->pageNotFoundAndExit(); | |
} | |
return $visibleObjects; | |
} | |
/** | |
* Index action of the widget controller | |
* | |
* @param string $currentLetter | |
* @return void | |
*/ | |
public function indexAction($currentLetter = 'all') | |
{ | |
$this->currentLetter = $currentLetter; | |
$this->view->assign('contentArguments', array( | |
$this->widgetConfiguration['as'] => $this->getVisibleObjects($this->objects) | |
)); | |
$this->view->assign('configuration', $this->configuration); | |
$this->view->assign('glossary', $this->buildGlossary()); | |
} | |
/** | |
* Returns first letter of given string, and converts umlauts to regular letters (ä => a) | |
* | |
* @param string $string to get first letter of | |
* @return string First letter of given string | |
*/ | |
protected function getFirstLetter($string) | |
{ | |
$firstLetter = mb_strtolower(mb_substr($string, 0, 1)); | |
switch ($firstLetter) { | |
case 'ä': | |
return 'a'; | |
case 'ö': | |
return 'o'; | |
case 'ü': | |
return 'u'; | |
case 'ß': | |
return 's'; | |
} | |
return $firstLetter; | |
} | |
/** | |
* Returns an array with letters | |
* | |
* @return array | |
*/ | |
protected function buildGlossary() | |
{ | |
$alphabeth = array( | |
'a' => array('lower' => 'a', 'upper' => 'A', 'used' => false, 'current' => false), | |
'b' => array('lower' => 'b', 'upper' => 'B', 'used' => false, 'current' => false), | |
'c' => array('lower' => 'c', 'upper' => 'C', 'used' => false, 'current' => false), | |
'd' => array('lower' => 'd', 'upper' => 'D', 'used' => false, 'current' => false), | |
'e' => array('lower' => 'e', 'upper' => 'E', 'used' => false, 'current' => false), | |
'f' => array('lower' => 'f', 'upper' => 'F', 'used' => false, 'current' => false), | |
'g' => array('lower' => 'g', 'upper' => 'G', 'used' => false, 'current' => false), | |
'h' => array('lower' => 'h', 'upper' => 'H', 'used' => false, 'current' => false), | |
'i' => array('lower' => 'i', 'upper' => 'I', 'used' => false, 'current' => false), | |
'j' => array('lower' => 'j', 'upper' => 'J', 'used' => false, 'current' => false), | |
'k' => array('lower' => 'k', 'upper' => 'K', 'used' => false, 'current' => false), | |
'l' => array('lower' => 'l', 'upper' => 'L', 'used' => false, 'current' => false), | |
'm' => array('lower' => 'm', 'upper' => 'M', 'used' => false, 'current' => false), | |
'n' => array('lower' => 'n', 'upper' => 'N', 'used' => false, 'current' => false), | |
'o' => array('lower' => 'o', 'upper' => 'O', 'used' => false, 'current' => false), | |
'p' => array('lower' => 'p', 'upper' => 'P', 'used' => false, 'current' => false), | |
'q' => array('lower' => 'q', 'upper' => 'Q', 'used' => false, 'current' => false), | |
'r' => array('lower' => 'r', 'upper' => 'R', 'used' => false, 'current' => false), | |
's' => array('lower' => 's', 'upper' => 'S', 'used' => false, 'current' => false), | |
't' => array('lower' => 't', 'upper' => 'T', 'used' => false, 'current' => false), | |
'u' => array('lower' => 'u', 'upper' => 'U', 'used' => false, 'current' => false), | |
'v' => array('lower' => 'v', 'upper' => 'V', 'used' => false, 'current' => false), | |
'w' => array('lower' => 'w', 'upper' => 'W', 'used' => false, 'current' => false), | |
'x' => array('lower' => 'x', 'upper' => 'X', 'used' => false, 'current' => false), | |
'y' => array('lower' => 'y', 'upper' => 'Y', 'used' => false, 'current' => false), | |
'z' => array('lower' => 'z', 'upper' => 'Z', 'used' => false, 'current' => false), | |
); | |
foreach ($alphabeth as $key => $letter) { | |
if (in_array(strtolower($key), $this->usedLetters)) { | |
$alphabeth[$key]['used'] = true; | |
} | |
if ($this->currentLetter == $key) { | |
$alphabeth[$key]['current'] = true; | |
} | |
} | |
$glossary = array( | |
'letters' => $alphabeth, | |
'allIsCurrent' => $this->currentLetter === 'all' | |
); | |
return $glossary; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Vendor\Package\ViewHelpers\Widget; | |
use TYPO3\CMS\Extbase\Persistence\ObjectStorage; | |
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; | |
/** | |
* Widget for glossary | |
* | |
* @author Armin Vieweg <[email protected]> | |
*/ | |
class GlossaryViewHelper extends \TYPO3\CMS\Fluid\Core\Widget\AbstractWidgetViewHelper | |
{ | |
/** | |
* @var Controller\GlossaryController | |
*/ | |
protected $controller; | |
/** | |
* Injection of widget controller | |
* | |
* @param Controller\GlossaryController $controller | |
* @return void | |
*/ | |
public function injectController(Controller\GlossaryController $controller) | |
{ | |
$this->controller = $controller; | |
} | |
/** | |
* The render method of widget | |
* | |
* @param QueryResultInterface|ObjectStorage|array $objects | |
* @param string $as | |
* @param array $configuration | |
* @return string | |
*/ | |
public function render( | |
$objects, | |
$as, | |
array $configuration = array('showAllLink' => TRUE, 'insertAbove' => FALSE, 'insertBelow' => TRUE) | |
) { | |
return $this->initiateSubRequest(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<f:if condition="{configuration.insertAbove}"> | |
<f:render section="glossary" arguments="{glossary: glossary, configuration: configuration}" /> | |
</f:if> | |
<f:renderChildren arguments="{contentArguments}" /> | |
<f:if condition="{configuration.insertBelow}"> | |
<f:render section="glossary" arguments="{glossary: glossary, configuration: configuration}" /> | |
</f:if> | |
<f:section name="glossary"> | |
<ul class="nav nav-justified nav-list"> | |
<!-- Letters --> | |
<f:for each="{glossary.letters}" as="letter"> | |
<f:if condition="{letter.used}"> | |
<li{f:if(condition: '{letter.current}', then: ' class="active"')}> | |
<f:if condition="{letter.current}"> | |
<f:then> | |
<a href="#">{letter.upper}</a> | |
</f:then> | |
<f:else> | |
<f:widget.link arguments="{currentLetter:'{letter.lower}'}">{letter.upper}</f:widget.link> | |
</f:else> | |
</f:if> | |
</li> | |
</f:if> | |
</f:for> | |
</ul> | |
<!-- Show all --> | |
<f:if condition="{configuration.showAllLink}"> | |
<f:if condition="{glossary.allIsCurrent}"> | |
<f:else> | |
<div class="text-center"> | |
<f:link.page class="btn btn-default">Filter zurücksetzen</f:link.page> | |
</div> | |
</f:else> | |
</f:if> | |
</f:if> | |
</f:section> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment