-
Torsten Oppermann authoredTorsten Oppermann authored
MailTemplateService.php 18.72 KiB
<?php
namespace SGalinski\SgMail\Service;
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (https://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use DateTime;
use SGalinski\SgMail\Domain\Model\Mail;
use SGalinski\SgMail\Domain\Model\Template;
use SGalinski\SgMail\Domain\Repository\MailRepository;
use SGalinski\SgMail\Domain\Repository\TemplateRepository;
use Swift_Attachment;
use Swift_OutputByteStream;
use TYPO3\CMS\Core\Mail\MailMessage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
/**
* MailTemplateService
*/
class MailTemplateService {
const MARKER_TYPE_STRING = 'String';
const MARKER_TYPE_ARRAY = 'Array';
const MARKER_TYPE_OBJECT = 'Object';
/**
* @var array $registerArray
*/
private static $registerArray = [];
/**
* @var array $toAddresses
*/
private $toAddresses = [];
/**
* @var string $fromAddress
*/
private $fromAddress;
/**
* @var array $ccAddresses
*/
private $ccAddresses;
/**
* @var string $replyToAddress
*/
private $replyToAddress;
/**
* @var string $language
*/
private $language;
/**
* @var boolean $ignoreMailQueue
*/
private $ignoreMailQueue = FALSE;
/**
* @var \TYPO3\CMS\Core\Mail\MailMessage $mailMessage
*/
private $mailMessage;
/**
* @var string $templateName
*/
private $templateName;
/**
* @var string $extensionKey
*/
private $extensionKey;
/**
* @var array $markers
*/
private $markers = [];
/**
* holds the TypoScript configuration for sg_mail
*
* @var array $tsSettings
*/
private $tsSettings;
/**
* @var array $bccAddresses
*/
private $bccAddresses;
/**
* @var int
*/
private $priority = Mail::PRIORITY_LOWEST;
/**
* @var int
*/
private $pid;
/**
* @var string
*/
private $fromName = '';
/**
* @var \SGalinski\SgMail\Domain\Repository\TemplateRepository
*/
protected $templateRepository;
/**
* @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
*/
protected $persistenceManager;
/**
* @var \TYPO3\CMS\Extbase\Object\ObjectManager
*/
protected $objectManager;
/**
* MailTemplateService constructor.
*
* @throws \InvalidArgumentException
*/
public function __construct() {
/** @var ObjectManager objectManager */
$this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/** @var MailMessage mailMessage */
$this->mailMessage = $this->objectManager->get(MailMessage::class);
/** @var TypoScriptSettingsService $typoScriptSettingsService */
$typoScriptSettingsService = $this->objectManager->get(TypoScriptSettingsService::class);
$this->tsSettings = $typoScriptSettingsService->getSettings(0, 'tx_sgmail');
$this->language = $this->tsSettings['templateDefaultLanguage'];
/** @var TemplateRepository templateRepository */
$this->templateRepository = $this->objectManager->get(TemplateRepository::class);
/** @var PersistenceManager persistenceManager */
$this->persistenceManager = $this->objectManager->get(PersistenceManager::class);
$this->fromAddress = $this->tsSettings['mail']['default']['from'];
$this->mailMessage->setFrom($this->fromAddress);
$this->bccAddresses = GeneralUtility::trimExplode(',', $this->tsSettings['mail']['default']['bcc']);
$this->ccAddresses = GeneralUtility::trimExplode(',', $this->tsSettings['mail']['default']['cc']);
foreach ($this->bccAddresses as $index => $email) {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
unset($this->bccAddresses[$index]);
}
}
foreach ($this->ccAddresses as $index => $email) {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
unset($this->ccAddresses[$index]);
}
}
if (count($this->bccAddresses) > 0) {
$this->mailMessage->setBcc($this->bccAddresses);
}
if (count($this->ccAddresses) > 0) {
$this->mailMessage->setCc($this->ccAddresses);
}
}
/**
* register a template with sg_mail
*
* description and subject can now be an array i.e. with elements such as 'en' => 'english description'
* or an translation string used in locallang.xml
*
* @deprecated public usage of this function is deprecated. use registerByFile instead
* @param string $extension
* @param string $templateName
* @param string $templatePath
* @param mixed $description
* @param array $markers
* @param mixed $subject
* @param string $usage
*/
public static function registerTemplate(
$extension, $templateName, $templatePath, $description, array $markers, $subject, $usage = ''
) {
MailTemplateService::$registerArray[$extension][$templateName] = [
'templatePath' => $templatePath,
'description' => $description,
'marker' => $markers,
'extension' => $extension,
'templateName' => $templateName,
'subject' => $subject,
'usage' => $usage
];
}
/**
* call in extlocalconf of an extension if you have a custom register class
*
* @param RegisterInterface $fileNameWithNamespace
* @param boolean $initObject Should the object initialize itself ?
*
* @return bool
* @throws \InvalidArgumentException
*/
public static function registerByFile($fileNameWithNamespace, $initObject = TRUE) {
$registerObject = GeneralUtility::makeInstance($fileNameWithNamespace);
// check instance of interface
if (!($registerObject instanceof RegisterInterface)) {
return FALSE;
}
// object calls registerTemplate, alternative way instead of localconf call
if ($initObject) {
$registerObject->init();
}
$registerObject->registerTemplate();
return TRUE;
}
/**
* Return default markers for sg_mail
*
* @param string $translationKey
* @param array $marker
* @param string $extensionKey
* @return array
*/
public static function getDefaultTemplateMarker($translationKey, array $marker, $extensionKey = 'sg_mail') {
$languagePath = 'LLL:EXT:' . $extensionKey . '/Resources/Private/Language/locallang.xlf:' . $translationKey;
// Need the key for translations
if (trim($extensionKey) === '') {
return [];
}
$generatedMarker = [];
foreach ($marker as $markerName) {
$generatedMarker[] = [
'marker' => $markerName,
'value' => $languagePath . '.example.' . $markerName,
'description' => $languagePath . '.description.' . $markerName,
'backend_translation_key' => $translationKey . '.example.' . $markerName,
'extension_key' => $extensionKey
];
}
return $generatedMarker;
}
/**
* Get all registered templates
*
* @return array
*/
public static function getRegisterArray() {
return self::$registerArray;
}
/**
* Send the Email
*
* @param boolean $isPreview
* @return boolean email was sent or added to mail queue successfully?
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
*/
public function sendEmail($isPreview = FALSE) {
if (TYPO3_MODE === 'FE') {
/** @var TypoScriptFrontendController $tsfe */
$tsfe = $GLOBALS['TSFE'];
$pageUid = $tsfe->id;
} else {
$pageUid = (int) GeneralUtility::_GP('id');
}
$siteRootId = BackendService::getSiteRoot($pageUid);
/** @var Template $template */
$template = $this->templateRepository->findOneByTemplate(
$this->extensionKey, $this->templateName, $this->language, $siteRootId
);
// if there is a template, prefer those values
if ($template) {
$this->loadTemplateValues($template);
}
// If there is no template for this language, use the default template
if ($template === NULL) {
$templatePath = self::$registerArray[$this->extensionKey][$this->templateName]['templatePath'];
$templateFile = $templatePath . $this->language . '.template.html';
if (file_exists($templateFile)) {
$defaultTemplateContent = file_get_contents($templatePath . $this->language . '.template.html');
} else {
// no language found and no default template
$this->setLanguage($this->tsSettings['templateDefaultLanguage'] ?: 'en');
// does an english default template exist ?
if (file_exists($templatePath . $this->language . '.template.html')) {
$this->sendEmail();
return TRUE;
}
return FALSE;
}
}
if ($isPreview) {
$previewMarker = [];
/** @var array $markerArray */
$markerArray = self::$registerArray[$this->extensionKey][$this->templateName]['marker'];
foreach ($markerArray as $marker) {
$markerPath = GeneralUtility::trimExplode('.', $marker['marker']);
$temporaryMarkerArray = [];
foreach (array_reverse($markerPath) as $index => $markerPathSegment) {
if ($index === 0) {
if ($marker['backend_translation_key']) {
$temporaryMarkerArray[$markerPathSegment] = LocalizationUtility::translate(
$marker['backend_translation_key'], $marker['extension_key']
);
} else {
$temporaryMarkerArray[$markerPathSegment] = $marker['value'];
}
} else {
$temporaryMarkerArray = [$markerPathSegment => $temporaryMarkerArray];
}
}
$previewMarker = array_merge_recursive($previewMarker, $temporaryMarkerArray);
}
$this->setIgnoreMailQueue(TRUE);
$this->setMarkers($previewMarker);
}
/** @var StandaloneView $emailView */
$emailView = $this->objectManager->get(StandaloneView::class);
if (NULL === $defaultTemplateContent) {
$emailView->setTemplateSource($template->getContent());
$subject = $template->getSubject();
} else {
$emailView->setTemplateSource($defaultTemplateContent);
$subject = self::$registerArray[$this->extensionKey][$this->templateName]['subject'];
if (is_array($subject)) {
$subject = self::$registerArray[$this->extensionKey][$this->templateName]['subject'][$this->language];
} else {
$subject = LocalizationUtility::translate(
self::$registerArray[$this->extensionKey][$this->templateName]['subject'],
$this->extensionKey
);
}
}
$this->mailMessage->setSubject($subject);
$emailView->assignMultiple($this->markers);
$emailBody = $emailView->render();
// insert <br /> tags, but replace every instance of three or more successive breaks with just two.
$emailBody = nl2br($emailBody);
$emailBody = preg_replace('/(<br[\s]?[\/]?>[\s]*){3,}/', '<br /><br />', $emailBody);
if ($this->ignoreMailQueue) {
$this->mailMessage->setBody($emailBody, 'text/html');
$this->mailMessage->send();
$dateTime = new DateTime();
$currentTimestamp = $dateTime->getTimestamp();
$this->addMailToMailQueue(
$this->extensionKey, $this->templateName, $subject, $emailBody, $this->priority,
$currentTimestamp, TRUE, $currentTimestamp, $this->language, $siteRootId
);
} else {
$this->addMailToMailQueue(
$this->extensionKey, $this->templateName, $subject, $emailBody, $this->priority, 0, FALSE, 0,
$this->language, $siteRootId
);
}
return TRUE;
}
/**
* Adds a new mail to the mail queue.
*
* @param string $extensionKey
* @param string $templateName
* @param string $subject
* @param string $emailBody
* @param int $sendingTime
* @param int $priority
* @param int $lastSendingTime
* @param string $language
* @param int $pid
* @param bool $sent
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
*/
private function addMailToMailQueue(
$extensionKey, $templateName, $subject, $emailBody, $priority, $sendingTime = 0, $sent = FALSE,
$lastSendingTime = 0, $language = 'en', $pid = 0
) {
$mail = $this->objectManager->get(Mail::class);
$mail->setPid($pid);
$mail->setExtensionKey($extensionKey);
$mail->setTemplateName($templateName);
$mail->setLanguage($language);
$mail->setFromAddress($this->fromAddress);
$mail->setFromName($this->fromName);
$mail->setToAddress($this->toAddresses);
$mail->setMailSubject($subject);
$mail->setMailBody($emailBody);
$mail->setPriority($priority);
$mail->setBccAddresses($this->bccAddresses);
$mail->setCcAddresses($this->ccAddresses);
$mail->setSent($sent);
$mail->setSendingTime($sendingTime);
$mail->setLastSendingTime($lastSendingTime);
$mail->setReplyTo($this->replyToAddress);
$mailRepository = $this->objectManager->get(MailRepository::class);
$mailRepository->add($mail);
$this->persistenceManager->persistAll();
}
/**
* Send a Mail from the queue, identified by its id
*
* @param int $uid
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
*/
public function sendMailFromQueue($uid) {
$mailRepository = $this->objectManager->get(MailRepository::class);
/** @var Mail $mailToSend */
$mailToSend = $mailRepository->findOneByUid($uid);
if ($mailToSend) {
$this->mailMessage->setBody($mailToSend->getMailBody(), 'text/html');
$this->mailMessage->setTo($mailToSend->getToAddress());
$this->mailMessage->setFrom($mailToSend->getFromAddress(), $mailToSend->getFromName());
$this->mailMessage->setSubject($mailToSend->getMailSubject());
if ($mailToSend->getBccAddresses()) {
$this->mailMessage->setBcc(GeneralUtility::trimExplode(',', $mailToSend->getBccAddresses()));
}
if ($mailToSend->getCcAddresses()) {
$this->mailMessage->setCc(GeneralUtility::trimExplode(',', $mailToSend->getCcAddresses()));
}
if ($mailToSend->getReplyTo()) {
$this->mailMessage->setReplyTo($mailToSend->getReplyTo());
}
$dateTime = new DateTime();
$mailToSend->setLastSendingTime($dateTime->getTimestamp());
$this->mailMessage->send();
if (!$mailToSend->getSent()) {
$mailToSend->setSent(TRUE);
}
$mailRepository->update($mailToSend);
}
}
/**
* @param array $registerArray
* @return void
*/
public static function setRegisterArray(array $registerArray) {
self::$registerArray = $registerArray;
}
/**
* @param string $toAddresses
* @return MailTemplateService
*/
public function setToAddresses($toAddresses) {
$this->toAddresses = $toAddresses;
$this->mailMessage->setTo($toAddresses);
return $this;
}
/**
* @param string $fromAddress
* @param string $fromName
* @return MailTemplateService
*/
public function setFromAddress($fromAddress, $fromName = '') {
if ($fromAddress) {
$this->fromAddress = $fromAddress;
$this->mailMessage->setFrom($fromAddress, $fromName);
}
return $this;
}
/**
* @param string $ccAddresses
* @return MailTemplateService
*/
public function setCcAddresses($ccAddresses) {
if ($ccAddresses) {
$this->ccAddresses = $ccAddresses;
$this->mailMessage->setCc(GeneralUtility::trimExplode(',', $this->ccAddresses));
}
return $this;
}
/**
* @param string $replyToAddress
* @return MailTemplateService
*/
public function setReplyToAddress($replyToAddress) {
if ($replyToAddress) {
$this->replyToAddress = $replyToAddress;
$this->mailMessage->setReplyTo($replyToAddress);
}
return $this;
}
/**
* @param string $language
* @return MailTemplateService
*/
public function setLanguage($language) {
$this->language = $language;
return $this;
}
/**
* @param boolean $ignoreMailQueue
* @return MailTemplateService
*/
public function setIgnoreMailQueue($ignoreMailQueue) {
$this->ignoreMailQueue = $ignoreMailQueue;
return $this;
}
/**
* @param string $templateName
* @return MailTemplateService
*/
public function setTemplateName($templateName) {
$this->templateName = $templateName;
return $this;
}
/**
* @param string $extensionKey
* @return MailTemplateService
*/
public function setExtensionKey($extensionKey) {
$this->extensionKey = $extensionKey;
return $this;
}
/**
* @param array $markers
* @return MailTemplateService
*/
public function setMarkers(array $markers) {
$this->markers = $markers;
return $this;
}
/**
* @param string $bccAddresses
* @return MailTemplateService
*/
public function setBccAddresses($bccAddresses) {
if ($bccAddresses) {
$this->bccAddresses = $bccAddresses;
$this->mailMessage->setBcc(GeneralUtility::trimExplode(',', $this->bccAddresses));
}
return $this;
}
/**
* @param int $priority
* @return MailTemplateService
*/
public function setPriority($priority) {
$this->priority = $priority;
return $this;
}
/**
* @param Swift_OutputByteStream $data
* @param string $filename
* @param string $contentType
* @return MailTemplateService
*/
public function addAttachment($data, $filename, $contentType) {
$attachment = Swift_Attachment::newInstance()
->setFilename($filename)
->setContentType($contentType)
->setBody($data);
$this->mailMessage->attach($attachment);
return $this;
}
/**
* @return MailMessage
*/
public function getMailMessage() {
return $this->mailMessage;
}
/**
* use all values from the given template
*
* @param Template $template
*/
private function loadTemplateValues($template) {
$this->setFromAddress($template->getFromMail(), $template->getFromName());
$this->setCcAddresses($template->getCc());
$this->setBccAddresses($template->getBcc());
$this->setReplyToAddress($template->getReplyTo());
$this->setFromName($template->getFromName());
$this->setReplyToAddress($template->getReplyTo());
}
/**
* @param string $fromName
*/
public function setFromName($fromName) {
$this->fromName = $fromName;
}
/**
* Provides translation for the marker data type
*
* @param string $markerType
*/
public static function getReadableMarkerType($markerType) {
switch ($markerType) {
case self::MARKER_TYPE_STRING :
LocalizationUtility::translate('backend.marker.type.string', 'sg_mail');
break;
case self::MARKER_TYPE_ARRAY :
LocalizationUtility::translate('backend.marker.type.array', 'sg_mail');
break;
case self::MARKER_TYPE_OBJECT :
LocalizationUtility::translate('backend.marker.type.object', 'sg_mail');
break;
default:
LocalizationUtility::translate('backend.marker.type.mixed', 'sg_mail');
}
}
/**
* set the page id from which this was called
*
* @param int $pid
* @return MailTemplateService
*/
public function setPid($pid) {
$this->pid = (int) $pid;
return $this;
}
}