I'm working in Sonata User Bundle avatar using Sonata Media Bundle. Every thing works as expected in Sonata Admin(Backend). i.e while updating form admin, only the old file is replaced.(works good).
Problem: While trying to edit user profile by custom form in frontend. The image uploads correctly and replacing the old one, but it additonally creating a new image in file folder, also a new entry in media. Only the new image id is added to the user entry(avatar), instead of old one. Normally only the old one will be used.
What I need is to edit/update old image and not to add new image&entry.
HINT : Folder permission is good - because it edit old file.
EXPECTED SOLUTION TO THE PROBLEM : How the new entry? instead of edit/update.!
User.php
namespace Application\Sonata\UserBundle\Entity;
// all use ... i deleted to reduce lines
/**
* @ORM\Table(name="fos__user_user")
* @ORM\Entity()
* @ORM\HasLifecycleCallbacks()
* @Assert\Callback(methods={ "isMediaSizeValid" })
*/
class User extends BaseUser {
/**
* @var string
*
* @ORM\OneToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media",cascade={"persist"} )
* @ORM\JoinColumns( { @ORM\JoinColumn( referencedColumnName="id", onDelete="CASCADE" ) } )
* @Assert\NotNull()
*/
private $profilePicture;
// generated getter and setter
public function setProfilePicture(\Application\Sonata\MediaBundle\Entity\Media $profilePicture = null) {
$this->profilePicture = $profilePicture;
return $this;
}
public function getProfilePicture() {
return $this->profilePicture;
}
public function isMediaSizeValid(ExecutionContextInterface $context) {
$this->fzValidateImage($context, $this->getProfilePicture());
}
private function fzValidateImage($context, $f) {
if ($f == NULL) {
// IMAGE can be null . If null it uses the default image
} else if ($f->getSize() > (self::FILE_SIZE * 1024)) {
$context->buildViolation('The file is too large ( %a% kb). Allowed maximum size is %b% kb.')->atPath(self::FILE_PATH)->setParameters(['%a%' => intval($f->getSize() / 1024), '%b%' => self::FILE_SIZE])->addViolation();
} else if ($f->getWidth() < self::FILE_MIN_WIDTH) {
$context->buildViolation('The image width is too small ( %a% px). Minimum width expected is %b% px.')->atPath(self::FILE_PATH)->setParameters(['%a%' => $f->getWidth(), '%b%' => self::FILE_MIN_WIDTH])->addViolation();
} else if ($f->getWidth() > self::FILE_MAX_WIDTH) {
$context->buildViolation('The image width is too big ( %a% px). Allowed maximum width is %b% px.')->atPath(self::FILE_PATH)->setParameters(['%a%' => $f->getWidth(), '%b%' => self::FILE_MAX_WIDTH])->addViolation();
} else if ($f->getHeight() < self::FILE_MIN_HEIGHT) {
$context->buildViolation('The image height is too small ( %a% px). Minimum height expected is %b% px.')->atPath(self::FILE_PATH)->setParameters(['%a%' => $f->getHeight(), '%b%' => self::FILE_MIN_HEIGHT])->addViolation();
} else if ($f->getHeight() > self::FILE_MAX_HEIGHT) {
$context->buildViolation('The image height is too big ( %a% px). Allowed maximum height is %b% px.')->atPath(self::FILE_PATH)->setParameters(['%a%' => $f->getHeight(), '%b%' => self::FILE_MAX_HEIGHT])->addViolation();
}
}
}
UserController.php type 1
/**
* @Route("/profile/edit", name="fz_user_profile_edit")
*/
public function editProfileAction(Request $request) {
$form = $this->get('sonata.user.profile.form');
$form->add('profilePicture', 'sonata_media_type', array(
'provider' => 'sonata.media.provider.image',
'context' => 'profile'
));
$form->get('profilePicture')->add('binaryContent', 'file', ['label' => 'Profile Picture']);
$form->get('profilePicture')->remove('unlink');
$formHandler = $this->get('sonata.user.profile.form.handler');
$process = $formHandler->process($user);
if ($process) {
$this->setFlash('notice', 'Profile updated!');
return $this->redirectToRoute('fz_user');
}
$x = ['cmf' => '', 'pTitle' => 'Profile'];
return $this->render('user/layout.html.twig', ['x' => $x, 'form' => $form->createView()]);
UserController.php type 2
/**
* @Route("/profile/edit", name="fz_user_profile_edit")
*/
public function editProfileAction(Request $request) {
$user = $this->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw $this->createAccessDeniedException('This user does not have access to this section.');
}
$builder = $this->createFormBuilder($user);
$builder->add('profilePicture', 'sonata_media_type', array(
'provider' => 'sonata.media.provider.image',
'context' => 'profile'
));
$form = $builder->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
$this->setFlash('notice', 'Profile updated!');
}
$x = ['cmf' => '', 'pTitle' => 'Profile'];
return $this->render('user/layout.html.twig', ['x' => $x, 'form' => $form->createView()]);
}
UserController.php type 1 - code is using FOSUserBundle. and UserController.php type 2 my custom code for symfony doc..
I solved for now by checking the file and delete. I think its a bundle error.
public function editProfileAction() {
$user = $this->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw $this->createAccessDeniedException('This user does not have access to this section.');
}
// Check user has allready media?
$om = $this->getUser()->getProfilePicture();
$oldPath = $om ? $this->getMediaPath($om->getId()) : NULL;
$form = $this->creteForm();
$formHandler = $this->get('sonata.user.profile.form.handler');
$process = $formHandler->process($user);
if ($process) {
// if new file - delete old file
$this->deleteOldMedia($om, $oldPath);
$this->setFlash('notice', 'Profile updated!');
return $this->redirectToRoute('fz_user');
}
$x = ['cmf' => '', 'pTitle' => 'Profile'];
return $this->render('user/layout.html.twig', ['x' => $x, 'form' => $form->createView()]);
}
private function getMediaPath($id) {
$mm = $this->container->get('sonata.media.manager.media');
$pr = $this->container->get('sonata.media.provider.image');
$media = $mm->findOneBy(['id' => $id]);
$format = $pr->getFormatName($media, 'reference');
return $pr->generatePublicUrl($media, $format);
}
protected function creteForm() {
$form = $this->get('sonata.user.profile.form');
$form->add('profilePicture', 'sonata_media_type', array(
'provider' => 'sonata.media.provider.image',
'context' => 'profile',
'new_on_update' => FALSE
));
$form->get('profilePicture')->add('binaryContent', 'file', ['label' => 'Profile Picture', 'required' => FALSE]);
$form->get('profilePicture')->remove('unlink');
return $form;
}
private function deleteOldMedia($om, $oldPath) {
if ($om) {
$newPath = $this->getMediaPath($this->getUser()->getProfilePicture()->getId());
if ($newPath && ($oldPath != $newPath)) {
$dir = $this->container->getParameter('kernel.root_dir');
$file = $dir . '/../public_html/' . $oldPath;
$i = file_exists($file) ? unlink($file) : NULL;
return $i;
}
}
}