Symfony 4 : Request object change - symfony

i'm working on Symfony 4.
I have a service:
App\EventListener\EbayExceptionListener:
tags:
- { name: kernel.event_listener, event: kernel.controller }
arguments: [ "#doctrine.orm.entity_manager" , "#router" , "#session" ]
And here is my listener :
<?php
namespace App\EventListener;
use App\Entity\Ebay;
use Doctrine\ORM\EntityManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\Routing\Router;
class EbayExceptionListener
{
private $repository;
private $router;
private $session;
private $redirectName = 'home';
public function __construct(EntityManager $entityManager, Router $router, Session $session)
{
$this->repository = $entityManager->getRepository(Ebay::class);
$this->router = $router;
$this->session = $session;
}
//Check if an eBay entity exist in the database, if not redirect to the form to create the eBay entity
public function onKernelController(FilterControllerEvent $event)
{
$ebay = $this->repository->findOneBy(['name' => 'Ebay']);
$request = $event->getRequest();
$routeName = $request->get('_route');
dump($routeName);
if ($routeName != "home" AND $ebay == null) {
$this->session->getFlashBag()->add('error', 'Please provide information for Ebay form');
return new RedirectResponse($this->router->generate($this->redirectName));
}
}
}
My Controller:
<?php
namespace App\Controller;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class HomeController extends Controller
{
/**
* #Route("/", name="home")
*/
public function index()
{
return $this->render('home/index.html.twig', [
'controller_name' => 'HomeController',
]);
}
}
I have a problem with the var $routeName inside my Listener, in fact the value of this variable should be the name of the current route. But when I use the dump($routeName)
I have 2 results : "_wdt" and "home"
I don't know why the $request parameters are not the same when my listener is executed and after the page has been generated.
Because I have no page call "_wdt" it supposed to be "home".
Did I do something wrong ?
Thank you for your help.

Related

HWIOAuthBundle add token attribute after success auth

I use HWIOAuthBundle for Symfony.
HWI\Bundle\OAuthBundle\Security\Core\Authentication\Provider\OAuthProvider.php has function "authenticate" where create and return OAuthToken.
public function authenticate(TokenInterface $token){
...
$token = new OAuthToken($oldToken->getRawToken(), $user->getRoles());
$token->setResourceOwnerName($resourceOwner->getName());
$token->setUser($user);
$token->setAuthenticated(true);
$token->setRefreshToken($oldToken->getRefreshToken());
$token->setCreatedAt($oldToken->getCreatedAt());
return $token;
}
I need set some attribute to this OAuthToken like :
$token->setAttribute('name' => 'value');
How can i do this ?
I use service with only one function "loadUserByOAuthUserResponse" which return user object :
class PartnerEntityUserProvider implements OAuthAwareUserProviderInterface{
...
public function loadUserByOAuthUserResponse(UserResponseInterface $response){
...
return $user;
}
...
}
Edited
I found solution with using service on security.interactive_login event :
config/services.yaml
services:
App\EventListener\InteractiveLoginListener:
tags:
- { name: kernel.event_listener, event: security.interactive_login }
src/EventListener/InteractiveLoginListener.php
<?php
namespace App\EventListener;
use App\Entity\Perimetre;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class InteractiveLoginListener
{
private $security;
private $entityManager;
public function __construct(Security $security, EntityManagerInterface $entityManager)
{
$this->security = $security;
$this->entityManager = $entityManager;
}
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
$this->security->getToken()->setAttribute('perimetre', $this->entityManager->getRepository(Perimetre::class)->findOneBy(['id' => $this->security->getToken()->getUser()->getFiliale()->getPerimetre()->getId()]));
}
}

Symfony 3.4: Access doctrine within an EventListener

