Переглянути джерело

Gestion des newsletters

reduction
Guillaume 4 роки тому
джерело
коміт
6c98e4763e
14 змінених файлів з 535 додано та 60 видалено
  1. +8
    -0
      ShopBundle/Context/NewsletterInterface.php
  2. +8
    -1
      ShopBundle/Controller/Admin/AdminController.php
  3. +31
    -23
      ShopBundle/Controller/Admin/NewsController.php
  4. +108
    -0
      ShopBundle/Controller/Frontend/NewsletterController.php
  5. +26
    -0
      ShopBundle/Form/Frontend/NewsletterType.php
  6. +86
    -1
      ShopBundle/Model/Merchant.php
  7. +38
    -18
      ShopBundle/Model/News.php
  8. +76
    -0
      ShopBundle/Model/Newsletter.php
  9. +33
    -17
      ShopBundle/Model/User.php
  10. +21
    -0
      ShopBundle/Repository/NewsRepository.php
  11. +21
    -0
      ShopBundle/Repository/NewsletterRepository.php
  12. +9
    -0
      ShopBundle/Repository/UserRepository.php
  13. +2
    -0
      ShopBundle/Twig/BridgeTwigExtension.php
  14. +68
    -0
      ShopBundle/Twig/FrontendTwigExtension.php

+ 8
- 0
ShopBundle/Context/NewsletterInterface.php Переглянути файл

@@ -0,0 +1,8 @@
<?php

namespace Lc\ShopBundle\Context ;

interface NewsletterInterface
{

}

+ 8
- 1
ShopBundle/Controller/Admin/AdminController.php Переглянути файл

@@ -8,12 +8,14 @@ use EasyCorp\Bundle\EasyAdminBundle\Controller\EasyAdminController;
use EasyCorp\Bundle\EasyAdminBundle\Event\EasyAdminEvents;
use FOS\UserBundle\Model\UserManagerInterface;
use Lc\ShopBundle\Context\FilterMultipleMerchantsInterface;
use Lc\ShopBundle\Context\GlobalParamInterface;
use Lc\ShopBundle\Context\MerchantInterface;
use Lc\ShopBundle\Context\SortableInterface;
use Lc\ShopBundle\Context\StatusInterface;
use Lc\ShopBundle\Context\TreeInterface;
use Lc\ShopBundle\Form\AbstractEditPositionType;
use Lc\ShopBundle\Services\Utils;
use Mailjet\MailjetSwiftMailer\SwiftMailer\MailjetTransport;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormEvent;
@@ -26,13 +28,18 @@ class AdminController extends EasyAdminController
protected $userManager;
protected $em;
protected $utils;
protected $globalParam ;
protected $mailjetTransport ;

public function __construct(Security $security, UserManagerInterface $userManager, EntityManagerInterface $em, Utils $utils)
public function __construct(Security $security, UserManagerInterface $userManager, EntityManagerInterface $em, Utils $utils,
GlobalParamInterface $globalParam, MailjetTransport $mailjetTransport)
{
$this->security = $security;
$this->userManager = $userManager;
$this->em = $em;
$this->utils = $utils;
$this->globalParam = $globalParam ;
$this->mailjetTransport = $mailjetTransport ;
}

