1 <?php 
declare(strict_types
=1); 
   4  * This file is part of the Rapsys UserBundle package. 
   6  * (c) Raphaël Gertz <symfony@rapsys.eu> 
   8  * For the full copyright and license information, please view the LICENSE 
   9  * file that was distributed with this source code. 
  12 namespace Rapsys\UserBundle\Controller
; 
  14 use Doctrine\ORM\EntityManagerInterface
; 
  15 use Doctrine\Persistence\ManagerRegistry
; 
  16 use Psr\Log\LoggerInterface
; 
  17 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController 
as BaseAbstractController
; 
  18 use Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait
; 
  19 use Symfony\Bundle\SecurityBundle\Security
; 
  20 use Symfony\Component\DependencyInjection\ContainerInterface
; 
  21 use Symfony\Component\HttpFoundation\Request
; 
  22 use Symfony\Component\HttpFoundation\RequestStack
; 
  23 use Symfony\Component\HttpFoundation\Response
; 
  24 use Symfony\Component\Mailer\MailerInterface
; 
  25 use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface
; 
  26 use Symfony\Component\Routing\Generator\UrlGeneratorInterface
; 
  27 use Symfony\Component\Routing\RouterInterface
; 
  28 use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface
; 
  29 use Symfony\Component\Security\Core\User\UserInterface
; 
  30 use Symfony\Contracts\Service\ServiceSubscriberInterface
; 
  31 use Symfony\Contracts\Translation\TranslatorInterface
; 
  34 use Rapsys\PackBundle\Util\SluggerUtil
; 
  36 use Rapsys\UserBundle\RapsysUserBundle
; 
  39  * Provides common features needed in controllers. 
  43 abstract class AbstractController 
