I am working in symfony sonata admin. I am trying to extend ProfileFOSUser1Controller but unable to extend it. I have tried by clearing the cache also but didn't work? This is my controller code:
<?php
namespace Application\Sonata\UserBundle\Controller;
use Sonata\UserBundle\Controller\ProfileFOSUser1Controller as BaseController;
/**
* Overwrite methods from the ProfileFOSUser1Controller if you want to change the behavior
* for the current profile
*
*/
class ProfileUserController extends BaseController
{
/**
* #throws AccessDeniedException
*
* #return Response|RedirectResponse
*/
public function editAuthenticationAction()
{
echo "here"; die;
$user = $this->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw new AccessDeniedException('This user does not have access to this section.');
}
$form = $this->get('sonata.user.authentication.form');
$formHandler = $this->get('sonata.user.authentication.form_handler');
$process = $formHandler->process($user);
if ($process) {
$this->setFlash('sonata_user_success', 'profile.flash.updated');
return $this->redirect($this->generateUrl('sonata_user_profile_show'));
}
return $this->render('SonataUserBundle:Profile:edit_authentication.html.twig', [
'form' => $form->createView(),
]);
}
}
have a look here How to Use Bundle Inheritance to Override Parts of a Bundle
I think your controller name should be ProfileFOSUser1Controller
This issue has been resolved, I have changed the class name to the same name as base class have: changed "ProfileUserController" to "ProfileFOSUser1Controller". Now its working fine.
Related
Im trying to override FOSUser RegistrationController. In SF2 I used to copy the controller in my AppBundle\Controller and add bundle inheritance
class AppBundle extends Bundle
{
public function getParent()
{
return 'FOSUserBundle';
}
}
In symfony 3 the bundle inheritance is not supported anymore, and when I do the same as above, I end up with errors saying that symfony cannot find the services used in this controller (cannot autowire..)
Does anyone has an idea how to override FOSUser in SF3 please ?
<?php
// src/Acme/UserBundle/Controller/RegistrationController.php
namespace Acme\UserBundle\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
class RegistrationController extends BaseController
{
public function registerAction()
{
$form = $this->container->get('fos_user.registration.form');
$formHandler = $this->container->get('fos_user.registration.form.handler');
$confirmationEnabled = $this->container->getParameter('fos_user.registration.confirmation.enabled');
$process = $formHandler->process($confirmationEnabled);
if ($process) {
$user = $form->getData();
/*****************************************************
* Add new functionality (e.g. log the registration) *
*****************************************************/
$this->container->get('logger')->info(
sprintf('New user registration: %s', $user)
);
if ($confirmationEnabled) {
$this->container->get('session')->set('fos_user_send_confirmation_email/email', $user->getEmail());
$route = 'fos_user_registration_check_email';
} else {
$this->authenticateUser($user);
$route = 'fos_user_registration_confirmed';
}
$this->setFlash('fos_user_success', 'registration.flash.user_created');
$url = $this->container->get('router')->generate($route);
return new RedirectResponse($url);
}
return $this->container->get('templating')->renderResponse('FOSUserBundle:Registration:register.html.twig', array(
'form' => $form->createView(),
));
}
}
from the official documentation
I'm not truly sure of my answer because i didnt override the FOS User Bundle but the Easy Admin Bundle in sf4. Here's what i did : create a new controller in src/Controller/MyCustomController. Next i extended MyCustomController with the Controller i wanted to overide :
<?php
namespace App\Controller;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AdminController as BaseAdminController;
class MyCustomController extends BaseAdminController {}
?>
I guess you can do the same in sf3 with the FosUserBundle.
Hope i'm right !
I have a problem with my FosUser login in this days i try to render the controller of my login html page in navbar and the login work well..
Now i put my site on the server, i clear the cache and after login the page refreshes without log in the site..
This is the controller
namespace FOS\UserBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
class SecurityController extends Controller
{
public function loginAction(Request $request)
{
/** #var $session \Symfony\Component\HttpFoundation\Session\Session */
$session = $request->getSession();
// get the error if any (works with forward and redirect -- see below)
if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(SecurityContextInterface::AUTHENTICATION_ERROR);
} elseif (null !== $session && $session->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
$error = $session->get(SecurityContextInterface::AUTHENTICATION_ERROR);
$session->remove(SecurityContextInterface::AUTHENTICATION_ERROR);
} else {
$error = null;
}
if (!$error instanceof AuthenticationException) {
$error = null; // The value does not come from the security component.
}
// last username entered by the user
$lastUsername = (null === $session) ? '' : $session->get(SecurityContextInterface::LAST_USERNAME);
$csrfToken = $this->has('form.csrf_provider')
? $this->get('form.csrf_provider')->generateCsrfToken('authenticate')
: null;
return $this->renderLogin(array(
'last_username' => $lastUsername,
'error' => $error,
'csrf_token' => $csrfToken,
));
}
/**
* Renders the login template with the given parameters. Overwrite this function in
* an extended controller to provide additional data for the login template.
*
* #param array $data
*
* #return \Symfony\Component\HttpFoundation\Response
*/
protected function renderLogin(array $data)
{
return $this->render('FOSUserBundle:Security:login.html.twig', $data);
}
public function checkAction()
{
throw new \RuntimeException('You must configure the check path to be handled by the firewall using form_login in your security firewall configuration.');
}
public function logoutAction()
{
throw new \RuntimeException('You must activate the logout in your security firewall configuration.');
}
}
How can i do??
Did you do a:
app/console cache:clear --env=prod
or a:
app/console cache:clear
You should use the first one for your production environment
https://reformatcode.com/browse
I'm curently developing an app on Symfony 2.5.0 using FOSUSerBundle, SonataAdminBundle and SonataUserBundle.
I've extended FOSUserbundle so my AppKernel.php has new Sonata\UserBundle\SonataUserBundle('FOSUserBundle') and I also generated my own Application\Sonata\UserBundle using Easy Extends.
In my Application\SonataUserBundle, i've overriden the ChangePasswordFOSUser1Controller as so:
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\HttpFoundation\Request;
use FOS\UserBundle\Model\UserInterface;
use Sonata\UserBundle\Controller\ChangePasswordFOSUser1Controller as BaseController;
class ChangePasswordFOSUser1Controller extends BaseController
{
public function changePasswordAction()
{
$user = $this->container->get('security.context')->getToken()->getUser();
if (!is_object($user) || !$user instanceof UserInterface)
{
throw new AccessDeniedException('This user does not have access to this section.');
}
$form = $this->container->get('fos_user.change_password.form');
$formHandler = $this->container->get('fos_user.change_password.form.handler');
$process = $formHandler->process($user);
if ($process)
{
$this->setFlash('fos_user_success', 'change_password.flash.success');
if ($user->getFirstConnection())
$user->setFirstConnection(false);
return new RedirectResponse($this->getRedirectionUrl($user));
}
return $this->container->get('templating')->renderResponse('SonataUserBundle:ChangePassword:changePassword.html.'.$this->container->getParameter('fos_user.template.engine'),
array('form' => $form->createView()));
}
/**
* {#inheritdoc}
*/
protected function getRedirectionUrl(UserInterface $user)
{
return $this->container->get('router')->generate('front_home');
}
/**
* #param string $action
* #param string $value
*/
protected function setFlash($action, $value)
{
$this->container->get('session')->getFlashBag()->set($action, $value);
}
}
The problem is: Whenever I go to my login page I see my controller's code printed twice in the "header section", right before the login form.
I've tried clearing my cache and VOILA ! cache is cleared but the same code gets printed twice in my shell. (yeah, I work with a shell)
I get the "bug" over and over again when clearing cache but on my login page it disappears after two page refresh.
Have anyone tried overriding that controller or got a similar error ? (would be a shame no one had)
Thx for the help !
<?php
Missing on ChangePasswordFOSUser1Controller.php
The code was defined as interpretable and so printed as plain text on every html page.
Version : Symfony 2.2
I'm trying to add a default role when a user register on my website. I use FOSUserBundle and i see that when a user register the role field is empty in a database.
I begin with this huge bundle and it's not very easy to understand. So i read all the documentation and i'm not sur what to do.
For now, i create an Event to add this role dynamically, but it doesn't work (i have no error but my database is still empty) I'm not even sur this is the good way to do that ?
My Event :
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class AddDefaultRoleListener implements EventSubscriberInterface {
private $container;
public function __construct(Container $container)
{
$this->container = $container;
}
/**
* {#inheritDoc}
*/
public static function getSubscribedEvents()
{
return array(
FOSUserEvents::REGISTRATION_SUCCESS => 'onAddDefaultRoleSuccess',
);
}
public function onAddDefaultRoleSuccess(FormEvent $event)
{
$doctrine = $this->container->get('doctrine');
$em = $doctrine->getManager();
$user = $event->getForm()->getData();
$user->addRole('ROLE_USER');
//$user->setRoles(array('ROLE_USER'));
$em->persist($user);
}
}
As you see i create a simple event which listen on REGISTRATION_SUCCESS, but nothing seems to work. It's my first try with Events and services. So if someone has an advice, i'll take it :)
The recommended way to do it as indicated by a main contributor to the FOSUserBundle (in the comment here linked) is to register an Event Listener on the REGISTRATION_SUCCESS event and use the $event->getForm()->getData() to access the user and modify it.
Following those guidelines, I created the following listener (which works!):
<?php
// src/Acme/DemoBundle/EventListener/RegistrationListener.php
namespace Acme\DemoBundle\EventListener;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Listener responsible for adding the default user role at registration
*/
class RegistrationListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
FOSUserEvents::REGISTRATION_SUCCESS => 'onRegistrationSuccess',
);
}
public function onRegistrationSuccess(FormEvent $event)
{
$rolesArr = array('ROLE_USER');
/** #var $user \FOS\UserBundle\Model\UserInterface */
$user = $event->getForm()->getData();
$user->setRoles($rolesArr);
}
}
Also, the service needs to be registered as follows:
// src/Acme/DemoBundle/Resources/config/services.yml
services:
demo_user.registration_listener:
class: Acme\DemoBundle\EventListener\RegistrationListener
arguments: []
tags:
- { name: kernel.event_subscriber }
Notice that adding a default role in the User class __construct() may have some issues as indicated in this other answer.
What i have done is override the entity constructor:
Here a piece of my Entity/User.php
public function __construct()
{
parent::__construct();
// your own logic
$this->roles = array('ROLE_USER');
}
This is the lazy way. If you want the right and better way see the #RayOnAir answer
I think #RayOnAir solution is right way of doing this. But it will not work due to FOS default role handling
to make possible to persist default role in database one need to override User::setRoles() method (add it to your User entity):
/**
* Overriding Fos User class due to impossible to set default role ROLE_USER
* #see User at line 138
* #link https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Model/User.php#L138
* {#inheritdoc}
*/
public function addRole($role)
{
$role = strtoupper($role);
if (!in_array($role, $this->roles, true)) {
$this->roles[] = $role;
}
return $this;
}
Tested under:
Symfony version 2.3.6,
FOSUserBundle 2.0.x-dev
You can add an Event Subscriber to a Form Class and use the form event "formEvents::POST_SUBMIT"
<?php
//src/yourNS/UserBundle/Form/Type/RegistrationFormType.php
use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
use yourNS\UserBundle\Form\EventListener\AddRoleFieldSubscriber;
class RegistrationFormType extends BaseType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
// add your custom field
$builder->add('firstName')
->add('lastName')
->add('address')
//...
//...
->add('phone');
$builder->addEventSubscriber(new AddRoleFieldSubscriber());
}
public function getName()
{
return 'yourNS_user_registration';
}
}
Now the logic for adding the role field resides in it own subscriber class
<?php
//src/yourNS/UserBundle/Form/EventListener/AddRoleFieldSubscriber.php
namespace yourNS\UserBundle\Form\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AddRoleFieldSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(FormEvents::POST_SUBMIT => 'setRole');
}
public function setRole(FormEvent $event)
{
$aRoles = array('ROLE_USER');
/** #var $user \FOS\UserBundle\Model\UserInterface */
$user = $event->getForm()->getData();
$user->setRoles($aRoles);
}
}
Ok now it's working with that :
public function onAddDefaultRoleSuccess(FilterUserResponseEvent $event)
{
$doctrine = $this->container->get('doctrine');
$em = $doctrine->getManager();
$user = $event->getUser();
$user->addRole('ROLE_BLOGGER');
$em->persist($user);
$em->flush();
}
I change my listener and know use REGISTRATION_COMPLETED. If someone has a better idea to do that, don't hesitate :)
public function __construct()
{
parent::__construct();
$this->setRoles(["ROLE_WHATEVER"]);
}
I would like to override the ProfileController's edit action of FosUserBundle. I've created the controller in my own UserBundle, copied the edit action into it and made some changes. In this controller there is a check if the logged in user is an instanceOf UserInterFace. Apparently it's not because it throws an access denied exception when I go to /profile/edit
Why isn't the logged in user an instanceOf UserInterFace anymore?
Controller:
namespace Tennisconnect\UserBundle\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use FOS\UserBundle\Controller\ProfileController as BaseController;
class ProfileController extends BaseController
{
/**
* Edit the user
*/
public function editAction()
{
$user = $this->container->get('security.context')->getToken()->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw new AccessDeniedException('This user does not have access to this section.');
}
$form = $this->container->get('fos_user.profile.form');
$formHandler = $this->container->get('fos_user.profile.form.handler');
$process = $formHandler->process($user);
if ($process) {
$user->upload();
$this->setFlash('fos_user_success', 'profile.flash.updated');
return new RedirectResponse($this->container->get('router')->generate('fos_user_profile_show'));
}
return $this->container->get('templating')->renderResponse(
'FOSUserBundle:Profile:edit.html.'.$this->container->getParameter('fos_user.template.engine'),
array('form' => $form->createView(), 'theme' => $this->container->getParameter('fos_user.template.theme'))
);
}
}
Reading your code snippet, I would say it's simply because you don't match the full qualified namespace of UserInterface.
Either import the class with:
use Symfony\Component\Security\Core\User\UserInterface;
or modify your code like this:
if (!is_object($user) || !$user instanceof Symfony\Component\Security\Core\User\UserInterface) {
The cleaner solution is to create a new Bundle "MyFOSBundle", in the bundle class :
getParent()
{
return "FosBundle";
}
Then you write the file you want override on the same location.
http://symfony.com/doc/master/cookbook/bundles/inheritance.html