Commit bbc50df0 authored by Mat's avatar Mat

améliore, factorise, déplace une fonction, utilise les objets si possible

parent e6b8094f
...@@ -4,7 +4,6 @@ namespace PotageBundle\Command; ...@@ -4,7 +4,6 @@ namespace PotageBundle\Command;
use PotageBundle\Entity\Offre; use PotageBundle\Entity\Offre;
use PotageBundle\Entity\User;
use PotageBundle\Services\LettreToken; use PotageBundle\Services\LettreToken;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
...@@ -34,12 +33,13 @@ class CronOffreCommand extends ContainerAwareCommand ...@@ -34,12 +33,13 @@ class CronOffreCommand extends ContainerAwareCommand
{ {
$this $this
->setName('potage:cron:offre') ->setName('potage:cron:offre')
->setDescription("Vérifie la date d'expiration des offres en cours"); ->setDescription("Archive les offres qui sont expirées");
} }
/** /**
* Vérifie que les offres en cours n'ont pas expiré. * Vérifie que les offres en cours n'ont pas expiré.
* Si c'est le cas, le statut est changé et un mail est envoyé aux maraichers. * Si c'est le cas, le statut est changé, les tokens associés sont révoqués
* et un mail est envoyé aux maraichers.
* *
* @param InputInterface $input * @param InputInterface $input
* @param OutputInterface $output * @param OutputInterface $output
...@@ -48,9 +48,11 @@ class CronOffreCommand extends ContainerAwareCommand ...@@ -48,9 +48,11 @@ class CronOffreCommand extends ContainerAwareCommand
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$em = $this->getContainer()->get('doctrine')->getManager(); $em = $this->getContainer()->get('doctrine')
->getManager();
$currentOffre = $em->getRepository('PotageBundle:Offre') $currentOffre = $em
->getRepository('PotageBundle:Offre')
->findAllByStatusForRead('current'); ->findAllByStatusForRead('current');
$now = new \DateTime('now'); $now = new \DateTime('now');
...@@ -62,16 +64,18 @@ class CronOffreCommand extends ContainerAwareCommand ...@@ -62,16 +64,18 @@ class CronOffreCommand extends ContainerAwareCommand
{ {
if ($offre->getEndedAt() <= $now) { if ($offre->getEndedAt() <= $now) {
// change le statut de l'offre
$offre->setStatus('closed');
$output->write( $output->write(
"\n" "\n"
. $offre->getReference() . $offre->getReference()
. ": offre expired since " . ": offre expired since "
. date_format($offre->getEndedAt(), "d/m/Y H:i") . date_format($offre->getEndedAt(), "d/m/Y H:i")
. ", change status to archive..\n"); . ", change status to archive..\n"
);
$offre->setStatus('closed'); // révoque les tokens
$ret = $this->lettreToken->revoquePotageUsersTokens($offre);
$ret = $this->revoquePotageUsersTokens($offre);
$output->writeln($ret); $output->writeln($ret);
// TODO envoyer un mail au gestionnaire pour notifier l'expiration de l'offre // TODO envoyer un mail au gestionnaire pour notifier l'expiration de l'offre
...@@ -81,49 +85,6 @@ class CronOffreCommand extends ContainerAwareCommand ...@@ -81,49 +85,6 @@ class CronOffreCommand extends ContainerAwareCommand
$output->write("\nDone\n"); $output->write("\nDone\n");
} }
/**
* On parcourt la table User, colonne tokenKey
* Chaque token est décodé et s'il correspond à l'offre expirée, on le supprime
*
* @param Offre $offre
* @return array
*/
private function revoquePotageUsersTokens(Offre $offre)
{
$em = $this->getContainer()
->get('doctrine')->getManager();
$usersTokenKeys = $em->getRepository('PotageBundle:User')
->findAllTokenKeys();
$log = array();
foreach ($usersTokenKeys as $userTokenKeys)
{
foreach ($userTokenKeys['tokenKey'] as $uTokenKey)
{
$uOffre = intval($this->lettreToken->decodePotageUserToken($uTokenKey)['offre_id']);
if ($uOffre === $offre->getId())
{
/**
* @var User $user
*/
$user = $em->getRepository('PotageBundle:User')
->find($userTokenKeys['id']);
$user->removeTokenKey($uTokenKey);
$log[] = " User ". $userTokenKeys['id'] . ", removing token ". $uTokenKey;
}
}
}
$em->flush();
count($log) === 0 ? $log[] = " No tokens detected for this offre !" : null ;
return $log;
}
......
...@@ -28,30 +28,20 @@ class DefaultController extends MasterController ...@@ -28,30 +28,20 @@ class DefaultController extends MasterController
* *
* @param Request $request * @param Request $request
* @param Newsletter $newsletter * @param Newsletter $newsletter
* @param LettreToken $lettreToken
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
* @throws \Twig_Error_Loader * @throws \Twig_Error_Loader
* @throws \Twig_Error_Runtime * @throws \Twig_Error_Runtime
* @throws \Twig_Error_Syntax * @throws \Twig_Error_Syntax
*/ */
public function testAction(Request $request, Newsletter $newsletter, LettreToken $lettreToken) public function testAction(Request $request, Newsletter $newsletter)
{ {
/** /**
* @var Lettre $lettre * @var Lettre $lettre
*/ */
$lettre = $this->get('doctrine')->getManager() $lettre = $this->get('doctrine')->getManager()
->getRepository('PotageBundle:Lettre') ->getRepository('PotageBundle:Lettre')
->findOneForSend(7); ->findOneForSend(5);
$header = array(
'id' => $lettre->getId(),
'start' => $lettre->getStartedAt(),
'end' => $lettre->getEndedAt(),
'status' => $lettre->getStatus(),
'subject' =>$lettre->getSubject(),
'reference' => $lettre->getReference(),
);
/** /**
* Initilalise un formulaire simple pour déclencher l'envoi * Initilalise un formulaire simple pour déclencher l'envoi
*/ */
...@@ -66,12 +56,13 @@ class DefaultController extends MasterController ...@@ -66,12 +56,13 @@ class DefaultController extends MasterController
$retour = null; $retour = null;
if ($form->isSubmitted() && $form->isValid()) if ($form->isSubmitted() && $form->isValid())
{ {
$retour = $newsletter->sendLettreToGroup($lettre, $lettreToken); // Envoi de la newsletter
$retour = $newsletter->sendLettreToGroup($lettre);
} }
return $this->render('@Potage/Default/test.html.twig', array( return $this->render('@Potage/Default/test.html.twig', array(
'lettre' => $header,
'formEnvoi' => $form->createView(), 'formEnvoi' => $form->createView(),
'lettre' => $lettre,
'retour'=> $retour, 'retour'=> $retour,
)); ));
} }
......
...@@ -12,19 +12,6 @@ use Symfony\Component\Security\Core\User\UserInterface; ...@@ -12,19 +12,6 @@ use Symfony\Component\Security\Core\User\UserInterface;
*/ */
class UserRepository extends \Doctrine\ORM\EntityRepository implements UserLoaderInterface class UserRepository extends \Doctrine\ORM\EntityRepository implements UserLoaderInterface
{ {
/**
* @param $id_utilisateur
* @return mixed
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function findOneByUtilisateur($id_utilisateur)
{
$qb = $this->createQueryBuilder('fu')
->join('fu.utilisateur', 'u')
->where('u.id = :id')
->setParameter(':id', $id_utilisateur);
return $qb->getQuery()->getOneOrNullResult();
}
/** /**
* Dans security, je ne peux me référer à une propriété, puisque token_key est un array sérialisé * Dans security, je ne peux me référer à une propriété, puisque token_key est un array sérialisé
......
...@@ -125,7 +125,6 @@ class UtilisateurRepository extends \Doctrine\ORM\EntityRepository ...@@ -125,7 +125,6 @@ class UtilisateurRepository extends \Doctrine\ORM\EntityRepository
public function findAllByGroup($id_group) public function findAllByGroup($id_group)
{ {
$qb = $this->createQueryBuilder('u') $qb = $this->createQueryBuilder('u')
->select('u.id', 'u.nom', 'u.prenom', 'u.email')
->join('u.groupes', 'g') ->join('u.groupes', 'g')
->where('g.id = :id') ->where('g.id = :id')
->setParameter(':id', $id_group); ->setParameter(':id', $id_group);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<h2>Infolettre #{{ lettre.id }}</h2> <h2>Infolettre #{{ lettre.id }}</h2>
<h3>{{ lettre.subject }}</h3> <h3>{{ lettre.subject }}</h3>
<h4>Période du {{ lettre.start|date('d-m-Y') }} au {{ lettre.end|date('d-m-Y') }}</h4> <h4>Période du {{ lettre.startedAt|date('d-m-Y') }} au {{ lettre.endedAt|date('d-m-Y') }}</h4>
<h3>Envoyer la lettre</h3> <h3>Envoyer la lettre</h3>
{{ form(formEnvoi) }} {{ form(formEnvoi) }}
...@@ -19,11 +19,15 @@ ...@@ -19,11 +19,15 @@
<hr> <hr>
<div> <div>
<h4>Référence: {{ lettre.reference }}</h4> <h4>Référence: {{ lettre.reference }}</h4>
<h5>Statut: {{ lettre.status }}</h5> <h5>Offre attachée: {{ lettre.offre.reference }} (#{{ lettre.offre.id }})</h5>
<h5>Envoi à :</h5> <h5>Envoi à :</h5>
<ul> <ul>
{% for item in retour %} {% for mail in retour %}
<li>{{ loop.index }}) {{ item.to }}{{ item.result }}</li> <li>{{ loop.index }}) {{ mail.tostring }} <span class="text-success">{{ mail.result }}</span><br>
<span class="small text-muted">→ token attached: {{ mail.to.token }}
{% if not mail.to.token %}<span class="text-danger">Null</span>{% endif %}
</span>
</li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace PotageBundle\Services; namespace PotageBundle\Services;
use PotageBundle\Entity\Lettre; use PotageBundle\Entity\Offre;
use PotageBundle\Entity\User; use PotageBundle\Entity\User;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
...@@ -36,23 +36,14 @@ class LettreToken ...@@ -36,23 +36,14 @@ class LettreToken
/** /**
* @param int $id_utilisateur * Encode un token unique pour une offre et un user
* @param Lettre $lettre *
* @param User $user
* @param Offre $offre
* @return mixed * @return mixed
*/ */
public function encodePotageUserToken($id_utilisateur, Lettre $lettre) public function encodePotageUserToken(User $user, Offre $offre)
{ {
/**
* Si l'utilisateur n'est pas associé à un user, token => null
* TODO il faudra alors l'inviter à se créer un compte user,
* après quoi il accèdera à sa page today, qui lui affichera alors les offres liée à ses groupes.
* Et cela même s'il n'avait pas encore de compte user quand la lettre a été envoyée !
*
* @var User $user
*/
$user = $this->container->get('doctrine')
->getRepository('PotageBundle:User')
->findOneByUtilisateur($id_utilisateur);
if ($user !== null) { if ($user !== null) {
...@@ -60,7 +51,7 @@ class LettreToken ...@@ -60,7 +51,7 @@ class LettreToken
* Vérifie d'abord qu'aucun token pour cette offre n'existe pour cet utilisateur. * Vérifie d'abord qu'aucun token pour cette offre n'existe pour cet utilisateur.
* Pour cela on va parcourir le tableau, récupérer l'offre, et la retourner si elle existe * Pour cela on va parcourir le tableau, récupérer l'offre, et la retourner si elle existe
*/ */
$newOffre = $lettre->getOffre()->getId(); $newOffre = $offre->getId();
$userTokenKeys = $user->getTokenKey(); $userTokenKeys = $user->getTokenKey();
foreach ($userTokenKeys as $uTokenKey) foreach ($userTokenKeys as $uTokenKey)
...@@ -68,7 +59,7 @@ class LettreToken ...@@ -68,7 +59,7 @@ class LettreToken
$uOffre = intval($this->decodePotageUserToken($uTokenKey)['offre_id']); $uOffre = intval($this->decodePotageUserToken($uTokenKey)['offre_id']);
if ($uOffre === $newOffre) if ($uOffre === $newOffre)
{ {
return $uTokenKey; return $uTokenKey; // on s'arrête là
} }
} }
...@@ -78,8 +69,8 @@ class LettreToken ...@@ -78,8 +69,8 @@ class LettreToken
$newKey = bin2hex(random_bytes(15)); $newKey = bin2hex(random_bytes(15));
$token = $newKey $token = $newKey
.'_'. $lettre->getOffre()->getId() .'_'. $offre->getId()
.'_'. $lettre->getOffre()->getReference(); .'_'. $offre->getReference();
$tokenKey = base64_encode($token); $tokenKey = base64_encode($token);
...@@ -101,6 +92,8 @@ class LettreToken ...@@ -101,6 +92,8 @@ class LettreToken
/** /**
* Décode un token
*
* @param $token * @param $token
* @return array * @return array
*/ */
...@@ -114,4 +107,55 @@ class LettreToken ...@@ -114,4 +107,55 @@ class LettreToken
'offre_ref' => $data[2], 'offre_ref' => $data[2],
); );
} }
/**
* Révoque les tokens d'une offre
*
* On parcourt la table User, colonne tokenKey
* Chaque token est décodé et s'il correspond à l'offre expirée, on le supprime
*
* @param Offre $offre
* @return array
*/
public function revoquePotageUsersTokens(Offre $offre)
{
$log = array();
$em = $this->container->get('doctrine')->getManager();
/**
* @var array $usersTokenKeys
*/
$usersTokenKeys = $em->getRepository('PotageBundle:User')
->findAllTokenKeys();
foreach ($usersTokenKeys as $userTokenKeys)
{
foreach ($userTokenKeys['tokenKey'] as $uTokenKey)
{
$uOffre = intval($this->decodePotageUserToken($uTokenKey)['offre_id']);
if ($uOffre === $offre->getId())
{
/**
* @var User $user
*/
$user = $em->getRepository('PotageBundle:User')
->find($userTokenKeys['id']);
// enlève le token
$user->removeTokenKey($uTokenKey);
$log[] = " User ". $userTokenKeys['id'] . ", removing token ". $uTokenKey;
}
}
}
$em->flush();
count($log) === 0 ? $log[] = " No tokens detected for this offre !" : null ;
return $log;
}
} }
\ No newline at end of file
...@@ -2,7 +2,10 @@ ...@@ -2,7 +2,10 @@
namespace PotageBundle\Services; namespace PotageBundle\Services;
use PotageBundle\Entity\Groupe;
use PotageBundle\Entity\Lettre; use PotageBundle\Entity\Lettre;
use PotageBundle\Entity\Offre;
use PotageBundle\Entity\User;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
class Newsletter class Newsletter
...@@ -11,22 +14,23 @@ class Newsletter ...@@ -11,22 +14,23 @@ class Newsletter
/** /**
* Expéditeur, l'application elle-même * Expéditeur, l'application elle-même
* alternc sur grabuge: la mbox postmaster@potage.domainepublic.site est redirigée vers * alternc sur grabuge: la mbox postmaster@potage.domainepublic.site est redirigée vers
* -> mathieu@grabuge.domainepublic.net
* -> jaummathieu@collectifs.net * -> jaummathieu@collectifs.net
*/ */
private $from = ['postmaster@potage.domainepublic.site' => 'Potage']; private $from = ['postmaster@potage.domainepublic.site' => 'Potage'];
private $container; private $container;
private $lettreToken;
/** /**
* Newsletter constructor. * Newsletter constructor.
* *
* @param ContainerInterface $container * @param ContainerInterface $container
* @param LettreToken $lettreToken
*/ */
public function __construct(ContainerInterface $container) public function __construct(ContainerInterface $container, LettreToken $lettreToken)
{ {
$this->container = $container; $this->container = $container;
$this->lettreToken = $lettreToken;
} }
...@@ -139,46 +143,68 @@ class Newsletter ...@@ -139,46 +143,68 @@ class Newsletter
* (à son groupe d'utilisateurs) * (à son groupe d'utilisateurs)
* *
* @param Lettre $lettre * @param Lettre $lettre
* @param LettreToken $lettreToken
* @return array * @return array
* @throws \Twig_Error_Loader * @throws \Twig_Error_Loader
* @throws \Twig_Error_Runtime * @throws \Twig_Error_Runtime
* @throws \Twig_Error_Syntax * @throws \Twig_Error_Syntax
*/ */
public function sendLettreToGroup(Lettre $lettre, LettreToken $lettreToken) public function sendLettreToGroup(Lettre $lettre)
{ {
$subject = $lettre->getSubject(); $subject = $lettre->getSubject();
/**
* @var Offre $offre
* @var Groupe $groupe
*/
$offre = $lettre->getOffre();
$groupe = $lettre->getGroupe();
/** /**
* A partir de l'infolettre on récupère les destinataires * Les destinataires du groupe de l'infolettre,
* un tableau d'utilisteurs
*
* @var array $utilisateurs * @var array $utilisateurs
*/ */
$groupe = $lettre->getGroupe()->getId();
$utilisateurs = $this->container->get('doctrine') $utilisateurs = $this->container->get('doctrine')
->getRepository('PotageBundle:Utilisateur') ->getRepository('PotageBundle:Utilisateur')
->findAllByGroup($groupe); ->findAllByGroup($groupe->getId());
/** /**
* Boucle sur chaque utilisateur, envoie le mail, * Boucle sur chaque utilisateur, envoie le mail,
* récupère le code de retour dans un tableau * récupère le code de retour dans un tableau
*/ */
$ret = array(); $retour = array();
for ($i = 0; $i < count($utilisateurs); $i++) for ($i = 0; $i < count($utilisateurs); $i++)
{ {
/**
* @var User $user
*/
$user = $utilisateurs[$i]->getUser();
$token = null;
if ($user) {
$token = $this->lettreToken->encodePotageUserToken($user, $offre);
}
// TODO quid des utilisateurs qui n'ont pas encore de compte user ?
$to = array( $to = array(
'id' => $utilisateurs[$i]['id'], 'fullName' => $utilisateurs[$i]->getPrenom() .' '. $utilisateurs[$i]->getNom(),
'fullName' => $utilisateurs[$i]['prenom'] .' '. $utilisateurs[$i]['nom'], 'email' => $utilisateurs[$i]->getEmail(),
'email' => $utilisateurs[$i]['email'], 'token' => $token
'token' => $lettreToken->encodePotageUserToken($utilisateurs[$i]['id'], $lettre) ); //dump($to);
);
dump($to); // envoi du mail
$result = $this->sendMail($to, $subject, $lettre) === 1 ? 'Sent' : 'Error';
$ret[$i] = array( $retour[$i] = array(
'to' => $this->parseMail($to), 'to' => $to,
'result' => $this->sendMail($to, $subject, $lettre) === 1 ? 'sent' : 'error' 'tostring' => $this->parseMail($to),
'result' => $result
); );
} }
return $ret; return $retour;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment