overriding template of password change fos user bundle - symfony

HI everyone Im working on a project using FOSUserBundle to manage users inside the application, what I want to do is to - almost the same thing as - move/copy the template of password change inside a page that contains the profile of the current user, it works fine, it displays for me ChangePasswordFormType, however when I submit the changes to the controller it gives me an error like this :
Catchable Fatal Error: Argument 1 passed to User\UserBundle\Entity\Acces::checkAllFields() must be an instance of Symfony\Component\Validator\ExecutionContext, instance of Symfony\Component\Validator\Context\ExecutionContext given
thats my controller :
$request = $this->get('request');
$em = $this->getDoctrine()->getManager();
$roles = $em->getRepository('AdminAdminBundle:Role')->findAll();
$userManager = $this->get('fos_user.user_manager');
$user = new \User\UserBundle\Entity\Acces();
$user = $this->container->get('security.context')->getToken()->getUser();
/** #var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
$dispatcher = $this->container->get('event_dispatcher');
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::CHANGE_PASSWORD_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
/** #var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
$formFactory = $this->container->get('fos_user.change_password.form.factory');
$form = $formFactory->createForm();
$form->setData($user);
$currentuser = $user;
$personnel = $em->getRepository('AdminAdminBundle:Personnel')->findBy(array('acces' => $user));
$user = $this->container->get('security.context')->getToken()->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw new AccessDeniedException('Cet utilisateur n\'a pas d\'acces à ce contenu.');
}
if ($request->isMethod('POST')) {
/** #var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
$formFactory = $this->get('fos_user.change_password.form.factory');
$form = $formFactory->createForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isValid()) {
/** #var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->container->get('fos_user.user_manager');
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::CHANGE_PASSWORD_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->container->get('router')->generate('personnel_profile');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::CHANGE_PASSWORD_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
}
The View code is :
<form role="form" name="passchange" method="post" {{ form_enctype(password_form) }} action="{{ path('personnel_update_personnal') }}" id="form_sample_2">
<input type="hidden" name="passchange" value="0" />
<div class="form-group">
<label class="control-label">Mot de passe actuel</label>
{{ form_widget(password_form.current_password,{ 'attr': {'required': 'required', 'class':'form-control'} }) }}
<span class="help-block">
{{ form_errors(password_form.current_password) }} </span>
</div>
<div class="form-group">
<label class="control-label">Nouveau mot de passe</label>
{{ form_widget(password_form.plainPassword.first,{ 'attr': {'required': 'required', 'class':'form-control'} }) }}
<span class="help-block">
{{ form_errors(password_form.plainPassword.first) }} </span>
</div>
<div class="form-group">
<label class="control-label">Confirmation mot de passe</label>
{{ form_widget(password_form.plainPassword.second,{ 'attr': {'required': 'required', 'class':'form-control'} }) }}
<span class="help-block">
{{ form_errors(password_form.plainPassword.second) }} </span>
</div>
<div class="margin-top-10">
<button type="submit" class="btn green-haze">Valider le changement</button>
<button type="reset" class="btn default reset">Annuler le changement</button>
</div>
</form>
A simple note: The entity User (of the userBundle) in my case is named Acces
The error given above is generated on the line : $form->handleRequest($request);
Plz if someone has encountered this error, any info could be helpful
Thanks a lot.
Edit : the Use Entity :
namespace User\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Symfony\Component\Validator\ExecutionContext;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
* #Assert\Callback(methods={"checkAllFields"})
* #ORM\AttributeOverrides({
* #ORM\AttributeOverride(name="username", column=#ORM\Column(nullable=true)),
* #ORM\AttributeOverride(name="email", column=#ORM\Column(nullable=true)),
* #ORM\AttributeOverride(name="password", column=#ORM\Column(nullable=true)),
* })
*/
class Acces extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="\Admin\AdminBundle\Entity\Role" )
* #ORM\JoinColumn(name="role_id", referencedColumnName="id")
* #Assert\Null(groups={"Registration"})
*/
private $role;
public function __construct()
{
parent::__construct();
// your own logic
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set role
*
* #param \Admin\AdminBundle\Entity\Role $role
* #return Acces
*/
public function setRole(\Admin\AdminBundle\Entity\Role $role = null)
{
$this->role = $role;
return $this;
}
/**
* Get role
*
* #return \Admin\AdminBundle\Entity\Role
*/
public function getRole()
{
return $this->role;
}
public function checkAllFields(ExecutionContext $context) {
if (!(($this->username == null && $this->password == null && $this->email == null && $this->role == null )
|| ($this->username != null && $this->password != null && $this->email != null && $this->role != null )
)) {
$context->validate($this->getRole(), 'Acces', array("Registration"));
}
}
public function __toString() {
return parent::__toString();
}
}

