getEvent()->getObject() in this case * * @var string */ protected $_eventObject = 'subscriber'; /** * True if data changed * * @var bool */ protected $_isStatusChanged = false; /** * Newsletter data * * @var \Magento\Newsletter\Helper\Data */ protected $_newsletterData = null; /** * Core store config * * @var \Magento\Framework\App\Config\ScopeConfigInterface */ protected $_scopeConfig; /** * Customer session * * @var \Magento\Customer\Model\Session */ protected $_customerSession; /** * Date * @var \Magento\Framework\Stdlib\DateTime\DateTime */ private $dateTime; /** * Store manager * * @var \Magento\Store\Model\StoreManagerInterface */ protected $_storeManager; /** * @var CustomerRepositoryInterface */ protected $customerRepository; /** * @var AccountManagementInterface */ protected $customerAccountManagement; /** * @var \Magento\Framework\Mail\Template\TransportBuilder */ protected $_transportBuilder; /** * @var \Magento\Framework\Translate\Inline\StateInterface */ protected $inlineTranslation; /** * @var CustomerInterfaceFactory */ private $customerFactory; /** * @var DataObjectHelper */ private $dataObjectHelper; /** * Initialize dependencies. * * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Newsletter\Helper\Data $newsletterData * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Customer\Model\Session $customerSession * @param CustomerRepositoryInterface $customerRepository * @param AccountManagementInterface $customerAccountManagement * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection * @param array $data * @param \Magento\Framework\Stdlib\DateTime\DateTime|null $dateTime * @param CustomerInterfaceFactory|null $customerFactory * @param DataObjectHelper|null $dataObjectHelper * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( \Magento\Framework\Model\Context $context, \Magento\Framework\Registry $registry, \Magento\Newsletter\Helper\Data $newsletterData, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Customer\Model\Session $customerSession, CustomerRepositoryInterface $customerRepository, AccountManagementInterface $customerAccountManagement, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [], \Magento\Framework\Stdlib\DateTime\DateTime $dateTime = null, CustomerInterfaceFactory $customerFactory = null, DataObjectHelper $dataObjectHelper = null ) { $this->_newsletterData = $newsletterData; $this->_scopeConfig = $scopeConfig; $this->_transportBuilder = $transportBuilder; $this->_storeManager = $storeManager; $this->_customerSession = $customerSession; $this->dateTime = $dateTime ?: \Magento\Framework\App\ObjectManager::getInstance()->get( \Magento\Framework\Stdlib\DateTime\DateTime::class ); $this->customerFactory = $customerFactory ?: ObjectManager::getInstance() ->get(CustomerInterfaceFactory::class); $this->dataObjectHelper = $dataObjectHelper ?: ObjectManager::getInstance() ->get(DataObjectHelper::class); $this->customerRepository = $customerRepository; $this->customerAccountManagement = $customerAccountManagement; $this->inlineTranslation = $inlineTranslation; parent::__construct($context, $registry, $resource, $resourceCollection, $data); } /** * Initialize resource model * * @return void */ protected function _construct() { $this->_init(\Magento\Newsletter\Model\ResourceModel\Subscriber::class); } /** * Alias for getSubscriberId() * * @return int */ public function getId() { return $this->getSubscriberId(); } /** * Alias for setSubscriberId() * * @param int $value * @return $this */ public function setId($value) { return $this->setSubscriberId($value); } /** * Alias for getSubscriberConfirmCode() * * @return string */ public function getCode() { return $this->getSubscriberConfirmCode(); } /** * Return link for confirmation of subscription * * @return string */ public function getConfirmationLink() { return $this->_newsletterData->getConfirmationUrl($this); } /** * Returns Unsubscribe url * * @return string */ public function getUnsubscriptionLink() { return $this->_newsletterData->getUnsubscribeUrl($this); } /** * Alias for setSubscriberConfirmCode() * * @param string $value * @return $this */ public function setCode($value) { return $this->setSubscriberConfirmCode($value); } /** * Alias for getSubscriberStatus() * * @return int */ public function getStatus() { return $this->getSubscriberStatus(); } /** * Alias for setSubscriberStatus() * * @param int $value * @return $this */ public function setStatus($value) { return $this->setSubscriberStatus($value); } /** * Set the error messages scope for subscription * * @param boolean $scope * @return $this */ public function setMessagesScope($scope) { $this->getResource()->setMessagesScope($scope); return $this; } /** * Alias for getSubscriberEmail() * * @return string */ public function getEmail() { return $this->getSubscriberEmail(); } /** * Alias for setSubscriberEmail() * * @param string $value * @return $this */ public function setEmail($value) { return $this->setSubscriberEmail($value); } /** * Set for status change flag * * @param boolean $value * @return $this */ public function setStatusChanged($value) { $this->_isStatusChanged = (boolean) $value; return $this; } /** * Return status change flag value * * @return boolean */ public function isStatusChanged() { return $this->_isStatusChanged; } /** * Return customer subscription status * * @return bool */ public function isSubscribed() { if ($this->getId() && $this->getStatus() == self::STATUS_SUBSCRIBED) { return true; } return false; } /** * Load subscriber data from resource model by email * * @param string $subscriberEmail * @return $this */ public function loadByEmail($subscriberEmail) { $storeId = $this->_storeManager->getStore()->getId(); $customerData = ['store_id' => $storeId, 'email'=> $subscriberEmail]; /** @var \Magento\Customer\Api\Data\CustomerInterface $customer */ $customer = $this->customerFactory->create(); $this->dataObjectHelper->populateWithArray( $customer, $customerData, \Magento\Customer\Api\Data\CustomerInterface::class ); $this->addData($this->getResource()->loadByCustomerData($customer)); return $this; } /** * Load subscriber info by customerId * * @param int $customerId * @return $this */ public function loadByCustomerId($customerId) { try { $customerData = $this->customerRepository->getById($customerId); $customerData->setStoreId($this->_storeManager->getStore()->getId()); if ($customerData->getWebsiteId() === null) { $customerData->setWebsiteId($this->_storeManager->getStore()->getWebsiteId()); } $data = $this->getResource()->loadByCustomerData($customerData); $this->addData($data); if (!empty($data) && $customerData->getId() && !$this->getCustomerId()) { $this->setCustomerId($customerData->getId()); $this->setSubscriberConfirmCode($this->randomSequence()); $this->save(); } } catch (NoSuchEntityException $e) { } return $this; } /** * Returns string of random chars * * @param int $length * @return string */ public function randomSequence($length = 32) { $id = ''; $par = []; $char = array_merge(range('a', 'z'), range(0, 9)); $charLen = count($char) - 1; for ($i = 0; $i < $length; $i++) { $disc = \Magento\Framework\Math\Random::getRandomNumber(0, $charLen); $par[$i] = $char[$disc]; $id = $id . $char[$disc]; } return $id; } /** * Subscribes by email * * @param string $email * @throws \Exception * @return int * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ public function subscribe($email) { $this->loadByEmail($email); if ($this->getId() && $this->getStatus() == self::STATUS_SUBSCRIBED) { return $this->getStatus(); } if (!$this->getId()) { $this->setSubscriberConfirmCode($this->randomSequence()); } $isConfirmNeed = $this->_scopeConfig->getValue( self::XML_PATH_CONFIRMATION_FLAG, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) == 1 ? true : false; $isSubscribeOwnEmail = $this->_customerSession->isLoggedIn() && $this->_customerSession->getCustomerDataObject()->getEmail() == $email; if (!$this->getId() || $this->getStatus() == self::STATUS_UNSUBSCRIBED || $this->getStatus() == self::STATUS_NOT_ACTIVE ) { if ($isConfirmNeed === true) { $this->setStatus(self::STATUS_NOT_ACTIVE); } else { $this->setStatus(self::STATUS_SUBSCRIBED); } $this->setSubscriberEmail($email); } if ($isSubscribeOwnEmail) { try { $customer = $this->customerRepository->getById($this->_customerSession->getCustomerId()); $this->setStoreId($customer->getStoreId()); $this->setCustomerId($customer->getId()); } catch (NoSuchEntityException $e) { $this->setStoreId($this->_storeManager->getStore()->getId()); $this->setCustomerId(0); } } else { $this->setStoreId($this->_storeManager->getStore()->getId()); $this->setCustomerId(0); } $this->setStatusChanged(true); try { /* Save model before sending out email */ $this->save(); if ($isConfirmNeed === true) { $this->sendConfirmationRequestEmail(); } else { $this->sendConfirmationSuccessEmail(); } return $this->getStatus(); } catch (\Exception $e) { throw new \Exception($e->getMessage()); } } /** * Unsubscribes loaded subscription * * @throws \Magento\Framework\Exception\LocalizedException * @return $this */ public function unsubscribe() { if ($this->hasCheckCode() && $this->getCode() != $this->getCheckCode()) { throw new \Magento\Framework\Exception\LocalizedException( __('This is an invalid subscription confirmation code.') ); } if ($this->getSubscriberStatus() != self::STATUS_UNSUBSCRIBED) { $this->setSubscriberStatus(self::STATUS_UNSUBSCRIBED)->save(); $this->sendUnsubscriptionEmail(); } return $this; } /** * Subscribe the customer with the id provided * * @param int $customerId * @return $this */ public function subscribeCustomerById($customerId) { return $this->_updateCustomerSubscription($customerId, true); } /** * Unsubscribe the customer with the id provided * * @param int $customerId * @return $this */ public function unsubscribeCustomerById($customerId) { return $this->_updateCustomerSubscription($customerId, false); } /** * Update the subscription based on latest information of associated customer. * * @param int $customerId * @return $this */ public function updateSubscription($customerId) { $this->loadByCustomerId($customerId); $this->_updateCustomerSubscription($customerId, $this->isSubscribed()); return $this; } /** * Saving customer subscription status * * @param int $customerId * @param bool $subscribe indicates whether the customer should be subscribed or unsubscribed * @return $this * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _updateCustomerSubscription($customerId, $subscribe) { try { $customerData = $this->customerRepository->getById($customerId); } catch (NoSuchEntityException $e) { return $this; } $this->loadByCustomerId($customerId); if (!$subscribe && !$this->getId()) { return $this; } if (!$this->getId()) { $this->setSubscriberConfirmCode($this->randomSequence()); } $sendInformationEmail = false; $status = self::STATUS_SUBSCRIBED; $isConfirmNeed = $this->_scopeConfig->getValue( self::XML_PATH_CONFIRMATION_FLAG, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) == 1 ? true : false; if ($subscribe) { if (AccountManagementInterface::ACCOUNT_CONFIRMATION_REQUIRED == $this->customerAccountManagement->getConfirmationStatus($customerId) ) { if ($this->getId() && $this->getStatus() == self::STATUS_SUBSCRIBED) { // if a customer was already subscribed then keep the subscribed $status = self::STATUS_SUBSCRIBED; } else { $status = self::STATUS_UNCONFIRMED; } } elseif ($isConfirmNeed) { if ($this->getStatus() != self::STATUS_SUBSCRIBED) { $status = self::STATUS_NOT_ACTIVE; } } } elseif (($this->getStatus() == self::STATUS_UNCONFIRMED) && ($customerData->getConfirmation() === null)) { $status = self::STATUS_SUBSCRIBED; $sendInformationEmail = true; } elseif (($this->getStatus() == self::STATUS_NOT_ACTIVE) && ($customerData->getConfirmation() === null)) { $status = self::STATUS_NOT_ACTIVE; } else { $status = self::STATUS_UNSUBSCRIBED; } /** * If subscription status has been changed then send email to the customer */ if ($status != self::STATUS_UNCONFIRMED && $status != $this->getStatus()) { $sendInformationEmail = true; } if ($status != $this->getStatus()) { $this->setStatusChanged(true); } $this->setStatus($status); $storeId = $customerData->getStoreId(); if ((int)$customerData->getStoreId() === 0) { $storeId = $this->_storeManager->getWebsite($customerData->getWebsiteId())->getDefaultStore()->getId(); } if (!$this->getId()) { $this->setStoreId($storeId) ->setCustomerId($customerData->getId()) ->setEmail($customerData->getEmail()); } else { $this->setStoreId($storeId) ->setEmail($customerData->getEmail()); } $this->save(); $sendSubscription = $sendInformationEmail; if ($sendSubscription === null xor $sendSubscription && $this->isStatusChanged()) { try { switch ($status) { case self::STATUS_UNSUBSCRIBED: $this->sendUnsubscriptionEmail(); break; case self::STATUS_SUBSCRIBED: $this->sendConfirmationSuccessEmail(); break; case self::STATUS_NOT_ACTIVE: if ($isConfirmNeed) { $this->sendConfirmationRequestEmail(); } break; } } catch (MailException $e) { // If we are not able to send a new account email, this should be ignored $this->_logger->critical($e); } } return $this; } /** * Confirms subscriber newsletter * * @param string $code * @return boolean */ public function confirm($code) { if ($this->getCode() == $code) { $this->setStatus(self::STATUS_SUBSCRIBED) ->setStatusChanged(true) ->save(); $this->sendConfirmationSuccessEmail(); return true; } return false; } /** * Mark receiving subscriber of queue newsletter * * @param \Magento\Newsletter\Model\Queue $queue * @return boolean */ public function received(\Magento\Newsletter\Model\Queue $queue) { $this->getResource()->received($this, $queue); return $this; } /** * Sends out confirmation email * * @return $this */ public function sendConfirmationRequestEmail() { if ($this->getImportMode()) { return $this; } if (!$this->_scopeConfig->getValue( self::XML_PATH_CONFIRM_EMAIL_TEMPLATE, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) || !$this->_scopeConfig->getValue( self::XML_PATH_CONFIRM_EMAIL_IDENTITY, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) ) { return $this; } $this->inlineTranslation->suspend(); $this->_transportBuilder->setTemplateIdentifier( $this->_scopeConfig->getValue( self::XML_PATH_CONFIRM_EMAIL_TEMPLATE, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) )->setTemplateOptions( [ 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'store' => $this->_storeManager->getStore()->getId(), ] )->setTemplateVars( ['subscriber' => $this, 'store' => $this->_storeManager->getStore()] )->setFrom( $this->_scopeConfig->getValue( self::XML_PATH_CONFIRM_EMAIL_IDENTITY, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) )->addTo( $this->getEmail(), $this->getName() ); $transport = $this->_transportBuilder->getTransport(); $transport->sendMessage(); $this->inlineTranslation->resume(); return $this; } /** * Sends out confirmation success email * * @return $this */ public function sendConfirmationSuccessEmail() { if ($this->getImportMode()) { return $this; } if (!$this->_scopeConfig->getValue( self::XML_PATH_SUCCESS_EMAIL_TEMPLATE, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) || !$this->_scopeConfig->getValue( self::XML_PATH_SUCCESS_EMAIL_IDENTITY, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) ) { return $this; } $this->inlineTranslation->suspend(); $this->_transportBuilder->setTemplateIdentifier( $this->_scopeConfig->getValue( self::XML_PATH_SUCCESS_EMAIL_TEMPLATE, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) )->setTemplateOptions( [ 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'store' => $this->_storeManager->getStore()->getId(), ] )->setTemplateVars( ['subscriber' => $this] )->setFrom( $this->_scopeConfig->getValue( self::XML_PATH_SUCCESS_EMAIL_IDENTITY, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) )->addTo( $this->getEmail(), $this->getName() ); $transport = $this->_transportBuilder->getTransport(); $transport->sendMessage(); $this->inlineTranslation->resume(); return $this; } /** * Sends out unsubscription email * * @return $this */ public function sendUnsubscriptionEmail() { if ($this->getImportMode()) { return $this; } if (!$this->_scopeConfig->getValue( self::XML_PATH_UNSUBSCRIBE_EMAIL_TEMPLATE, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) || !$this->_scopeConfig->getValue( self::XML_PATH_UNSUBSCRIBE_EMAIL_IDENTITY, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) ) { return $this; } $this->inlineTranslation->suspend(); $this->_transportBuilder->setTemplateIdentifier( $this->_scopeConfig->getValue( self::XML_PATH_UNSUBSCRIBE_EMAIL_TEMPLATE, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) )->setTemplateOptions( [ 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'store' => $this->_storeManager->getStore()->getId(), ] )->setTemplateVars( ['subscriber' => $this] )->setFrom( $this->_scopeConfig->getValue( self::XML_PATH_UNSUBSCRIBE_EMAIL_IDENTITY, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) )->addTo( $this->getEmail(), $this->getName() ); $transport = $this->_transportBuilder->getTransport(); $transport->sendMessage(); $this->inlineTranslation->resume(); return $this; } /** * Retrieve Subscribers Full Name if it was set * * @return string|null */ public function getSubscriberFullName() { $name = null; if ($this->hasFirstname() || $this->hasLastname()) { $name = $this->getFirstname() . ' ' . $this->getLastname(); } return $name; } /** * Set date of last changed status * * @return $this * @since 100.2.1 */ public function beforeSave() { parent::beforeSave(); if ($this->dataHasChangedFor('subscriber_status')) { $this->setChangeStatusAt($this->dateTime->gmtDate()); } return $this; } }