Skip to content

Instantly share code, notes, and snippets.

@bwaidelich
Created December 6, 2012 11:36
Show Gist options
  • Save bwaidelich/4223855 to your computer and use it in GitHub Desktop.
Save bwaidelich/4223855 to your computer and use it in GitHub Desktop.
TYPO3 Flow menu with Fluid and DTOs
<ul class="nav{f:if(condition: menuClass, then: ' {menuClass}')}"<f:for each="{menu.attributes}" as="attributeValue" key="attributeName"> {attributeName}="{attributeValue}"</f:for>>
<f:for each="{menu.menuItems}" as="menuItem" iteration="iteration">
<f:if condition="{menuItem.header}">
<f:then>
<li class="nav-header {menuItem.class}"<f:for each="{menuItem.attributes}" as="attributeValue" key="attributeName"> {attributeName}="{attributeValue}"</f:for>>{menuItem.label}</li>
</f:then>
<f:else>
<f:if condition="{menuItem.separator}">
<f:then>
<li class="divider {menuItem.class}"<f:for each="{menuItem.attributes}" as="attributeValue" key="attributeName"> {attributeName}="{attributeValue}"</f:for>></li>
</f:then>
<f:else>
<li class="{menuItem.class}{f:if(condition: menuItem.active, then: ' active')}"<f:for each="{menuItem.attributes}" as="attributeValue" key="attributeName"> {attributeName}="{attributeValue}"</f:for>>
<a href="<f:uri.action action="{menuItem.targetActionName}" controller="{menuItem.targetControllerName}" arguments="{menuItem.targetActionArguments}"></f:uri.action>">
{menuItem.label}
</a>
<f:if condition="{menuItem.subMenuItems}">
<f:render section="subMenuItems" arguments="{subMenuItems: menuItem.subMenuItems, menu: menu}" />
</f:if>
</li>
</f:else>
</f:if>
</f:else>
</f:if>
</f:for>
</ul>
<f:section name="subMenuItems">
<ul class="nav nav-list nav-nested">
<f:for each="{subMenuItems}" as="subMenuItem" iteration="iteration">
<li class="{subMenuItem.class}{f:if(condition: subMenuItem.active, then: ' active')}"<f:for each="{subMenuItem.attributes}" as="attributeValue" key="attributeName"> {attributeName}="{attributeValue}"</f:for>>
<a href="<f:uri.action action="{subMenuItem.targetActionName}" controller="{subMenuItem.targetControllerName}" arguments="{subMenuItem.targetActionArguments}"></f:uri.action>">
{subMenuItem.label}
</a>
</li>
</f:for>
</ul>
</f:section>
<?php
namespace My\Package\Domain\Dto;
use TYPO3\Flow\Annotations as Flow;
/**
* Simple Menu that can be rendered with Fluid
*/
class Menu {
/**
* @var array<\Yeebase\Guruhelp\Domain\Dto\MenuItem>
*/
protected $menuItems;
/**
* @var array
*/
protected $attributes = array();
public function __construct(array $attributes = array()) {
$this->attributes = $attributes;
$this->menuItems = array();
}
/**
* @param string $attributeName
* @param string $attributeValue
*/
public function addAttribute($attributeName, $attributeValue) {
$this->attributes[$attributeName] = $attributeValue;
}
/**
* @return array
*/
public function getAttributes() {
return $this->attributes;
}
/**
* @return array
*/
public function getMenuItems() {
return $this->menuItems;
}
/**
* Adds a menu item to the end of this menu
*
* @param MenuItem $menuItem
* @return Menu the current instance to enable method chaining
*/
public function addMenuItem(\Yeebase\Guruhelp\Domain\Dto\MenuItem $menuItem) {
$this->menuItems[] = $menuItem;
return $this;
}
/**
* @param string $label
* @param string $targetControllerName if omitted, the resulting menu item is a separator/menu header
* @param string $targetActionName
* @param array $targetActionArguments
* @return Menu the current instance to enable method chaining
*/
public function createMenuItem($label, $targetControllerName = NULL, $targetActionName = NULL, array $targetActionArguments = array()) {
$this->menuItems[] = new MenuItem($label, $targetControllerName, $targetActionName, $targetActionArguments);
return $this;
}
/**
* @param \TYPO3\Flow\Mvc\ActionRequest $request
* @return void
*/
public function setActiveMenuItem(\TYPO3\Flow\Mvc\ActionRequest $request) {
foreach ($this->menuItems as $menuItem) {
$menuItem->setActive($menuItem->matchesRequest($request));
foreach ($menuItem->getSubMenuItems() as $subMenuItem) {
$subMenuItem->setActive($subMenuItem->matchesRequest($request));
}
}
}
}
<?php
namespace My\Package\Domain\Dto;
use TYPO3\Flow\Annotations as Flow;
/**
* A Menu item
*/
class MenuItem {
/**
* @Flow\Inject
* @var \TYPO3\Flow\Persistence\PersistenceManagerInterface
*/
protected $persistenceManager;
/**
* @var string
*/
protected $label = '';
/**
* @var boolean
*/
protected $active = FALSE;
/**
* @var string
*/
protected $targetControllerName;
/**
* @var string
*/
protected $targetActionName;
/**
* @var array
*/
protected $targetActionArguments = array();
/**
* @var array<MenuItem>
*/
protected $subMenuItems = array();
/**
* @var array
*/
protected $attributes = array();
/**
* @param string $label
* @param string $targetControllerName
* @param string $targetActionName
* @param array $targetActionArguments
* @param array $attributes
*/
public function __construct($label, $targetControllerName = NULL, $targetActionName = NULL, array $targetActionArguments = array(), array $attributes = array()) {
$this->label = $label;
$this->targetControllerName = $targetControllerName;
$this->targetActionName = $targetActionName;
$this->targetActionArguments = $targetActionArguments;
$this->attributes = $attributes;
}
/**
* @param string $attributeName
* @param string $attributeValue
*/
public function addAttribute($attributeName, $attributeValue) {
$this->attributes[$attributeName] = $attributeValue;
}
/**
* @return array
*/
public function getAttributes() {
return $this->attributes;
}
/**
* returns TRUE if the given $request points to the controller/action specified in this menu item
*
* @param \TYPO3\Flow\Mvc\ActionRequest $request
* @return boolean TRUE if this menuItem is active for the given $request, otherwise FALSE
*/
public function matchesRequest(\TYPO3\Flow\Mvc\ActionRequest $request) {
if ($this->isHeader()) {
return FALSE;
}
if ($this->getTargetControllerName() === $request->getControllerName()) {
if ($this->getTargetActionName() === NULL) {
return TRUE;
}
if ($this->targetActionName !== $request->getControllerActionName()) {
return FALSE;
}
$targetActionArguments = $this->getTargetActionArguments();
$targetActionArguments = $this->persistenceManager->convertObjectsToIdentityArrays($targetActionArguments);
\TYPO3\Flow\Utility\Arrays::sortKeysRecursively($targetActionArguments);
$requestArguments = $request->getArguments();
\TYPO3\Flow\Utility\Arrays::sortKeysRecursively($requestArguments);
return ($targetActionArguments === $requestArguments);
}
return FALSE;
}
/**
* @param boolean $active
*/
public function setActive($active) {
$this->active = (boolean)$active;
}
/**
* @return boolean
*/
public function isActive() {
return $this->active;
}
/**
* @param string $label
*/
public function setLabel($label) {
$this->label = $label;
}
/**
* @return string
*/
public function getLabel() {
return $this->label;
}
/**
* @param string $targetController
* @return void
*/
public function setTargetControllerName($targetController) {
$this->targetControllerName = $targetController;
}
/**
* @return string
*/
public function getTargetControllerName() {
return $this->targetControllerName;
}
/**
* @param string $targetActionName
* @return void
*/
public function setTargetActionName($targetActionName) {
$this->targetActionName = $targetActionName;
}
/**
* @return string
*/
public function getTargetActionName() {
return $this->targetActionName;
}
/**
* @param array $targetActionArguments
*/
public function setTargetActionArguments(array $targetActionArguments) {
$this->targetActionArguments = $targetActionArguments;
}
/**
* @return array
*/
public function getTargetActionArguments() {
return $this->targetActionArguments;
}
/**
* @return boolean TRUE if this menu item is just a header
*/
public function isHeader() {
return $this->targetControllerName === NULL && $this->label !== '';
}
/**
* @return boolean TRUE if this menu item is just a separator
*/
public function isSeparator() {
return $this->label === '';
}
/**
* @return string the normalized target controller & action name that can be used to render the css class of an menu item
*/
public function getClass() {
$class = str_replace('\\', '-', $this->targetControllerName);
if ($this->targetActionName !== NULL) {
$class = sprintf('%s-%s', $class, $this->targetActionName);
}
return strtolower($class);
}
/**
* @param array<MenuItem> $subMenuItems
*/
public function setSubMenuItems(array $subMenuItems) {
$this->subMenuItems = $subMenuItems;
}
/**
* @return array<MenuItem>
*/
public function getSubMenuItems() {
return $this->subMenuItems;
}
/**
* @param MenuItem $subMenuItem
* @return MenuItem the current instance to enable method chaining
*/
public function addSubMenuItem(MenuItem $subMenuItem) {
$this->subMenuItems[] = $subMenuItem;
return $this;
}
/**
* @return boolean
*/
public function hasSubMenuItems() {
return $this->subMenuItems !== array();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment