Verified Commit 64bb693b authored by Alan Poulain's avatar Alan Poulain
Browse files

Add news to newsletter

parent 42798b80
......@@ -218,6 +218,12 @@ services:
tags:
- { name: sonata.admin, manager_type: doctrine_mongodb, group: emailing, label: Mails / Newsletter }
admin.news:
class: App\Admin\NewsAdmin
arguments: [~, App\Document\News, 'PixSortableBehaviorBundle:SortableAdmin']
tags:
- { name: sonata.admin, manager_type: doctrine_mongodb, group: emailing, label: Nouvelles (newsletter) }
admin.api_config:
class: App\Admin\ConfigurationAPIAdmin
arguments: [~, App\Document\Configuration, 'App\Controller\Admin\ConfigurationAdminController']
......
......@@ -79,15 +79,18 @@ class ConfigurationMailAdmin extends ConfigurationAbstractAdmin
->add('reportResolvedMail',AdminType::class, $featureFormOption, $featureFormTypeOption)->end()
->end()
->tab('Newsletter')
->with("Informations concernant lanewsletter", array('box_class' => 'box box-danger',
->with("Informations concernant la newsletter", array('box_class' => 'box box-danger',
'description' => "Ce mail est envoyé automatiquement aux utilisateurs y ayant souscrit. Il donne la liste des derniers éléments ajoutés dans une zone
géographique determinée</br></br>
géographique determinée et optionnellement des nouvelles</br></br>
<b>Il est nécessaire d'inclure la variable <u>{{ newElements }}</u> et/ou <u>{{ pendingElements }}</u></b> qui seront respectivement remplacées par la liste des nouveaux élements et des nouveaux élements en attente de validation</br></br>
Il est possible d'inclure les variables suivantes dans les messages (en conservant les '{{}}' ) : </br>
<ul>
<li>{{ news }} la dernière nouvelle publiée</li>
<li>{{ user }} le nom ou l'adresse mail du contributeur</li>
<li>{{ homeUrl }} l'adresse de la page d'accueil du site</li>
<li>{{ userProfileUrl }} l'adresse de la page \"Mes paramètres\" dans l'espace utilisateur</li>
<li>{{ showOnMapBtn }} un bouton pour renvoyer vers la carte centrée sur la position de l'utilisateur</li>
</ul>
</br>
<b>Une fois le mail sauvegardé</b>, vous pouvez cliquer sur le bouton <b>TESTER</b> pour visualiser le rendu"))->end()
->with("Newsletter" . $this->getEmailTestLink($router, 'newsletter'), array('class' => 'col-md-12'))
......
<?php
declare(strict_types=1);
namespace App\Admin;
use App\Enum\NewsStatus;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Sonata\FormatterBundle\Form\Type\SimpleFormatterType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
final class NewsAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $form): void
{
$form
->add('title', TextType::class, ['label' => 'Titre'])
->add('content', SimpleFormatterType::class, [
'label' => 'Contenu',
'format' => 'richhtml',
'ckeditor_context' => 'full',
])
->add('publicationDate', DateTimeType::class, ['label' => 'Date de publication'])
->add('status', ChoiceType::class, ['label' => 'Statut', 'choices' => [
'Brouillon (non publiée)' => NewsStatus::DRAFT,
'Publiée' => NewsStatus::PUBLISHED,
]])
;
}
protected function configureListFields(ListMapper $list): void
{
$list
->addIdentifier('title', 'text', ['label' => 'Titre'])
->add('publicationDate', 'datetime', ['label' => 'Date de publication', 'format' => 'd/m/Y à H:i'])
->add('status', 'choice', ['label' => 'Statut', 'choices'=> [
NewsStatus::DRAFT => 'Brouillon (non publiée)',
NewsStatus::PUBLISHED => 'Publiée',
]])
;
}
protected function configureDatagridFilters(DatagridMapper $filter): void
{
$filter
->add('title', null, ['label' => 'Titre'])
->add('status', 'doctrine_mongo_choice', ['label' => 'Statut'], ChoiceType::class, ['choices'=> [
'Brouillon (non publiée)' => NewsStatus::DRAFT,
'Publiée' => NewsStatus::PUBLISHED,
]])
;
}
protected function configureShowFields(ShowMapper $show): void
{
$show
->add('title', 'text', ['label' => 'Titre'])
->add('publicationDate', 'datetime', ['label' => 'Date de publication', 'format' => 'd/m/Y à H:i'])
->add('status', 'choice', ['label' => 'Statut', 'choices'=> [
NewsStatus::DRAFT => 'Brouillon (non publiée)',
NewsStatus::PUBLISHED => 'Publiée',
]])
;
}
}
......@@ -3,6 +3,7 @@
namespace App\Command;
use App\Command\GoGoAbstractCommand;
use Doctrine\ODM\MongoDB\DocumentManager;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use App\Document\GoGoLogUpdate;
......@@ -14,14 +15,14 @@ use Symfony\Component\Console\Input\InputArgument;
*/
class AddMessageCommand extends GoGoAbstractCommand
{
protected function gogoConfigure()
protected function gogoConfigure(): void
{
$this->setName('gogolog:add:message')
->addArgument('message', InputArgument::REQUIRED, 'Message to add')
->setDescription('Update datatabse each time after code update');
}
protected function gogoExecute($dm, InputInterface $input, OutputInterface $output)
protected function gogoExecute(DocumentManager $dm, InputInterface $input, OutputInterface $output): void
{
$log = new GoGoLogUpdate('info', $input->getArgument('message'));
......
......@@ -23,14 +23,14 @@ class CheckExternalSourceToUpdateCommand extends GoGoAbstractCommand
parent::__construct($dm, $commandsLogger, $security);
}
protected function gogoConfigure()
protected function gogoConfigure(): void
{
$this
->setName('app:elements:checkExternalSourceToUpdate')
->setDescription('Check for updating external sources');
}
protected function gogoExecute($dm, InputInterface $input, OutputInterface $output)
protected function gogoExecute(DocumentManager $dm, InputInterface $input, OutputInterface $output): void
{
$qb = $dm->createQueryBuilder('App\Document\ImportDynamic');
......
......@@ -22,7 +22,7 @@ class CheckVoteCommand extends GoGoAbstractCommand
parent::__construct($dm, $commandsLogger, $security);
}
protected function gogoConfigure()
protected function gogoConfigure(): void
{
$this
->setName('app:elements:checkvote')
......@@ -30,7 +30,7 @@ class CheckVoteCommand extends GoGoAbstractCommand
;
}
protected function gogoExecute($dm, InputInterface $input, OutputInterface $output)
protected function gogoExecute(DocumentManager $dm, InputInterface $input, OutputInterface $output): void
{
$elementRepo = $dm->getRepository('App\Document\Element');
$elements = $elementRepo->findPendings();
......
<?php
namespace App\Command;
use Doctrine\ODM\MongoDB\DocumentManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
......@@ -12,7 +13,7 @@ use App\Command\GoGoAbstractCommand;
class ElementsRemoveOptionsCommand extends GoGoAbstractCommand
{
protected function gogoConfigure()
protected function gogoConfigure(): void
{
$this
->setName('app:elements:removeOptions')
......@@ -20,7 +21,7 @@ class ElementsRemoveOptionsCommand extends GoGoAbstractCommand
;
}
protected function gogoExecute($dm, InputInterface $input, OutputInterface $output)
protected function gogoExecute(DocumentManager $dm, InputInterface $input, OutputInterface $output): void
{
try {
$this->log("Elements remove options begin, options ids to remove : " . $input->getArgument('ids'));
......
......@@ -22,7 +22,7 @@ class GenerateElementsCommand extends GoGoAbstractCommand
parent::__construct($dm, $commandsLogger, $security);
}
protected function gogoConfigure()
protected function gogoConfigure(): void
{
$this
->setName('app:elements:generate')
......@@ -33,7 +33,7 @@ class GenerateElementsCommand extends GoGoAbstractCommand
;
}
protected function gogoExecute($dm, InputInterface $input, OutputInterface $output)
protected function gogoExecute(DocumentManager $dm, InputInterface $input, OutputInterface $output): void
{
$this->output = $output;
......
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use App\Document\GoGoLog;
use App\Document\GoGoLogLevel;
......@@ -15,6 +15,9 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInt
class GoGoAbstractCommand extends Command
{
protected $dm;
protected $logger;
protected $security;
protected $output;
public function __construct(DocumentManager $dm, LoggerInterface $commandsLogger,
......@@ -51,9 +54,9 @@ class GoGoAbstractCommand extends Command
}
}
protected function gogoExecute($dm, InputInterface $input, OutputInterface $output) {}
protected function gogoExecute(DocumentManager $dm, InputInterface $input, OutputInterface $output): void {}
protected function gogoConfigure() {}
protected function gogoConfigure(): void {}
protected function log($message)
{
......
......@@ -24,7 +24,7 @@ class ImportSourceCommand extends GoGoAbstractCommand
parent::__construct($dm, $commandsLogger, $security);
}
protected function gogoConfigure()
protected function gogoConfigure(): void
{
$this
->setName('app:elements:importSource')
......@@ -32,7 +32,7 @@ class ImportSourceCommand extends GoGoAbstractCommand
->addArgument('sourceNameOrImportId', InputArgument::REQUIRED, 'The name of the source');
}
protected function gogoExecute($dm, InputInterface $input, OutputInterface $output)
protected function gogoExecute(DocumentManager $dm, InputInterface $input, OutputInterface $output): void
{
try {
$this->output = $output;
......
......@@ -65,13 +65,13 @@ class MigrationCommand extends GoGoAbstractCommand
parent::__construct($dm, $commandsLogger, $security);
}
protected function gogoConfigure()
protected function gogoConfigure(): void
{
$this->setName('db:migrate')
->setDescription('Update datatabse each time after code update');
}
protected function gogoExecute($dm, InputInterface $input, OutputInterface $output)
protected function gogoExecute(DocumentManager $dm, InputInterface $input, OutputInterface $output): void
{
$migrationState = $dm->createQueryBuilder('App\Document\MigrationState')->getQuery()->getSingleResult();
if ($migrationState == null) // Meaning the migration state was not yet in the place in the code
......
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use App\Document\User;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use App\Command\GoGoAbstractCommand;
use Doctrine\ODM\MongoDB\DocumentManager;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use App\Services\NewsletterService;
class NewsletterCommand extends GoGoAbstractCommand
final class NewsletterCommand extends GoGoAbstractCommand
{
private $newsletterService;
public function __construct(DocumentManager $dm, LoggerInterface $commandsLogger,
TokenStorageInterface $security,
NewsletterService $newsletterService)
......@@ -22,22 +22,21 @@ class NewsletterCommand extends GoGoAbstractCommand
parent::__construct($dm, $commandsLogger, $security);
}
protected function gogoConfigure()
protected function gogoConfigure(): void
{
$this
->setName('app:users:sendNewsletter')
->setDescription('Check for sending the enwsletter to each user')
;
->setName('app:users:sendNewsletter')
->setDescription('Send the newsletter to each user')
;
}
protected function gogoExecute($dm, InputInterface $input, OutputInterface $output)
protected function gogoExecute(DocumentManager $dm, InputInterface $input, OutputInterface $output): void
{
$usersRepo = $dm->getRepository('App\Document\User');
$usersRepo = $dm->getRepository(User::class);
$users = $usersRepo->findNeedsToReceiveNewsletter();
$nbrUsers = $users->count();
foreach ($users as $key => $user)
{
$dm->persist($user);
......@@ -46,6 +45,6 @@ class NewsletterCommand extends GoGoAbstractCommand
}
$dm->flush();
$this->log('Nombre newsletter envoyées : ' . $nbrUsers);
$this->log('Nombre newsletters envoyées : ' . $nbrUsers);
}
}
\ No newline at end of file
}
......@@ -23,7 +23,7 @@ class UpdateElementsJsonCommand extends GoGoAbstractCommand
parent::__construct($dm, $commandsLogger, $security);
}
protected function gogoConfigure()
protected function gogoConfigure(): void
{
$this
->setName('app:elements:updateJson')
......@@ -31,7 +31,7 @@ class UpdateElementsJsonCommand extends GoGoAbstractCommand
->setDescription('Calculate again all the element json representation');
}
protected function gogoExecute($dm, InputInterface $input, OutputInterface $output)
protected function gogoExecute(DocumentManager $dm, InputInterface $input, OutputInterface $output): void
{
try {
......
......@@ -21,14 +21,14 @@ class WebhooksPostCommand extends GoGoAbstractCommand
parent::__construct($dm, $commandsLogger, $security);
}
protected function gogoConfigure()
protected function gogoConfigure(): void
{
$this
->setName('app:webhooks:post')
->setDescription('Post the queued data to the given webhooks');
}
protected function gogoExecute($dm, InputInterface $input, OutputInterface $output)
protected function gogoExecute(DocumentManager $dm, InputInterface $input, OutputInterface $output): void
{
$numPosts = $this->webhookService->processPosts(10);
......
<?php
declare(strict_types=1);
namespace App\Document;
use App\Enum\NewsStatus;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
/**
* @ODM\Document(repositoryClass="App\Repository\NewsRepository")
*/
class News
{
/**
* @var int
*
* @ODM\Id(strategy="INCREMENT")
*/
private $id;
/**
* @var null|string
*
* @ODM\Field
*/
private $title;
/**
* @var null|string
*
* @ODM\Field
*/
private $content;
/**
* @var null|\DateTime
*
* @ODM\Field(type="date")
*/
private $publicationDate;
/**
* @var int
*
* @ODM\Field(type="int")
*
* @see NewsStatus
*/
private $status = NewsStatus::DRAFT;
public function __construct()
{
$this->publicationDate = new \DateTime();
}
public function getId(): int
{
return $this->id;
}
public function setTitle(string $title): News
{
$this->title = $title;
return $this;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setContent(string $content): News
{
$this->content = $content;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setPublicationDate(\DateTime $publicationDate): News
{
$this->publicationDate = $publicationDate;
return $this;
}
public function getPublicationDate(): ?\DateTime
{
return $this->publicationDate;
}
public function setStatus(int $status): News
{
$this->status = $status;
return $this;
}
public function getStatus(): int
{
return $this->status;
}
public function __toString(): string
{
return sprintf('Nouvelle %s (%d)', $this->title, $this->id);
}
}
......@@ -735,7 +735,7 @@ class User extends BaseUser
/**
* Get lastNewsletterSentAt
*
* @return date $lastNewsletterSentAt
* @return \DateTime $lastNewsletterSentAt
*/
public function getLastNewsletterSentAt()
{
......
<?php
declare(strict_types=1);
namespace App\Enum;
final class NewsStatus
{
public const DRAFT = 0;
public const PUBLISHED = 1;
}
<?php
declare(strict_types=1);
namespace App\Repository;
use App\Document\News;
use App\Enum\NewsStatus;
use Doctrine\ODM\MongoDB\Repository\DocumentRepository;
final class NewsRepository extends DocumentRepository
{
public function findLastPublishedNews(\DateTime $lastNewsletterSentAt): ?News
{
return $this->createQueryBuilder()
->field('status')->equals(NewsStatus::PUBLISHED)
->sort('publicationDate', 'desc')
->field('publicationDate')->lte(new \DateTime())
->field('publicationDate')->gte($lastNewsletterSentAt)
->limit(1)
->getQuery()
->getSingleResult();
}
}
<?php
namespace App\Services;
use App\Document\Configuration;
use App\Document\News;
use Doctrine\ODM\MongoDB\DocumentManager;
use App\Document\UserInteractionReport;
use App\Document\Element;
......@@ -13,6 +15,7 @@ class MailService
{
protected $dm;
protected $config;
private $newsRepository;
protected $mailer;
protected $router;
protected $twig;
......@@ -20,13 +23,11 @@ class MailService
protected $email;
protected $instanceName;
/**
* Constructor
*/
public function __construct(DocumentManager $dm, \Swift_Mailer $mailer, RouterInterface $router, Environment $twig, $baseUrl, $basePath, $saas, $fromEmail, $instanceName)
{
$this->dm = $dm;
$this->config = $this->dm->getRepository('App\Document\Configuration')->findConfiguration();
$this->config = $this->dm->getRepository(Configuration::class)->findConfiguration();
$this->newsRepository = $this->dm->getRepository(News::class);
$this->mailer = $mailer;
$this->router = $router;
$this->twig = $twig;
......@@ -184,6 +185,11 @@ class MailService
}
}
if ('newsletter' === $mailType && $element instanceof User) {
$lastNews = $this->newsRepository->findLastPublishedNews($element->getLastNewsletterSentAt());
$string = preg_replace('/({{((?:\s)+)?news((?:\s)+)?}})/i', $lastNews ? $lastNews->getContent() : '', $string);
}
$homeUrl = $this->generateRoute('gogo_homepage');
$userContributionsUrl = $this->generateRoute('gogo_user_contributions');
$userProfileUrl = $this->generateRoute('gogo_user_profile');
......
<?php
namespace App\Services;
use App\Document\Element;
use Doctrine\ODM\MongoDB\DocumentManager;
use App\Services\MailService;
class NewsletterService
{
......@@ -11,14 +12,11 @@ class NewsletterService
protected $mailService;
protected $config;
/**
* Constructor
*/
public function __construct(DocumentManager $dm, MailService $mailService)
{
$this->dm = $dm;
$this->mailService = $mailService;
$this->elementRepo = $this->dm->getRepository('App\Document\Element');
$this->elementRepo = $this->dm->getRepository(Element::class);
}
public function sendTo($user)
......
Markdown is supported
0%