Related

add remeber me to Symfony 4.2 Security with custom User Entity

I'm working with Symfony 4.2,
I'm working with Security Component and I'm trying to add remember me.
At first Remember Me worked for me, but when my User Entity Became Customized, the remember me doesn't work anymore,
My Custom User:
I'm connected to a wordpress DB that I can't do any change on it ( I must Read Only ),
And I need to add some field to the User, So I have to create a new table User OneToOne with WpUsers (wordpress Users),
So, I use doctrine to create entity from the existing DB, I didn't touch to those entities, I just create my User Entity just to add roles field to the User System:
Wordpress pass is hashed with phpass.
Entity\WpUsers (generated by doctrine):
/**
* WpUsers
*
* #ORM\Table(name="wp_users", indexes={#ORM\Index(name="user_nicename", columns={"user_nicename"}), #ORM\Index(name="user_login_key", columns={"user_login"}), #ORM\Index(name="user_email", columns={"user_email"})})
* #ORM\Entity(repositoryClass="App\Repository\WpUsersRepository")
*/
class WpUsers
{
/**
* #var int
*
* #ORM\Column(name="ID", type="bigint", nullable=false, options={"unsigned"=true})
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="user_login", type="string", length=60, nullable=false)
*/
private $userLogin = '';
/**
* #var string
*
* #ORM\Column(name="user_pass", type="string", length=255, nullable=false)
*/
private $userPass = '';
/**
* #var string
*
* #ORM\Column(name="user_nicename", type="string", length=50, nullable=false)
*/
private $userNicename = '';
/**
* #var string
*
* #ORM\Column(name="user_email", type="string", length=100, nullable=false)
*/
private $userEmail = '';
/**
* #var string
*
* #ORM\Column(name="user_url", type="string", length=100, nullable=false)
*/
private $userUrl = '';
/**
* #var \DateTime
*
* #ORM\Column(name="user_registered", type="datetime", nullable=false, options={"default"="0000-00-00 00:00:00"})
*/
private $userRegistered = '0000-00-00 00:00:00';
/**
* #var string
*
* #ORM\Column(name="user_activation_key", type="string", length=255, nullable=false)
*/
private $userActivationKey = '';
/**
* #var int
*
* #ORM\Column(name="user_status", type="integer", nullable=false)
*/
private $userStatus = '0';
/**
* #var string
*
* #ORM\Column(name="display_name", type="string", length=250, nullable=false)
*/
private $displayName = '';
Entity\User.php:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="json_array")
*/
private $roles = [];
/**
* #ORM\OneToOne(targetEntity="App\Entity\WpUsers", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="wp_user_id", referencedColumnName="ID",nullable=false)
*/
private $wpUser;
public function getId(): ?int
{
return $this->id;
}
/**
* A visual identifier that represents this user.
*
* #see UserInterface
*/
public function getUsername(): string
{
return $this->getWpUser()->getUserLogin();
}
/**
* #see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* #see UserInterface
*/
public function getPassword()
{
return $this->getWpUser()->getUserPass();
}
/**
* #see UserInterface
*/
public function getSalt()
{
// not needed for apps that do not check user passwords
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getWpUser(): ?WpUsers
{
return $this->wpUser;
}
public function setWpUser(WpUsers $wpUser): self
{
$this->wpUser = $wpUser;
return $this;
}
}
security.yaml:
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
# encoders:
# App\Entity\WpUsers:
# algorithm: bcrypt
providers:
# in_memory: { memory: ~ }
app_user_provider:
entity:
class: App\Entity\User
property: wpUser.userLogin
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
guard:
authenticators:
- App\Security\LoginFormAuthenticator
remember_me:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
Security\LoginFormAuthenticator:
namespace App\Security;
// use ...
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
use TargetPathTrait;
private $entityManager;
private $urlGenerator;
private $csrfTokenManager;
// private $passwordEncorder;
private $router;
public function __construct(
EntityManagerInterface $entityManager,
UrlGeneratorInterface $urlGenerator,
CsrfTokenManagerInterface $csrfTokenManager,
// UserPasswordEncoderInterface $passwordEncorder,
// PasswordHash $passwordHash
RouterInterface $router
)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
// $this->passwordEncorder = $passwordEncorder;
$this->router = $router;
$this->passwordHash = new PasswordHash(8,false);
}
public function supports(Request $request)
{
return 'app_login' === $request->attributes->get('_route')
&& $request->isMethod('POST');
}
public function getCredentials(Request $request)
{
$credentials = [
'userLogin' => $request->request->get('userLogin'),
'password' => $request->request->get('password'),
'csrf_token' => $request->request->get('_csrf_token'),
];
$request->getSession()->set(
Security::LAST_USERNAME,
$credentials['userLogin']
);
return $credentials;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token)) {
throw new InvalidCsrfTokenException();
}
$wpUser = $this->entityManager->getRepository(WpUsers::class)->findOneBy(['userLogin' => $credentials['userLogin']]);
if (!$wpUser) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('User Login could not be found.');
}
$user = $this->entityManager->getRepository(User::class)->findOneBy(['wpUser' => $wpUser ]);
if(!$user){
$user = new USER();
$user->setWpUser($wpUser);
$this->entityManager->persist($user);
$this->entityManager->flush();
}
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token)) {
throw new InvalidCsrfTokenException();
}
// return $this->passwordEncorder->isPasswordValid($user, $credentials['password']);
return $this->passwordHash->CheckPassword($credentials['password'],$user->getPassword());
// Check the user's password or other credentials and return true or false
// If there are no credentials to check, you can just return true
throw new \Exception('TODO: check the credentials inside '.__FILE__);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}
// For example : return new RedirectResponse($this->urlGenerator->generate('some_route'));
// throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
return new RedirectResponse($this->router->generate('commandes'));
}
protected function getLoginUrl()
{
return $this->urlGenerator->generate('app_login');
}
}
login.twig.html:
{% extends 'myBase.html.twig' %}
{% block title %}Log in!{% endblock %}
{% block body %}
<form method="post">
{% if error %}
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<label for="inputUserLogin" class="sr-only">User Login</label>
<input type="text" value="{{ last_username }}" name="userLogin" id="inputUserLogin" class="form-control" placeholder="User Login" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required>
<input type="hidden" name="_csrf_token"
value="{{ csrf_token('authenticate') }}"
>
<!-- Uncomment this section and add a remember_me option below your firewall to activate remember me functionality.
See https://symfony.com/doc/current/security/remember_me.html -->
<div class="checkbox mb-3">
<label>
<input type="checkbox" name="_remember_me"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary" type="submit">
Sign in
</button>
</form>
{% endblock %}
I believe what you are missing is a supportsRememberMe() Guard Authenticator method. As you can read in the documentation:
supportsRememberMe()
If you want to support "remember me" functionality, return true from this method. You will still
need to activate remember_me under your firewall for it to work...
So the solution should be adding above mentioned method to your authenticator:
public function supportsRememberMe()
{
return true;
}
The Answer is that I have to implement a custom User Provider because my loading User Process is not related to direct Entity.
bin/console make:user
And choose that the user shouldn't be saved in the DB, So that the CLI will create for you the UserProvider.