/**

+ 31
- 23
ShopBundle/Controller/Admin/NewsController.php Переглянути файл

@@ -14,35 +14,43 @@ class NewsController extends AdminController
public function sendAction()
{
$idNews = $this->request->get('id') ;
$users = $this->em->getRepository($this->em->getClassMetadata(UserInterface::class)->getName())->findBy([
'isSubscribedNewsletter' => true
]) ;
$countUsers = count($users) ;
$messages = [];
$news = $this->em->getRepository($this->em->getClassMetadata(NewsInterface::class)->getName())->find($idNews) ;
if($news) {
foreach ($users as $user) {
$message = new \Swift_Message('[Place du Local] '.$news->getTitle());
$message->addTo($user->getEmail())
->addFrom($this->getParameter('app.noreply_email'), $this->getParameter('app.site_name'))
->setBody($this->renderView('mail/news.html.twig', [
'message' => $news->getDescription(),
'image' => $news->getImage(),
]), 'text/html');
array_push($messages, $message);
}

$result = $this->mailjetTransport->bulkSend($messages);

if($countUsers > 0) {
$this->addFlash('success', 'Actualité envoyée à '.count($users).' utilisateurs.');
$newsletter = $this->globalParam->getCurrentMerchant()->getNewsletter() ;

if($newsletter) {
$users = $this->em->getRepository($this->em->getClassMetadata(UserInterface::class)->getName())->findAllByNewsletter($newsletter) ;
$countUsers = count($users) ;
$messages = [];
$news = $this->em->getRepository($this->em->getClassMetadata(NewsInterface::class)->getName())->find($idNews) ;
if($news) {
foreach ($users as $user) {
$message = new \Swift_Message('[Place du Local] '.$news->getTitle());
$message->addTo($user->getEmail())
->addFrom($this->getParameter('app.noreply_email'), $this->getParameter('app.site_name'))
->setBody($this->renderView('mail/news.html.twig', [
'message' => $news->getDescription(),
'image' => $news->getImage(),
'newsletter' => $newsletter,
'user' => $user
]), 'text/html');
array_push($messages, $message);
}

$result = $this->mailjetTransport->bulkSend($messages);

if($countUsers > 0) {
$this->addFlash('success', 'Actualité envoyée à '.count($users).' utilisateurs.');
}
else {
$this->addFlash('error', 'Aucun utilisateur inscrit à la newsletter.');
}
}
else {
$this->addFlash('error', 'Aucun utilisateur inscrit à la newsletter.');
throw new NotFoundHttpException('Actualité introuvable') ;
}
}
else {
throw new NotFoundHttpException('Actualité introuvable') ;
throw new \ErrorException('Aucune newsletter n\'est lié à ce Merchant.') ;
}

return $this->redirectToRoute('easyadmin', ['entity' => 'News', 'action' => 'list']) ;

+ 108
- 0
ShopBundle/Controller/Frontend/NewsletterController.php Переглянути файл

@@ -0,0 +1,108 @@
<?php

namespace Lc\ShopBundle\Controller\Frontend ;

use Doctrine\ORM\EntityManagerInterface;
use FOS\UserBundle\Util\UserManipulator;
use Lc\ShopBundle\Context\GlobalParamInterface;
use Lc\ShopBundle\Form\Frontend\NewsletterType;
use Lc\ShopBundle\Repository\NewsletterRepository;
use Lc\ShopBundle\Repository\UserRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class NewsletterController extends AbstractController
{
protected $em ;
protected $userRepository ;
protected $globalParam ;
protected $newsletterRepository ;

public function __construct(EntityManagerInterface $em, UserRepository $userRepository, NewsletterRepository $newsletterRepository, GlobalParamInterface $globalParam)
{
$this->em = $em ;
$this->userRepository = $userRepository ;
$this->newsletterRepository = $newsletterRepository ;
$this->globalParam = $globalParam ;
}

public function subscribe(Request $request, UserManipulator $userManipulator)
{
$form = $this->createForm(NewsletterType::class);

$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {

$data = $form->getData() ;
$email = $data['email'] ;
$userExist = $this->userRepository->findOneBy(['email' => $email]) ;
$newsletter = $this->globalParam->getCurrentMerchant()->getNewsletter() ;

if($newsletter) {
$userSubscribe = false ;
if($userExist) {
if($this->getUser() && $userExist && $this->getUser() == $userExist) {
if($userExist->getNewsletters()->contains($newsletter)) {
$this->addFlash('error','Vous êtes déjà inscrit à cette newsletter.');
}
else {
$userExist->addNewsletter($newsletter) ;
$userSubscribe = true ;
$this->em->persist($userExist);
}
}
else {
$form->get('email')->addError(new FormError('Cette adresse email est déjà utilisée')) ;
}
}
else {
$user = $userManipulator->create($email, '9e438d8a7b036ea9b8d4375377d47e1a', $email, false, false) ;
$user->addNewsletter($newsletter) ;
$user->addRole('ROLE_NEWSLETTER') ;
$this->em->persist($user);
$userSubscribe = true ;
}

if($userSubscribe) {
$this->addFlash('success','Vous avez bien été ajouté à la newsletter.');
$this->em->flush() ;
return $this->redirectToRoute('frontend_newsletter_subscribe') ;
}
}
else {
throw new \ErrorException('Aucune newsletter définie.') ;
}
}

return $this->render('frontend/site/newsletter.html.twig', [
'form' => $form->createView()
]);
}

public function unsubscribe($idUser, $idNewsletter)
{
$user = $this->userRepository->find($idUser) ;
$newsletter = $this->newsletterRepository->find($idNewsletter) ;

if(!$user) {
throw new NotFoundHttpException('Utilisateur introuvable') ;
}

if(!$newsletter) {
throw new NotFoundHttpException('Newsletter introuvable') ;
}

if($user->getNewsletters()->contains($newsletter)) {
$user->removeNewsletter($newsletter) ;
$this->em->persist($user);
$this->em->flush() ;

return $this->render('frontend/site/newsletter_confirm_unsubscribe.html.twig');
}

return $this->redirectToRoute('frontend_index') ;
}
}

+ 26
- 0
ShopBundle/Form/Frontend/NewsletterType.php Переглянути файл

@@ -0,0 +1,26 @@
<?php

namespace Lc\ShopBundle\Form\Frontend;

use Lc\ShopBundle\Validator\Constraints\UniqueEmailValidator;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class NewsletterType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('email', EmailType::class, [
'label' => 'Renseignez votre adresse email :'
]);
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([

]);
}
}

+ 86
- 1
ShopBundle/Model/Merchant.php Переглянути файл

@@ -2,6 +2,8 @@

namespace Lc\ShopBundle\Model;

use App\Entity\News;
use App\Entity\Newsletter;
use App\Entity\ProductCategory;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
@@ -46,16 +48,28 @@ abstract class Merchant extends AbstractDocumentEntity
protected $address;

/**
* @ORM\OneToMany(targetEntity="App\Entity\ProductCategory", mappedBy="merchant", orphanRemoval=true)
* @ORM\OneToMany(targetEntity="Lc\ShopBundle\Context\ProductCategoryInterface", mappedBy="merchant", orphanRemoval=true)
*/
protected $productCategories;

