Files
piratepoet/lib/Subscribers/ConfirmationEmailMailer.php
Rodrigo Primo d39d09dd72 Remove calls to Subscriber::setError() from ConfirmationEmailMailer
This commit is part of a task to replace Paris with Doctrine in the
class ConfirmationEmailMailer. Specifically, it removes two calls to
Subscriber::setError() inside ConfirmationEmailMailer::sendConfirmationEmail().

setError() was used to define an error message that was used only in one
of the instances where sendConfirmationEmail() is called
(API::subscribeToLists()). setError() was replaced with code that throws
an exception when there is an error. Thus it was necessary to change all
the places where ConfirmationEmailMailer::sendConfirmationEmail() is
called to handle the exception.

In some cases, there are some oddities as sendConfirmationEmail() can
return false or throw an exception in case of an error and calling code
must account for both. I decided to settle with this approach as
refactoring the rest of this method to use exceptions instead of
returning false seemed outside of the scope of this task.

[MAILPOET-3815]
2021-12-13 16:03:07 +01:00

149 lines
4.4 KiB
PHP

<?php
namespace MailPoet\Subscribers;
use Html2Text\Html2Text;
use MailPoet\Entities\SegmentEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\Mailer\Mailer;
use MailPoet\Mailer\MetaInfo;
use MailPoet\Services\AuthorizedEmailsController;
use MailPoet\Services\Bridge;
use MailPoet\Settings\SettingsController;
use MailPoet\Subscription\SubscriptionUrlFactory;
use MailPoet\Util\Helpers;
use MailPoet\WP\Functions as WPFunctions;
class ConfirmationEmailMailer {
const MAX_CONFIRMATION_EMAILS = 3;
/** @var Mailer */
private $mailer;
/** @var WPFunctions */
private $wp;
/** @var SettingsController */
private $settings;
/** @var MetaInfo */
private $mailerMetaInfo;
/** @var SubscribersRepository */
private $subscribersRepository;
/** @var SubscriptionUrlFactory */
private $subscriptionUrlFactory;
/** @var array Cache for confirmation emails sent within a request */
private $sentEmails = [];
public function __construct(
Mailer $mailer,
WPFunctions $wp,
SettingsController $settings,
SubscribersRepository $subscribersRepository,
SubscriptionUrlFactory $subscriptionUrlFactory
) {
$this->mailer = $mailer;
$this->wp = $wp;
$this->settings = $settings;
$this->mailerMetaInfo = new MetaInfo;
$this->subscriptionUrlFactory = $subscriptionUrlFactory;
$this->subscribersRepository = $subscribersRepository;
}
/**
* Use this method if you want to make sure the confirmation email
* is not sent multiple times within a single request
* e.g. if sending confirmation emails from hooks
* @throws \Exception if unable to send the email.
*/
public function sendConfirmationEmailOnce(SubscriberEntity $subscriber): bool {
if (isset($this->sentEmails[$subscriber->getId()])) {
return true;
}
return $this->sendConfirmationEmail($subscriber);
}
/**
* @throws \Exception if unable to send the email.
*/
public function sendConfirmationEmail(SubscriberEntity $subscriber) {
$signupConfirmation = $this->settings->get('signup_confirmation');
if ((bool)$signupConfirmation['enabled'] === false) {
return false;
}
if (!$this->wp->isUserLoggedIn() && $subscriber->getConfirmationsCount() >= self::MAX_CONFIRMATION_EMAILS) {
return false;
}
$authorizationEmailsValidation = $this->settings->get(AuthorizedEmailsController::AUTHORIZED_EMAIL_ADDRESSES_ERROR_SETTING);
$unauthorizedSenderEmail = isset($authorizationEmailsValidation['invalid_sender_address']);
if (Bridge::isMPSendingServiceEnabled() && $unauthorizedSenderEmail) {
return false;
}
$segments = $subscriber->getSegments()->toArray();
$segmentNames = array_map(function(SegmentEntity $segment) {
return $segment->getName();
}, $segments);
$body = nl2br($signupConfirmation['body']);
// replace list of segments shortcode
$body = str_replace(
'[lists_to_confirm]',
'<strong>' . join(', ', $segmentNames) . '</strong>',
$body
);
// replace activation link
$body = Helpers::replaceLinkTags(
$body,
$this->subscriptionUrlFactory->getConfirmationUrl($subscriber),
['target' => '_blank'],
'activation_link'
);
//create a text version. @ is important here, Html2Text throws warnings
$text = @Html2Text::convert(
(mb_detect_encoding($body, 'UTF-8', true)) ? $body : utf8_encode($body),
true
);
// build email data
$email = [
'subject' => $signupConfirmation['subject'],
'body' => [
'html' => $body,
'text' => $text,
],
];
// send email
$extraParams = [
'meta' => $this->mailerMetaInfo->getConfirmationMetaInfo($subscriber),
];
try {
$result = $this->mailer->send($email, $subscriber, $extraParams);
} catch (\Exception $e) {
throw new \Exception(__('Something went wrong with your subscription. Please contact the website owner.', 'mailpoet'));
}
if ($result['response'] === false) {
throw new \Exception(__('Something went wrong with your subscription. Please contact the website owner.', 'mailpoet'));
};
if (!$this->wp->isUserLoggedIn()) {
$subscriber->setConfirmationsCount($subscriber->getConfirmationsCount() + 1);
$this->subscribersRepository->persist($subscriber);
$this->subscribersRepository->flush();
}
$this->sentEmails[$subscriber->getId()] = true;
return true;
}
}