Syfmony: upload files with dropzone

I'm developing a king of simple CMS, with Symfony 4.1.
Regarding my question, we have 2 entities:
Post Entity:
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="App\Repository\PostRepository")
*/
class Post extends BaseEntity
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="text")
*/
private $content;
/**
* #ORM\Column(type="boolean")
*/
private $status;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Category", inversedBy="posts")
*/
private $categories;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Picture", mappedBy="post", orphanRemoval=true, cascade={"persist"})
*/
private $pictures;
/**
* #Assert\All({#Assert\Image(mimeTypes="image/jpeg")})
*
*/
private $pictureFiles;
/**
* Post constructor.
*/
public function __construct()
{
$this->categories = new ArrayCollection();
$this->pictures = new ArrayCollection();
}
/**
* #return int|null
*/
public function getId(): ?int
{
return $this->id;
}
/**
* #return null|string
*/
public function getContent(): ?string
{
return $this->content;
}
/**
* #param string $content
* #return Post
*/
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
/**
* #return bool|null
*/
public function getStatus(): ?bool
{
return $this->status;
}
/**
* #param bool $status
* #return Post
*/
public function setStatus(bool $status): self
{
$this->status = $status;
return $this;
}
/**
* #return Collection|Category[]
*/
public function getCategories(): Collection
{
return $this->categories;
}
/**
* #param Category $category
* #return Post
*/
public function addCategory(Category $category): self
{
if (!$this->categories->contains($category)) {
$this->categories[] = $category;
}
return $this;
}
/**
* #param Category $category
* #return Post
*/
public function removeCategory(Category $category): self
{
if ($this->categories->contains($category)) {
$this->categories->removeElement($category);
}
return $this;
}
/**
* #return Collection|Picture[]
*/
public function getPictures(): Collection
{
return $this->pictures;
}
/**
* #param Picture $picture
* #return Post
*/
public function addPicture(Picture $picture): self
{
if (!$this->pictures->contains($picture)) {
$this->pictures[] = $picture;
$picture->setPost($this);
}
return $this;
}
/**
* #param Picture $picture
* #return Post
*/
public function removePicture(Picture $picture): self
{
if ($this->pictures->contains($picture)) {
$this->pictures->removeElement($picture);
if ($picture->getPost() === $this) {
$picture->setPost(null);
}
}
return $this;
}
/**
* #return mixed
*/
public function getPictureFiles()
{
return $this->pictureFiles;
}
/**
* #param $pictureFiles
* #return Post
*/
public function setPictureFiles($pictureFiles): self
{
foreach ($pictureFiles as $pictureFile) {
/** #var Picture $picture */
$picture = new Picture();
$picture->setImageFile($pictureFile);
$this->addPicture($picture);
}
$this->pictureFiles = $pictureFiles;
return $this;
}
}
Picture Entity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\File;
/**
* #ORM\Entity(repositoryClass="App\Repository\PictureRepository")
*/
class Picture
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var File|null
* #Assert\Image(mimeTypes="image/jpeg")
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255)
*/
private $filename;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Post", inversedBy="pictures")
* #ORM\JoinColumn(nullable=false)
*/
private $post;
/**
* #return int|null
*/
public function getId(): ?int
{
return $this->id;
}
/**
* #return File|null
*/
public function getImageFile(): ? File
{
return $this->imageFile;
}
/**
* #param File|null $imageFile
* #return Picture
*/
public function setImageFile(? File $imageFile): self
{
$this->imageFile = $imageFile;
return $this;
}
/**
* #return string|null
*/
public function getFilename(): ?string
{
return $this->filename;
}
/**
* #param string $filename
* #return Picture
*/
public function setFilename(string $filename): self
{
$this->filename = $filename;
return $this;
}
/**
* #return Post|null
*/
public function getPost(): ?Post
{
return $this->post;
}
/**
* #param Post|null $post
* #return Picture
*/
public function setPost(?Post $post): self
{
$this->post = $post;
return $this;
}
}
So for adding a Post, I have a PostType:
<?php
namespace App\Form;
use App\Entity\Category;
use App\Entity\Post;
use FOS\CKEditorBundle\Form\Type\CKEditorType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Class PostType
* #package App\Form
*/
class PostType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('content', CKEditorType::class)
->add('categories', EntityType::class,
[
'class' => Category::class,
'required' => true,
'choice_label' => 'name',
'multiple' => true,
]
)
->add('pictureFiles', FileType::class,
[
'required' => false,
'multiple' => true,
'label' => 'Add files...',
'attr' =>
[
'action' => '%kernel.project_dir%/public/media/posts'
]
]
)
->add('status')
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Post::class,
]);
}
}
The view corresponding to that form:
{% form_theme form '/admin/form/switch_btn_layout.html.twig' %}
{{ form_start(form) }}
{{ form_errors(form) }}
<div class="form-row">
<div class="col-md-6">
{{ form_row(form.name) }}
{{ form_row(form.categories) }}
{{ form_row(form.status) }}
</div>
<div class="col-md-6 dropzone" id="postDropzone">
{{ form_row(form.pictureFiles, {'attr': {'class': 'dropzone'}} ) }}
<div class="dropzone-previews" style="border: 1px solid red"></div>
</div>
</div>
<div class="form-group">
{{ form_row(form.content) }}
</div>
<div class="form-group">
{{ form_row(form.status) }}
</div>
{{ form_rest(form) }}
<button class="btn btn-success btn-lg btn-block" id="postSubmit">
{{ button_label|default('Save') }}
</button>
{{ form_end(form) }}
As you can see, the "input" for files as the dropzone css class.
Indeed, my project include the oneup_uploader bundle, for dropzone.
Here the configuration for oneup_uploader:
oneup_uploader:
mappings:
# This is a mapping example, remove it and create your own mappings.
post_image:
frontend: dropzone
namer: oneup_uploader.namer.uniqid
storage:
directory: '%kernel.project_dir%/public/media/posts'
And my script for Dropzone:
Dropzone.autoDiscover = false;
var postDropzone = new Dropzone('.dropzone', {
url: '%kernel.project_dir%/public/media/posts',
// url: 'file/post',
maxFiles: 10,
addRemoveLinks: true,
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
});
postDropzone.on("addedfile", function (file) {
file.previewElement.addEventListener("click", function () {
postDropzone.removeFile(file);
})
});
The issue for me is:
no file is save in the folder
the Post entity is save in my DB, but nothing is save for Pictures.
I also tried to not use OneUploaderBundle, and use VichUploader: the saving part in DB is perfect, but I can't link it to dropzone.
Some help guys ?
Thanks a lot !
Might be useful for new visitors.
You can use a library that extends Symfony Form and adds a new type DropzneType.
1.Install the library
composer require emrdev/symfony-dropzone
This way you will have a new form type DropzoneType
2.Use the type in your form like this
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder, array $options)
{
// userFiles is OneToMany
$builder->add('userFiles', DropzoneType::class, [
'class' => File::class,
'maxFiles' => 6,
'uploadHandler'=>'uploadHandler', // route name
'removeHandler'=> 'removeHandler'// route name
]);
}
Change the uploadHandler and removeHandler options to your endpoints
3.Route uploadHandler/removeHandler might look something like this
/**
* #Route("/uploadhandler", name="uploadHandler")
*/
public function uploadhandler(Request $request, ImageUploader $uploader) {
$doc = $uploader->upload($request->files->get('file'));
$file = new File();
$file->setSrc($doc['src']);
...
$this->getDoctrine()->getManager()->persist($file);
$this->getDoctrine()->getManager()->flush();
return new JsonResponse($file);
}
/**
* #Route("/removeHandler/{id}", name="removeHandler")
*/
public function removeHandler(Request $request,File $file = null) {
$this->getDoctrine()->getManager()->remove($file);
$this->getDoctrine()->getManager()->flush();
return new JsonResponse(true);
}
note that uploadhandler should return a File object
you should pass upload url instead of upload directory
generate url in twig - {{ oneup_uploader_endpoint('post_image') }}
var postDropzone = new Dropzone('.dropzone', {
url: '{{ oneup_uploader_endpoint('post_image') }}',
// url: '%kernel.project_dir%/public/media/posts',
// url: 'file/post',
maxFiles: 10,
addRemoveLinks: true,
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
});