/**
* @ORM\OneToMany(targetEntity="Lc\ShopBundle\Context\NewsInterface", mappedBy="merchant", orphanRemoval=true)
*/
protected $news;

/**
* @ORM\OneToMany(targetEntity="Lc\ShopBundle\Context\NewsletterInterface", mappedBy="merchant")
*/
protected $newsletters;

public function __construct()
{
$this->pointSales = new ArrayCollection();
$this->productFamilies = new ArrayCollection();
$this->merchantConfigs = new ArrayCollection();
$this->productCategories = new ArrayCollection();
$this->news = new ArrayCollection();
$this->newsletters = new ArrayCollection();
}

public function getCreditConfig(): ?CreditConfig
@@ -227,4 +241,75 @@ abstract class Merchant extends AbstractDocumentEntity

return $this;
}

/**
* @return Collection|News[]
*/
public function getNews(): Collection
{
return $this->news;
}

public function addNews(News $news): self
{
if (!$this->news->contains($news)) {
$this->news[] = $news;
$news->setMerchant($this);
}

return $this;
}

public function removeNews(News $news): self
{
if ($this->news->contains($news)) {
$this->news->removeElement($news);
// set the owning side to null (unless already changed)
if ($news->getMerchant() === $this) {
$news->setMerchant(null);
}
}

return $this;
}

/**
* @return Collection|Newsletter[]
*/
public function getNewsletters(): Collection
{
return $this->newsletters;
}

public function addNewsletter(Newsletter $newsletter): self
{
if (!$this->newsletters->contains($newsletter)) {
$this->newsletters[] = $newsletter;
$newsletter->setMerchant($this);
}

return $this;
}

public function removeNewsletter(Newsletter $newsletter): self
{
if ($this->newsletters->contains($newsletter)) {
$this->newsletters->removeElement($newsletter);
// set the owning side to null (unless already changed)
if ($newsletter->getMerchant() === $this) {
$newsletter->setMerchant(null);
}
}

return $this;
}

public function getNewsletter()
{
$newsletters = $this->getNewsletters() ;
if(isset($newsletters[0])) {
return $newsletters[0] ;
}
return false ;
}
}

+ 38
- 18
ShopBundle/Model/News.php Переглянути файл

@@ -2,30 +2,50 @@

namespace Lc\ShopBundle\Model;

use App\Entity\Hub;
use Doctrine\ORM\Mapping as ORM;
use Lc\ShopBundle\Context\FilterMerchantInterface;
use Lc\ShopBundle\Model\AbstractDocumentEntity;
use Gedmo\Mapping\Annotation as Gedmo;

/**
* @ORM\MappedSuperclass()
*/
abstract class News extends AbstractDocumentEntity
abstract class News extends AbstractDocumentEntity implements FilterMerchantInterface
{
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="create")
*/
protected $date;

