This commit is contained in:
Xes
2025-08-14 22:41:49 +02:00
parent 2de81ccc46
commit 8ce45119b6
39774 changed files with 4309466 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\AdminBundle\Menu\Matcher\Voter;
use Knp\Menu\ItemInterface;
use Knp\Menu\Matcher\Voter\VoterInterface;
/**
* Active menu voter bases in extra `active`.
*
* @author Samusev Andrey <andrey.simfi@ya.ru>
*/
class ActiveVoter implements VoterInterface
{
/**
* {@inheritdoc}
*/
public function matchItem(ItemInterface $item)
{
if (!$item->getExtra('sonata_admin', false)) {
return;
}
return $item->getExtra('active', null);
}
}

View File

@@ -0,0 +1,74 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\AdminBundle\Menu\Matcher\Voter;
use Knp\Menu\ItemInterface;
use Knp\Menu\Matcher\Voter\VoterInterface;
use Sonata\AdminBundle\Admin\AdminInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Admin menu voter based on extra `admin`.
*
* @author Samusev Andrey <andrey.simfi@ya.ru>
*/
class AdminVoter implements VoterInterface
{
/**
* @var Request
*/
private $request = null;
/**
* @param Request $request
*
* @return $this
*/
public function setRequest($request)
{
$this->request = $request;
return $this;
}
/**
* {@inheritdoc}
*/
public function matchItem(ItemInterface $item)
{
$admin = $item->getExtra('admin');
if ($admin instanceof AdminInterface
&& $admin->hasRoute('list') && $admin->hasAccess('list')
&& $this->request
) {
$requestCode = $this->request->get('_sonata_admin');
if ($admin->getCode() === $requestCode) {
return true;
}
foreach ($admin->getChildren() as $child) {
if ($child->getBaseCodeRoute() === $requestCode) {
return true;
}
}
}
$route = $item->getExtra('route');
if ($route && $this->request && $route == $this->request->get('_route')) {
return true;
}
return null;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\AdminBundle\Menu\Matcher\Voter;
use Knp\Menu\ItemInterface;
use Knp\Menu\Matcher\MatcherInterface;
use Knp\Menu\Matcher\Voter\VoterInterface;
/**
* Children menu voter based on children items.
*
* @author Samusev Andrey <andrey.simfi@ya.ru>
*/
class ChildrenVoter implements VoterInterface
{
/**
* @var MatcherInterface
*/
private $matcher;
/**
* ChildrenVoter constructor.
*
* @param MatcherInterface $matcher
*/
public function __construct(MatcherInterface $matcher)
{
$this->matcher = $matcher;
}
/**
* {@inheritdoc}
*/
public function matchItem(ItemInterface $item)
{
if (!$item->getExtra('sonata_admin', false)) {
return;
}
$children = $item->getChildren();
$match = null;
foreach ($children as $child) {
if ($this->matcher->isCurrent($child)) {
$match = true;
break;
}
}
return $match;
}
}

View File

@@ -0,0 +1,98 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\AdminBundle\Menu;
use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;
use Knp\Menu\Provider\MenuProviderInterface;
use Sonata\AdminBundle\Admin\Pool;
use Sonata\AdminBundle\Event\ConfigureMenuEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* Sonata menu builder.
*
* @author Martin Hasoň <martin.hason@gmail.com>
* @author Alexandru Furculita <alex@furculita.net>
*/
class MenuBuilder
{
/**
* @var Pool
*/
private $pool;
/**
* @var FactoryInterface
*/
private $factory;
/**
* @var MenuProviderInterface
*/
private $provider;
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
/**
* @param Pool $pool
* @param FactoryInterface $factory
* @param MenuProviderInterface $provider
* @param EventDispatcherInterface $eventDispatcher
*/
public function __construct(Pool $pool, FactoryInterface $factory, MenuProviderInterface $provider, EventDispatcherInterface $eventDispatcher)
{
$this->pool = $pool;
$this->factory = $factory;
$this->provider = $provider;
$this->eventDispatcher = $eventDispatcher;
}
/**
* Builds sidebar menu.
*
* @return ItemInterface
*/
public function createSidebarMenu()
{
$menu = $this->factory->createItem('root');
foreach ($this->pool->getAdminGroups() as $name => $group) {
$extras = [
'icon' => $group['icon'],
'label_catalogue' => $group['label_catalogue'],
'roles' => $group['roles'],
'sonata_admin' => true,
];
$menuProvider = isset($group['provider']) ? $group['provider'] : 'sonata_group_menu';
$subMenu = $this->provider->get(
$menuProvider,
[
'name' => $name,
'group' => $group,
]
);
$subMenu = $menu->addChild($subMenu);
$subMenu->setExtras(array_merge($subMenu->getExtras(), $extras));
}
$event = new ConfigureMenuEvent($this->factory, $menu);
$this->eventDispatcher->dispatch(ConfigureMenuEvent::SIDEBAR, $event);
return $event->getMenu();
}
}

View File

@@ -0,0 +1,183 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\AdminBundle\Menu\Provider;
use Knp\Menu\FactoryInterface;
use Knp\Menu\Provider\MenuProviderInterface;
use Sonata\AdminBundle\Admin\Pool;
/**
* Menu provider based on group options.
*
* @author Alexandru Furculita <alex@furculita.net>
*/
class GroupMenuProvider implements MenuProviderInterface
{
/**
* @var FactoryInterface
*/
private $menuFactory;
/**
* @var Pool
*/
private $pool;
/**
* NEXT_MAJOR: Use AuthorizationCheckerInterface when bumping requirements to >=Symfony 2.6.
*
* @var \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface|\Symfony\Component\Security\Core\SecurityContextInterface
*/
private $checker;
/**
* NEXT_MAJOR: Remove default value null of $checker.
* NEXT_MAJOR: Allow only injection of AuthorizationCheckerInterface when bumping requirements to >=Symfony 2.6.
*
* @param FactoryInterface $menuFactory
* @param Pool $pool
* @param \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface|
* \Symfony\Component\Security\Core\SecurityContextInterface|null $checker
*/
public function __construct(FactoryInterface $menuFactory, Pool $pool, $checker = null)
{
$this->menuFactory = $menuFactory;
$this->pool = $pool;
/*
* NEXT_MAJOR: Remove this if blocks.
* NEXT_MAJOR: Remove instance type checking when bumping requirements to >=Symfony 2.6.
*/
if (null === $checker) {
@trigger_error(
'Passing no 3rd argument is deprecated since version 3.10 and will be mandatory in 4.0.
Pass Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface as 3rd argument.',
E_USER_DEPRECATED
);
} elseif (!$checker instanceof \Symfony\Component\Security\Core\SecurityContextInterface
&& !$checker instanceof \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface
) {
throw new \InvalidArgumentException(
'Argument 3 must be an instance of either \Symfony\Component\Security\Core\SecurityContextInterface or
\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface'
);
}
$this->checker = $checker;
}
/**
* Retrieves the menu based on the group options.
*
* @param string $name
* @param array $options
*
* @return \Knp\Menu\ItemInterface
*
* @throws \InvalidArgumentException if the menu does not exists
*/
public function get($name, array $options = [])
{
$group = $options['group'];
$menuItem = $this->menuFactory->createItem(
$options['name'],
[
'label' => $group['label'],
]
);
if (empty($group['on_top'])) {
foreach ($group['items'] as $item) {
if (isset($item['admin']) && !empty($item['admin'])) {
$admin = $this->pool->getInstance($item['admin']);
// skip menu item if no `list` url is available or user doesn't have the LIST access rights
if (!$admin->hasRoute('list') || !$admin->hasAccess('list')) {
continue;
}
$label = $admin->getLabel();
$options = $admin->generateMenuUrl('list', [], $item['route_absolute']);
$options['extras'] = [
'label_catalogue' => $admin->getTranslationDomain(),
'admin' => $admin,
];
} else {
//NEXT_MAJOR: Remove if statement of null checker.
if (null !== $this->checker) {
if ((!empty($item['roles']) && !$this->checker->isGranted($item['roles']))
|| (!empty($group['roles']) && !$this->checker->isGranted($group['roles'], $item['route']))
) {
continue;
}
}
$label = $item['label'];
$options = [
'route' => $item['route'],
'routeParameters' => $item['route_params'],
'routeAbsolute' => $item['route_absolute'],
'extras' => [
'label_catalogue' => $group['label_catalogue'],
],
];
}
$menuItem->addChild($label, $options);
}
if (false === $menuItem->hasChildren()) {
$menuItem->setDisplay(false);
} elseif (!empty($group['keep_open'])) {
$menuItem->setAttribute('class', 'keep-open');
$menuItem->setExtra('keep_open', $group['keep_open']);
}
} else {
foreach ($group['items'] as $item) {
if (isset($item['admin']) && !empty($item['admin'])) {
$admin = $this->pool->getInstance($item['admin']);
// Do not display group if no `list` url is available or user doesn't have the LIST access rights
if (!$admin->hasRoute('list') || !$admin->hasAccess('list')) {
$menuItem->setDisplay(false);
continue;
}
$options = $admin->generateUrl('list');
$menuItem->setExtra('route', $admin->getBaseRouteName().'_list');
$menuItem->setExtra('on_top', $group['on_top']);
$menuItem->setUri($options);
} else {
$router = $this->pool->getContainer()->get('router');
$menuItem->setUri($router->generate($item['route']));
}
}
}
return $menuItem;
}
/**
* Checks whether a menu exists in this provider.
*
* @param string $name
* @param array $options
*
* @return bool
*/
public function has($name, array $options = [])
{
return 'sonata_group_menu' === $name;
}
}