GroupMenuProvider.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <?php
  2. /*
  3. * This file is part of the Sonata Project package.
  4. *
  5. * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Sonata\AdminBundle\Menu\Provider;
  11. use Knp\Menu\FactoryInterface;
  12. use Knp\Menu\Provider\MenuProviderInterface;
  13. use Sonata\AdminBundle\Admin\Pool;
  14. /**
  15. * Menu provider based on group options.
  16. *
  17. * @author Alexandru Furculita <alex@furculita.net>
  18. */
  19. class GroupMenuProvider implements MenuProviderInterface
  20. {
  21. /**
  22. * @var FactoryInterface
  23. */
  24. private $menuFactory;
  25. /**
  26. * @var Pool
  27. */
  28. private $pool;
  29. /**
  30. * NEXT_MAJOR: Use AuthorizationCheckerInterface when bumping requirements to >=Symfony 2.6.
  31. *
  32. * @var \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface|\Symfony\Component\Security\Core\SecurityContextInterface
  33. */
  34. private $checker;
  35. /**
  36. * NEXT_MAJOR: Remove default value null of $checker.
  37. * NEXT_MAJOR: Allow only injection of AuthorizationCheckerInterface when bumping requirements to >=Symfony 2.6.
  38. *
  39. * @param FactoryInterface $menuFactory
  40. * @param Pool $pool
  41. * @param \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface|
  42. * \Symfony\Component\Security\Core\SecurityContextInterface|null $checker
  43. */
  44. public function __construct(FactoryInterface $menuFactory, Pool $pool, $checker = null)
  45. {
  46. $this->menuFactory = $menuFactory;
  47. $this->pool = $pool;
  48. /*
  49. * NEXT_MAJOR: Remove this if blocks.
  50. * NEXT_MAJOR: Remove instance type checking when bumping requirements to >=Symfony 2.6.
  51. */
  52. if (null === $checker) {
  53. @trigger_error(
  54. 'Passing no 3rd argument is deprecated since version 3.10 and will be mandatory in 4.0.
  55. Pass Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface as 3rd argument.',
  56. E_USER_DEPRECATED
  57. );
  58. } elseif (!$checker instanceof \Symfony\Component\Security\Core\SecurityContextInterface
  59. && !$checker instanceof \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface
  60. ) {
  61. throw new \InvalidArgumentException(
  62. 'Argument 3 must be an instance of either \Symfony\Component\Security\Core\SecurityContextInterface or
  63. \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface'
  64. );
  65. }
  66. $this->checker = $checker;
  67. }
  68. /**
  69. * Retrieves the menu based on the group options.
  70. *
  71. * @param string $name
  72. * @param array $options
  73. *
  74. * @return \Knp\Menu\ItemInterface
  75. *
  76. * @throws \InvalidArgumentException if the menu does not exists
  77. */
  78. public function get($name, array $options = array())
  79. {
  80. $group = $options['group'];
  81. $menuItem = $this->menuFactory->createItem(
  82. $options['name'],
  83. array(
  84. 'label' => $group['label'],
  85. )
  86. );
  87. if (empty($group['on_top'])) {
  88. foreach ($group['items'] as $item) {
  89. if (isset($item['admin']) && !empty($item['admin'])) {
  90. $admin = $this->pool->getInstance($item['admin']);
  91. // skip menu item if no `list` url is available or user doesn't have the LIST access rights
  92. if (!$admin->hasRoute('list') || !$admin->hasAccess('list')) {
  93. continue;
  94. }
  95. $label = $admin->getLabel();
  96. $options = $admin->generateMenuUrl('list', array(), $item['route_absolute']);
  97. $options['extras'] = array(
  98. 'label_catalogue' => $admin->getTranslationDomain(),
  99. 'admin' => $admin,
  100. );
  101. } else {
  102. //NEXT_MAJOR: Remove if statement of null checker.
  103. if (null !== $this->checker) {
  104. if ((!empty($item['roles']) && !$this->checker->isGranted($item['roles']))
  105. || (!empty($group['roles']) && !$this->checker->isGranted($group['roles'], $item['route']))
  106. ) {
  107. continue;
  108. }
  109. }
  110. $label = $item['label'];
  111. $options = array(
  112. 'route' => $item['route'],
  113. 'routeParameters' => $item['route_params'],
  114. 'routeAbsolute' => $item['route_absolute'],
  115. 'extras' => array(
  116. 'label_catalogue' => $group['label_catalogue'],
  117. ),
  118. );
  119. }
  120. $menuItem->addChild($label, $options);
  121. }
  122. if (false === $menuItem->hasChildren()) {
  123. $menuItem->setDisplay(false);
  124. } elseif (!empty($group['keep_open'])) {
  125. $menuItem->setAttribute('class', 'keep-open');
  126. $menuItem->setExtra('keep_open', $group['keep_open']);
  127. }
  128. } else {
  129. foreach ($group['items'] as $item) {
  130. if (isset($item['admin']) && !empty($item['admin'])) {
  131. $admin = $this->pool->getInstance($item['admin']);
  132. // Do not display group if no `list` url is available or user doesn't have the LIST access rights
  133. if (!$admin->hasRoute('list') || !$admin->hasAccess('list')) {
  134. $menuItem->setDisplay(false);
  135. continue;
  136. }
  137. $options = $admin->generateUrl('list');
  138. $menuItem->setExtra('route', $admin->getBaseRouteName().'_list');
  139. $menuItem->setExtra('on_top', $group['on_top']);
  140. $menuItem->setUri($options);
  141. } else {
  142. $router = $this->pool->getContainer()->get('router');
  143. $menuItem->setUri($router->generate($item['route']));
  144. }
  145. }
  146. }
  147. return $menuItem;
  148. }
  149. /**
  150. * Checks whether a menu exists in this provider.
  151. *
  152. * @param string $name
  153. * @param array $options
  154. *
  155. * @return bool
  156. */
  157. public function has($name, array $options = array())
  158. {
  159. return 'sonata_group_menu' === $name;
  160. }
  161. }