public function getDate(): ?\DateTimeInterface
{
return $this->date;
}

public function setDate(\DateTimeInterface $date): self
{
$this->date = $date;

return $this;
}
/**
* @ORM\ManyToOne(targetEntity="Lc\ShopBundle\Context\MerchantInterface", inversedBy="news")
* @ORM\JoinColumn(nullable=false)
*/
protected $merchant;

/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="create")
*/
protected $date;

public function getDate(): ?\DateTimeInterface
{
return $this->date;
}

public function setDate(\DateTimeInterface $date): self
{
$this->date = $date;

return $this;
}

public function getMerchant(): ?Hub
{
return $this->merchant;
}

public function setMerchant(?Hub $merchant): self
{
$this->merchant = $merchant;

return $this;
}
}

+ 76
- 0
ShopBundle/Model/Newsletter.php Переглянути файл

@@ -0,0 +1,76 @@
<?php

namespace Lc\ShopBundle\Model;

use App\Entity\Hub;
use App\Entity\User;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Lc\ShopBundle\Context\FilterMerchantInterface;

/**
* @ORM\MappedSuperclass()
*/
abstract class Newsletter extends AbstractDocumentEntity implements FilterMerchantInterface
{
/**
* @ORM\ManyToOne(targetEntity="Lc\ShopBundle\Context\MerchantInterface", inversedBy="newsletters")
*/
protected $merchant;

/**
* @ORM\ManyToMany(targetEntity="Lc\ShopBundle\Context\UserInterface", mappedBy="newsletters")
*/
protected $users;

public function __toString()
{
return $this->getTitle() ;
}

public function __construct()
{
$this->users = new ArrayCollection();
}

public function getMerchant(): ?Hub
{
return $this->merchant;
}

public function setMerchant(?Hub $merchant): self
{
$this->merchant = $merchant;

return $this;
}

/**
* @return Collection|User[]
*/
public function getUsers(): Collection
{
return $this->users;
}

public function addUser(User $user): self
{
if (!$this->users->contains($user)) {
$this->users[] = $user;
$user->addNewsletter($this);
}

return $this;
}

public function removeUser(User $user): self
{
if ($this->users->contains($user)) {
$this->users->removeElement($user);
$user->removeNewsletter($this);
}

return $this;
}
}

+ 33
- 17
ShopBundle/Model/User.php Переглянути файл

@@ -2,6 +2,7 @@

namespace Lc\ShopBundle\Model;

use App\Entity\Newsletter;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
@@ -49,11 +50,6 @@ abstract class User extends UserModelFOS
*/
protected $carts;

/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $isSubscribedNewsletter;

/**
* @ORM\Column(type="string", length=64, nullable=true)
*/
@@ -69,6 +65,11 @@ abstract class User extends UserModelFOS
*/
protected $gender;

/**
* @ORM\ManyToMany(targetEntity="Lc\ShopBundle\Context\NewsletterInterface", inversedBy="users")
*/
protected $newsletters;

public function __construct()
{
parent::__construct();
@@ -76,6 +77,7 @@ abstract class User extends UserModelFOS
$this->addresses = new ArrayCollection();
$this->orders = new ArrayCollection();
$this->carts = new ArrayCollection();
$this->newsletters = new ArrayCollection();
}

public function setEmail($email)
@@ -244,18 +246,6 @@ abstract class User extends UserModelFOS
return $this;
}

public function getIsSubscribedNewsletter(): ?bool
{
return $this->isSubscribedNewsletter;
}

public function setIsSubscribedNewsletter(?bool $isSubscribedNewsletter): self
{
$this->isSubscribedNewsletter = $isSubscribedNewsletter;

return $this;
}

public function getFirstname(): ?string
{
return $this->firstname;
@@ -291,4 +281,30 @@ abstract class User extends UserModelFOS

return $this;
}

/**
* @return Collection|Newsletter[]
*/
public function getNewsletters(): Collection
{
return $this->newsletters;
}

public function addNewsletter(Newsletter $newsletter): self
{
if (!$this->newsletters->contains($newsletter)) {
$this->newsletters[] = $newsletter;
}

return $this;
}

public function removeNewsletter(Newsletter $newsletter): self
{
if ($this->newsletters->contains($newsletter)) {
$this->newsletters->removeElement($newsletter);
}

return $this;
}
}

+ 21
- 0
ShopBundle/Repository/NewsRepository.php Переглянути файл

