<?php
namespace App\Listener;
use App\Entity\User;
use App\Services\Common\ModuleSettingService;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class CheckBoModulesListener
{
private RouterInterface $router;
private KernelInterface $kernel;
private TokenStorageInterface $token;
private ModuleSettingService $moduleSettingService;
public function __construct(
RouterInterface $router,
KernelInterface $kernel,
TokenStorageInterface $token,
ModuleSettingService $moduleSettingService
)
{
$this->router = $router;
$this->kernel = $kernel;
$this->token = $token;
$this->moduleSettingService = $moduleSettingService;
}
/**
* @param ResponseEvent $event
*
* @return void
*/
public function onKernelResponse( ResponseEvent $event )
{
$request = $event->getRequest();
$currentRoute = $request->get( '_route' );
if ( NULL === $currentRoute ) {
return;
}
$route = $this->router->getRouteCollection()->get( $currentRoute );
if ( $route->getOption( 'global_module' ) === TRUE ) {
return;
}
// INFORMATION IMPORTANTE:
// Le traitement des routes exclues de listener ne se fait plus ici mais
// directement dans la route en ajoutant l'option "global_module" à TRUE
// exemple:
// back_setting_point_point_transaction_type_list:
// path: /back/setting/point/point-transaction-type/list
// controller: App\Controller\Back\Setting\Point\PointTransactionTypeController::list
// methods: GET
// options:
// global_module: true <== ICI ON ACTIVE LA FONCTION
// requirements:
// _locale: '%app_locales%'
if ( strpos( $currentRoute, 'back_' ) === 0 ) {
// Partie qui gère le back
// On récupère le setting MODULE_SETTING
$modules = $this->moduleSettingService->getModuleSetting();
if ( $modules === [] ) {
return;
}
// On vérifie si le module point est activé afin de ne pas bloquer l'accès à la page de configuration des points
if ( isset( $modules[ 'point' ] ) ) {
if ( $route->getOption( 'global_module' ) === 'point' ) {
return;
}
}
$token = $this->token->getToken();
if( null === $token ) {
return;
}
$currentUser = $token->getUser();
$defaultModules = $this->moduleSettingService->getDefaultYamlModuleSetting($currentUser);
// Exemple d'utilisation
$selectedModules = $this->arrayIntersectKey( $defaultModules[ 'items' ], $modules );
$routes = $this->collectRoutes( $selectedModules, $routes );
if ( !in_array( $request->get( '_route' ), $routes, TRUE ) ) {
$token = $this->token->getToken();
/** @var User $currentUser */
$currentUser = $token ? $token->getUser() : NULL;
if ( $currentUser && $this->kernel->getEnvironment() === 'dev' && $currentUser->isDeveloper() ) {
$event->setResponse(
new RedirectResponse(
$this->router->generate( 'back_route_not_in_module', [
'route' => $request->get( '_route' ),
'referer' => $_SERVER[ 'HTTP_REFERER' ] ?? '',
] ),
),
);
} else {
$event->setResponse( new RedirectResponse( $this->router->generate( 'back_dashboard' ) ) );
}
}
}
// @TODO : Partie qui gère le front
// Il conviendrait de traiter ici la même logique mais pour le front
}
/**
* @param $defaultModules
* @param $currentModules
*
* @return array
*/
private function arrayIntersectKey( $defaultModules, $currentModules ): array
{
$result = [];
foreach ( $defaultModules as $key => $value ) {
if ( isset( $currentModules[ $key ] ) ) {
$result[ $key ] = $value;
}
}
foreach ( $result as $key => $value ) {
if ( !empty( $value[ 'subItems' ] ) ) {
foreach ( $value[ 'subItems' ] as $subKey => $subValue ) {
if ( !isset( $currentModules[ $key ][ 'subItems' ][ $subKey ] ) ) {
unset( $result[ $key ][ 'subItems' ][ $subKey ] );
}
}
}
}
return $result;
}
/**
* @param $array
* @param $result
*
* @return array
*/
private function collectRoutes( $array, &$result ): array
{
if ( !is_array( $result ) ) {
$result = [];
}
foreach ( $array as $value ) {
if ( is_array( $value ) ) {
if ( isset( $value[ 'route' ] ) ) {
$result[] = $value[ 'route' ];
}
if ( isset( $value[ 'mainRoute' ] ) ) {
$result[] = $value[ 'mainRoute' ];
}
if ( isset( $value[ 'subItems' ] ) && is_array( $value[ 'subItems' ] ) ) {
// Collecter les "includedRoutes" du sous-niveau
foreach ( $value[ 'subItems' ] as $subItem ) {
if ( isset( $subItem[ 'includedRoutes' ] ) && is_array( $subItem[ 'includedRoutes' ] ) ) {
$result = array_merge( $result, $subItem[ 'includedRoutes' ] );
}
}
}
$this->collectRoutes( $value, $result ); // Appel récursif pour explorer les sous-tableaux
}
}
return $result; // Retourne le tableau résultat une fois que la collecte est terminée
}
}