Удалить RouteVoter на KnpMenu

Каждый пакет экстранета является независимым приложением. В моем меню перечислены все приложения, и мне нравится отмечать текущее в зависимости от фактического префикса маршрута.

Сначала код веточки в base.html.twig:

{{ knp_menu_render('AppBundle:Builder:mainMenu', { 'currentClass': 'active'}) }}

Функция строителя:

public function mainMenu(FactoryInterface $factory, array $options){
  $main = $factory->createItem('root');

  foreach($this->getExtranetBundles() as $bundle){
    $main->addChild($bundle->getAcronym(), array('route' => $bundle->getRoute()));
  }

  // Current Element
  $matcher = new Matcher();
  $matcher->addVoter(new BundleVoter($this->getCurrentBundle()));
  $renderer = new ListRenderer($matcher);
  $renderer->render($main);

  return $main;
}

Мой класс BundleVoter работает правильно и возвращает true, если найдено текущее меню. Но в HTML текущий элемент никогда не содержит "активный" класс.

Я прочитал немного больше в KnpMenuBundle и добавил некоторый отладочный код в класс Knp\Menu\Matcher:

public function addVoter(VoterInterface $voter)
{
    echo "add voter: " . get_class($voter);
    $this->voters[] = $voter;
}

И получил этот вывод:

add voter: AppBundle\Menu\BundleVoter
add voter: Knp\Menu\Matcher\Voter\RouteVoter

Откуда появился таинственный RouteVoter? Перезаписывает ли мой выбор BundleVoter текущих элементов? И как я могу деактивировать / перезаписать это?

1 ответ

Решение

Нашел способ изменить стандартный класс knp_menu. Я отредактировал файл services.yml следующим образом:

parameters:
    knp_menu.voter.router.class: AppBundle\Menu\BundleVoter

services:
    appbundle.menu.voter.request:
        class: AppBundle\Menu\BundleVoter
        arguments: [@service_container]
        tags:
          - { name: knp_menu.voter }

Класс по-прежнему создается два раза, к сожалению, я должен проверить, является ли переданный параметр пустым или нет. И параметр $container должен быть необязательным...

class BundleVoter implements VoterInterface
{
  private $container;

  public function __construct($container = null)
  {
    if($container != null)
      $this->container = $container;
  }

  public function matchItem(ItemInterface $item)
  {
    if($this->container != null){
      $bundle = $this->container->get('menubundles')->getCurrentBundle();
      if (null === $bundle || null === $item->getName()) {
        return null;
      }

      if ($item->getName() == $bundle->getAcronym()) {
        return true;
      }
    }

    return null;
  }
}

Пожалуйста, напишите, если вы нашли лучшее решение:-) Thx

Другие вопросы по тегам