extends BaseAbstractController 
implements ServiceSubscriberInterface 
{ 
  47         protected array $config; 
  52         protected array $context; 
  62         protected string $locale; 
  70          * AuthorizationCheckerInterface instance 
  72         protected AuthorizationCheckerInterface 
$checker; 
  75          * ManagerRegistry instance 
  77         protected ManagerRegistry 
$doctrine; 
  80          * UserPasswordHasherInterface instance 
  82         protected UserPasswordHasherInterface 
$hasher; 
  85          * LoggerInterface instance 
  87         protected LoggerInterface 
$logger; 
  90          * MailerInterface instance 
  92         protected MailerInterface 
$mailer; 
  95          * EntityManagerInterface instance 
  97         protected EntityManagerInterface 
$manager; 
 102         protected Request 
$request; 
 107         protected RouterInterface 
$router; 
 112         protected Security 
$security; 
 115          * Slugger util instance 
 117         protected SluggerUtil 
$slugger; 
 120          * Translator instance 
 122         protected TranslatorInterface 
$translator; 
 125          * Twig\Environment instance 
 127         protected Environment 
$twig; 
 130          * Abstract constructor 
 132          * @param AuthorizationCheckerInterface $checker The checker instance 
 133          * @param ContainerInterface $container The container instance 
 134          * @param ManagerRegistry $doctrine The doctrine instance 
 135          * @param UserPasswordHasherInterface $hasher The password hasher instance 
 136          * @param LoggerInterface $logger The logger instance 
 137          * @param MailerInterface $mailer The mailer instance 
 138          * @param EntityManagerInterface $manager The manager instance 
 139          * @param RouterInterface $router The router instance 
 140          * @param Security $security The security instance 
 141          * @param SluggerUtil $slugger The slugger instance 
 142          * @param RequestStack $stack The stack instance 
 143          * @param TranslatorInterface $translator The translator instance 
 144          * @param Environment $twig The twig environment instance 
 145          * @param integer $limit The page limit 
 147         public function __construct(AuthorizationCheckerInterface 
$checker, ContainerInterface 
$container, ManagerRegistry 
$doctrine, UserPasswordHasherInterface 
$hasher, LoggerInterface 
$logger, MailerInterface 
$mailer, EntityManagerInterface 
$manager, RouterInterface 
$router, Security 
$security, SluggerUtil 
$slugger, RequestStack 
$stack, TranslatorInterface 
$translator, Environment 
$twig, int $limit = 5) { 
 149                 $this->config 
= $container->getParameter(RapsysUserBundle
::getAlias()); 
 152                 $this->checker 
= $checker; 
 155                 $this->container 
= $container; 
 158                 $this->doctrine 
= $doctrine; 
 161                 $this->hasher 
= $hasher; 
 164                 $this->logger 
= $logger; 
 167                 $this->limit 
= $limit; 
 170                 $this->mailer 
= $mailer; 
 173                 $this->manager 
= $manager; 
 176                 $this->router 
= $router; 
 179                 $this->security 
= $security; 
 182                 $this->slugger 
= $slugger; 
 185                 $this->translator 
= $translator; 
 190                 //Get current request 
 191                 $this->request 
= $stack->getCurrentRequest(); 
 194                 $this->page 
= (int) $this->request
->query
->get('page'); 
 197                 if ($this->page 
< 0) { 
 202                 $this->locale 
= $this->request
->getLocale(); 
 204                 //Set translate array 
 207                 //Look for keys to translate 
 208                 if (!empty($this->config
['translate'])) { 
 209                         //Iterate on keys to translate 
 210                         foreach($this->config
['translate'] as $translate) { 
 215                                 foreach(array_reverse(explode('.', $translate)) as $curkey) { 
 216                                         $tmp = array_combine([$curkey], [$tmp]); 
 220                                 $translates = array_replace_recursive($translates, $tmp); 
 224                 //Inject every requested route in view and mail context 
 225                 foreach($this->config 
as $tag => $current) { 
 226                         //Look for entry with route subkey 
 227                         if (!empty($current['route'])) { 
 228                                 //Generate url for both view and mail 
 229                                 foreach(['view', 'mail'] as $view) { 
 230                                         //Check that context key is usable 
 231                                         if (isset($current[$view]['context']) && is_array($current[$view]['context'])) { 
 232                                                 //Merge with global context 
 233                                                 $this->config
[$tag][$view]['context'] = array_replace_recursive($this->config
['context'], $this->config
[$tag][$view]['context']); 
 235                                                 //Process every routes 
 236                                                 foreach($current['route'] as $route => $key) { 
 238                                                         if ($route == 'confirm') { 
 239                                                                 //Skip route as it requires some parameters 
 244                                                         $value = $this->router
->generate( 
 245                                                                 $this->config
['route'][$route]['name'], 
 246                                                                 $this->config
['route'][$route]['context'], 
 247                                                                 //Generate absolute url for mails 
 248                                                                 $view=='mail'?UrlGeneratorInterface
::ABSOLUTE_URL
:UrlGeneratorInterface
::ABSOLUTE_PATH
 
 252                                                         if (strpos($key, '.') !== false) { 
 257                                                                 foreach(array_reverse(explode('.', $key)) as $curkey) { 
 258                                                                         $tmp = array_combine([$curkey], [$tmp]); 
 262                                                                 $this->config
[$tag][$view]['context'] = array_replace_recursive($this->config
[$tag][$view]['context'], $tmp); 
 266                                                                 $this->config
[$tag][$view]['context'][$key] = $value; 
 270                                                 //Look for successful intersections 
 271                                                 if (!empty(array_intersect_key($translates, $this->config
[$tag][$view]['context']))) { 
 272                                                         //Iterate on keys to translate 
 273                                                         foreach($this->config
['translate'] as $translate) { 
 275                                                                 $keys = explode('.', $translate); 
 278                                                                 $tmp = $this->config
[$tag][$view]['context']; 
 281                                                                 foreach($keys as $curkey) { 
 283                                                                         if (!isset($tmp[$curkey])) { 
 289                                                                         $tmp = $tmp[$curkey]; 
 292                                                                 //Translate tmp value 
 293                                                                 $tmp = $this->translator
->trans($tmp); 
 296                                                                 foreach(array_reverse($keys) as $curkey) { 
 298                                                                         $tmp = array_combine([$curkey], [$tmp]); 
 302                                                                 $this->config
[$tag][$view]['context'] = array_replace_recursive($this->config
[$tag][$view]['context'], $tmp); 
 307                                                 if ($view == 'view') { 
 309                                                         $pathInfo = $this->router
->getContext()->getPathInfo(); 
 311                                                         //Iterate on locales excluding current one 
 312                                                         foreach(($locales = array_keys($this->config
['languages'])) as $locale) { 
 316                                                                 //Iterate on other locales 
 317                                                                 foreach(array_diff($locales, [$locale]) as $other) { 
 318                                                                         $titles[$other] = $this->translator
->trans($this->config
['languages'][$locale], [], null, $other); 
 321                                                                 //Retrieve route matching path 
 322                                                                 $route = $this->router
->match($pathInfo); 
 325                                                                 $name = $route['_route']; 
 328                                                                 unset($route['_route']); 
 330                                                                 //With current locale 
 331                                                                 if ($locale == $this->locale
) { 
 332                                                                         //Set locale locales context 
 333                                                                         $this->config
[$tag][$view]['context']['head']['canonical'] = $this->router
->generate($name, ['_locale' => $locale]+
$route, UrlGeneratorInterface
::ABSOLUTE_URL
); 
 335                                                                         //Set locale locales context 
 336                                                                         $this->config
[$tag][$view]['context']['head']['alternates'][$locale] = [ 
 337                                                                                 'absolute' => $this->router
->generate($name, ['_locale' => $locale]+
$route, UrlGeneratorInterface
::ABSOLUTE_URL
), 
 338                                                                                 'relative' => $this->router
->generate($name, ['_locale' => $locale]+
$route), 
 339                                                                                 'title' => implode('/', $titles), 
 340                                                                                 'translated' => $this->translator
->trans($this->config
['languages'][$locale], [], null, $locale) 
 345                                                                 if (empty($this->config
[$tag][$view]['context']['head']['alternates'][$slocale = substr($locale, 0, 2)])) { 
 347                                                                         $this->config
[$tag][$view]['context']['head']['alternates'][$slocale] = [ 
 348                                                                                 'absolute' => $this->router
->generate($name, ['_locale' => $locale]+
$route, UrlGeneratorInterface
::ABSOLUTE_URL
), 
 349                                                                                 'relative' => $this->router
->generate($name, ['_locale' => $locale]+
$route), 
 350                                                                                 'title' => implode('/', $titles), 
 351                                                                                 'translated' => $this->translator
->trans($this->config
['languages'][$locale], [], null, $locale) 
 367         protected function render(string $view, array $parameters = [], Response 
$response = null): Response 
{ 
 368                 //Create response when null 
 369                 $response ??= new Response(); 
 371                 //With empty head locale 
 372                 if (empty($parameters['head']['locale'])) { 
 374                         $parameters['head']['locale'] = $this->locale
; 
 377                 //With empty head title and section 
 378                 if (empty($parameters['head']['title']) && !empty($parameters['section'])) { 
 380                         $parameters['head']['title'] = implode(' - ', [$parameters['title'], $parameters['section'], $parameters['head']['site']]); 
 381                 //With empty head title 
 382                 } elseif (empty($parameters['head']['title'])) { 
 384                         $parameters['head']['title'] = implode(' - ', [$parameters['title'], $parameters['head']['site']]); 
 387                 //Call twig render method 
 388                 $content = $this->twig
->render($view, $parameters); 
 390                 //Invalidate OK response on invalid form 
 391                 if (200 === $response->getStatusCode()) { 
 392                         foreach ($parameters as $v) { 
 393                                 if ($v instanceof FormInterface 
&& $v->isSubmitted() && !$v->isValid()) { 
 394                                         $response->setStatusCode(422); 
 400                 //Store content in response 
 401                 $response->setContent($content); 
 410          * @see vendor/symfony/framework-bundle/Controller/AbstractController.php 
 412         public static function getSubscribedServices(): array { 
 413                 //Return subscribed services 
 415                         'doctrine' => ManagerRegistry
::class, 
 416                         'doctrine.orm.default_entity_manager' => EntityManagerInterface
::class, 
 417                         'logger' => LoggerInterface
::class, 
 418                         'mailer.mailer' => MailerInterface
::class, 
 419                         'rapsys_pack.slugger_util' => SluggerUtil
::class, 
 420                         'request_stack' => RequestStack
::class, 
 421                         'router' => RouterInterface
::class, 
 422                         'security.authorization_checker' => AuthorizationCheckerInterface
::class, 
 423                         'security' => Security
::class, 
 424                         'security.user_password_hasher' => UserPasswordHasherInterface
::class, 
 425                         'service_container' => ContainerInterface
::class, 
 426                         'translator' => TranslatorInterface
::class