Telegram notifications on user subscribers list changes. Some refactoring of SubscriptionsManager and event system.

This commit is contained in:
Alexey Skobkin 2017-01-07 21:46:50 +03:00
parent 9488eddd9f
commit 88be9e99ae
8 changed files with 196 additions and 27 deletions

View file

@ -0,0 +1,66 @@
<?php
namespace Skobkin\Bundle\PointToolsBundle\Event;
use Skobkin\Bundle\PointToolsBundle\Entity\User;
use Symfony\Component\EventDispatcher\Event;
/**
* Dispatched when user subscribers list was changed
*/
class UserSubscribersUpdatedEvent extends Event
{
const NAME = 'app.user.subscribers_updated';
/**
* @var User
*/
private $user;
/**
* @var User[]
*/
private $subscribed;
/**
* @var User[]
*/
private $unsubscribed;
/**
* UserSubscribersUpdatedEvent constructor.
*
* @param User[] $subscribed
* @param User[] $unsubscribed
*/
public function __construct(User $user, array $subscribed, array $unsubscribed)
{
$this->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;
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace Skobkin\Bundle\PointToolsBundle\EventListener;
use Skobkin\Bundle\PointToolsBundle\Event\UserSubscribersUpdatedEvent;
use Skobkin\Bundle\PointToolsBundle\Service\Telegram\Notifier;
class UserSubscribersUpdatedListener
{
/**
* @var Notifier
*/
private $notifier;
/**
* UsersRenameNotifierListener constructor.
*
* @param Notifier $notifier
*/
public function __construct(Notifier $notifier)
{
$this->notifier = $notifier;
}
public function onAppUserSubscribersUpdated(UserSubscribersUpdatedEvent $event)
{
$this->notifier->sendUserSubscribersUpdatedNotification($event->getUser(), $event->getSubscribedUsers(), $event->getUnsubscribedUsers());
}
}

View file

@ -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

View file

@ -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();
;
}
}

View file

@ -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:

View file

@ -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.

View file

@ -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);
}
/**

View file

@ -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,
]
);
}
}