add post follow
This commit is contained in:
parent
bf901ad799
commit
6607b03e3b
1
.php-version
Normal file
1
.php-version
Normal file
|
@ -0,0 +1 @@
|
|||
8.1
|
|
@ -15,6 +15,8 @@ core:
|
|||
- {name: 'Blog\PostController::rss', action: 'App\Controller\Blog\PostController::rss'}
|
||||
- {name: 'Blog\PostController::jsonApi', action: 'App\Controller\Blog\PostController::jsonApi'}
|
||||
- {name: 'Blog\CategoryController::categories', action: 'App\Controller\Blog\CategoryController::categories'}
|
||||
- {name: 'Blog\PostFollowController::enable', action: 'App\Controller\Blog\PostFollowController::enable'}
|
||||
- {name: 'Blog\PostFollowController::disable', action: 'App\Controller\Blog\PostFollowController::disable'}
|
||||
- {name: 'StlMeshController::meshes', action: 'App\Controller\StlMeshController::meshes'}
|
||||
pages:
|
||||
App\Entity\Page\SimplePage:
|
||||
|
@ -62,7 +64,7 @@ core:
|
|||
templates:
|
||||
- {name: "Par défaut", file: "page/text/default.txt.twig"}
|
||||
App\Entity\Page\TitledPage:
|
||||
name: '_'
|
||||
name: 'Page avec titre'
|
||||
templates:
|
||||
- {name: "Par défaut", file: "page/text/default.txt.twig"}
|
||||
|
||||
|
|
33
migrations/Version20220205165823.php
Normal file
33
migrations/Version20220205165823.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20220205165823 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE post_follow (id INT AUTO_INCREMENT NOT NULL, post_id INT NOT NULL, comment_id INT NOT NULL, hash VARCHAR(255) NOT NULL, is_enabled TINYINT(1) NOT NULL, INDEX IDX_5816A0154B89032C (post_id), INDEX IDX_5816A015F8697D13 (comment_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||
$this->addSql('ALTER TABLE post_follow ADD CONSTRAINT FK_5816A0154B89032C FOREIGN KEY (post_id) REFERENCES post (id)');
|
||||
$this->addSql('ALTER TABLE post_follow ADD CONSTRAINT FK_5816A015F8697D13 FOREIGN KEY (comment_id) REFERENCES comment (id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('DROP TABLE post_follow');
|
||||
}
|
||||
}
|
31
migrations/Version20220205172820.php
Normal file
31
migrations/Version20220205172820.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20220205172820 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE post_follow ADD created_at DATETIME NOT NULL, ADD updated_at DATETIME NOT NULL');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE post_follow DROP created_at, DROP updated_at');
|
||||
}
|
||||
}
|
37
migrations/Version20220206181024.php
Normal file
37
migrations/Version20220206181024.php
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20220206181024 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE post_follow DROP FOREIGN KEY FK_5816A015F8697D13');
|
||||
$this->addSql('ALTER TABLE post_follow DROP FOREIGN KEY FK_5816A0154B89032C');
|
||||
$this->addSql('ALTER TABLE post_follow ADD CONSTRAINT FK_5816A015F8697D13 FOREIGN KEY (comment_id) REFERENCES comment (id) ON DELETE CASCADE');
|
||||
$this->addSql('ALTER TABLE post_follow ADD CONSTRAINT FK_5816A0154B89032C FOREIGN KEY (post_id) REFERENCES post (id) ON DELETE CASCADE');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE post_follow DROP FOREIGN KEY FK_5816A0154B89032C');
|
||||
$this->addSql('ALTER TABLE post_follow DROP FOREIGN KEY FK_5816A015F8697D13');
|
||||
$this->addSql('ALTER TABLE post_follow ADD CONSTRAINT FK_5816A0154B89032C FOREIGN KEY (post_id) REFERENCES post (id)');
|
||||
$this->addSql('ALTER TABLE post_follow ADD CONSTRAINT FK_5816A015F8697D13 FOREIGN KEY (comment_id) REFERENCES comment (id)');
|
||||
}
|
||||
}
|
|
@ -17,6 +17,8 @@ use App\UrlGenerator\PostGenerator;
|
|||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use App\Factory\Blog\PostFollowFactory;
|
||||
use App\Manager\PostFollowManager;
|
||||
|
||||
class PostController extends PageController
|
||||
{
|
||||
|
@ -36,6 +38,7 @@ class PostController extends PageController
|
|||
Post $post,
|
||||
string $slug,
|
||||
CommentFactory $commentFactory,
|
||||
PostFollowManager $postFollowManager,
|
||||
Request $request,
|
||||
EntityManager $entityManager
|
||||
): Response {
|
||||
|
@ -61,6 +64,7 @@ class PostController extends PageController
|
|||
if ($form->isValid()) {
|
||||
$data = $request->request->get($form->getName());
|
||||
$parentCommentId = (int) $data['parentCommentId'];
|
||||
$follow = (bool) ($data['follow'] ?? false);
|
||||
|
||||
foreach ($post->getComments(['id' => $parentCommentId]) as $comment) {
|
||||
$form->getData()->setParentComment($comment);
|
||||
|
@ -70,8 +74,13 @@ class PostController extends PageController
|
|||
|
||||
$this->addFlash('success', 'Commentaire publié !');
|
||||
|
||||
if ($follow && $form->getData()->getEmail()) {
|
||||
$postFollowManager->create($post, $form->getData());
|
||||
}
|
||||
|
||||
return $this->redirect($request->getUri());
|
||||
}
|
||||
|
||||
$this->addFlash('error', 'Le formulaire n\'est pas valide.');
|
||||
}
|
||||
|
||||
|
|
47
src/Controller/Blog/PostFollowController.php
Normal file
47
src/Controller/Blog/PostFollowController.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\Blog;
|
||||
|
||||
use App\Core\Controller\Site\PageController;
|
||||
use App\Core\Site\SiteRequest;
|
||||
use App\Core\Site\SiteStore;
|
||||
use App\Entity\Blog\PostFollow;
|
||||
use App\Manager\PostFollowManager;
|
||||
|
||||
class PostFollowController extends PageController
|
||||
{
|
||||
protected PostFollowManager $manager;
|
||||
|
||||
public function __construct(PostFollowManager $manager, SiteRequest $siteRequest, SiteStore $siteStore)
|
||||
{
|
||||
parent::__construct($siteRequest, $siteStore);
|
||||
|
||||
$this->manager = $manager;
|
||||
}
|
||||
|
||||
public function enable(PostFollow $postFollow)
|
||||
{
|
||||
$this->manager->enable($postFollow);
|
||||
|
||||
$this->addFlash('success', 'Votre e-mail a bien été confirmé.');
|
||||
|
||||
return $this->redirectToRoute('blog_menu_post', [
|
||||
'post' => $postFollow->getPost()->getId(),
|
||||
'slug' => $postFollow->getPost()->getSlug(),
|
||||
'_domain' => $this->siteRequest->getDomain(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function disable(PostFollow $postFollow)
|
||||
{
|
||||
$this->manager->disable($postFollow);
|
||||
|
||||
$this->addFlash('success', 'Vous ne recevrez plus de notification pour cet article.');
|
||||
|
||||
return $this->redirectToRoute('blog_menu_post', [
|
||||
'post' => $postFollow->getPost()->getId(),
|
||||
'slug' => $postFollow->getPost()->getSlug(),
|
||||
'_domain' => $this->siteRequest->getDomain(),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -66,9 +66,15 @@ class Comment implements EntityInterface
|
|||
*/
|
||||
private $comments;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=PostFollow::class, mappedBy="comment", orphanRemoval=true)
|
||||
*/
|
||||
private $postFollows;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->comments = new ArrayCollection();
|
||||
$this->postFollows = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
|
@ -220,4 +226,34 @@ class Comment implements EntityInterface
|
|||
substr($this->getContent(), 0, 20).'…'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|PostFollow[]
|
||||
*/
|
||||
public function getPostFollows(): Collection
|
||||
{
|
||||
return $this->postFollows;
|
||||
}
|
||||
|
||||
public function addPostFollow(PostFollow $postFollow): self
|
||||
{
|
||||
if (!$this->postFollows->contains($postFollow)) {
|
||||
$this->postFollows[] = $postFollow;
|
||||
$postFollow->setComment($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removePostFollow(PostFollow $postFollow): self
|
||||
{
|
||||
if ($this->postFollows->removeElement($postFollow)) {
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($postFollow->getComment() === $this) {
|
||||
$postFollow->setComment(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,10 +118,16 @@ class Post implements EntityInterface
|
|||
*/
|
||||
private $notebook;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=PostFollow::class, mappedBy="post", orphanRemoval=true)
|
||||
*/
|
||||
private $postFollows;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->categories = new ArrayCollection();
|
||||
$this->comments = new ArrayCollection();
|
||||
$this->postFollows = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
|
@ -410,4 +416,34 @@ class Post implements EntityInterface
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|PostFollow[]
|
||||
*/
|
||||
public function getPostFollows(): Collection
|
||||
{
|
||||
return $this->postFollows;
|
||||
}
|
||||
|
||||
public function addPostFollow(PostFollow $postFollow): self
|
||||
{
|
||||
if (!$this->postFollows->contains($postFollow)) {
|
||||
$this->postFollows[] = $postFollow;
|
||||
$postFollow->setPost($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removePostFollow(PostFollow $postFollow): self
|
||||
{
|
||||
if ($this->postFollows->removeElement($postFollow)) {
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($postFollow->getPost() === $this) {
|
||||
$postFollow->setPost(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
99
src/Entity/Blog/PostFollow.php
Normal file
99
src/Entity/Blog/PostFollow.php
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity\Blog;
|
||||
|
||||
use App\Core\Doctrine\Timestampable;
|
||||
use App\Core\Entity\EntityInterface;
|
||||
use App\Repository\Blog\PostFollowRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass=PostFollowRepository::class)
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*/
|
||||
class PostFollow implements EntityInterface
|
||||
{
|
||||
use Timestampable;
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private $hash;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $isEnabled;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=Post::class, inversedBy="postFollows")
|
||||
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
|
||||
*/
|
||||
private $post;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=Comment::class, inversedBy="postFollows")
|
||||
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
|
||||
*/
|
||||
private $comment;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getHash(): ?string
|
||||
{
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
public function setHash(string $hash): self
|
||||
{
|
||||
$this->hash = $hash;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsEnabled(): ?bool
|
||||
{
|
||||
return $this->isEnabled;
|
||||
}
|
||||
|
||||
public function setIsEnabled(bool $isEnabled): self
|
||||
{
|
||||
$this->isEnabled = $isEnabled;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPost(): ?Post
|
||||
{
|
||||
return $this->post;
|
||||
}
|
||||
|
||||
public function setPost(?Post $post): self
|
||||
{
|
||||
$this->post = $post;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getComment(): ?Comment
|
||||
{
|
||||
return $this->comment;
|
||||
}
|
||||
|
||||
public function setComment(?Comment $comment): self
|
||||
{
|
||||
$this->comment = $comment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,8 @@ use App\Core\Notification\MailNotifier;
|
|||
use App\Entity\Blog\Comment;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use App\Core\Setting\SettingManager;
|
||||
use App\Repository\Blog\PostFollowRepositoryQuery;
|
||||
use App\Core\Site\SiteRequest;
|
||||
|
||||
/**
|
||||
* class CommentEventSubscriber.
|
||||
|
@ -20,12 +22,22 @@ class CommentEventSubscriber extends EntityManagerEventSubscriber
|
|||
protected MailNotifier $notifier;
|
||||
protected UrlGeneratorInterface $urlGenerator;
|
||||
protected SettingManager $settingManager;
|
||||
protected PostFollowRepository $postFollowRepository;
|
||||
protected SiteRequest $siteRequest;
|
||||
|
||||
public function __construct(MailNotifier $notifier, UrlGeneratorInterface $urlGenerator, SettingManager $settingManager)
|
||||
public function __construct(
|
||||
MailNotifier $notifier,
|
||||
UrlGeneratorInterface $urlGenerator,
|
||||
SettingManager $settingManager,
|
||||
PostFollowRepositoryQuery $postFollowRepositoryQuery,
|
||||
SiteRequest $siteRequest
|
||||
)
|
||||
{
|
||||
$this->notifier = $notifier;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->settingManager = $settingManager;
|
||||
$this->postFollowRepositoryQuery = $postFollowRepositoryQuery;
|
||||
$this->siteRequest = $siteRequest;
|
||||
}
|
||||
|
||||
public function support(EntityInterface $entity)
|
||||
|
@ -50,9 +62,41 @@ class CommentEventSubscriber extends EntityManagerEventSubscriber
|
|||
'post' => $this->urlGenerator->generate('blog_menu_post', [
|
||||
'post' => $event->getEntity()->getPost()->getId(),
|
||||
'slug' => $event->getEntity()->getPost()->getSlug(),
|
||||
'_domain' => $this->siteRequest->getDomain(),
|
||||
], UrlGeneratorInterface::ABSOLUTE_URL).'#review-'.$event->getEntity()->getId(),
|
||||
],
|
||||
], 'text/plain')
|
||||
;
|
||||
|
||||
$postFollows = $this->postFollowRepositoryQuery->create()
|
||||
->where('.post = :post')
|
||||
->andWhere('.isEnabled = 1')
|
||||
->setParameter(':post', $event->getEntity()->getPost()->getId())
|
||||
->find();
|
||||
|
||||
foreach ($postFollows as $postFollow) {
|
||||
if ($event->getEntity()->getEmail() !== $postFollow->getComment()->getEmail()) {
|
||||
$this->notifier
|
||||
->init()
|
||||
->setFrom($this->settingManager->get('email_sender')->getValue())
|
||||
->addRecipient($this->settingManager->get('email_comment')->getValue())
|
||||
->setSubject('[Deblan] Nouveau commentaire')
|
||||
->notify('mail/post_follow_comment.html.twig', [
|
||||
'post' => $event->getEntity()->getPost(),
|
||||
'links' => [
|
||||
'post' => $this->urlGenerator->generate('blog_menu_post', [
|
||||
'post' => $event->getEntity()->getPost()->getId(),
|
||||
'slug' => $event->getEntity()->getPost()->getSlug(),
|
||||
'_domain' => $this->siteRequest->getDomain(),
|
||||
], UrlGeneratorInterface::ABSOLUTE_URL).'#review-'.$event->getEntity()->getId(),
|
||||
'disable' => $this->urlGenerator->generate('blog_tech_follow_disable', [
|
||||
'hash' => $postFollow->getHash(),
|
||||
'_domain' => $this->siteRequest->getDomain(),
|
||||
], UrlGeneratorInterface::ABSOLUTE_URL),
|
||||
],
|
||||
], 'text/plain')
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
75
src/EventSuscriber/Blog/PostFollowEventSubscriber.php
Normal file
75
src/EventSuscriber/Blog/PostFollowEventSubscriber.php
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace App\EventSuscriber\Blog;
|
||||
|
||||
use App\Core\Entity\EntityInterface;
|
||||
use App\Core\Event\EntityManager\EntityManagerEvent;
|
||||
use App\Core\EventSuscriber\EntityManagerEventSubscriber;
|
||||
use App\Core\Notification\MailNotifier;
|
||||
use App\Core\Setting\SettingManager;
|
||||
use App\Entity\Blog\PostFollow;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use App\Core\Site\SiteRequest;
|
||||
|
||||
/**
|
||||
* class PostFollowEventSubscriber.
|
||||
*
|
||||
* @author Simon Vieille <simon@deblan.fr>
|
||||
*/
|
||||
class PostFollowEventSubscriber extends EntityManagerEventSubscriber
|
||||
{
|
||||
protected MailNotifier $notifier;
|
||||
protected UrlGeneratorInterface $urlGenerator;
|
||||
protected SettingManager $settingManager;
|
||||
protected SiteRequest $siteRequest;
|
||||
|
||||
public function __construct(
|
||||
MailNotifier $notifier,
|
||||
UrlGeneratorInterface $urlGenerator,
|
||||
SettingManager $settingManager,
|
||||
SiteRequest $siteRequest
|
||||
)
|
||||
{
|
||||
$this->notifier = $notifier;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->settingManager = $settingManager;
|
||||
$this->siteRequest = $siteRequest;
|
||||
}
|
||||
|
||||
public function support(EntityInterface $entity)
|
||||
{
|
||||
return $entity instanceof PostFollow;
|
||||
}
|
||||
|
||||
public function onCreate(EntityManagerEvent $event)
|
||||
{
|
||||
if (!$this->support($event->getEntity())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->notifier
|
||||
->init()
|
||||
->setFrom($this->settingManager->get('email_sender')->getValue())
|
||||
->addRecipient($event->getEntity()->getComment()->getEmail())
|
||||
->setSubject('[Deblan] Confirmer votre e-mail')
|
||||
->notify('mail/post_follow_subscription.html.twig', [
|
||||
'entity' => $event->getEntity(),
|
||||
'links' => [
|
||||
'post' => $this->urlGenerator->generate('blog_menu_post', [
|
||||
'post' => $event->getEntity()->getPost()->getId(),
|
||||
'slug' => $event->getEntity()->getPost()->getSlug(),
|
||||
'_domain' => $this->siteRequest->getDomain(),
|
||||
], UrlGeneratorInterface::ABSOLUTE_URL),
|
||||
'enable' => $this->urlGenerator->generate('blog_tech_follow_enable', [
|
||||
'hash' => $event->getEntity()->getHash(),
|
||||
'_domain' => $this->siteRequest->getDomain(),
|
||||
], UrlGeneratorInterface::ABSOLUTE_URL),
|
||||
'disable' => $this->urlGenerator->generate('blog_tech_follow_disable', [
|
||||
'hash' => $event->getEntity()->getHash(),
|
||||
'_domain' => $this->siteRequest->getDomain(),
|
||||
], UrlGeneratorInterface::ABSOLUTE_URL),
|
||||
],
|
||||
], 'text/plain')
|
||||
;
|
||||
}
|
||||
}
|
24
src/Factory/Blog/PostFollowFactory.php
Normal file
24
src/Factory/Blog/PostFollowFactory.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace App\Factory\Blog;
|
||||
|
||||
use App\Core\Factory\FactoryInterface;
|
||||
use App\Entity\Blog\Comment;
|
||||
use App\Entity\Blog\Post;
|
||||
use App\Entity\Blog\PostFollow as Entity;
|
||||
|
||||
class PostFollowFactory implements FactoryInterface
|
||||
{
|
||||
public function create(Post $post, Comment $comment): Entity
|
||||
{
|
||||
$entity = new Entity();
|
||||
$entity
|
||||
->setPost($post)
|
||||
->setComment($comment)
|
||||
->setIsEnabled(false)
|
||||
->setHash(hash('sha256', bin2hex(random_bytes(32))))
|
||||
;
|
||||
|
||||
return $entity;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
|||
use Symfony\Component\Validator\Constraints\Email;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use Symfony\Component\Validator\Constraints\Url;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
|
||||
class UserCommentType extends AbstractType
|
||||
{
|
||||
|
@ -75,6 +76,16 @@ class UserCommentType extends AbstractType
|
|||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'follow',
|
||||
CheckboxType::class,
|
||||
[
|
||||
'label' => 'Recevoir une notification par e-mail si un commentaire est déposé sur cet article',
|
||||
'mapped' => false,
|
||||
'required' => false,
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'parentCommentId',
|
||||
HiddenType::class,
|
||||
|
|
70
src/Manager/PostFollowManager.php
Normal file
70
src/Manager/PostFollowManager.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace App\Manager;
|
||||
|
||||
use App\Core\Manager\EntityManager;
|
||||
use App\Entity\Blog\Comment;
|
||||
use App\Entity\Blog\Post;
|
||||
use App\Entity\Blog\PostFollow;
|
||||
use App\Factory\Blog\PostFollowFactory;
|
||||
use App\Repository\Blog\PostFollowRepositoryQuery;
|
||||
|
||||
/**
|
||||
* class PostFollowManager.
|
||||
*
|
||||
* @author Simon Vieille <simon@deblan.fr>
|
||||
*/
|
||||
class PostFollowManager
|
||||
{
|
||||
protected PostFollowFactory $factory;
|
||||
protected PostFollowRepositoryQuery $repository;
|
||||
protected EntityManager $manager;
|
||||
|
||||
public function __construct(
|
||||
PostFollowFactory $factory,
|
||||
PostFollowRepositoryQuery $repository,
|
||||
EntityManager $manager
|
||||
) {
|
||||
$this->factory = $factory;
|
||||
$this->repository = $repository;
|
||||
$this->manager = $manager;
|
||||
}
|
||||
|
||||
public function create(Post $post, Comment $comment): PostFollow
|
||||
{
|
||||
$postFollow = $this->find($post, $comment);
|
||||
|
||||
if (!$postFollow) {
|
||||
$postFollow = $this->factory->create($post, $comment);
|
||||
|
||||
$this->manager->create($postFollow);
|
||||
}
|
||||
|
||||
return $postFollow;
|
||||
}
|
||||
|
||||
public function find(Post $post, Comment $comment): ?PostFollow
|
||||
{
|
||||
return $this->repository->create()
|
||||
->where('.post = :post')
|
||||
->andWhere('.comment = :comment')
|
||||
->setParameters([
|
||||
':post' => $post->getId(),
|
||||
':comment' => $comment->getId(),
|
||||
])
|
||||
->findOne()
|
||||
;
|
||||
}
|
||||
|
||||
public function enable(PostFollow $postFollow): void
|
||||
{
|
||||
$postFollow->setIsEnabled(true);
|
||||
|
||||
$this->manager->update($postFollow);
|
||||
}
|
||||
|
||||
public function disable(PostFollow $postFollow): void
|
||||
{
|
||||
$this->manager->delete($postFollow);
|
||||
}
|
||||
}
|
20
src/Repository/Blog/PostFollowRepository.php
Normal file
20
src/Repository/Blog/PostFollowRepository.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository\Blog;
|
||||
|
||||
use App\Entity\Blog\PostFollow;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
class PostFollowRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, PostFollow::class);
|
||||
}
|
||||
|
||||
public function getEm()
|
||||
{
|
||||
return $this->getEntityManager();
|
||||
}
|
||||
}
|
15
src/Repository/Blog/PostFollowRepositoryQuery.php
Normal file
15
src/Repository/Blog/PostFollowRepositoryQuery.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository\Blog;
|
||||
|
||||
use App\Core\Repository\RepositoryQuery;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use App\Repository\Blog\PostFollowRepository as Repository;
|
||||
|
||||
class PostFollowRepositoryQuery extends RepositoryQuery
|
||||
{
|
||||
public function __construct(Repository $repository, PaginatorInterface $paginator)
|
||||
{
|
||||
parent::__construct($repository, 'p', $paginator);
|
||||
}
|
||||
}
|
8
templates/mail/post_follow_comment.html.twig
Normal file
8
templates/mail/post_follow_comment.html.twig
Normal file
|
@ -0,0 +1,8 @@
|
|||
Un nouveau commentaire a été déposé sur l'article suivant :
|
||||
|
||||
{{ post.title|raw }}
|
||||
{{ links.post }}
|
||||
|
||||
Vous pourrez supprimer les notifications de cet article via ce lien :
|
||||
|
||||
{{ links.disable }}
|
14
templates/mail/post_follow_subscription.html.twig
Normal file
14
templates/mail/post_follow_subscription.html.twig
Normal file
|
@ -0,0 +1,14 @@
|
|||
Vous avez décidé de recevoir les notifications de cet article :
|
||||
|
||||
{{ entity.post.title|raw }}
|
||||
{{ links.post }}
|
||||
|
||||
Si vous n'êtes pas à l'origine de cette demande, vous pouvez ignorer ce message et votre e-mail sera automatiquement supprimé dans quelques jours.
|
||||
|
||||
Veuillez cliquer sur le lien de confirmation pour valider votre e-mail :
|
||||
|
||||
{{ links.enable }}
|
||||
|
||||
Vous pourrez vous désinscrire à tout moment via ce lien :
|
||||
|
||||
{{ links.disable }}
|
|
@ -148,6 +148,13 @@
|
|||
{{ form_errors(form.email) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="field col-12">
|
||||
{{ form_label(form.follow) }}
|
||||
{{ form_widget(form.follow) }}
|
||||
{{ form_errors(form.follow) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<p class="no-margin">
|
||||
{{- 'Votre commentaire - Vous pouvez utiliser du markdown ' }}
|
||||
|
|
Loading…
Reference in a new issue