Csrf token is invalid

i've been having the Csrf token is invalid I tried to add the {{ form_end(form) }}
or remove token from {{ form_widget(form._token) }} but it doens't work please help me fix this problem
here'is my registration content file
{% trans_default_domain 'FOSUserBundle' %}
<div class="login-container bg-white">
<div class="p-l-50 m-l-20 p-r-50 m-r-20 p-t-50 m-t-30 sm-p-l-15 sm-p-r-15 sm-p-t-40">
<img src="assets/img/logo.png" alt="logo" data-src="assets/img/logo.png"
data-src-retina="assets/img/logo_2x.png" width="78" height="22">
<p class="p-t-35">Sign into your pages account</p>
<form action="{{ path("fos_user_security_check") }}" method="post">
<div class="form-group form-group-default">
<label>Username</label>
<div class="controls">
{{ form_widget(form.username,{'attr' : {'class' : 'form-control' , 'placeholder' : 'E-mail'}}) }}
</div>
</div>
<div class="form-group form-group-default">
<label>E-mail</label>
<div class="controls">
{{ form_widget(form.email,{'attr' : {'class' : 'form-control' , 'placeholder' : 'E-mail'}}) }}
</div>
</div>
<div class="form-group form-group-default">
<label>Passowrd</label>
<div class="controls">
{{ form_widget(form.plainPassword.first,{'attr' : {'class' : 'form-control' , 'placeholder' : 'Mot de passe'}}) }}
</div>
</div>
<div class="form-group form-group-default">
<label>Passowrd</label>
<div class="controls">
{{ form_widget(form.plainPassword.second,{'attr' : {'class' : 'form-control' , 'placeholder' : 'Confirmez mot de passe'}}) }}
</div>
</div>
{{ form_rest(form) }}
{{ form_widget(form._token) }}
<input type="submit" value="{{ 'registration.submit'|trans }}"class="btn btn-primary btn-cons m-t-10" />
</form>
<div class="pull-bottom sm-pull-bottom">
<div class="m-b-30 p-r-80 sm-m-t-20 sm-p-r-15 sm-p-b-20 clearfix">
<div class="col-sm-3 col-md-2 no-padding">
<img alt="" class="m-t-5" data-src="assets/img/demo/pages_icon.png"
data-src-retina="assets/img/demo/pages_icon_2x.png" height="60"
src="assets/img/demo/pages_icon.png" width="60">
</div>
<div class="col-sm-9 no-padding m-t-10">
<p>
<small>
Create a pages account. If you have a facebook account, log into it for this
process. Sign in with Facebook or <a href="#"
class="text-info">Google</a>
</small>
</p>
</div>
</div>
</div>
</div>
</div>
<?php
/*
* This file is part of the FOSUserBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FOS\UserBundle\Controller;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Form\Factory\FactoryInterface;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Model\UserInterface;
use FOS\UserBundle\Model\UserManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
/**
* Controller managing the registration.
*
* #author Thibault Duplessis <thibault.duplessis#gmail.com>
* #author Christophe Coevoet <stof#notk.org>
*/
class RegistrationController extends Controller
{
/**
* #param Request $request
*
* #return Response
*/
public function registerAction(Request $request)
{
/** #var $formFactory FactoryInterface */
$formFactory = $this->get('fos_user.registration.form.factory');
/** #var $userManager UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
/** #var $dispatcher EventDispatcherInterface */
$dispatcher = $this->get('event_dispatcher');
$user = $userManager->createUser();
$user->setEnabled(true);
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $formFactory->createForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event);
if (null !== $response = $event->getResponse()) {
return $response;
}
}
return $this->render('#FOSUser/Registration/register.html.twig', array(
'form' => $form->createView(),
));
}
/**
* Tell the user to check their email provider.
*/
public function checkEmailAction()
{
$email = $this->get('session')->get('fos_user_send_confirmation_email/email');
if (empty($email)) {
return new RedirectResponse($this->get('router')->generate('fos_user_registration_register'));
}
$this->get('session')->remove('fos_user_send_confirmation_email/email');
$user = $this->get('fos_user.user_manager')->findUserByEmail($email);
if (null === $user) {
throw new NotFoundHttpException(sprintf('The user with email "%s" does not exist', $email));
}
return $this->render('#FOSUser/Registration/check_email.html.twig', array(
'user' => $user,
));
}
/**
* Receive the confirmation token from user email provider, login the user.
*
* #param Request $request
* #param string $token
*
* #return Response
*/
public function confirmAction(Request $request, $token)
{
/** #var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->findUserByConfirmationToken($token);
if (null === $user) {
throw new NotFoundHttpException(sprintf('The user with confirmation token "%s" does not exist', $token));
}
/** #var $dispatcher EventDispatcherInterface */
$dispatcher = $this->get('event_dispatcher');
$user->setConfirmationToken(null);
$user->setEnabled(true);
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_CONFIRM, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_CONFIRMED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
/**
* Tell the user his account is now confirmed.
*/
public function confirmedAction()
{
$user = $this->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw new AccessDeniedException('This user does not have access to this section.');
}
return $this->render('#FOSUser/Registration/confirmed.html.twig', array(
'user' => $user,
'targetUrl' => $this->getTargetUrlFromSession(),
));
}
/**
* #return mixed
*/
private function getTargetUrlFromSession()
{
$key = sprintf('_security.%s.target_path', $this->get('security.token_storage')->getToken()->getProviderKey());
if ($this->get('session')->has($key)) {
return $this->get('session')->get($key);
}
}
}

