src/Diplix/KMGBundle/Controller/BaseController.php line 179

Open in your IDE?
  1. <?php
  2. namespace Diplix\KMGBundle\Controller;
  3. use Cocur\Slugify\Slugify;
  4. use Diplix\KMGBundle\Entity\Customer;
  5. use Diplix\KMGBundle\Entity\File;
  6. use Diplix\KMGBundle\Entity\Role;
  7. use Diplix\KMGBundle\Entity\SessionParameters;
  8. use Diplix\KMGBundle\Entity\User;
  9. use Diplix\KMGBundle\Exception\PasswordAgeExceededException;
  10. use Diplix\KMGBundle\Repository\FileRepository;
  11. use Doctrine\ORM\AbstractQuery;
  12. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  13. use Symfony\Component\Form\FormInterface;
  14. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  15. use Symfony\Component\HttpFoundation\File\UploadedFile;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\HttpFoundation\Response;
  18. use Symfony\Component\HttpFoundation\ResponseHeaderBag;
  19. use Symfony\Component\PropertyAccess\PropertyAccess;
  20. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  21. class BaseController extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController
  22. {
  23.     /** @var FileRepository */
  24.     protected $fileRepo null;
  25.     /**
  26.      * @var SessionParameters
  27.      */
  28.     protected $sessionParameters null;
  29.     /**
  30.      * @return SessionParameters
  31.      */
  32.     protected function getSessionParameters()
  33.     {
  34.         if ($this->sessionParameters === null)
  35.         {
  36.             $session $this->get("session");
  37.             $this->sessionParameters $session->get(SessionParameters::SESSION_KEY, new SessionParameters());
  38.         }
  39.         return $this->sessionParameters;
  40.     }
  41.     protected function saveSessionParameters()
  42.     {
  43.         $session $this->get("session");
  44.         $session->set(SessionParameters::SESSION_KEY$this->sessionParameters);
  45.     }
  46.     /**
  47.      * Guess the needed content-type to respond to a json request
  48.      * @return string
  49.      */
  50.     protected function guessJsonContentType()
  51.     {
  52.         return 'application/json'// 9 years later, this seems to work right...
  53. /*        // Use plain browser-wide and let the js assume that the format will be json
  54.         // this seems to work with every browser
  55.         return  'text/plain';
  56. */
  57.     }
  58.     /**
  59.      * format an array as json response
  60.      * @param \Symfony\Component\HttpFoundation\Request $request
  61.      * @param array|\stdClass $responseData
  62.      * @param int $httpResponseCode
  63.      * @return \Symfony\Component\HttpFoundation\Response
  64.      */
  65.     protected function getJsonResponse($request$responseData$httpResponseCode Response::HTTP_OK )
  66.     {
  67.         $resp = new Response(json_encode($responseData),
  68.                 $httpResponseCode,
  69.                 array(    'content-type'=> $this->guessJsonContentType(),
  70.                         'cache-control'=>'no-store, no-cache, must-revalidate',
  71.                         'pragma'=>'no-cache'));
  72.         $resp->prepare($request);
  73.         $resp->setCache(array('last_modified' => new \DateTime()));
  74.         $resp->expire();
  75.         return $resp;
  76.     }
  77.     /**
  78.      * format a simple json success / error response
  79.      * which looks like array( 'success'=>(true|false), 'error'=>(error message string) )
  80.      *
  81.      * @param \Symfony\Component\HttpFoundation\Request $request
  82.      * @param bool|string $responseData use true to indicate a success or a string message to indicate an error
  83.      * @deprecated
  84.      */
  85.     protected function getJsonResultResponse($request,$responseData)
  86.     {
  87.         if ($responseData===true)
  88.             return $this->getJsonDataResponse($request,true,null);
  89.         else
  90.             return $this->getJsonDataResponse($request,false,['error'=>$responseData] ,$responseData);
  91.     }
  92.     protected function getJsonDataResponse($request,$success true$responseData=null$message=null)
  93.     {
  94.         $ret = array(   'success'=>$success,
  95.                         "message"=> $message != null $message : ($success"OK." "Failed."),
  96.                         "data" => $responseData    );
  97.         // compat for exceptions with old format
  98.         if ( (is_array($responseData))&&(array_key_exists('error',$responseData)) )
  99.         {
  100.             $ret['error'] = $responseData['error'];
  101.         }
  102.         else
  103.         // compat for ret = false with old format
  104.         if (!$success)
  105.         {
  106.             $ret['error'] = var_export($responseData,true);
  107.         }
  108.         return $this->getJsonResponse($request$retResponse::HTTP_OK /* a failed request will kill our js code flow :: $success ? Response::HTTP_OK : Response::HTTP_BAD_REQUEST */);
  109.     }
  110.     /**
  111.      * get the the currently logged in user
  112.      * @return User
  113.      */
  114.     protected function getCurrentUser($refresh false)
  115.     {
  116.         $token $this->container->get('security.token_storage')->getToken();
  117.         $u $token->getUser();
  118.         if ($refresh)
  119.         {
  120.             //$u = $this->getDoctrine()->getRepository(User::class)->findOneBy(["id"=>$u->getId()]);
  121.             $r $this->getDoctrine()->getRepository(User::class);
  122.             $u $r->createQueryBuilder("u")
  123.                 ->select("u,c,s,sc")
  124.                 ->leftJoin("u.customer","c")
  125.                 ->leftJoin("u.currentSubstituteUser","s")
  126.                 ->leftJoin("s.customer","sc")
  127.                 ->where("u.id = :id")
  128.                 ->setParameter("id",$u->getId())
  129.                 ->getQuery()
  130.                 ->getSingleResult(AbstractQuery::HYDRATE_OBJECT);
  131.             //$this->addFlash("notice",$u->getCustomer()->getId());
  132.             //$this->addFlash("notice",get_class($u->getCustomer()));
  133.         }
  134.         return $u;
  135.     }
  136.     /**
  137.      * @param $roleIdentifier
  138.      * @param bool|false $exclusive set to true to disable a positive result for SUPER_ADMIN
  139.      * @return bool
  140.      */
  141.     protected function hasUserRole($roleIdentifier,$exclusive=false)
  142.     {
  143.         $sac $this->get('security.authorization_checker');
  144.         $super = (!$exclusive)&&$sac->isGranted(Role::SUPER_ADMIN);
  145.         if (false === $super// super admin role allows everything
  146.         {
  147.             return $sac->isGranted($roleIdentifier);
  148.         }
  149.         else
  150.         {
  151.             return true;
  152.         }
  153.     }
  154.     /**
  155.      * Ensure that a User hat the given role
  156.      * @param string $roleIdentifier
  157.      * @throws AccessDeniedException
  158.      */
  159.     protected function ensureUserHasRole($roleIdentifier)
  160.     {
  161.         if (!$this->hasUserRole($roleIdentifier))
  162.         {
  163.             throw new AccessDeniedException();
  164.         }
  165.     }
  166.             /**
  167.      * Issue an access denied response
  168.      *
  169.      */
  170.     protected function accessDenied(Request $request$optionalMessage '')
  171.     {
  172.         $out $this->render('@Twig/Exception/error403.html.twig',array('message'=>$optionalMessage));
  173.         return $out;
  174.     }
  175.     protected function getDownloadResponse($fullPathToFile,$fileName)
  176.     {
  177.         // @see http://stackoverflow.com/questions/25680932/symfony2-file-download-and-the-filename-fallback-must-only-contain-ascii-char
  178.         // @see https://github.com/symfony/symfony/issues/9093
  179.         $sl = new Slugify();
  180.         $fnFallback $sl->slugify($fileName); // need to provide a ascii fallback for filename to be http conform
  181.         $br = new BinaryFileResponse($fullPathToFile200, array(), true);
  182.         $br->setContentDisposition(
  183.             ResponseHeaderBag::DISPOSITION_ATTACHMENT,
  184.             $fileName,    // or '' to guess the file name from $file
  185.             $fnFallback
  186.         );
  187.         return $br;
  188.     }
  189. //    /**
  190. //     * @param string $type
  191. //     * @param string|array $message
  192. //     */
  193. //    protected function addFlash($type, $message): void
  194. //    {
  195. //        parent::addFlash($type, $message);
  196. //    }
  197.     protected function checkPasswordAge()
  198.     {
  199.         $up $this->getCurrentUser()->getLastPasswordChange();
  200.         $age $this->getCurrentUser()->getCustomer()->getMaxPasswordAge();
  201.         if ($age 0)
  202.         {
  203.             $di = new \DateInterval(sprintf("P%dD"$age));
  204.             if (
  205.                 (!is_object($up)) ||
  206.                 ($up->add($di) < new \DateTime())
  207.             )
  208.             {
  209.                 throw new PasswordAgeExceededException();
  210.             }
  211.         }
  212.     }
  213.     protected function getCustomerContextFromSession($required=true)
  214.     {
  215.         $ctx $this->getSessionParameters()->selectedCustomer;
  216.         if ($required)
  217.         {
  218.             if (! is_object($ctx)) throw new \Exception("No customer selected.");
  219.         }
  220.         if (is_object($ctx))
  221.         {
  222.             // refresh, then detach
  223.             $ctx $this->getDoctrine()->getManager()->find(Customer::class,$ctx->getId());
  224.             $this->getDoctrine()->getManager()->detach($ctx);
  225.             // for unknown reasons, we need to access the object once in code
  226.             // after detaching. only then we can use it correctly in in twig in every case
  227.             // todo: check this weird behaviour
  228.             $dummy $ctx->getName();
  229.         }
  230.         return $ctx;
  231.     }
  232.     protected function handleFileUpload(FormInterface $form$entity$fieldName$fileType)
  233.     {
  234.         // TODO: NOT WORKING WITH PHP8 !!!!! (form->getData() is always null)
  235.         if ($this->fileRepo === null)
  236.         {
  237.             throw new \RuntimeException("fileRepo not set. Update controller !");
  238.         }
  239.         $accessor PropertyAccess::createPropertyAccessor();
  240.         $exist $accessor->getValue($entity,$fieldName);
  241.         /* @var $file UploadedFile */
  242.         $file $form->get($fieldName)->getData();
  243.         if ($file !== null)
  244.         {
  245.             if ($fileType===null)
  246.             {
  247.                 $fileType $file->getMimeType();
  248.             }
  249.             $newObj null;
  250.             try
  251.             {
  252.                 $newObj $this->fileRepo->receiveUpload($fileType"img"$file);
  253.             }
  254.             catch (\Exception $ex)
  255.             {
  256.                 $this->addFlash('warning'"File Upload Error: " $ex->getMessage());
  257.                 return false;
  258.             }
  259.             // new file successfully received at this point, delete an existing one
  260.             if (($exist !== null) && ($exist instanceof File)) $this->fileRepo->delete($exist);
  261.             // persist the new one
  262.             $this->fileRepo->persistFlush($newObj);
  263.             // attach it
  264.             $accessor->setValue($entity$fieldName$newObj);
  265.             $this->addFlash("info"sprintf("Upload %s received."$newObj->getFileName()));
  266.         }
  267.         else
  268.         {
  269.             // we only need to handle an explicit deletion if there has been no new file
  270.             $del = ($form->has($fieldName.'_delete') ? $form->get($fieldName.'_delete')->getData() : );
  271.             if ($del == 1)
  272.             {
  273.                 if ( ($exist !== null) && ($exist instanceof File) )
  274.                 {
  275.                     $this->fileRepo->delete($exist);
  276.                     $this->addFlash("info",sprintf("File %s has been deleted.",$exist->getFileName()));
  277.                 }
  278.                 $accessor->setValue($entity,$fieldName,null);
  279.             }
  280.         }
  281.         return true;
  282.     }
  283. }