Skip to content

Instantly share code, notes, and snippets.

@bwaidelich
Last active April 13, 2017 12:28
Show Gist options
  • Select an option

  • Save bwaidelich/f3a3d6373acb558a7aa6 to your computer and use it in GitHub Desktop.

Select an option

Save bwaidelich/f3a3d6373acb558a7aa6 to your computer and use it in GitHub Desktop.

Revisions

  1. Bastian Waidelich revised this gist Jun 3, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Menu.html
    Original file line number Diff line number Diff line change
    @@ -20,7 +20,7 @@
    <f:if condition="{menuItem.icon}">
    <i class="fa fa-fw fa-{menuItem.icon}"></i>
    </f:if>
    {menuItem.label}{f:if(condition: menuItem.active, then: ' (active)')}
    {menuItem.label}
    <f:if condition="{menuItem.badge}">
    <span class="pull-right badge badge-info badge-hidden">{menuItem.badge}</span>
    </f:if>
  2. Bastian Waidelich revised this gist Jun 3, 2015. 1 changed file with 40 additions and 0 deletions.
    40 changes: 40 additions & 0 deletions Menu.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,40 @@
    <ul class="nav">
    <f:for each="{menu.menuItems}" as="menuItem">
    <f:render section="menuItem" arguments="{menuItem: menuItem}" />
    </f:for>
    </ul>

    <f:section name="menuItem">
    <f:if condition="{menuItem.header}">
    <f:then>
    <li class="nav-header">{menuItem.label}</li>
    </f:then>
    <f:else>
    <f:if condition="{menuItem.separator}">
    <f:then>
    <li class="divider"></li>
    </f:then>
    <f:else>
    <li class="{f:if(condition: menuItem.active, then: 'active')}">
    <a href="{f:uri.action(action: menuItem.targetActionName, controller: menuItem.targetControllerName, package: menuItem.targetPackageKey)}">
    <f:if condition="{menuItem.icon}">
    <i class="fa fa-fw fa-{menuItem.icon}"></i>
    </f:if>
    {menuItem.label}{f:if(condition: menuItem.active, then: ' (active)')}
    <f:if condition="{menuItem.badge}">
    <span class="pull-right badge badge-info badge-hidden">{menuItem.badge}</span>
    </f:if>
    </a>
    <f:if condition="{menuItem.subMenuItems}">
    <ul>
    <f:for each="{menuItem.subMenuItems}" as="subMenuItem">
    <f:render section="menuItem" arguments="{menuItem: subMenuItem}" />
    </f:for>
    </ul>
    </f:if>
    </li>
    </f:else>
    </f:if>
    </f:else>
    </f:if>
    </f:section>
  3. Bastian Waidelich revised this gist Jun 3, 2015. 2 changed files with 2 additions and 2 deletions.
    2 changes: 1 addition & 1 deletion Menu.php
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    <?php
    namespace Wwwision\Test\Domain\Dto;
    namespace Acme\SomePackage\Domain\Dto;

    use TYPO3\Flow\Annotations as Flow;
    use TYPO3\Flow\Mvc\ActionRequest;
    2 changes: 1 addition & 1 deletion MenuItem.php
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    <?php
    namespace Wwwision\Test\Domain\Dto;
    namespace Acme\SomePackage\Domain\Dto;

    use TYPO3\Flow\Annotations as Flow;
    use TYPO3\Flow\Persistence\PersistenceManagerInterface;
  4. Bastian Waidelich created this gist Jun 3, 2015.
    88 changes: 88 additions & 0 deletions Menu.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    <?php
    namespace Wwwision\Test\Domain\Dto;

    use TYPO3\Flow\Annotations as Flow;
    use TYPO3\Flow\Mvc\ActionRequest;

    /**
    * Simple Menu that can be rendered with Fluid
    */
    class Menu {

    /**
    * @var ActionRequest
    */
    protected $actionRequest;

    /**
    * @var MenuItem[]
    */
    protected $menuItems = [];

    /**
    * @param ActionRequest $actionRequest
    * @param array $configuration in the format ['label' => 'A', 'targetPackageKey' => 'Some.Package', ..., 'subMenuItems' => ['label' => A.1', ...], ...]
    */
    public function __construct(ActionRequest $actionRequest, array $configuration = NULL) {
    $this->actionRequest = $actionRequest;
    if ($configuration !== NULL && isset($configuration['menuItems'])) {
    $this->menuItems = $this->createMenuItems($configuration['menuItems']);
    $this->setActiveMenuItems();
    }
    }

    /**
    * Recursively creates menu and sub menu items corresponding to the given $configuration
    *
    * @param array $menuItemsConfiguration
    * @return MenuItem[]
    */
    protected function createMenuItems(array $menuItemsConfiguration) {
    $menuItems = [];
    foreach ($menuItemsConfiguration as $menuItemConfiguration) {
    $label = isset($menuItemConfiguration['label']) ? $menuItemConfiguration['label'] : NULL;
    $targetPackageKey = isset($menuItemConfiguration['package']) ? $menuItemConfiguration['package'] : NULL;
    $targetControllerName = isset($menuItemConfiguration['controller']) ? $menuItemConfiguration['controller'] : NULL;
    $targetActionName = isset($menuItemConfiguration['action']) ? $menuItemConfiguration['action'] : 'index';
    $targetActionArguments = isset($menuItemConfiguration['arguments']) ? $menuItemConfiguration['arguments'] : [];
    $icon = isset($menuItemConfiguration['icon']) ? $menuItemConfiguration['icon'] : NULL;
    $badge = isset($menuItemConfiguration['badge']) ? $menuItemConfiguration['badge'] : NULL;
    $menuItem = new MenuItem($label, $targetPackageKey, $targetControllerName, $targetActionName, $targetActionArguments, $icon, $badge);
    if (isset($menuItemConfiguration['menuItems'])) {
    $menuItem->setSubMenuItems($this->createMenuItems($menuItemConfiguration['menuItems']));
    }
    $menuItems[] = $menuItem;
    }
    return $menuItems;
    }

    /**
    * @return MenuItem[]
    */
    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(MenuItem $menuItem) {
    $this->menuItems[] = $menuItem;

    return $this;
    }

    /**
    * Recursively activates all menu items that match the given actionRequest
    *
    * @return void
    */
    public function setActiveMenuItems() {
    foreach ($this->menuItems as $menuItem) {
    $menuItem->activateForRequest($this->actionRequest);
    }
    }
    }
    246 changes: 246 additions & 0 deletions MenuItem.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,246 @@
    <?php
    namespace Wwwision\Test\Domain\Dto;

    use TYPO3\Flow\Annotations as Flow;
    use TYPO3\Flow\Persistence\PersistenceManagerInterface;
    use TYPO3\Flow\Security\Account;
    use TYPO3\Flow\Security\Context;
    use TYPO3\Flow\Utility\Arrays;
    use TYPO3\Flow\Mvc\ActionRequest;

    /**
    * Simple Menu that can be rendered with Fluid
    */
    class MenuItem {

    /**
    * @Flow\Inject
    * @var PersistenceManagerInterface
    */
    protected $persistenceManager;

    /**
    * @var string
    */
    protected $label = '';

    /**
    * @var boolean
    */
    protected $active = FALSE;

    /**
    * @var string
    */
    protected $targetPackageKey;

    /**
    * @var string
    */
    protected $targetControllerName;

    /**
    * @var string
    */
    protected $targetActionName;

    /**
    * @var array
    */
    protected $targetActionArguments = [];

    /**
    * @var string
    */
    protected $icon;

    /**
    * @var string
    */
    protected $badge;

    /**
    * @var MenuItem[]
    */
    protected $subMenuItems = [];

    /**
    * @param string $label label of the menu item - if omitted, the resulting menu item is considered a separator
    * @param string $targetPackageKey key of the target package - if omitted, the resulting menu item is considered a menu header
    * @param string $targetControllerName name of the target controller
    * @param string $targetActionName the target action name
    * @param array $targetActionArguments the target action arguments
    * @param string $icon an optional icon identifier (to be used from the fluid template)
    * @param string $badge an optional badge text (to be used from the fluid template)
    */
    public function __construct($label, $targetPackageKey = NULL, $targetControllerName = NULL, $targetActionName = NULL, array $targetActionArguments = [], $icon = NULL, $badge = NULL) {
    $this->label = $label;
    $this->targetPackageKey = $targetPackageKey;
    $this->targetControllerName = $targetControllerName;
    $this->targetActionName = $targetActionName;
    $this->targetActionArguments = $targetActionArguments;
    $this->icon = $icon;
    $this->badge = $badge;
    }

    /**
    * Sets the menu item (and it's sub items) active if it matches the given $actionRequest:
    *
    * If the menu item has sub menu items, matching package and controller is enough to mark the item active.
    * Otherwise the action name has to match as well (unless that is not defined).
    *
    * @param ActionRequest $actionRequest
    * @return void
    */
    public function activateForRequest(ActionRequest $actionRequest) {
    if ($this->isHeader() || $this->isSeparator()) {
    return;
    }
    if (!$this->matchesRequest($actionRequest)) {
    return;
    }
    $this->active = TRUE;
    foreach ($this->subMenuItems as $subMenuItem) {
    $subMenuItem->activateForRequest($actionRequest);
    }
    }

    /**
    * returns TRUE if the given $request points to the controller/action specified in this menu item
    *
    * @param ActionRequest $actionRequest
    * @return boolean TRUE if this menuItem is active for the given $request, otherwise FALSE
    */
    protected function matchesRequest(ActionRequest $actionRequest) {
    if ($this->hasSubMenuItems() || $this->targetActionName === NULL) {
    return $this->targetPackageKey === $actionRequest->getControllerPackageKey() && $this->targetControllerName === $actionRequest->getControllerName();
    }

    if ($this->targetPackageKey !== $actionRequest->getControllerPackageKey()) {
    return FALSE;
    }
    if ($this->targetControllerName !== $actionRequest->getControllerName()) {
    return FALSE;
    }

    // for items with sub items a matching controller is enough to turn it active
    if ($this->hasSubMenuItems() || $this->targetActionName === NULL) {
    return TRUE;
    }

    if ($this->targetActionName !== $actionRequest->getControllerActionName()) {
    return FALSE;
    }

    $targetActionArguments = $this->targetActionArguments;
    $targetActionArguments = $this->persistenceManager->convertObjectsToIdentityArrays($targetActionArguments);
    Arrays::sortKeysRecursively($targetActionArguments);
    $requestArguments = $actionRequest->getArguments();
    Arrays::sortKeysRecursively($requestArguments);

    return ($targetActionArguments === $requestArguments);
    }

    /**
    * @return boolean TRUE if this menu item is just a header (i.e. no target package set)
    */
    public function isHeader() {
    return $this->targetPackageKey === NULL && $this->label !== '';
    }

    /**
    * @return boolean TRUE if this menu item is just a separator (i.e. no label set)
    */
    public function isSeparator() {
    return $this->label === '';
    }

    /**
    * @return MenuItem[]
    */
    public function getSubMenuItems() {
    return $this->subMenuItems;
    }

    /**
    * @param MenuItem[] $subMenuItems
    * @return void
    */
    public function setSubMenuItems(array $subMenuItems) {
    $this->subMenuItems = $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 !== [];
    }

    /**
    * @return string
    */
    public function getTargetPackageKey() {
    return $this->targetPackageKey;
    }

    /**
    * @return string
    */
    public function getTargetControllerName() {
    return $this->targetControllerName;
    }

    /**
    * @return string
    */
    public function getTargetActionName() {
    return $this->targetActionName;
    }

    /**
    * @return array
    */
    public function getTargetActionArguments() {
    return $this->targetActionArguments;
    }

    /**
    * @return boolean
    */
    public function isActive() {
    return $this->active;
    }

    /**
    * @return string
    */
    public function getLabel() {
    return $this->label;
    }

    /**
    * @return string
    */
    public function getBadge() {
    return $this->badge;
    }

    /**
    * @return string
    */
    public function getIcon() {
    return $this->icon;
    }

    }