vendor/sonata-project/user-bundle/src/DependencyInjection/SonataUserExtension.php line 47

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\UserBundle\DependencyInjection;
  12. use Sonata\EasyExtendsBundle\Mapper\DoctrineCollector;
  13. use Sonata\UserBundle\Document\BaseGroup as DocumentGroup;
  14. use Sonata\UserBundle\Document\BaseUser as DocumentUser;
  15. use Sonata\UserBundle\Entity\BaseGroup as EntityGroup;
  16. use Sonata\UserBundle\Entity\BaseUser as EntityUser;
  17. use Symfony\Component\Config\Definition\Processor;
  18. use Symfony\Component\Config\FileLocator;
  19. use Symfony\Component\DependencyInjection\ContainerBuilder;
  20. use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
  21. use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
  22. use Symfony\Component\HttpKernel\DependencyInjection\Extension;
  23. /**
  24.  * @author     Thomas Rabaix <thomas.rabaix@sonata-project.org>
  25.  */
  26. class SonataUserExtension extends Extension implements PrependExtensionInterface
  27. {
  28.     /**
  29.      * {@inheritdoc}
  30.      */
  31.     public function prepend(ContainerBuilder $container): void
  32.     {
  33.         if ($container->hasExtension('twig')) {
  34.             // add custom form widgets
  35.             $container->prependExtensionConfig('twig', ['form_themes' => ['@SonataUser/Form/form_admin_fields.html.twig']]);
  36.         }
  37.     }
  38.     /**
  39.      * {@inheritdoc}
  40.      */
  41.     public function load(array $configsContainerBuilder $container): void
  42.     {
  43.         $processor = new Processor();
  44.         $configuration = new Configuration();
  45.         $config $processor->processConfiguration($configuration$configs);
  46.         $config $this->fixImpersonating($config);
  47.         $bundles $container->getParameter('kernel.bundles');
  48.         $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
  49.         if (isset($bundles['SonataAdminBundle'])) {
  50.             $loader->load('admin.xml');
  51.             $loader->load(sprintf('admin_%s.xml'$config['manager_type']));
  52.         }
  53.         $loader->load(sprintf('%s.xml'$config['manager_type']));
  54.         $this->aliasManagers($container$config['manager_type']);
  55.         $loader->load('form.xml');
  56.         if (class_exists('Google\Authenticator\GoogleAuthenticator')) {
  57.             @trigger_error(
  58.                 'The \'Google\Authenticator\' namespace is deprecated in sonata-project/GoogleAuthenticator since version 2.1 and will be removed in 3.0.',
  59.                 E_USER_DEPRECATED
  60.             );
  61.         }
  62.         if (class_exists('Google\Authenticator\GoogleAuthenticator') ||
  63.             class_exists('Sonata\GoogleAuthenticator\GoogleAuthenticator')) {
  64.             $loader->load('google_authenticator.xml');
  65.         }
  66.         $loader->load('twig.xml');
  67.         $loader->load('command.xml');
  68.         $loader->load('actions.xml');
  69.         $loader->load('mailer.xml');
  70.         if ('orm' === $config['manager_type'] && isset(
  71.             $bundles['FOSRestBundle'],
  72.             $bundles['NelmioApiDocBundle'],
  73.             $bundles['JMSSerializerBundle']
  74.         )) {
  75.             $loader->load('serializer.xml');
  76.             $loader->load('api_form.xml');
  77.             $loader->load('api_controllers.xml');
  78.         }
  79.         if ($config['security_acl']) {
  80.             $loader->load('security_acl.xml');
  81.         }
  82.         $this->checkManagerTypeToModelTypesMapping($config);
  83.         $this->registerDoctrineMapping($config);
  84.         $this->configureAdminClass($config$container);
  85.         $this->configureClass($config$container);
  86.         $this->configureTranslationDomain($config$container);
  87.         $this->configureController($config$container);
  88.         $this->configureMailer($config$container);
  89.         $container->setParameter('sonata.user.default_avatar'$config['profile']['default_avatar']);
  90.         $container->setParameter('sonata.user.impersonating'$config['impersonating']);
  91.         $this->configureGoogleAuthenticator($config$container);
  92.     }
  93.     /**
  94.      * @throws \RuntimeException
  95.      *
  96.      * @return array
  97.      */
  98.     public function fixImpersonating(array $config)
  99.     {
  100.         if (isset($config['impersonating'], $config['impersonating_route'])) {
  101.             throw new \RuntimeException('you can\'t have `impersonating` and `impersonating_route` keys defined at the same time');
  102.         }
  103.         if (isset($config['impersonating_route'])) {
  104.             $config['impersonating'] = [
  105.                 'route' => $config['impersonating_route'],
  106.                 'parameters' => [],
  107.             ];
  108.         }
  109.         if (!isset($config['impersonating']['parameters'])) {
  110.             $config['impersonating']['parameters'] = [];
  111.         }
  112.         if (!isset($config['impersonating']['route'])) {
  113.             $config['impersonating'] = false;
  114.         }
  115.         return $config;
  116.     }
  117.     /**
  118.      * @param array $config
  119.      *
  120.      * @throws \RuntimeException
  121.      *
  122.      * @return mixed
  123.      */
  124.     public function configureGoogleAuthenticator($configContainerBuilder $container)
  125.     {
  126.         $container->setParameter('sonata.user.google.authenticator.enabled'$config['google_authenticator']['enabled']);
  127.         if (!$config['google_authenticator']['enabled']) {
  128.             $container->removeDefinition('sonata.user.google.authenticator');
  129.             $container->removeDefinition('sonata.user.google.authenticator.provider');
  130.             $container->removeDefinition('sonata.user.google.authenticator.interactive_login_listener');
  131.             $container->removeDefinition('sonata.user.google.authenticator.request_listener');
  132.             return;
  133.         }
  134.         if (!class_exists('Google\Authenticator\GoogleAuthenticator')
  135.             && !class_exists('Sonata\GoogleAuthenticator\GoogleAuthenticator')) {
  136.             throw new \RuntimeException('Please add ``sonata-project/google-authenticator`` package');
  137.         }
  138.         $container->setParameter('sonata.user.google.authenticator.forced_for_role'$config['google_authenticator']['forced_for_role']);
  139.         $container->setParameter('sonata.user.google.authenticator.ip_white_list'$config['google_authenticator']['ip_white_list']);
  140.         $container->getDefinition('sonata.user.google.authenticator.provider')
  141.             ->replaceArgument(0$config['google_authenticator']['server']);
  142.     }
  143.     /**
  144.      * @param array $config
  145.      */
  146.     public function configureClass($configContainerBuilder $container): void
  147.     {
  148.         if ('orm' === $config['manager_type']) {
  149.             $modelType 'entity';
  150.         } elseif ('mongodb' === $config['manager_type']) {
  151.             $modelType 'document';
  152.         } else {
  153.             throw new \InvalidArgumentException(sprintf('Invalid manager type "%s".'$config['manager_type']));
  154.         }
  155.         $container->setParameter(sprintf('sonata.user.admin.user.%s'$modelType), $config['class']['user']);
  156.         $container->setParameter(sprintf('sonata.user.admin.group.%s'$modelType), $config['class']['group']);
  157.     }
  158.     /**
  159.      * @param array $config
  160.      */
  161.     public function configureAdminClass($configContainerBuilder $container): void
  162.     {
  163.         $container->setParameter('sonata.user.admin.user.class'$config['admin']['user']['class']);
  164.         $container->setParameter('sonata.user.admin.group.class'$config['admin']['group']['class']);
  165.     }
  166.     /**
  167.      * @param array $config
  168.      */
  169.     public function configureTranslationDomain($configContainerBuilder $container): void
  170.     {
  171.         $container->setParameter('sonata.user.admin.user.translation_domain'$config['admin']['user']['translation']);
  172.         $container->setParameter('sonata.user.admin.group.translation_domain'$config['admin']['group']['translation']);
  173.     }
  174.     /**
  175.      * @param array $config
  176.      */
  177.     public function configureController($configContainerBuilder $container): void
  178.     {
  179.         $container->setParameter('sonata.user.admin.user.controller'$config['admin']['user']['controller']);
  180.         $container->setParameter('sonata.user.admin.group.controller'$config['admin']['group']['controller']);
  181.     }
  182.     public function registerDoctrineMapping(array $config): void
  183.     {
  184.         foreach ($config['class'] as $type => $class) {
  185.             if (!class_exists($class)) {
  186.                 return;
  187.             }
  188.         }
  189.         $collector DoctrineCollector::getInstance();
  190.         $collector->addAssociation($config['class']['user'], 'mapManyToMany', [
  191.             'fieldName' => 'groups',
  192.             'targetEntity' => $config['class']['group'],
  193.             'cascade' => [],
  194.             'joinTable' => [
  195.                 'name' => $config['table']['user_group'],
  196.                 'joinColumns' => [
  197.                     [
  198.                         'name' => 'user_id',
  199.                         'referencedColumnName' => 'id',
  200.                         'onDelete' => 'CASCADE',
  201.                     ],
  202.                 ],
  203.                 'inverseJoinColumns' => [[
  204.                     'name' => 'group_id',
  205.                     'referencedColumnName' => 'id',
  206.                     'onDelete' => 'CASCADE',
  207.                 ]],
  208.             ],
  209.         ]);
  210.     }
  211.     /**
  212.      * Adds aliases for user & group managers depending on $managerType.
  213.      *
  214.      * @param string $managerType
  215.      */
  216.     protected function aliasManagers(ContainerBuilder $container$managerType): void
  217.     {
  218.         $container->setAlias('sonata.user.user_manager'sprintf('sonata.user.%s.user_manager'$managerType));
  219.         $container->setAlias('sonata.user.group_manager'sprintf('sonata.user.%s.group_manager'$managerType));
  220.         // NEXT_MAJOR: call setPublic(true) directly, when dropping support for Sf 3.3
  221.         $container->getAlias('sonata.user.user_manager')->setPublic(true);
  222.         $container->getAlias('sonata.user.group_manager')->setPublic(true);
  223.     }
  224.     private function checkManagerTypeToModelTypesMapping(array $config): void
  225.     {
  226.         $managerType $config['manager_type'];
  227.         if (!\in_array($managerType, ['orm''mongodb'], true)) {
  228.             throw new \InvalidArgumentException(sprintf('Invalid manager type "%s".'$managerType));
  229.         }
  230.         $this->prohibitModelTypeMapping(
  231.             $config['class']['user'],
  232.             'orm' === $managerType DocumentUser::class : EntityUser::class,
  233.             $managerType
  234.         );
  235.         $this->prohibitModelTypeMapping(
  236.             $config['class']['group'],
  237.             'orm' === $managerType DocumentGroup::class : EntityGroup::class,
  238.             $managerType
  239.         );
  240.     }
  241.     /**
  242.      * Prohibit using wrong model type mapping.
  243.      */
  244.     private function prohibitModelTypeMapping(
  245.         string $actualModelClass,
  246.         string $prohibitedModelClass,
  247.         string $managerType
  248.     ): void {
  249.         if (is_a($actualModelClass$prohibitedModelClasstrue)) {
  250.             throw new \InvalidArgumentException(
  251.                 sprintf(
  252.                     'Model class "%s" does not correspond to manager type "%s".',
  253.                     $actualModelClass,
  254.                     $managerType
  255.                 )
  256.             );
  257.         }
  258.     }
  259.     private function configureMailer(array $configContainerBuilder $container): void
  260.     {
  261.         $container->setAlias('sonata.user.mailer'$config['mailer']);
  262.     }
  263. }