I am trying to access to doctrine within an EventListener which tests a database table, if it is invalid then the user will be redirected to a config page where he will fix the issues!
The test will be executed before every call to a controller, so I will use the Event kernel.controller:
[EDITED: SOLVED, TESTING AND REDIRECTING VERY FINE]
<?php
namespace AdminBundle\EventListener;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Doctrine\ORM\EntityManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Session;
class BuildReferencesEventListener
{
/**
* #var EntityManager
*/
protected $em;
/**
* #var Router
*/
protected $router;
protected $references = [
1 => 'oxygen',
2 => 'pH',
3 => 'pCO2'
];
protected $redirect_route = 'references';
protected $requestStack;
protected $session;
public function __construct(EntityManager $entityManager, Router $router, RequestStack $requestStack, Session $session)
{
$this->em = $entityManager;
$this->router = $router;
$this->requestStack = $requestStack;
$this->session = $session;
}
public function onKernelController()
{
$em = $this->em;
$savedReferences = $em->getRepository('AdminBundle:ParamReference')->findAll();
$references = $this->references;
if (count($savedReferences) <= 0){
$this->redirect();
}
for ($i =0; $i<count($savedReferences); $i++){
if ($savedReferences[$i] !== $references[$i]) {
$this->redirect();
}
}
}
public function redirect()
{
$request = $this->requestStack->getCurrentRequest();
$route = $request->get('_route');
$this->session->getFlashBag()->add('warning', 'You need to setup the references for the parameters before starting the work');
if ($route != 'references'){
$url = $this->router->generate('references');
$redirect = new RedirectResponse($url);
$redirect->send();
}
}
}
Here is services.yml
build.references:
class: AdminBundle\EventListener\BuildReferencesEventListener
arguments: ['#doctrine.orm.entity_manager', '#router', '#request_stack', '#session']
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
Add argument inside your service.yml event listner service section
Your.service:
Class: AdminBundle\EventListener\BuildReferencesEventListener
arguments: ['#doctrine.orm.entity_manager']
tags:
- { name: kernel.event_listener, event: kernel.controller }
And add this __cunstruct code inside your listner:
namespace AdminBundle\EventListener;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Doctrine\ORM\EntityManager;
class BuildReferencesEventListener
{
protected $em;
function __construct(EntityManager $em)
{
$this->em = $em;
}
public function onKernelController(FilterControllerEvent $event)
{
//TO DO call doctrine
// $em = Enity Manager...
// $em->getRepository...
// I hope its clear enough what im trying to do
}
In Symfony 3.4 and above, autowiring is enabled by default, so you just have to add a type-hinted argument to your service's constructor method and a private property to assign the argument's value to.
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
class BuildReferencesEventListener
{
private $em;
public __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public function onKernelController(FilterControllerEvent $event)
{
$em = this->em;
// [...]
}
}
If you need to
declare arguments explicitly, you could do this in your service configuration:
# config/services.yaml
services:
# ... same code as before
# explicitly configure the service
AdminBundle\EventListener\BuildReferencesEventListener:
arguments:
$em: '#doctrine.orm.entity_manager_interface'
This could be useful to pass parameters that the service container doesn't know.
To learn more about the service container, https://symfony.com/doc/3.4/service_container.html#injecting-services-config-into-a-service.

How do redirecting, in my exception, if exception call on controller, which render in twig

I need to redirect from the controller rendered in twig, which is available in the example along the route "/login_form"
On production don't work, on dev work, i'm confused as to how to get this code to work in the producion?
Symfony 3.4
The code is made only as an example for the test
services.yml:
services:
kernel.listener.redirectexception:
class: AppBundle\EventListener\RedirectExceptionListener
arguments:
- "#router"
tags:
- { name: kernel.event_listener, event: kernel.exception }
DefaultController.php:
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Exception\RedirectException;
class DefaultController extends Controller
{
/**
* #Route("/", name="homepage")
*/
public function indexAction(Request $request)
{
return $this->render('default/index.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.project_dir')).DIRECTORY_SEPARATOR,
]);
}
/**
* #Route("/login", name="login")
*/
public function loginAction(Request $request)
{
if ($this->getUser()) {
throw new RedirectException('This user does not have access to this section.');
}
return $this->render('default/login.html.twig', []);
}
/**
* #Route("/login_form", name="login_form")
*/
public function loginFormAction(Request $request)
{
return $this->render('default/login_form.html.twig', []);
}
}
RedirectExceptionListener.php:
<?php
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use AppBundle\Exception\RedirectException;
use Symfony\Component\Routing\RouterInterface;
class RedirectExceptionListener
{
private $router;
public function __construct(RouterInterface $router)
{
$this->router = $router;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
if ((!$event->getException()->getPrevious() instanceof RedirectException)
&& (!$event->getException() instanceof RedirectException)) {
return;
}
$response = new RedirectResponse($this->router->generate('homepage'));
$event->setResponse($response);
}
}
login_form.html.twig:
{{ render(controller('AppBundle:Default:login')) }}

how to redirect after login success by using EventListener

