src/Menu/Builder.php line 74

Open in your IDE?
  1. <?php
  2. namespace App\Menu;
  3. use App\Entity\Brand;
  4. use App\Entity\User;
  5. use App\Entity\UserRetailer;
  6. use App\Repository\BrandRepository;
  7. use App\Service\PageService;
  8. use Doctrine\ORM\EntityManagerInterface;
  9. use Knp\Menu\FactoryInterface;
  10. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  11. use Symfony\Component\Security\Core\Security;
  12. use Symfony\Component\Security\Core\User\UserInterface as UserInterfaceAlias;
  13. class Builder
  14. {
  15. /** @var FactoryInterface */
  16. private $factory;
  17. /** @var AuthorizationCheckerInterface */
  18. private $authorizationChecker;
  19. /**
  20. * @var Security
  21. */
  22. private $security;
  23. /**
  24. * @var PageService
  25. */
  26. private $pageService;
  27. /**
  28. * @var EntityManagerInterface
  29. */
  30. private $entityManager;
  31. /**
  32. * @var BrandRepository
  33. */
  34. private $brandRepository;
  35. public function __construct(
  36. FactoryInterface $factory,
  37. AuthorizationCheckerInterface $authorizationChecker,
  38. Security $security,
  39. EntityManagerInterface $entityManager,
  40. PageService $pageService,
  41. BrandRepository $brandRepository,
  42. ) {
  43. $this->factory = $factory;
  44. $this->authorizationChecker = $authorizationChecker;
  45. $this->security = $security;
  46. $this->pageService = $pageService;
  47. $this->entityManager = $entityManager;
  48. $this->brandRepository = $brandRepository;
  49. }
  50. public function mainMenu(array $options)
  51. {
  52. $menu = $this->factory->createItem('root', [
  53. 'childrenAttributes' => [
  54. 'class' => 'navbar-nav mb-2 mb-lg-0 ',
  55. ],
  56. ],
  57. );
  58. $menu->addChild('Home', ['route' => 'homepage'])
  59. ->setLinkAttribute('class', 'nav-link ')
  60. ;
  61. if (!$this->can('ROLE_USER')) {
  62. // Check if About Us page exists and is active before adding to menu
  63. $aboutUsPage = $this->pageService->getAboutUsPage();
  64. if ($aboutUsPage && $aboutUsPage->getActive()) {
  65. $menu->addChild('About Us', ['route' => 'aboutUs'])
  66. ->setLinkAttribute('class', 'nav-link ')
  67. ;
  68. }
  69. // Check if News & Events page exists and is active before adding to menu
  70. $newsAndEventsPage = $this->pageService->getNewsAndEventsPage();
  71. if ($newsAndEventsPage && $newsAndEventsPage->getActive()) {
  72. $menu->addChild('News & Events', ['route' => 'newsAndEvents'])
  73. ->setLinkAttribute('class', 'nav-link ')
  74. ;
  75. }
  76. $menu->addChild('Brands', ['route' => 'brands'])
  77. ->setLinkAttribute('class', 'nav-link ')
  78. ;
  79. $menu->addChild('Retailers', ['route' => 'retailers'])
  80. ->setLinkAttribute('class', 'nav-link ')
  81. ;
  82. }
  83. if ($this->can('ROLE_USER')) {
  84. $menu->addChild('Education', ['uri' => '#'])
  85. ->setAttributes([
  86. 'class' => 'nav-item dropdown',
  87. ])
  88. // ->setLinkAttribute('class', 'nav-link ')
  89. ->setLinkAttributes([
  90. 'class' => 'nav-link dropdown-toggle',
  91. 'data-toggle' => 'dropdown',
  92. 'role' => 'button',
  93. 'data-bs-toggle' => 'dropdown',
  94. 'href' => '#',
  95. 'aria-haspopup' => 'true',
  96. 'aria-expanded' => 'false',
  97. ])
  98. ->setChildrenAttributes([
  99. 'class' => 'dropdown-menu',
  100. ])
  101. ;
  102. // Check if user has multiple brands
  103. $userBrands = [];
  104. if ($this->user() instanceof User) {
  105. // Get user brands directly from the database
  106. $conn = $this->entityManager->getConnection();
  107. $sql = '
  108. SELECT DISTINCT b.*
  109. FROM brand b
  110. JOIN user_retailer ur ON ur.brand_id = b.id
  111. WHERE ur.user_id = :userId
  112. AND ur.manage_status = :status
  113. AND b.active = 1
  114. ';
  115. $stmt = $conn->prepare($sql);
  116. $result = $stmt->executeQuery([
  117. 'userId' => $this->user()->getId(),
  118. 'status' => UserRetailer::MANAGE_STATUS_APPROVED,
  119. ]);
  120. $userBrands = $result->fetchAllAssociative();
  121. }
  122. if (count($userBrands) > 1) {
  123. $menu->addChild('Offers', ['uri' => '#'])
  124. ->setAttributes([
  125. 'class' => 'nav-item dropdown',
  126. ])
  127. // ->setLinkAttribute('class', 'nav-link ')
  128. ->setLinkAttributes([
  129. 'class' => 'nav-link dropdown-toggle',
  130. 'data-toggle' => 'dropdown',
  131. 'role' => 'button',
  132. 'data-bs-toggle' => 'dropdown',
  133. 'href' => '#',
  134. 'aria-haspopup' => 'true',
  135. 'aria-expanded' => 'false',
  136. ])
  137. ->setChildrenAttributes([
  138. 'class' => 'dropdown-menu',
  139. ])
  140. ;
  141. foreach ($userBrands as $brandData) {
  142. // Create a Brand object from the array data
  143. $brandId = $brandData['id'];
  144. $brandName = $brandData['name'];
  145. $isActive = (bool) $brandData['active'];
  146. if ($isActive) {
  147. $menu['Education']->addChild($brandName, [
  148. 'route' => 'education.list',
  149. 'routeParameters' => ['brand' => $brandId],
  150. ])->setLinkAttribute('class', 'dropdown-item ');
  151. $menu['Offers']->addChild($brandName, [
  152. 'route' => 'offers.list',
  153. 'routeParameters' => ['brand' => $brandId],
  154. ])->setLinkAttribute('class', 'dropdown-item ');
  155. }
  156. }
  157. } else {
  158. if (count($userBrands)) {
  159. $brandData = array_values($userBrands)[0];
  160. $brandId = $brandData['id'];
  161. $brandName = $brandData['name'];
  162. $menu['Education']->addChild($brandName, [
  163. 'route' => 'education.list',
  164. 'routeParameters' => ['brand' => $brandId],
  165. ])->setLinkAttribute('class', 'dropdown-item ');
  166. $menu->addChild('Offers', [
  167. 'route' => 'offers.list',
  168. 'routeParameters' => ['brand' => $brandId],
  169. ])
  170. ->setLinkAttribute('class', 'nav-link ')
  171. ;
  172. }
  173. }
  174. $menu->addChild('FAQ', ['route' => 'faq'])->setLinkAttribute('class', 'nav-link ');
  175. $menu->addChild('My Rewards', ['uri' => '#'])
  176. ->setAttributes(['class' => 'nav-item dropdown'])
  177. ->setLinkAttributes([
  178. 'class' => 'nav-link dropdown-toggle',
  179. 'data-toggle' => 'dropdown',
  180. 'role' => 'button',
  181. 'data-bs-toggle' => 'dropdown',
  182. 'href' => '#',
  183. 'aria-haspopup' => 'true',
  184. 'aria-expanded' => 'false',
  185. ])
  186. ->setChildrenAttributes(['class' => 'dropdown-menu'])
  187. ;
  188. $menu['My Rewards']->addChild('My Rewards', ['route' => 'submission.list'])
  189. ->setLinkAttribute('class', 'dropdown-item ')
  190. ;
  191. // Only show Surreal Leaderboard link if user has a retailer with Surreal Diamond brand
  192. if ($this->userHasSurrealRetailer()) {
  193. $menu['My Rewards']->addChild('SURREAL LEADERBOARD', ['route' => 'leaderboard.index'])
  194. ->setLinkAttribute('class', 'dropdown-item ')
  195. ;
  196. }
  197. $menu->addChild('My Card', ['route' => 'card'])
  198. ->setLinkAttribute('class', 'nav-link ')
  199. ;
  200. $menu->addChild('My Account', ['route' => 'profile.index'])
  201. ->setLinkAttribute('class', 'nav-link ')
  202. ;
  203. if ($this->can('ROLE_PREVIOUS_ADMIN')) {
  204. $menu->addChild('Exit', [
  205. 'route' => 'sonata_admin_dashboard',
  206. 'routeParameters' => ['_impersonating_user' => '_exit']])
  207. ->setLinkAttribute('class', 'nav-link ');
  208. } else {
  209. $menu->addChild('Signout', ['route' => 'logout'])
  210. ->setLinkAttribute('class', 'nav-link btn btn-outline-warning btn-sm mb-sm-3 mb-md-0')
  211. ;
  212. }
  213. } else {
  214. $menu->addChild('Sign In', ['route' => 'login'])->setLinkAttribute('class', 'nav-link ');
  215. $menu->addChild('Register', ['route' => 'registration'])
  216. ->setLinkAttribute('class', 'nav-link btn btn-outline-primary btn-sm mb-sm-3 mb-md-0 ')
  217. ;
  218. }
  219. if ($this->can('ROLE_ADMIN_PAGE')) {
  220. $menu->addChild('Admin', ['route' => 'sonata_admin_dashboard'])
  221. ->setLinkAttribute('class', 'nav-link btn btn-danger btn-sm text-white')
  222. ;
  223. }
  224. return $menu;
  225. }
  226. /**
  227. * laconic function alias for checking granted.
  228. *
  229. * @return bool
  230. */
  231. protected function can($role)
  232. {
  233. return $this->authorizationChecker->isGranted($role);
  234. }
  235. protected function user(): ?UserInterfaceAlias
  236. {
  237. return $this->security->getUser();
  238. }
  239. /**
  240. * Check if the current user has a retailer with Surreal Diamond brand.
  241. */
  242. protected function userHasSurrealRetailer(): bool
  243. {
  244. $user = $this->security->getUser();
  245. if (!$user instanceof User) {
  246. return false;
  247. }
  248. // Get the Surreal Diamond brand
  249. $surrealBrand = $this->brandRepository->findOneBy(['name' => 'Surreal Diamond']);
  250. if (!$surrealBrand) {
  251. return false;
  252. }
  253. $conn = $this->entityManager->getConnection();
  254. $sql = '
  255. SELECT COUNT(ur.id) as retailer_count
  256. FROM user_retailer ur
  257. JOIN retailer r ON ur.retailer_id = r.id
  258. WHERE ur.user_id = :userId AND r.brand_id = :brandId
  259. ';
  260. $stmt = $conn->prepare($sql);
  261. $result = $stmt->executeQuery([
  262. 'userId' => $user->getId(),
  263. 'brandId' => $surrealBrand->getId(),
  264. ]);
  265. $data = $result->fetchAssociative();
  266. return (int) ($data['retailer_count'] ?? 0) > 0;
  267. }
  268. }