![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/mautic.corals.io/app/bundles/CoreBundle/Menu/ |
<?php namespace Mautic\CoreBundle\Menu; use Mautic\CoreBundle\Helper\CoreParametersHelper; use Mautic\CoreBundle\Security\Permissions\CorePermissions; use Mautic\PluginBundle\Helper\IntegrationHelper; use Symfony\Component\HttpFoundation\RequestStack; class MenuHelper { /** * Stores items that are assigned to another parent outside it's bundle. */ private array $orphans = []; public function __construct( protected CorePermissions $security, protected RequestStack $requestStack, private CoreParametersHelper $coreParametersHelper, protected IntegrationHelper $integrationHelper ) { } /** * Converts menu config into something KNP menus expects. * * @param int $depth * @param int $defaultPriority * @param string $type */ public function createMenuStructure(&$items, $depth = 0, $defaultPriority = 9999, $type = 'main'): void { foreach ($items as $k => &$i) { if (!is_array($i) || empty($i)) { continue; } // Remove the item if the checks fail if (false === $this->handleChecks($i)) { unset($items[$k]); continue; } // Set ID to route name if (!isset($i['id'])) { if (!empty($i['route'])) { $i['id'] = $i['route']; } else { $i['id'] = 'menu-item-'.uniqid(); } } // Set link attributes if (!isset($i['linkAttributes'])) { $i['linkAttributes'] = [ 'data-menu-link' => $i['id'], 'id' => $i['id'], ]; } elseif (!isset($i['linkAttributes']['id'])) { $i['linkAttributes']['id'] = $i['id']; $i['linkAttributes']['data-menu-link'] = $i['id']; } elseif (!isset($i['linkAttributes']['data-menu-link'])) { $i['linkAttributes']['data-menu-link'] = $i['id']; } $i['extras'] = []; $i['extras']['depth'] = $depth; // Note a divider if (!empty($i['divider'])) { $i['extras']['divider'] = true; } // Note a header if (!empty($i['header'])) { $i['extras']['header'] = $i['header']; } // Set the icon class for the menu item if (!empty($i['iconClass'])) { $i['extras']['iconClass'] = $i['iconClass']; } // Set the actual route name so that it's available to the menu template if (isset($i['route'])) { $i['extras']['routeName'] = $i['route']; } // Repeat for sub items if (isset($i['children'])) { $this->createMenuStructure($i['children'], $depth + 1, $defaultPriority); } // Determine if this item needs to be listed in a bundle outside it's own if (isset($i['parent'])) { if (!isset($this->orphans[$type])) { $this->orphans[$type] = []; } if (!isset($this->orphans[$type][$i['parent']])) { $this->orphans[$type][$i['parent']] = []; } $this->orphans[$type][$i['parent']][$k] = $i; unset($items[$k]); // Don't set a default priority here as it'll assume that of it's parent } elseif (!isset($i['priority'])) { // Ensure a priority for non-orphans $i['priority'] = $defaultPriority; } } } /** * Get and reset orphaned menu items. * * @param string $type * * @return mixed */ public function resetOrphans($type = 'main') { $orphans = $this->orphans[$type] ?? []; $this->orphans[$type] = []; return $orphans; } /** * Give orphaned menu items a home. * * @param bool $appendOrphans * @param int $depth */ public function placeOrphans(array &$menuItems, $appendOrphans = false, $depth = 1, $type = 'main'): void { foreach ($menuItems as $key => &$items) { if (isset($this->orphans[$type]) && isset($this->orphans[$type][$key])) { $priority = $items['priority'] ?? 9999; foreach ($this->orphans[$type][$key] as &$orphan) { if (!isset($orphan['extras'])) { $orphan['extras'] = []; } $orphan['extras']['depth'] = $depth; if (!isset($orphan['priority'])) { $orphan['priority'] = $priority; } } $items['children'] = (!isset($items['children'])) ? $this->orphans[$type][$key] : array_merge($items['children'], $this->orphans[$type][$key]); unset($this->orphans[$type][$key]); } elseif (isset($items['children'])) { foreach ($items['children'] as $subItems) { $this->placeOrphans($subItems, false, $depth + 1, $type); } } } // Append orphans that couldn't find a home if ($appendOrphans && !empty($this->orphans[$type])) { $menuItems = array_merge($menuItems, $this->orphans[$type]); $this->orphans[$type] = []; } } /** * Sort menu items by priority. */ public function sortByPriority(&$menuItems, $defaultPriority = 9999): void { foreach ($menuItems as &$items) { $parentPriority = $items['priority'] ?? $defaultPriority; if (isset($items['children'])) { $this->sortByPriority($items['children'], $parentPriority); } } uasort( $menuItems, function ($a, $b) use ($defaultPriority): int { $ap = (isset($a['priority']) ? (int) $a['priority'] : $defaultPriority); $bp = (isset($b['priority']) ? (int) $b['priority'] : $defaultPriority); return $bp <=> $ap; } ); } /** * @return mixed */ protected function getParameter($name) { return $this->coreParametersHelper->get($name, false); } /** * @param string $integrationName */ protected function handleIntegrationChecks($integrationName, array $config): bool { $integration = $this->integrationHelper->getIntegrationObject($integrationName); if (!$integration) { return false; } $settings = $integration->getIntegrationSettings(); $passChecks = true; foreach ($config as $key => $value) { switch ($key) { case 'enabled': $passChecks = $settings->getIsPublished() == $value; break; case 'features': $supportedFeatures = $settings->getSupportedFeatures(); foreach ($value as $featureName) { if (!in_array($featureName, $supportedFeatures)) { $passChecks = false; break; } } break; } } return $passChecks; } /** * @param string $name * @param mixed $value */ protected function handleParametersChecks($name, $value): bool { return $this->getParameter($name) == $value; } /** * @param string $name * @param mixed $value */ protected function handleRequestChecks($name, $value): bool { return $this->requestStack->getCurrentRequest()->get($name) == $value; } /** * @return bool */ protected function handleAccessCheck($accessLevel) { return match ($accessLevel) { 'admin' => $this->security->isAdmin(), default => $this->security->isGranted($accessLevel, 'MATCH_ONE'), }; } /** * Handle access check and other checks for menu items. * * @return bool Returns false if the item fails the access check or any other checks */ protected function handleChecks(array $menuItem): bool { if (isset($menuItem['access']) && false === $this->handleAccessCheck($menuItem['access'])) { return false; } if (isset($menuItem['checks']) && is_array($menuItem['checks'])) { foreach ($menuItem['checks'] as $checkGroup => $checkConfig) { $checkMethod = 'handle'.ucfirst($checkGroup).'Checks'; if (!method_exists($this, $checkMethod)) { continue; } foreach ($checkConfig as $name => $value) { if (false === $this->$checkMethod($name, $value)) { return false; } } } } return true; } }