vendor/sonata-project/admin-bundle/src/Admin/Pool.php line 353

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of the Sonata Project package.
  5.  *
  6.  * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  7.  *
  8.  * For the full copyright and license information, please view the LICENSE
  9.  * file that was distributed with this source code.
  10.  */
  11. namespace Sonata\AdminBundle\Admin;
  12. use InvalidArgumentException;
  13. use Sonata\AdminBundle\Templating\MutableTemplateRegistryInterface;
  14. use Symfony\Component\DependencyInjection\ContainerInterface;
  15. use Symfony\Component\PropertyAccess\PropertyAccess;
  16. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  17. /**
  18.  * @final since sonata-project/admin-bundle 3.52
  19.  *
  20.  * @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
  21.  */
  22. class Pool
  23. {
  24.     /**
  25.      * @var ContainerInterface
  26.      */
  27.     protected $container;
  28.     /**
  29.      * @var string[]
  30.      */
  31.     protected $adminServiceIds = [];
  32.     /**
  33.      * @var array
  34.      */
  35.     protected $adminGroups = [];
  36.     /**
  37.      * @var array
  38.      */
  39.     protected $adminClasses = [];
  40.     /**
  41.      * @deprecated since sonata-project/admin-bundle 3.34, will be dropped in 4.0. Use TemplateRegistry "sonata.admin.global_template_registry" instead
  42.      *
  43.      * @var array
  44.      */
  45.     protected $templates = [];
  46.     /**
  47.      * @var array
  48.      */
  49.     protected $assets = [];
  50.     /**
  51.      * @var string
  52.      */
  53.     protected $title;
  54.     /**
  55.      * @var string
  56.      */
  57.     protected $titleLogo;
  58.     /**
  59.      * @var array
  60.      */
  61.     protected $options;
  62.     /**
  63.      * @var PropertyAccessorInterface
  64.      */
  65.     protected $propertyAccessor;
  66.     /**
  67.      * @var MutableTemplateRegistryInterface
  68.      */
  69.     private $templateRegistry;
  70.     /**
  71.      * @param string $title
  72.      * @param string $logoTitle
  73.      * @param array  $options
  74.      */
  75.     public function __construct(
  76.         ContainerInterface $container,
  77.         $title,
  78.         $logoTitle,
  79.         $options = [],
  80.         ?PropertyAccessorInterface $propertyAccessor null
  81.     ) {
  82.         $this->container $container;
  83.         $this->title $title;
  84.         $this->titleLogo $logoTitle;
  85.         $this->options $options;
  86.         $this->propertyAccessor $propertyAccessor;
  87.     }
  88.     /**
  89.      * @return array
  90.      */
  91.     public function getGroups()
  92.     {
  93.         $groups $this->adminGroups;
  94.         foreach ($this->adminGroups as $name => $adminGroup) {
  95.             foreach ($adminGroup as $id => $options) {
  96.                 $groups[$name][$id] = $this->getInstance($id);
  97.             }
  98.         }
  99.         return $groups;
  100.     }
  101.     /**
  102.      * Returns whether an admin group exists or not.
  103.      *
  104.      * @param string $group
  105.      *
  106.      * @return bool
  107.      */
  108.     public function hasGroup($group)
  109.     {
  110.         return isset($this->adminGroups[$group]);
  111.     }
  112.     /**
  113.      * @return array
  114.      */
  115.     public function getDashboardGroups()
  116.     {
  117.         $groups $this->adminGroups;
  118.         foreach ($this->adminGroups as $name => $adminGroup) {
  119.             if (isset($adminGroup['items'])) {
  120.                 foreach ($adminGroup['items'] as $key => $item) {
  121.                     // Only Admin Group should be returned
  122.                     if ('' !== $item['admin']) {
  123.                         $admin $this->getInstance($item['admin']);
  124.                         if ($admin->showIn(AbstractAdmin::CONTEXT_DASHBOARD)) {
  125.                             $groups[$name]['items'][$key] = $admin;
  126.                         } else {
  127.                             unset($groups[$name]['items'][$key]);
  128.                         }
  129.                     } else {
  130.                         unset($groups[$name]['items'][$key]);
  131.                     }
  132.                 }
  133.             }
  134.             if (empty($groups[$name]['items'])) {
  135.                 unset($groups[$name]);
  136.             }
  137.         }
  138.         return $groups;
  139.     }
  140.     /**
  141.      * Returns all admins related to the given $group.
  142.      *
  143.      * @param string $group
  144.      *
  145.      * @throws \InvalidArgumentException
  146.      *
  147.      * @return AdminInterface[]
  148.      */
  149.     public function getAdminsByGroup($group)
  150.     {
  151.         if (!isset($this->adminGroups[$group])) {
  152.             throw new \InvalidArgumentException(sprintf('Group "%s" not found in admin pool.'$group));
  153.         }
  154.         $admins = [];
  155.         if (!isset($this->adminGroups[$group]['items'])) {
  156.             return $admins;
  157.         }
  158.         foreach ($this->adminGroups[$group]['items'] as $item) {
  159.             $admins[] = $this->getInstance($item['admin']);
  160.         }
  161.         return $admins;
  162.     }
  163.     /**
  164.      * Return the admin related to the given $class.
  165.      *
  166.      * @param string $class
  167.      *
  168.      * @return \Sonata\AdminBundle\Admin\AdminInterface|null
  169.      */
  170.     public function getAdminByClass($class)
  171.     {
  172.         if (!$this->hasAdminByClass($class)) {
  173.             return null;
  174.         }
  175.         if (!\is_array($this->adminClasses[$class])) {
  176.             throw new \RuntimeException('Invalid format for the Pool::adminClass property');
  177.         }
  178.         if (\count($this->adminClasses[$class]) > 1) {
  179.             throw new \RuntimeException(sprintf(
  180.                 'Unable to find a valid admin for the class: %s, there are too many registered: %s',
  181.                 $class,
  182.                 implode(', '$this->adminClasses[$class])
  183.             ));
  184.         }
  185.         return $this->getInstance($this->adminClasses[$class][0]);
  186.     }
  187.     /**
  188.      * @param string $class
  189.      *
  190.      * @return bool
  191.      */
  192.     public function hasAdminByClass($class)
  193.     {
  194.         return isset($this->adminClasses[$class]);
  195.     }
  196.     /**
  197.      * Returns an admin class by its Admin code
  198.      * ie : sonata.news.admin.post|sonata.news.admin.comment => return the child class of post.
  199.      *
  200.      * @param string $adminCode
  201.      *
  202.      * @throws \InvalidArgumentException if the root admin code is an empty string
  203.      *
  204.      * @return AdminInterface|false
  205.      */
  206.     public function getAdminByAdminCode($adminCode)
  207.     {
  208.         if (!\is_string($adminCode)) {
  209.             @trigger_error(sprintf(
  210.                 'Passing a non string value as argument 1 for %s() is deprecated since sonata-project/admin-bundle 3.51 and will cause a \TypeError in 4.0.',
  211.                 __METHOD__
  212.             ), E_USER_DEPRECATED);
  213.             return false;
  214.             // NEXT_MAJOR : remove this condition check and declare "string" as type without default value for argument 1
  215.         }
  216.         $codes explode('|'$adminCode);
  217.         $code trim(array_shift($codes));
  218.         if ('' === $code) {
  219.             throw new \InvalidArgumentException('Root admin code must contain a valid admin reference, empty string given.');
  220.         }
  221.         $admin $this->getInstance($code);
  222.         foreach ($codes as $code) {
  223.             if (!\in_array($code$this->adminServiceIdstrue)) {
  224.                 @trigger_error(sprintf(
  225.                     'Passing an invalid admin code as argument 1 for %s() is deprecated since sonata-project/admin-bundle 3.50 and will throw an exception in 4.0.',
  226.                     __METHOD__
  227.                 ), E_USER_DEPRECATED);
  228.                 // NEXT_MAJOR : throw `\InvalidArgumentException` instead
  229.             }
  230.             if (!$admin->hasChild($code)) {
  231.                 @trigger_error(sprintf(
  232.                     'Passing an invalid admin hierarchy inside argument 1 for %s() is deprecated since sonata-project/admin-bundle 3.51 and will throw an exception in 4.0.',
  233.                     __METHOD__
  234.                 ), E_USER_DEPRECATED);
  235.                 // NEXT_MAJOR : remove the previous `trigger_error()` call, uncomment the following exception and declare AdminInterface as return type
  236.                 // throw new \InvalidArgumentException(sprintf(
  237.                 //    'Argument 1 passed to %s() must contain a valid admin hierarchy, "%s" is not a valid child for "%s"',
  238.                 //    __METHOD__,
  239.                 //    $code,
  240.                 //    $admin->getCode()
  241.                 // ));
  242.                 return false;
  243.             }
  244.             $admin $admin->getChild($code);
  245.         }
  246.         return $admin;
  247.     }
  248.     /**
  249.      * Checks if an admin with a certain admin code exists.
  250.      */
  251.     final public function hasAdminByAdminCode(string $adminCode): bool
  252.     {
  253.         try {
  254.             if (!$this->getAdminByAdminCode($adminCode) instanceof AdminInterface) {
  255.                 // NEXT_MAJOR : remove `if (...instanceof...) { return false; }` as getAdminByAdminCode() will then always throw an \InvalidArgumentException when somethings wrong
  256.                 return false;
  257.             }
  258.         } catch (\InvalidArgumentException $e) {
  259.             return false;
  260.         }
  261.         return true;
  262.     }
  263.     /**
  264.      * Returns a new admin instance depends on the given code.
  265.      *
  266.      * @param string $id
  267.      *
  268.      * @throws \InvalidArgumentException
  269.      *
  270.      * @return AdminInterface
  271.      */
  272.     public function getInstance($id)
  273.     {
  274.         if (!\in_array($id$this->adminServiceIdstrue)) {
  275.             $msg sprintf('Admin service "%s" not found in admin pool.'$id);
  276.             $shortest = -1;
  277.             $closest null;
  278.             $alternatives = [];
  279.             foreach ($this->adminServiceIds as $adminServiceId) {
  280.                 $lev levenshtein($id$adminServiceId);
  281.                 if ($lev <= $shortest || $shortest 0) {
  282.                     $closest $adminServiceId;
  283.                     $shortest $lev;
  284.                 }
  285.                 if ($lev <= \strlen($adminServiceId) / || false !== strpos($adminServiceId$id)) {
  286.                     $alternatives[$adminServiceId] = $lev;
  287.                 }
  288.             }
  289.             if (null !== $closest) {
  290.                 asort($alternatives);
  291.                 unset($alternatives[$closest]);
  292.                 $msg sprintf(
  293.                     'Admin service "%s" not found in admin pool. Did you mean "%s" or one of those: [%s]?',
  294.                     $id,
  295.                     $closest,
  296.                     implode(', 'array_keys($alternatives))
  297.                 );
  298.             }
  299.             throw new \InvalidArgumentException($msg);
  300.         }
  301.         $admin $this->container->get($id);
  302.         if (!$admin instanceof AdminInterface) {
  303.             throw new InvalidArgumentException(sprintf('Found service "%s" is not a valid admin service'$id));
  304.         }
  305.         return $admin;
  306.     }
  307.     /**
  308.      * @return ContainerInterface|null
  309.      */
  310.     public function getContainer()
  311.     {
  312.         return $this->container;
  313.     }
  314.     public function setAdminGroups(array $adminGroups)
  315.     {
  316.         $this->adminGroups $adminGroups;
  317.     }
  318.     /**
  319.      * @return array
  320.      */
  321.     public function getAdminGroups()
  322.     {
  323.         return $this->adminGroups;
  324.     }
  325.     public function setAdminServiceIds(array $adminServiceIds)
  326.     {
  327.         $this->adminServiceIds $adminServiceIds;
  328.     }
  329.     /**
  330.      * @return array
  331.      */
  332.     public function getAdminServiceIds()
  333.     {
  334.         return $this->adminServiceIds;
  335.     }
  336.     public function setAdminClasses(array $adminClasses)
  337.     {
  338.         $this->adminClasses $adminClasses;
  339.     }
  340.     /**
  341.      * @return array
  342.      */
  343.     public function getAdminClasses()
  344.     {
  345.         return $this->adminClasses;
  346.     }
  347.     final public function setTemplateRegistry(MutableTemplateRegistryInterface $templateRegistry)
  348.     {
  349.         $this->templateRegistry $templateRegistry;
  350.     }
  351.     /**
  352.      * @deprecated since sonata-project/admin-bundle 3.34, will be dropped in 4.0. Use TemplateRegistry "sonata.admin.global_template_registry" instead
  353.      */
  354.     public function setTemplates(array $templates)
  355.     {
  356.         // NEXT MAJOR: Remove this line
  357.         $this->templates $templates;
  358.         $this->templateRegistry->setTemplates($templates);
  359.     }
  360.     /**
  361.      * @deprecated since sonata-project/admin-bundle 3.34, will be dropped in 4.0. Use TemplateRegistry "sonata.admin.global_template_registry" instead
  362.      *
  363.      * @return array
  364.      */
  365.     public function getTemplates()
  366.     {
  367.         return $this->templateRegistry->getTemplates();
  368.     }
  369.     /**
  370.      * @deprecated since sonata-project/admin-bundle 3.34, will be dropped in 4.0. Use TemplateRegistry "sonata.admin.global_template_registry" instead
  371.      *
  372.      * @param string $name
  373.      *
  374.      * @return string|null
  375.      */
  376.     public function getTemplate($name)
  377.     {
  378.         return $this->templateRegistry->getTemplate($name);
  379.     }
  380.     /**
  381.      * @return string
  382.      */
  383.     public function getTitleLogo()
  384.     {
  385.         return $this->titleLogo;
  386.     }
  387.     /**
  388.      * @return string
  389.      */
  390.     public function getTitle()
  391.     {
  392.         return $this->title;
  393.     }
  394.     /**
  395.      * @param string $name
  396.      * @param mixed  $default
  397.      *
  398.      * @return mixed
  399.      */
  400.     public function getOption($name$default null)
  401.     {
  402.         if (isset($this->options[$name])) {
  403.             return $this->options[$name];
  404.         }
  405.         return $default;
  406.     }
  407.     public function getPropertyAccessor()
  408.     {
  409.         if (null === $this->propertyAccessor) {
  410.             $this->propertyAccessor PropertyAccess::createPropertyAccessor();
  411.         }
  412.         return $this->propertyAccessor;
  413.     }
  414. }