I have a problem in the code of event listener because i need to make a EventListener when i login as type 1 ==>redirect to:
return $this->redirect($this->generateUrl('demands_patient'));
else redirect to another path .And this is the code of loginlistener
use Doctrine\ORM\Event\LifecycleEventArgs;
use Register\UserBundle\Entity\User;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Core\AuthenticationEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class LoginListener implements EventSubscriberInterface
{
private $router;
public function __construct(UrlGeneratorInterface $router)
{
$this->router = $router;
}
public static function onSecurityInteractiveLogin()
{
return array(
FOSUserEvents::AUTHENTICATION_SUCCESS => 'redirectlogin',
);
}
public function redirectlogin(InteractiveLoginEvent $event)
{
$user = $event->getUser();
if($user->getType()=="1")
{
return $this->redirect($this->generateUrl('demands_patient'));
}
else
{
return $this->redirect($this->generateUrl('demands'));
}
}
}
and i add configuration in services.yml:
register_user.eventlistener.loginlistener:
class: Register\UserBundle\EventListener\LoginListener
arguments: [#router]
tags:
- { name: kernel.onSecurityInteractiveLogin }
Just today I faced a similar problem.
My solution was to use a Handler instead of a Listener, as explained in http://www.reecefowell.com/2011/10/26/redirecting-on-loginlogout-in-symfony2-using-loginhandlers/
What I did is:
In my bundle's `services.yml':
parameters:
cambra_comunitats.handler.user_login_redirect_handler.class: Cambra\ComunitatsBundle\Handler\UserLoginRedirectHandler
services:
cambra_comunitats.handler.user_login_redirect_handler:
class: "%cambra_comunitats.handler.user_login_redirect_handler.class%"
arguments: [#router, #security.context]
tags:
- { name: 'monolog.logger', channel: 'security' }
Then, I created the Cambra\ComunitatsBundle\Handler\UserLoginRedirectHandler class:
class UserLoginRedirectHandler implements \Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface
{
protected $router;
protected $security;
public function __construct(\Symfony\Component\Routing\Router $router, \Symfony\Component\Security\Core\SecurityContext $security)
{
$this->router = $router;
$this->security = $security;
}
public function onAuthenticationSuccess(\Symfony\Component\HttpFoundation\Request $request, \Symfony\Component\Security\Core\Authentication\Token\TokenInterface $token)
{
if ($this->security->isGranted('ROLE_ADMIN') && $this->security->getToken()->getUser()->isMustRedirect())
{
$response = new \Symfony\Component\HttpFoundation\RedirectResponse($this->router->generate('new_destination'));
} else
{
$referer_url = $this->router->generate('index_page');
$response = new \Symfony\Component\HttpFoundation\RedirectResponse($referer_url);
}
return $response;
}
}
And, finally, I enabled it on security.yml, inside of firewalls.main.form_login:
//.....
firewalls:
//...
main:
//...
form_login:
//...
success_handler: cambra_comunitats.handler.user_login_redirect_handler

FatalErrorException: Error: Call to a member function has() on a non-object symfony

I am using a symfony controller as a service.But when I call doctrine manager in the controller it gives the error FatalErrorException: Error: Call to a member function has() on a non-object.
Here is my controller:
namespace Acme\StoreBundle\Controller;
use Doctrine\ORM\EntityManager;
class ServiceController extends Controller {
/**
*
* #var EntityManager
*/
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
}
and my services.yml is like:
services:
service_controller:
class: Acme\StoreBundle\Controller\ServiceController
arguments: ["#doctrine.orm.entity_manager"]
I am calling the entity manager in an other controller which DbController:
<?php
public function users()
{
$query = $this->em->createQuery('select u from AcmeStoreBundle:User u');
$user = $query->getResult();
}
You can get the EntityManager in ServiceController likeļ¼š
$em = $this->getDoctrine()->getManager();
so the following codes make no sense:
service_controller:
class: Acme\StoreBundle\Controller\ServiceController
arguments: ["#doctrine.orm.entity_manager"]
And i really want to see your DbController codes, can you show that?
My DbController is like:
<?php
namespace Acme\StoreBundle\Controller;
use Acme\StoreBundle\Entity\UserCategoryTag;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DbController extends Controller
{
//Suppose you want get all users you can do some like this..
public function Users() {
$em = $this->getDoctrine()->getManager();
$repository = $em->getRepository('AcmeStoreBundle:User');
$user = $repository->findAll();
}
}
You can also get using per-execute method like follow:
1] Create new listener class for pre-execute method
namespace Acme\Listener;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
/**
* Acme\Listener\ControllerListener
*/
class ControllerListener
{
/**
* On Core Controller this is used to set pre execute
*
* #param GetResponseEvent $event
*/
public function onCoreController(FilterControllerEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) {
$_controller = $event->getController();
if (isset($_controller[0])) {
$controller = $_controller[0];
if (method_exists($controller, 'preExecute')) {
$controller->preExecute();
}
}
}
}
}
2] configure listener in your config file app/config/config.yml
services:
controller.pre_execute_listener:
class: Acme\Listener\ControllerListener
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onCoreController }
3] controller file
namespace Acme\StoreBundle\Controller;
use Doctrine\ORM\EntityManager;
class ServiceController extends Controller {
public function preExecute()
{
$this->em = $this->getDoctrine()->getEntityManager();
}
}
4] your function
<?php
public function users()
{
$query = $this->em->createQuery('select u from AcmeStoreBundle:User u');
$user = $query->getResult();
}
I solved this by trying a lot of things.
Here is the solution for this :
You have to use your controller as service.I used TagClass Controller as a service.Here is my controller code:
<?php
namespace Acme\StoreBundle\Controller;
class TagClassController extends Controller
{
public $em;
public function __construct(Entity Manager $em)
{
$this->em = $em;
}
public function ParseWebsite($categoryid){
}
}
?>
For using this you have to define the controller as service in your services.yml like this:
parameters:
acme.controller.tagclass.class: Acme\StoreBundle\Controller\TagClassController
services:
acme.controller.tagclass:
class: "%acme.controller.tagclass.class%"
arguments: [ #doctrine.orm.entity_manager ]
And you can call any method with in TagClass like this:
$this->forward('acme.controller.tagclass:ParseWebsite',array($categoryid));

Resources