Assert does not works in my Form

I have a strange problem using a form in Symfony 3.
And my Assert does not works in my entity file.
In "the developer tools" it show the phrase but in the view all is in blank.
<?php
namespace TestBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* User
*
* #ORM\Table(name="users")
* #UniqueEntity("name")
* #UniqueEntity("email")
* #ORM\HasLifecycleCallbacks()
*/
class User implements UserInterface
{
/**
* #Assert\NotBlank()
* #Assert\NotBlank(message="Please enter your name.")
*/
private $name;
/**
* #Assert\NotBlank()
* #ORM\Column(type="string", length=50, nullable=false)
*/
private $sername;
/**
* #var string
* #Assert\NotBlank()
* #Assert\Email()
*/
private $email;
/**
* #var string
*/
private $password;
/**
* #var integer
*/
private $role;
/**
* #var \DateTime
*/
private $created;
/**
* #var integer
*/
private $id;
/**
* Set name
*
* #param string $name
*
* #return User
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set sername
*
* #param string $sername
*
* #return User
*/
public function setSername($sername)
{
$this->sername = $sername;
return $this;
}
/**
* Get sername
*
* #return string
*/
public function getSername()
{
return $this->sername;
}
/**
* Set email
*
* #param string $email
*
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set password
*
* #param string $password
*
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set role
*
* #param integer $role
*
* #return User
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
/**
* Get role
*
* #return integer
*/
public function getRole()
{
return $this->role;
}
/**
* Set created
*
* #param \DateTime $created
*
* #return User
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
public function getRoles()
{
return array($this->role);
}
public function getSalt()
{
return null;
}
public function eraseCredentials()
{
}
/**
* Get username
*
* #return string
*/
public function getUsername()
{
return null;
}
}
My form Action ( I put required in false to use the symfony valid option):
public function addAction(Request $request){
$user = new User();
$form = $this->createFormBuilder($user)
->add('Name', TextType::class,array('required'=> false,'empty_data' => null))
->add('SerName', TextType::class,array('required'=> false,'empty_data' => null))
->add('role', TextType::class,array('required'=> false,'empty_data' => null))
->add('email', EmailType::class,array('required'=> false,'empty_data' => null))
->add('password', RepeatedType::class, array(
'type' => PasswordType::class,
'first_name' => 'pass',
'second_name' => 'confirm',
'required' => false,
))
->add('save', SubmitType::class, array('label' => 'Create Post'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//$user = new Users();
// $form->getData() holds the submitted values
// but, the original `$task` variable has also been updated
$password = $form->get('password')->getData();
$encoder = $this->container->get('security.password_encoder');
$encoded = $encoder->encodePassword($user,$password);
$user->setPassword($encoded);
$user = $form->getData();
// ... perform some action, such as saving the task to the database
// for example, if Task is a Doctrine entity, save it!
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return $this->redirectToRoute('test_homepage');
}
//return $this->render('UserBundle:Default:add.html.twig');
return $this->render("TestBundle:Default:add.html.twig",array("form"=>$form->createView()));
}
EDIT (I PUT VIEW FILE):
My view:
{%extends "principal.html.twig"%}
{% block body %}
{{parent()}}
<h1> {% trans %}New User{% endtrans %}</h1>
{{ form_start(form,{'attr':{'novalidate':'novalidate','role':'form'}}) }}
{{ form_label(form.Name,'Username', {'label_attr': {'class': 'foo'}}) }}
{{ form_widget(form.Name,{'attr':{'class':'form-control'}}) }}
{{form_errors(form.Name)}}
{{ form_label(form.SerName,'Last name', {'label_attr': {'class': 'foo'}}) }}
{{ form_errors(form.SerName) }}
{{ form_widget(form.SerName,{'attr':{'class':'form-control'}}) }}
{{ form_label(form.role,'Role', {'label_attr': {'class': 'foo'}}) }}
{{ form_errors(form.role) }}
{{ form_widget(form.role,{'attr':{'class':'form-control'}}) }}
{{ form_label(form.email,'Email', {'label_attr': {'class': 'foo'}}) }}
{{ form_widget(form.email, {'attr':{'class':'form-control'}}) }}
{{ form_errors(form.email) }}
{{ form_label(form.password.pass, "Password", {'attr':{'class':'form-control'}}) }}
{{ form_errors(form.password) }}
{{ form_widget(form.password.pass, {'attr':{'class':'form-control'}}) }}
{{ form_label(form.password.confirm, "Confirm" , {'attr':{'class':'form-control'}}) }}
{{ form_widget(form.password.confirm, {'attr':{'class':'form-control'}}) }}
{{ form_widget(form.save, { 'label': 'Create User','attr':{'class':'btn btn-primary'}}) }}
{{ form_end(form) }}
{% endblock %}
You should read the doc about form rendering
In your twig template, you have to display the errors by using
{{ form_errors(form.age) }}
Or the whole row (label , error message, inpout) with
{{ form_row(form.age) }}
Which is almost equal to
<div>
{{ form_label(form.age) }}
{{ form_errors(form.age) }}
{{ form_widget(form.age) }}
</div>
In your case, it means you have to add form_errors this way:
{{ form_label(form.Name,'Username', {'label_attr': {'class': 'foo'}}) }}
{{ form_widget(form.Name,{'attr':{'class':'form-control'}}) }}
{{ form_errors(form.Name) }}

Symfony2 Doctrine2 trouble with optional one to many relation

I have a problem with Doctrine2 and two relationed entities.
There is a user-entity that can (not must) have one or a collection of social-entity referenced which contains a social network link.
I do not control Doctrine and I'm still learning relationship.
I want to add a user with/without adding social network link.
After several researches and testing, I am still unable to find a solution.
Here is my user-entity
<?php
//...
/**
* User
*
* #ORM\Table(name="admin_users")
* #ORM\Entity(repositoryClass="UserRepository")
* #ORM\HasLifecycleCallbacks()
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=25, unique=true)
*/
private $username;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=40)
*/
private $password;
/**
*
* #var string
*
* #Assert\NotBlank
*/
private $plainPassword;
//...
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="Social", mappedBy="user", cascade={"persist","remove"})
* #ORM\JoinColumn(nullable=true)
*/
private $socials;
public function __construct()
{
$this->socials = new ArrayCollection();
}
//Some getters setters
/**
* Add socials
*
* #param Social $socials
* #return User
*/
public function addSocials(Social $socials)
{
$this->socials[] = $socials;
$socials->setUser($this);
return $this;
}
/**
* Remove socials
*
* #param Social $socials
*/
public function removeSocials(Social $socials)
{
$this->socials->removeElement($socials);
}
/**
* Get socials
*
* #return Collection
*/
public function getSocials()
{
return $this->socials;
}
}
Here is the social-entity
<?php
/**
* Social
*
* #ORM\Table(name="admin_social")
* #ORM\Entity(repositoryClass="SocialRepository")
*/
class Social
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=20, nullable=true)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="url", type="string", length=255, nullable=true)
*/
private $url;
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="socials", cascade={"persist","remove"})
* #ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true)
*/
private $user;
//getters setters
/**
* Set user
*
* #param User $user
* #return Social
*/
public function setUser(User $user)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return User
*/
public function getUser()
{
return $this->user;
}
}
The userType code looks like this:
$builder
->add('username', 'text', array(
'attr'=> array('class' => 'span6',),
'label_attr' => array('class' => 'control-label'),
)
)
// ....
->add('sociaux', 'collection', array('type' => new SocialType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,))
;
Finally the controller code :
public function addAction()
{
$user = new User;
// Create the form
$form = $this->createForm( new UserType, $user );
// Gets the request
$request = $this->getRequest();
// Checks if the request have type POST
if ( $request->getMethod() == 'POST' ) {
// Links the request and the form
$form->bind( $request );
// Checks if all input values are correct
if ( $form->isValid() ) {
// Save user object in database
$em = $this->getDoctrine()->getManager();
// Persist entity user
$em->persist( $user );
$em->flush();
//...
}
}
//...
}
When I try to add a user without social-entity I have no error, but in the database I have in social table a row with null values. Please help.
UPDATE
In user-entity I added this :
if( !( $socials->getName() === null && $socials->getUrl() === null ) )
{
$this->socials[] = $socials;
$socials->setUser($this);
}
Now there is no row inserted in social table, but when I try editing the user, I have two collection field (duplicated).
See the screenshot
Here my template file (Twig) :
<div class="widget-body">
{{ form_start(form, { 'action': path('acme_admin_edit_user', {'id': userId}), 'attr': {'class': 'form-horizontal'} }) }}
<div class="control-group">
{{ form_errors(form.username) }}
{{ form_label(form.username) }}
<div class="controls">
{{ form_widget(form.username) }}
</div>
</div>
<!-- ... -->
<div id="acme_adminbundle_useredittype_socials" data-prototype="{{ form_row(form.socials.vars.prototype) | escape }}">
{% for social in form.socials %}
<div>
<label class="required text-primary lead">Lien n°{{ loop.index }}</label>
<div id="acme_adminbundle_useredittype_socials_{{ loop.index0 }}">
<div class="control-group">
{{ form_errors(social.name) }}
{{ form_label(social.name) }}
<div class="controls">
{{ form_widget(social.name) }}
</div>
</div>
<div class="control-group">
{{ form_errors(social.url) }}
{{ form_label(social.url) }}
<div class="controls">
{{ form_widget(social.url) }}
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<div class="txt-center well">
<input type="submit" class="auto-margin btn btn-primary btn-large" />
</div>
{{ form_end(form) }}
</div>
Try removing:
#ORM\JoinColumn(nullable=true)
from your User class. #JoinColumn should be defined only on one side of relationship and since Social entity contains name and referencedColumnName it is unnecessary inside the User.

Resources