@@ -0,0 +1,21 @@
<?php

namespace Lc\ShopBundle\Repository;

use App\Entity\News;
use Lc\ShopBundle\Context\DefaultRepositoryInterface;
use Lc\ShopBundle\Context\NewsInterface;

/**
* @method News|null find($id, $lockMode = null, $lockVersion = null)
* @method News|null findOneBy(array $criteria, array $orderBy = null)
* @method News[] findAll()
* @method News[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class NewsRepository extends BaseRepository implements DefaultRepositoryInterface
{
public function getInterfaceClass()
{
return NewsInterface::class;
}
}

+ 21
- 0
ShopBundle/Repository/NewsletterRepository.php Переглянути файл

@@ -0,0 +1,21 @@
<?php

namespace Lc\ShopBundle\Repository;

use App\Entity\News;
use Lc\ShopBundle\Context\DefaultRepositoryInterface;
use Lc\ShopBundle\Context\NewsletterInterface;

/**
* @method News|null find($id, $lockMode = null, $lockVersion = null)
* @method News|null findOneBy(array $criteria, array $orderBy = null)
* @method News[] findAll()
* @method News[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class NewsletterRepository extends BaseRepository implements DefaultRepositoryInterface
{
public function getInterfaceClass()
{
return NewsletterInterface::class;
}
}

+ 9
- 0
ShopBundle/Repository/UserRepository.php Переглянути файл

@@ -18,4 +18,13 @@ class UserRepository extends BaseRepository implements DefaultRepositoryInterfac
return UserInterface::class;
}

public function findAllByNewsletter($newsletter)
{
return $this->createQueryBuilder('e')
->where(':newsletter MEMBER OF e.newsletters')
->setParameter('newsletter', $newsletter->getId())
->getQuery()
->getResult() ;
}

}

+ 2
- 0
ShopBundle/Twig/BridgeTwigExtension.php Переглянути файл

@@ -3,6 +3,7 @@
namespace Lc\ShopBundle\Twig;

use Lc\ShopBundle\Context\PageInterface;
use Lc\ShopBundle\Form\Frontend\NewsletterType;
use Lc\ShopBundle\Services\Utils;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
@@ -22,6 +23,7 @@ class BridgeTwigExtension extends AbstractExtension
new TwigFunction('getDayByNumber', [$this, 'getDayByNumber']),
new TwigFunction('getUnitsList', [$this, 'getUnitsList']),
new TwigFunction('getElementByDevAlias', [$this, 'getElementByDevAlias']),
new TwigFunction('get_form_newsletter', [$this, 'getFormNewsletter']),
);
}


+ 68
- 0
ShopBundle/Twig/FrontendTwigExtension.php Переглянути файл

@@ -0,0 +1,68 @@
<?php

namespace Lc\ShopBundle\Twig;

use App\Services\GlobalParam;
use Doctrine\ORM\EntityManagerInterface;
use Lc\ShopBundle\Form\Frontend\NewsletterType;
use Lc\ShopBundle\Repository\ProductCategoryRepository;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Security\Core\Security;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;

class FrontendTwigExtension extends AbstractExtension
{
protected $em ;
protected $security ;
protected $repositoryProductCategory ;
protected $globalParam ;
protected $formFactory ;

public function __construct(EntityManagerInterface $em, Security $security, ProductCategoryRepository $repositoryProductCategory,
GlobalParam $globalParam, FormFactoryInterface $formFactory)
{
$this->em = $em ;
$this->security = $security ;
$this->repositoryProductCategory = $repositoryProductCategory ;
$this->globalParam = $globalParam ;
$this->formFactory = $formFactory ;
}

public function getFunctions()
{
return array(
new TwigFunction('get_product_categories', [$this, 'getProductCategories']),
new TwigFunction('get_form_newsletter', [$this, 'getFormNewsletter']),
);
}

public function getFilters()
{
return [
new TwigFilter('format_price', [$this, 'format_price']),
];
}

public function getProductCategories()
{
$categories = $this->repositoryProductCategory->findAllParents($this->globalParam->getCurrentMerchant()) ;
return $categories ;
}

public function getFormNewsletter()
{
$form = $this->formFactory->create(NewsletterType::class);
return $form->createView() ;
}

public function format_price($price)
{
$price = number_format($price, 2) ;
$price = str_replace('.',',',$price) ;
$price = $price .'&nbsp;€' ;
return $price ;
}

}

Завантаження…
Відмінити
Зберегти