From 88be9e99ae8a1321ae046fbce352ca0a5b7e778b Mon Sep 17 00:00:00 2001 From: Alexey Skobkin Date: Sat, 7 Jan 2017 21:46:50 +0300 Subject: [PATCH] Telegram notifications on user subscribers list changes. Some refactoring of SubscriptionsManager and event system. --- .../Event/UserSubscribersUpdatedEvent.php | 66 +++++++++++++++++++ .../UserSubscribersUpdatedListener.php | 30 +++++++++ ...rListener.php => UsersRenamedListener.php} | 2 +- .../Repository/SubscriptionRepository.php | 25 ++++++- .../Resources/config/services.yml | 10 ++- ...r_subscribers_updated_notification.md.twig | 20 ++++++ .../Service/SubscriptionsManager.php | 38 +++++------ .../Service/Telegram/Notifier.php | 32 +++++++++ 8 files changed, 196 insertions(+), 27 deletions(-) create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Event/UserSubscribersUpdatedEvent.php create mode 100644 src/Skobkin/Bundle/PointToolsBundle/EventListener/UserSubscribersUpdatedListener.php rename src/Skobkin/Bundle/PointToolsBundle/EventListener/{UsersRenamedNotifierListener.php => UsersRenamedListener.php} (94%) create mode 100644 src/Skobkin/Bundle/PointToolsBundle/Resources/views/Telegram/user_subscribers_updated_notification.md.twig diff --git a/src/Skobkin/Bundle/PointToolsBundle/Event/UserSubscribersUpdatedEvent.php b/src/Skobkin/Bundle/PointToolsBundle/Event/UserSubscribersUpdatedEvent.php new file mode 100644 index 0000000..4ab8b1e --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/Event/UserSubscribersUpdatedEvent.php @@ -0,0 +1,66 @@ +user = $user; + $this->subscribed = $subscribed; + $this->unsubscribed = $unsubscribed; + } + + /** + * @return User + */ + public function getUser(): User + { + return $this->user; + } + + /** + * @return User[] + */ + public function getSubscribedUsers(): array + { + return $this->subscribed; + } + + /** + * @return User[] + */ + public function getUnsubscribedUsers(): array + { + return $this->unsubscribed; + } +} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/EventListener/UserSubscribersUpdatedListener.php b/src/Skobkin/Bundle/PointToolsBundle/EventListener/UserSubscribersUpdatedListener.php new file mode 100644 index 0000000..987898d --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/EventListener/UserSubscribersUpdatedListener.php @@ -0,0 +1,30 @@ +notifier = $notifier; + } + + public function onAppUserSubscribersUpdated(UserSubscribersUpdatedEvent $event) + { + $this->notifier->sendUserSubscribersUpdatedNotification($event->getUser(), $event->getSubscribedUsers(), $event->getUnsubscribedUsers()); + } +} \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/EventListener/UsersRenamedNotifierListener.php b/src/Skobkin/Bundle/PointToolsBundle/EventListener/UsersRenamedListener.php similarity index 94% rename from src/Skobkin/Bundle/PointToolsBundle/EventListener/UsersRenamedNotifierListener.php rename to src/Skobkin/Bundle/PointToolsBundle/EventListener/UsersRenamedListener.php index 90875b4..fd4ae1c 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/EventListener/UsersRenamedNotifierListener.php +++ b/src/Skobkin/Bundle/PointToolsBundle/EventListener/UsersRenamedListener.php @@ -5,7 +5,7 @@ namespace Skobkin\Bundle\PointToolsBundle\EventListener; use Skobkin\Bundle\PointToolsBundle\Event\UsersRenamedEvent; use Skobkin\Bundle\PointToolsBundle\Service\Telegram\Notifier; -class UsersRenamedNotifierListener +class UsersRenamedListener { /** * @var Notifier diff --git a/src/Skobkin/Bundle/PointToolsBundle/Repository/SubscriptionRepository.php b/src/Skobkin/Bundle/PointToolsBundle/Repository/SubscriptionRepository.php index 0c02625..9d96948 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Repository/SubscriptionRepository.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Repository/SubscriptionRepository.php @@ -3,14 +3,16 @@ namespace Skobkin\Bundle\PointToolsBundle\Repository; use Doctrine\ORM\EntityRepository; +use Skobkin\Bundle\PointToolsBundle\Entity\User; class SubscriptionRepository extends EntityRepository { /** - * @param integer $id - * @return integer + * @param int $id + * + * @return int */ - public function getUserSubscribersCountById($id) + public function getUserSubscribersCountById($id): int { if (!is_int($id)) { throw new \InvalidArgumentException('$id must be an integer'); @@ -25,4 +27,21 @@ class SubscriptionRepository extends EntityRepository ->getQuery()->getSingleScalarResult() ; } + + /** + * @param User $user + * @param User[] $subscribers + */ + public function removeSubscribers(User $user, array $subscribers) + { + $qb = $this->createQueryBuilder('s'); + $qb + ->delete() + ->where('s.author = :author') + ->andWhere('s.subscriber IN (:subscribers)') + ->setParameter('author', $user->getId()) + ->setParameter('subscribers', $subscribers) + ->getQuery()->execute(); + ; + } } \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/Resources/config/services.yml b/src/Skobkin/Bundle/PointToolsBundle/Resources/config/services.yml index d72edef..a220c19 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Resources/config/services.yml +++ b/src/Skobkin/Bundle/PointToolsBundle/Resources/config/services.yml @@ -35,7 +35,7 @@ services: skobkin_point_tools.subscriptions_manager: class: Skobkin\Bundle\PointToolsBundle\Service\SubscriptionsManager - arguments: [ @doctrine.orm.entity_manager ] + arguments: [ @doctrine.orm.entity_manager, @event_dispatcher ] # Factories @@ -92,11 +92,17 @@ services: - { name: doctrine.event_subscriber, connection: default } point_tools.event_listener.users_renamed_notifier: - class: Skobkin\Bundle\PointToolsBundle\EventListener\UsersRenamedNotifierListener + class: Skobkin\Bundle\PointToolsBundle\EventListener\UsersRenamedListener arguments: [@point_tools.telegram.notifier] tags: - { name: kernel.event_listener, event: app.users.renamed } + point_tools.event_listener.user_subscribers_updated: + class: Skobkin\Bundle\PointToolsBundle\EventListener\UserSubscribersUpdatedListener + arguments: [@point_tools.telegram.notifier] + tags: + - { name: kernel.event_listener, event: app.user.subscribers_updated } + # Twig extensions point_tools.twig.point_avatar_extension: diff --git a/src/Skobkin/Bundle/PointToolsBundle/Resources/views/Telegram/user_subscribers_updated_notification.md.twig b/src/Skobkin/Bundle/PointToolsBundle/Resources/views/Telegram/user_subscribers_updated_notification.md.twig new file mode 100644 index 0000000..c4d9a0c --- /dev/null +++ b/src/Skobkin/Bundle/PointToolsBundle/Resources/views/Telegram/user_subscribers_updated_notification.md.twig @@ -0,0 +1,20 @@ +{# @var subscribed \Skobkin\Bundle\PointToolsBundle\Entity\User[] #} +{# @var unsubscribed \Skobkin\Bundle\PointToolsBundle\Entity\User[] #} +*Subscribers list changed:* + +{% if subscribed|length > 0 %} +New subscribers: +{% for subscriber in subscribed %} +[@{{ subscriber.login }}]({{ subscriber.login|point_user_url(true) }}) +{% endfor %} +{% endif %} +{% if unsubscribed|length > 0 %} + +Lost subscribers: +{% for subscriber in unsubscribed %} +[@{{ subscriber.login }}]({{ subscriber.login|point_user_url(true) }}) +{% endfor %} +{% endif %} + +{# @todo remove hardcoded URL #} +See full subscribers history on [Point Tools](https://point.skobk.in{{ path('user_show', {'login': user.login}) }}) site. \ No newline at end of file diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/SubscriptionsManager.php b/src/Skobkin/Bundle/PointToolsBundle/Service/SubscriptionsManager.php index 74f9ea9..38bf7df 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/SubscriptionsManager.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/SubscriptionsManager.php @@ -3,28 +3,34 @@ namespace Skobkin\Bundle\PointToolsBundle\Service; use Doctrine\ORM\EntityManager; -use Doctrine\ORM\QueryBuilder; use Skobkin\Bundle\PointToolsBundle\Entity\Subscription; use Skobkin\Bundle\PointToolsBundle\Entity\SubscriptionEvent; use Skobkin\Bundle\PointToolsBundle\Entity\User; +use Skobkin\Bundle\PointToolsBundle\Event\UserSubscribersUpdatedEvent; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; class SubscriptionsManager { /** * @var EntityManager */ - protected $em; + private $em; + + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; - // @todo Add logger - public function __construct(EntityManager $entityManager) + public function __construct(EntityManager $entityManager, EventDispatcherInterface $eventDispatcher) { $this->em = $entityManager; + $this->eventDispatcher = $eventDispatcher; } /** * @param User $user - * @param User[]|array $newSubscribersList + * @param User[] $newSubscribersList */ public function updateUserSubscribers(User $user, $newSubscribersList = []) { @@ -37,6 +43,7 @@ class SubscriptionsManager $oldSubscribersList[] = $subscription->getSubscriber(); } + // @todo remove $isFirstTime = false; // Preventing to add garbage subscriptions for first processing @@ -66,16 +73,6 @@ class SubscriptionsManager } } - unset($subscribedList); - - /** @var QueryBuilder $unsubscribedQuery */ - $unsubscribedQuery = $this->em->getRepository('SkobkinPointToolsBundle:Subscription')->createQueryBuilder('s'); - $unsubscribedQuery - ->delete() - ->where('s.author = :author') - ->andWhere('s.subscriber IN (:subscribers)') - ; - /** @var User $unsubscribedUser */ foreach ($unsubscribedList as $unsubscribedUser) { $logEvent = new SubscriptionEvent($user, $unsubscribedUser, SubscriptionEvent::ACTION_UNSUBSCRIBE); @@ -84,13 +81,12 @@ class SubscriptionsManager $user->addNewSubscriberEvent($logEvent); } - $unsubscribedQuery - ->setParameter('author', $user->getId()) - ->setParameter('subscribers', $unsubscribedList) - ->getQuery()->execute(); - ; + // Removing users from database + $this->em->getRepository('SkobkinPointToolsBundle:Subscription')->removeSubscribers($user, $unsubscribedList); - unset($unsubscribedList); + // Dispatching event + $subscribersUpdatedEvent = new UserSubscribersUpdatedEvent($user, $subscribedList, $unsubscribedList); + $this->eventDispatcher->dispatch(UserSubscribersUpdatedEvent::NAME, $subscribersUpdatedEvent); } /** diff --git a/src/Skobkin/Bundle/PointToolsBundle/Service/Telegram/Notifier.php b/src/Skobkin/Bundle/PointToolsBundle/Service/Telegram/Notifier.php index 921aa08..fa345fa 100644 --- a/src/Skobkin/Bundle/PointToolsBundle/Service/Telegram/Notifier.php +++ b/src/Skobkin/Bundle/PointToolsBundle/Service/Telegram/Notifier.php @@ -4,6 +4,7 @@ namespace Skobkin\Bundle\PointToolsBundle\Service\Telegram; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Skobkin\Bundle\PointToolsBundle\Entity\User; use Skobkin\Bundle\PointToolsBundle\Entity\UserRenameEvent; /** @@ -50,4 +51,35 @@ class Notifier $this->messenger->sendMassTemplatedMessage($accounts, '@SkobkinPointTools/Telegram/users_renamed_notification.md.twig', ['events' => $userRenameEvents]); } + + /** + * Send notification about changes in user's subscribers list + * + * @param User $user + * @param array $subscribed + * @param array $unsubscribed + */ + public function sendUserSubscribersUpdatedNotification(User $user, array $subscribed, array $unsubscribed) + { + $account = $this->accountsRepo->findOneBy( + [ + 'user' => $user, + 'subscriberNotification' => true, + ] + ); + + if (null === $account) { + return; + } + + $this->messenger->sendTemplatedMessage( + $account, + '@SkobkinPointTools/Telegram/user_subscribers_updated_notification.md.twig', + [ + 'user' => $user, + 'subscribed' => $subscribed, + 'unsubscribed' => $unsubscribed, + ] + ); + } } \ No newline at end of file