src/Package/Admin/Main/Controller/Route/RouteController.php line 68

Open in your IDE?
  1. <?php
  2. namespace App\Package\Admin\Main\Controller\Route;
  3. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  4. use Symfony\Component\HttpFoundation\{ RequestResponse };
  5. use App\Package\Toolkit\Exception\Exception\Exception,
  6.     App\Package\Toolkit\Exception\NotFoundException\NotFoundException;
  7. use App\Package\Admin\Main\EntityInterface\{ AdminActionInterfaceAdminModuleInterface };
  8. use App\Package\Admin\Tools\AdminState\AdminState;
  9. /**
  10.  * RouteController
  11.  * 
  12.  * Main routing point for administration panel (urls: panel.{domain})
  13.  * 
  14.  * IMPORTANT: All controllers to which this controller fowards to MUST BE REGISTERED AS SERVICES
  15.  * 
  16.  * @todo       if not exact amount of needed arguments were passed then throw exception
  17.  * 
  18.  * @author     Daniel Balowski <d.balowski@openform.pl> (_creator)
  19.  * @copyright  Openform
  20.  * @since      03.2019
  21.  */
  22. class RouteController extends AbstractController
  23. {
  24.     /**
  25.      * @var AdminState
  26.      */
  27.     protected $adminState;
  28.     /**
  29.      * Configuration of controller paths
  30.      * - see yml parameter "app.admin.controller.paths"
  31.      * 
  32.      * @var string
  33.      */
  34.     protected $controllerPaths;
  35.     /**
  36.      * @var string
  37.      */
  38.     protected $targetControllerPath;
  39.     /**
  40.      * @param AdminState  $adminState
  41.      * @param array       $controllerPaths
  42.      */
  43.     public function __construct(AdminState $adminState, array $controllerPaths)
  44.     {
  45.         $this->adminState      $adminState;
  46.         $this->controllerPaths $controllerPaths;
  47.     }
  48.     /**
  49.      * Main routing point
  50.      * 
  51.      * @param Request       $request
  52.      * @param string|null   $moduleSlug    (optional)
  53.      * @param string|null   $objectId      (optional)
  54.      * @param string|null   $actionSlug    (optional)
  55.      * @param string|null   $additional    (optional)
  56.      * 
  57.      * @return void
  58.      */
  59.     public function indexAction(
  60.         Request $request
  61.         string $moduleSlug null
  62.         string $objectId   null
  63.         string $actionSlug null
  64.         string $additional null
  65.     ) : Response {
  66.         $locale $request->getLocale();
  67.         
  68.         // 1.   Get current module and verify if is enabled
  69.         $currentModule $this->adminState->getCurrentModule();
  70.         $this->verifyAdminModule($currentModule$moduleSlug);
  71.         // 2.   Get current action and verify if is enabled
  72.         $currentAction $this->adminState->getCurrentAction();
  73.         $this->verifyAdminAction($currentAction$actionSlug);
  74.         // 3.   Verify if current action is registered within target controller
  75.         $this->setTargetControllerPath($currentModule)
  76.              ->verifyControllerRegisteredActions($currentModule$currentAction);
  77.         // 4.   Verify if request method (GET, POST, ..) is allowed for current action
  78.         $this->verifyActionRequestMethods($currentModule$currentAction$request);
  79.         // 5.   Verify if all required arguments for current action are set
  80.         $passedArgs       = ( new \ReflectionMethod(get_class($this), 'indexAction') )->getParameters();
  81.         $passedValues     func_get_args();
  82.         $availableArgs    = [];
  83.         foreach($passedArgs as $key => $passedArg) {
  84.             $availableArgs$passedArg->getName() ] = $passedValues$key ];
  85.         }
  86.         $argsToBePassed $argsToBeLogged $this->verifyActionRequiredArguments($currentModule$currentAction$availableArgs);
  87.         // 6.   Log to request target point and args (for profiler)
  88.         foreach($argsToBeLogged as $key => $value) {
  89.             if ( is_object($value) && (get_class($value) == Request::class) ) {
  90.                 $argsToBeLogged$key ] = 'Request object (see Request tab for more info)';
  91.             }
  92.         }
  93.         $request->_targetPoint =
  94.             [ 
  95.                 'controller' => $this->targetControllerPath,
  96.                 'action'     => $currentAction->getName() . 'Action',
  97.                 'args'       => $argsToBeLogged
  98.             ];
  99.         // 7.   Invoke target action and forwards its return value
  100.         return call_user_func_array(
  101.             [ $this->get$this->targetControllerPath ), $currentAction->getName() . 'Action' ],
  102.             $argsToBePassed
  103.         );
  104.     }
  105.     /**
  106.      * Verifies current module
  107.      * - checks if NOT NULL
  108.      * - checks if ENABLED
  109.      * 
  110.      * @param AdminModuleInterface|null  $adminModule    (optional)
  111.      * @param string|null                $moduleSlug     (optional)
  112.      * 
  113.      * @throws Exception    a) if module does not exist
  114.      *                      b) if module is not enabled
  115.      * 
  116.      * @return void
  117.      */
  118.     protected function verifyAdminModule(AdminModuleInterface $adminModule nullstring $moduleSlug null) : void
  119.     {
  120.         if (! $adminModule) {
  121.             throw new NotFoundException(
  122.                 ' >> 404 AdminModule -' . ($moduleSlug ' slug: ' $moduleSlug ' name: Home')
  123.             );
  124.         }
  125.         if (! $adminModule->getStat()) {
  126.             throw new NotFoundException(
  127.                 ' >> AdminModule is disabled - slug: ' . ($moduleSlug ' slug: ' $moduleSlug ' name: Home')
  128.             );
  129.         }
  130.         
  131.         return;
  132.     }
  133.     /**
  134.      * Verifies current action
  135.      * - checks if NOT NULL
  136.      * - checks if ENABLED
  137.      *
  138.      * @param AdminActionInterface|null  $adminAction    (optional)
  139.      * @param string|null                $actionSlug     (optional)
  140.      * 
  141.      * @throws NotFoundException    a) if action does not exist
  142.      *                              b) if action is not enabled
  143.      * 
  144.      * @return void
  145.      */
  146.     protected function verifyAdminAction(AdminActionInterface $adminAction nullstring $actionSlug null) : void
  147.     {
  148.         if (! $adminAction) {
  149.             throw new NotFoundException(
  150.                 ' >> 404 AdminAction - slug: ' . ($actionSlug ' slug: ' $actionSlug ' name: index')
  151.             );
  152.         } 
  153.         if (! $adminAction->getStat()) {
  154.             throw new NotFoundException(
  155.                 ' >> AdminAction is disabled - slug: ' . ($actionSlug ' slug: ' $actionSlug ' name: index')
  156.             );
  157.         }
  158.         return;
  159.     }
  160.     /**
  161.      * Sets target controller path
  162.      *
  163.      * @param AdminModuleInterface  $adminModule
  164.      * 
  165.      * @return RouteController
  166.      */
  167.     protected function setTargetControllerPath(AdminModuleInterface $adminModule) : RouteController
  168.     {
  169.         if ( array_key_exists(
  170.                 $singleControllerHash $adminModule->getPackage() . '.' $adminModule->getName(), 
  171.                 $this->controllerPaths'single' ] )
  172.         ) {
  173.             $this->targetControllerPath $this->controllerPaths'single' ][ $singleControllerHash ];
  174.             return $this;
  175.         }
  176.         if ( array_key_exists($adminModule->getPackage(), $this->controllerPaths'package' ]) ) {
  177.             $targetControllerPath null;
  178.             
  179.             foreach($this->controllerPaths'package' ][ $adminModule->getPackage() ] as $packagePath) {
  180.                 $targetControllerPath 
  181.                     $this->has($packagePath '\\' $adminModule->getName() . 'Controller') ?
  182.                     $packagePath '\\' $adminModule->getName() . 'Controller' 
  183.                     $targetControllerPath;
  184.             }
  185.             $this->targetControllerPath $targetControllerPath;
  186.         }
  187.         $this->targetControllerPath 
  188.             $this->targetControllerPath ??
  189.             'App\\Package\\' $adminModule->getPackage() . '\\Controller\\'
  190.             $adminModule->getName() . 'Controller';
  191.             
  192.         return $this;
  193.     }
  194.     /**
  195.      * Gets target controller path
  196.      * 
  197.      * @return string
  198.      */
  199.     public function getTargetControllerPath() : string
  200.     {
  201.         return $this->targetControllerPath;
  202.     }
  203.     
  204.     /**
  205.      * Verifies if current action is registered within target controller
  206.      *
  207.      * @param AdminModuleInterface  $adminModule
  208.      * @param AdminActionInterface  $adminAction
  209.      * 
  210.      * @throws Exception    if action not registered to target controller is tried to be accessed
  211.      * 
  212.      * @return void
  213.      */
  214.     protected function verifyControllerRegisteredActions(
  215.         AdminModuleInterface $adminModule
  216.         AdminActionInterface $adminAction
  217.     ) : void {
  218.         $registeredActions $this->get$this->targetControllerPath )->getConfiguration()->getRegisteredActions();
  219.         
  220.         if (! in_array($adminAction->getName(), $registeredActions)) {
  221.             throw new Exception(
  222.                 ' >> You have tried to access action not registered to target controller' PHP_EOL
  223.                 ' [ Controller: ' ucfirst($adminModule->getName()) . ' ]' PHP_EOL
  224.                 ' [ Action: ' $adminAction->getName() . ' ]' PHP_EOL
  225.                 ' [ Registered actions: ' implode(', '$registeredActions) . ' ]'
  226.             );
  227.         }
  228.         
  229.         return;
  230.     }
  231.     /**
  232.      * Verifies if request method (GET, POST, ..) is allowed for current action
  233.      * 
  234.      * @param AdminModuleInterface  $adminModule
  235.      * @param AdminActionInterface  $adminAction
  236.      * @param Request               $request
  237.      * 
  238.      * @throws Exception    if request method is not allowed for current action
  239.      * 
  240.      * @return void
  241.      */
  242.     protected function verifyActionRequestMethods(
  243.         AdminModuleInterface $adminModule
  244.         AdminActionInterface $adminAction,
  245.         Request $request
  246.     ) : void {
  247.         if (! $adminAction->getMethods()) {
  248.             return;
  249.         }
  250.         $methods explode(','str_replace(' '''$adminAction->getMethods()));
  251.         foreach($methods as $method) {
  252.             if (strtolower($request->getMethod()) === strtolower($method)) {
  253.                 return;
  254.             }
  255.         }
  256.         throw new Exception(
  257.             ' >> Request method not allowed for current action - method: ' $request->getMethod() . PHP_EOL
  258.             ' [ Controller: ' $adminModule->getName() . ' ]' PHP_EOL
  259.             ' [ Action: ' $adminAction->getName() . ' ] ' PHP_EOL
  260.             ' [ Allowed methods: ' $adminAction->getMethods() . ' ]'
  261.         );
  262.     }
  263.     /**
  264.      * Verifies if all required arguments for current action are set
  265.      *
  266.      * @param AdminModuleInterface  $adminModule
  267.      * @param AdminActionInterface  $adminAction
  268.      * @param array                 $availableArgs
  269.      * 
  270.      * @throws Exception    if there is missing argument for current action
  271.      * 
  272.      * @return array
  273.      */
  274.     protected function verifyActionRequiredArguments(
  275.         AdminModuleInterface $adminModule
  276.         AdminActionInterface $adminAction
  277.         array $availableArgs
  278.     ) : array {
  279.         $requiredArgs   = ( new \ReflectionMethod($this->targetControllerPath$adminAction->getName() . 'Action') )->getParameters();
  280.         $argsToBePassed = [];
  281.         foreach($requiredArgs as $requiredArg) {
  282.             if (
  283.                 ! array_key_exists($requiredArg->getName(), $availableArgs) || 
  284.                 (! $requiredArg->isOptional() && ! $availableArgs$requiredArg->getName() ])
  285.             ) {
  286.                 throw new Exception(
  287.                     ' >> Missing argument/argument value for current action - name: $' $requiredArg->getName() . PHP_EOL
  288.                     ' [ Controller: ' $adminModule->getName() . ' ]' PHP_EOL
  289.                     ' [ Action: ' $adminAction->getName() . ' ] ' PHP_EOL
  290.                     ' [ Required arguments: ' implode(', 'array_map( function($a) { return '$' $a->getName(); }, $requiredArgs )) . ' ]'
  291.                 );
  292.             }
  293.     
  294.             $argsToBePassed[] = $availableArgs$requiredArg->getName() ];
  295.         }
  296.         return $argsToBePassed;
  297.     }
  298. }