View source
<?php
namespace Drupal\simplenews\Subscription;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\DestructableInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Psr\Log\LoggerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Utility\Token;
use Drupal\simplenews\Entity\Newsletter;
use Drupal\simplenews\Entity\Subscriber;
use Drupal\simplenews\Mail\MailerInterface;
use Drupal\simplenews\NewsletterInterface;
use Drupal\simplenews\SubscriberInterface;
class SubscriptionManager implements SubscriptionManagerInterface, DestructableInterface {
protected $combineConfirmations = FALSE;
protected $confirmations = [];
protected $subscribedCache = [];
protected $mailer;
protected $languageManager;
protected $config;
protected $token;
protected $logger;
protected $currentUser;
protected $subscriberStorage;
public function __construct(LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory, MailerInterface $mailer, Token $token, LoggerInterface $logger, AccountInterface $current_user) {
$this->languageManager = $language_manager;
$this->config = $config_factory
->get('simplenews.settings');
$this->mailer = $mailer;
$this->token = $token;
$this->logger = $logger;
$this->currentUser = $current_user;
$this->subscriberStorage = \Drupal::entityTypeManager()
->getStorage('simplenews_subscriber');
}
public function subscribe($mail, $newsletter_id, $confirm = NULL, $source = 'unknown', $preferred_langcode = NULL) {
$preferred_langcode = $preferred_langcode ?? $this->languageManager
->getCurrentLanguage();
$subscriber = Subscriber::loadByMail($mail, 'create', $preferred_langcode);
$newsletter = Newsletter::load($newsletter_id);
if ($confirm === NULL) {
$confirm = $this
->requiresConfirmation($newsletter, $subscriber
->getUserId());
}
if ($confirm) {
if (!$subscriber
->isSubscribed($newsletter_id)) {
$subscriber
->subscribe($newsletter_id, SIMPLENEWS_SUBSCRIPTION_STATUS_UNCONFIRMED, $source);
$subscriber
->save();
}
$this
->addConfirmation('subscribe', $subscriber, $newsletter);
}
elseif (!$subscriber
->isSubscribed($newsletter_id)) {
$subscriber
->subscribe($newsletter_id, SIMPLENEWS_SUBSCRIPTION_STATUS_SUBSCRIBED, $source);
$subscriber
->save();
}
return $this;
}
public function unsubscribe($mail, $newsletter_id, $confirm = NULL, $source = 'unknown') {
$subscriber = Subscriber::loadByMail($mail);
if (!$subscriber) {
throw new \Exception('The subscriber does not exist.');
}
if (!($newsletter = Newsletter::load($newsletter_id))) {
$this->logger
->error('Attempt to unsubscribe from non existing mailing list ID %id', [
'%id' => $newsletter_id,
]);
return $this;
}
if ($confirm === NULL) {
$confirm = $this
->requiresConfirmation($newsletter, $subscriber
->getUserId());
}
if ($confirm) {
$this
->addConfirmation('unsubscribe', $subscriber, $newsletter);
}
elseif ($subscriber
->isSubscribed($newsletter_id)) {
$subscriber
->unsubscribe($newsletter_id, $source);
$subscriber
->save();
}
return $this;
}
public function isSubscribed($mail, $newsletter_id) {
if (!isset($this->subscribedCache[$mail][$newsletter_id])) {
$subscriber = Subscriber::loadByMail($mail);
$this->subscribedCache[$mail][$newsletter_id] = $subscriber && $subscriber
->getStatus() && $subscriber
->isSubscribed($newsletter_id);
}
return $this->subscribedCache[$mail][$newsletter_id];
}
public function getChangesList(SubscriberInterface $subscriber, array $changes = NULL, $langcode = NULL) {
if (empty($langcode)) {
$language = $this->languageManager
->getCurrentLanguage();
$langcode = $language
->getId();
}
if (empty($changes)) {
$changes = $subscriber
->getChanges();
}
$changes_list = [];
foreach ($changes as $newsletter_id => $action) {
$subscribed = $subscriber
->isSubscribed($newsletter_id);
if ($action == 'subscribe' && !$subscribed) {
$line = $this->config
->get('subscription.confirm_combined_line_subscribe_unsubscribed');
}
elseif ($action == 'subscribe' && $subscribed) {
$line = $this->config
->get('subscription.confirm_combined_line_subscribe_subscribed');
}
elseif ($action == 'unsubscribe' && !$subscribed) {
$line = $this->config
->get('subscription.confirm_combined_line_unsubscribe_unsubscribed');
}
elseif ($action == 'unsubscribe' && $subscribed) {
$line = $this->config
->get('subscription.confirm_combined_line_unsubscribe_subscribed');
}
$newsletter_context = [
'simplenews_subscriber' => $subscriber,
'newsletter' => Newsletter::load($newsletter_id),
];
$changes_list[$newsletter_id] = $this->token
->replace($line, $newsletter_context, [
'sanitize' => FALSE,
]);
}
return $changes_list;
}
public function sendConfirmations() {
foreach ($this->confirmations as $mail => $changes) {
$subscriber = Subscriber::loadByMail($mail, 'create', $this->languageManager
->getCurrentLanguage());
$subscriber
->setChanges($changes);
$this->mailer
->sendCombinedConfirmation($subscriber);
if ($subscriber
->id()) {
$subscriber
->save();
}
}
$sent = !empty($this->confirmations);
$this->confirmations = [];
return $sent;
}
public function reset() {
$this->subscribedCache = [];
}
public function tidy() {
$days = $this->config
->get('subscription.tidy_unconfirmed');
if (!$days) {
return;
}
$max_age = strtotime("-{$days} days");
$unconfirmed = \Drupal::entityQuery('simplenews_subscriber')
->condition('subscriptions.status', SIMPLENEWS_SUBSCRIPTION_STATUS_UNCONFIRMED)
->condition('subscriptions.timestamp', $max_age, '<')
->execute();
$confirmed = \Drupal::entityQuery('simplenews_subscriber')
->condition('subscriptions.status', SIMPLENEWS_SUBSCRIPTION_STATUS_UNCONFIRMED, '<>')
->execute();
$delete = array_diff($unconfirmed, $confirmed);
$this->subscriberStorage
->delete($this->subscriberStorage
->loadMultiple($delete));
}
public function destruct() {
$this
->sendConfirmations();
}
protected function addConfirmation($action, SubscriberInterface $subscriber, NewsletterInterface $newsletter) {
$this->confirmations[$subscriber
->getMail()][$newsletter
->id()] = $action;
}
protected function requiresConfirmation(NewsletterInterface $newsletter, $uid) {
if ($this->currentUser
->id() && $uid && $this->currentUser
->id() == $uid) {
return FALSE;
}
else {
return $newsletter->opt_inout == 'double';
}
}
}