Services/NotificationsService.php
<?php
/**
* @author Rafał Muszyński <rafal.muszynski@sourcefabric.org>
* @copyright 2014 Sourcefabric z.ú.
* @license http://www.gnu.org/licenses/gpl-3.0.txt
*/
namespace Newscoop\PaywallBundle\Services;
use Newscoop\Services\EmailService;
use Newscoop\NewscoopBundle\Services\SystemPreferencesService;
use Newscoop\Services\PlaceholdersService;
use Newscoop\Services\TemplatesService;
use Newscoop\PaywallBundle\Notifications\Emails;
use Newscoop\PaywallBundle\Meta\MetaSubscription;
use Doctrine\ORM\EntityManager;
use Newscoop\PaywallBundle\Events\PaywallEvents;
use Newscoop\EventDispatcher\Events\GenericEvent;
use Newscoop\PaywallBundle\Entity\UserSubscription;
use Newscoop\PaywallBundle\Entity\Order;
/**
* Notifications service.
*/
class NotificationsService
{
/**
* @var EmailService
*/
protected $emailService;
/**
* @var SystemPreferencesService
*/
protected $systemPreferences;
/**
* @var TemplatesService
*/
protected $templatesService;
/**
* @var PlaceholdersService
*/
protected $placeholdersService;
/**
* @var EntityManager
*/
protected $em;
protected $dispatcher;
/**
* @param EmailService $emailService
* @param SystemPreferencesService $systemPreferences
* @param TemplatesService $templatesService
* @param PlaceholdersService $placeholdersService
* @param EntityManager $em
* @param ContainerAwareEventDispatcher $dispatcher
*/
public function __construct(
EmailService $emailService,
SystemPreferencesService $systemPreferences,
TemplatesService $templatesService,
PlaceholdersService $placeholdersService,
EntityManager $em,
$dispatcher
) {
$this->emailService = $emailService;
$this->systemPreferences = $systemPreferences;
$this->templatesService = $templatesService;
$this->placeholdersService = $placeholdersService;
$this->em = $em;
$this->dispatcher = $dispatcher;
}
/**
* Sends email notifications.
*
* @param string $code Email message type
* @param Newscoop\Entity\User $user User object
* @param PaywallBundle\Entity\UserSubscription $userSubscription User's subscription
*/
public function sendNotification($code, array $recipients = array(), array $data = array())
{
if ($this->systemPreferences->PaywallEmailNotifyEnabled != '1') {
return;
}
$smarty = $this->templatesService->getSmarty();
$smarty->assign('user', new \MetaUser($data['user']));
$subscriptions = array();
$order = new Order();
if (!$data['subscriptions'] instanceof UserSubscription) {
$subscription = $data['subscriptions'][0];
$order = $subscription->getOrder();
foreach ($data['subscriptions'] as $key => $value) {
$subscriptions[] = new MetaSubscription($value);
}
$smarty->assign('userSubscriptions', $subscriptions);
} else {
$subscription = $data['subscriptions'];
$order = $subscription->getOrder();
$smarty->assign('userSubscription', new MetaSubscription($subscription));
}
$smarty->assign('order', $order);
try {
$message = $this->loadProperMessageTemplateBy($code);
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
$recipients = !empty($recipients) ? $recipients : $this->systemPreferences->PaywallMembershipNotifyEmail;
$this->emailService->send(
$this->placeholdersService->get('subject'),
$message,
$recipients,
$this->systemPreferences->PaywallMembershipNotifyFromEmail
);
}
private function loadProperMessageTemplateBy($code)
{
switch ($code) {
case Emails::USER_CONFIRMATION:
$message = $this->templatesService->fetchTemplate(
'_paywall/email_notify_user.tpl'
);
break;
case Emails::SUBSCRIPTION_CONFIRMATION:
$message = $this->templatesService->fetchTemplate(
'_paywall/email_notify_admin.tpl'
);
break;
case Emails::SUBSCRIPTION_STATUS:
$message = $this->templatesService->fetchTemplate(
'_paywall/email_subscription_status.tpl'
);
break;
case Emails::SUBSCRIPTION_EXPIRATION:
$message = $this->templatesService->fetchTemplate(
'_paywall/email_subscription_expiration.tpl'
);
break;
case Emails::ADMIN_CREATED_CONFIRMATION:
$message = $this->templatesService->fetchTemplate(
'_paywall/email_subscription_admin_created.tpl'
);
break;
default:
break;
}
return $message;
}
/**
* Sets notify sent flag for given user subscription.
* Level one of the notifications, for instance,
* sends notifications 7 days before expiration.
*
* @param UserSubscription $subscription User subscription
* @param \DateTime $datetime Date time when notify has been sent
*/
public function setSentDateTimeOnLevelOne(UserSubscription $subscription, $datetime = null)
{
$subscription->setNotifySentLevelOne($datetime ?: new \DateTime('now'));
$this->em->flush();
}
/**
* Sets notify sent flag for given user subscription.
* Level two of the notifications, for instance,
* sends notifications 3 days before expiration.
*
* @param UserSubscription $subscription User subscription
* @param \DateTime $datetime Date time when notify has been sent
*/
public function setSentDateTimeOnLevelTwo(UserSubscription $subscription, $datetime = null)
{
$subscription->setNotifySentLevelTwo($datetime ?: new \DateTime('now'));
$this->em->flush();
}
/**
* Processes expiring subscriptions and sends email
* notifications to users.
*
* @param \DateTime $now Current date time
* @param int $subscriptionsCount Subscriptions count
*/
public function processExpiringSubscriptions($now, $notify, $count = 0, $days = 7)
{
if ($count === 0) {
$count = $this->getExpiringSubscriptionsCount($now);
}
$batch = 100;
$steps = ($count > $batch) ? ceil($count / $batch) : 1;
for ($i = 0; $i < $steps; ++$i) {
$offset = $i * $batch;
$query = $this->em->getRepository('Newscoop\PaywallBundle\Entity\UserSubscription')
->getExpiringSubscriptions($offset, $batch, $now, $notify, $days);
$expiringSubscriptions = $query->getResult();
$this->dispatchNotificationSend($expiringSubscriptions);
}
}
/**
* Gets expiring subscriptions count.
*
* @param \DateTime $now Current date time
*
* @return int
*/
public function getExpiringSubscriptionsCount($now, $notify, $days = 7)
{
$query = $this->em->getRepository('Newscoop\PaywallBundle\Entity\UserSubscription')
->getExpiringSubscriptionsCount($now, $notify, $days);
return (int) $query->getSingleScalarResult();
}
private function dispatchNotificationSend($expiringSubscriptions)
{
foreach ($expiringSubscriptions as $key => $subscription) {
$this->dispatcher->dispatch(
PaywallEvents::SUBSCRIPTION_EXPIRATION,
new GenericEvent($subscription)
);
}
}
}