diff --git a/Classes/Command/SendMailCommandController.php b/Classes/Command/SendMailCommandController.php index efb100b0554c1be5769e5a0422d91739d1358777..80f63032916d918cbf1916a326c80de131a07a9a 100644 --- a/Classes/Command/SendMailCommandController.php +++ b/Classes/Command/SendMailCommandController.php @@ -25,14 +25,11 @@ namespace SGalinski\SgMail\Command; -use SGalinski\SgMail\Domain\Model\Mail; use SGalinski\SgMail\Domain\Repository\MailRepository; -use SGalinski\SgMail\Service\PlaintextService; +use SGalinski\SgMail\Service\MailTemplateService; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use TYPO3\CMS\Core\Mail\MailMessage; -use TYPO3\CMS\Core\Resource\FileInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use Symfony\Component\Console\Command\Command; use TYPO3\CMS\Core\Utility\VersionNumberUtility; @@ -54,17 +51,10 @@ class SendMailCommandController extends Command { } /** - * Execute the command - * - * @param InputInterface $input - * @param OutputInterface $output - * @return int + * @return MailRepository * @throws Exception - * @throws IllegalObjectTypeException - * @throws UnknownObjectException */ - public function execute(InputInterface $input, OutputInterface $output): int { - $sendCount = $input->getArgument('sendCount'); + protected function getMailRepository(): MailRepository { if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { $objectManager = GeneralUtility::makeInstance(ObjectManager::class); /** @var MailRepository $mailRepository */ @@ -73,93 +63,25 @@ class SendMailCommandController extends Command { $mailRepository = GeneralUtility::makeInstance(MailRepository::class); } - $mailsToSend = $mailRepository->findMailsToSend($sendCount); - foreach ($mailsToSend as $mailToSend) { - /** @var Mail $mailToSend */ - $fromAddress = $mailToSend->getFromAddress(); - $toAddresses = trim($mailToSend->getToAddress()); - $addressesArray = GeneralUtility::trimExplode(',', $toAddresses, TRUE); - if (\count($addressesArray) > 1) { - $toAddresses = $addressesArray; - } - $ccAddresses = GeneralUtility::trimExplode(',', $mailToSend->getCcAddresses(), TRUE); - $bccAddresses = GeneralUtility::trimExplode(',', $mailToSend->getBccAddresses(), TRUE); - $mailSubject = $mailToSend->getMailSubject(); - $mailBody = $mailToSend->getMailBody(); - - $mailToSend->setSendingTime(time()); - $mailToSend->setLastSendingTime(time()); - - if (empty($fromAddress) || empty($toAddresses)) { - continue; - } - $mailRepository->update($mailToSend); - - $mailMessage = GeneralUtility::makeInstance(MailMessage::class); - $mailMessage->setFrom($fromAddress, $mailToSend->getFromName()); - $mailMessage->setTo($toAddresses); - $mailMessage->setSubject($mailSubject); - if (\count($ccAddresses)) { - $mailMessage->setCc($ccAddresses); - } - - if (\count($bccAddresses)) { - $mailMessage->setBcc($bccAddresses); - } - - $replyTo = $mailToSend->getReplyTo(); - if ($replyTo) { - $mailMessage->setReplyTo($replyTo); - } - - $plaintextService = GeneralUtility::makeInstance(PlaintextService::class); - $plaintextBody = $plaintextService->makePlain($mailBody); - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { - $mailMessage->setBody($mailBody, 'text/html'); - $mailMessage->addPart($plaintextBody, 'text/plain'); - } else { - $mailMessage->html($mailBody); - $mailMessage->text($plaintextBody); - } - - $attachments = $mailToSend->getAttachments(); - if ($attachments->count() > 0) { - foreach ($attachments as $attachment) { - try { - /** @var FileInterface $file */ - $file = $attachment->getOriginalResource(); - if (!$file) { - continue; - } - - $file = $file->getOriginalFile(); - if (!$file) { - continue; - } - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { - $mailMessage->attach( - \Swift_Attachment::newInstance( - $file->getContents(), $file->getName(), $file->getMimeType() - ) - ); - } else { - $mailMessage->attach($file->getContents(), $file->getName(), $file->getMimeType()); - } - } catch (\Exception $exception) { - continue; - } - } - } + return $mailRepository; + } - try { - $mailMessage->send(); - } catch (\Exception $exception) { - // Ignore that. We can't do much here in a misconfiguration case. - } - } + /** + * Execute the command + * + * @param InputInterface $input + * @param OutputInterface $output + * @return int + * @throws Exception + * @throws IllegalObjectTypeException + * @throws UnknownObjectException + */ + public function execute(InputInterface $input, OutputInterface $output): int { + $sendCount = $input->getArgument('sendCount'); - // Important for command controllers that change data - $mailRepository->persist(); + $mailsToSend = $this->getMailRepository()->findMailsToSend($sendCount)->toArray(); + $mailService = GeneralUtility::makeInstance(MailTemplateService::class); + $mailService->sendMailsFromQueue($mailsToSend); return 0; } } diff --git a/Classes/Controller/QueueController.php b/Classes/Controller/QueueController.php index 3d4f1de86c04ebddd7d1a12b0a24bb21ea30752f..08342ef5c9a739ae31d3723c679c19af93d53660 100644 --- a/Classes/Controller/QueueController.php +++ b/Classes/Controller/QueueController.php @@ -25,6 +25,7 @@ namespace SGalinski\SgMail\Controller; +use SGalinski\SgMail\Domain\Model\Mail; use SGalinski\SgMail\Domain\Repository\MailRepository; use SGalinski\SgMail\Service\BackendService; use SGalinski\SgMail\Service\MailTemplateService; @@ -32,16 +33,13 @@ use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Messaging\FlashMessage; -use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException; use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException; use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; use TYPO3\CMS\Extbase\Object\Exception; -use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException; use TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException; -use TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; /** @@ -140,23 +138,35 @@ class QueueController extends AbstractController { /** * send or resend a mail in the queue * - * @param int $uid - * @throws IllegalObjectTypeException - * @throws ResourceDoesNotExistException + * @param Mail $mail * @throws StopActionException - * @throws UnknownObjectException */ - public function sendMailAction(int $uid): void { + public function sendMailAction(Mail $mail): void { $mailService = new MailTemplateService(); - if ($mailService->sendMailFromQueue($uid)) { - $message = LocalizationUtility::translate('backend.success_mail_queue', 'sg_mail'); - $this->addFlashMessage($message, '', FlashMessage::OK); - } else { + try { + $mailService->sendMailsFromQueue([$mail]); + } catch (\TYPO3\CMS\Core\Exception $exception) { $message = LocalizationUtility::translate( 'backend.error_mail_queue', 'sg_mail' ); $this->addFlashMessage($message, '', FlashMessage::ERROR); + $this->redirect('index', NULL, NULL, $this->request->getArguments()); + } + + + if ($mail->getStatus() !== Mail::STATUS_ERROR) { + $this->addFlashMessage( + LocalizationUtility::translate('backend.success_mail_queue', 'sg_mail'), + '', + FlashMessage::OK + ); + } else { + $this->addFlashMessage( + $mail->getErrorMessage(), + '', + FlashMessage::ERROR + ); } $this->redirect('index', NULL, NULL, $this->request->getArguments()); @@ -165,12 +175,10 @@ class QueueController extends AbstractController { /** * Preview for a mail * - * @param int $uid + * @param Mail $mail */ - public function previewAction(int $uid): void { - $mailService = new MailTemplateService(); - $mailToPreview = $mailService->getMailObjectByUid($uid); - $this->view->assign('mail', $mailToPreview); + public function previewAction(Mail $mail): void { + $this->view->assign('mail', $mail); } /** diff --git a/Classes/Domain/Model/Mail.php b/Classes/Domain/Model/Mail.php index 704e3279be285ab004a0bd4413c722e6b71f3aca..2f2c20f945f9b1b9ca1c747c645bd40a9c819080 100644 --- a/Classes/Domain/Model/Mail.php +++ b/Classes/Domain/Model/Mail.php @@ -39,6 +39,9 @@ class Mail extends AbstractEntity { public const PRIORITY_MEDIUM = 100; public const PRIORITY_HIGH = 150; public const PRIORITY_HIGHEST = 200; + public const STATUS_PENDING = 'pending'; + public const STATUS_SENT = 'sent'; + public const STATUS_ERROR = 'error'; /** * @var string @@ -120,6 +123,16 @@ class Mail extends AbstractEntity { */ protected $attachments; + /** + * @var string + */ + protected $status = self::STATUS_PENDING; + + /** + * @var string + */ + protected $errorMessage = ''; + /** * Mail constructor. */ @@ -371,4 +384,32 @@ class Mail extends AbstractEntity { public function addAttachment(FileReference $attachment): void { $this->attachments->attach($attachment); } + + /** + * @return string + */ + public function getStatus(): string { + return $this->status; + } + + /** + * @param string $status + */ + public function setStatus(string $status): void { + $this->status = $status; + } + + /** + * @return string + */ + public function getErrorMessage(): string { + return $this->errorMessage; + } + + /** + * @param string $errorMessage + */ + public function setErrorMessage(string $errorMessage): void { + $this->errorMessage = $errorMessage; + } } diff --git a/Classes/Service/MailTemplateService.php b/Classes/Service/MailTemplateService.php index 9dd5f76a15b1e70efaaf23fae39ffee61c748f2b..d52ae23b7f605f833f359de58ef025ad96a1b8c0 100644 --- a/Classes/Service/MailTemplateService.php +++ b/Classes/Service/MailTemplateService.php @@ -25,39 +25,63 @@ namespace SGalinski\SgMail\Service; use DateTime; -use SGalinski\SgMail\Domain\Model\Layout; use SGalinski\SgMail\Domain\Model\Mail; use SGalinski\SgMail\Domain\Model\Template; use SGalinski\SgMail\Domain\Repository\LayoutRepository; use SGalinski\SgMail\Domain\Repository\MailRepository; use SGalinski\SgMail\Domain\Repository\TemplateRepository; +use Swift_Attachment; use Symfony\Component\Mailer\Exception\TransportException; -use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException; use TYPO3\CMS\Core\Mail\MailMessage; +use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException; use TYPO3\CMS\Core\Resource\File; +use TYPO3\CMS\Core\Resource\FileInterface; +use TYPO3\CMS\Core\Resource\FileReference as CoreFileReference; use TYPO3\CMS\Core\Resource\ResourceFactory; -use TYPO3\CMS\Core\Routing\SiteMatcher; +use TYPO3\CMS\Core\Site\Entity\SiteLanguage; +use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\VersionNumberUtility; use TYPO3\CMS\Extbase\Domain\Model\FileReference; +use TYPO3\CMS\Extbase\Object\Exception; use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException; +use TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; use TYPO3\CMS\Fluid\View\StandaloneView; +use function array_key_exists; +use function array_merge; +use function array_merge_recursive; +use function array_reverse; +use function count; +use function file_exists; +use function file_get_contents; +use function filter_var; +use function is_array; +use function is_bool; +use function is_object; +use function is_string; +use function method_exists; +use function nl2br; +use function preg_replace; +use function str_replace; +use function trim; /** * MailTemplateService */ class MailTemplateService { - const MARKER_TYPE_STRING = 'String'; - const MARKER_TYPE_ARRAY = 'Array'; - const MARKER_TYPE_OBJECT = 'Object'; - const MARKER_TYPE_FILE = 'File'; - const DEFAULT_LANGUAGE = 'default'; - const DEFAULT_TEMPLATE_PATH = 'Resources/Private/Templates/SgMail/'; - const CACHE_NAME = 'sg_mail_registerArrayCache'; - const CACHE_LIFETIME_IN_SECONDS = 86400; - const REGISTER_FILE = 'Register.php'; - const CONFIG_PATH = 'Configuration/MailTemplates'; + public const MARKER_TYPE_STRING = 'String'; + public const MARKER_TYPE_ARRAY = 'Array'; + public const MARKER_TYPE_OBJECT = 'Object'; + public const MARKER_TYPE_FILE = 'File'; + public const DEFAULT_LANGUAGE = 'default'; + public const DEFAULT_TEMPLATE_PATH = 'Resources/Private/Templates/SgMail/'; + public const CACHE_NAME = 'sg_mail_registerArrayCache'; + public const CACHE_LIFETIME_IN_SECONDS = 86400; + public const REGISTER_FILE = 'Register.php'; + public const CONFIG_PATH = 'Configuration/MailTemplates'; /** * @var array @@ -68,16 +92,24 @@ class MailTemplateService { * @var array */ private static $mailObjectCache = []; + /** - * @var \SGalinski\SgMail\Domain\Repository\TemplateRepository + * @var TemplateRepository */ protected $templateRepository; + /** - * @var \SGalinski\SgMail\Domain\Repository\LayoutRepository + * @var LayoutRepository */ protected $layoutRepository; + + /** + * @var MailRepository + */ + protected $mailRepository; + /** - * @var \TYPO3\CMS\Extbase\Object\ObjectManager + * @var ObjectManager * @deprecated Not used since TYPO3 10 */ protected $objectManager; @@ -87,97 +119,95 @@ class MailTemplateService { */ protected $registerService; - /** - * @var \TYPO3\CMS\Core\Resource\ResourceFactory - */ - protected $resourceFactory; /** * @var string $toAddresses */ private $toAddresses = ''; + /** * @var string $fromAddress */ private $fromAddress = ''; + /** * @var string $ccAddresses */ private $ccAddresses; + /** * @var string $replyToAddress */ private $replyToAddress = ''; + /** - * @var string $language + * @var SiteLanguage */ - private $language = 'default'; + private $siteLanguage; + /** * @var boolean $ignoreMailQueue */ private $ignoreMailQueue = TRUE; - /** - * @var \TYPO3\CMS\Core\Mail\MailMessage $mailMessage - */ - private $mailMessage; + /** * @var string $templateName */ private $templateName; + /** * @var string $subject */ private $subject; + /** * @var string $overwrittenEmailBody */ private $overwrittenEmailBody = ''; + /** * @var string $extensionKey */ private $extensionKey; + /** * @var array $markers */ private $markers; + /** * @var array $markerLabels */ private $markerLabels; + /** * @var string $bccAddresses */ private $bccAddresses; + /** * @var int */ private $priority = Mail::PRIORITY_LOWEST; + /** * @var int */ private $pid; - /** - * @var string - */ - private $fromName = ''; - /** - * @var string - */ - private $mailBodyToSend; /** * @var string */ - private $subjectToSend; + private $fromName = ''; /** * @var string */ - private $defaultFromAddress; + private $mailBodyToSend = ''; /** * @var string */ - private $defaultFromName; + private $subjectToSend; /** * MailTemplateService constructor. @@ -186,58 +216,41 @@ class MailTemplateService { * @param string $extensionKey * @param array $markers * @param array $markerLabels - * @throws \InvalidArgumentException + * @throws Exception */ - public function __construct($templateName = '', $extensionKey = '', $markers = [], $markerLabels = []) { + public function __construct(string $templateName = '', string $extensionKey = '', array $markers = [], array $markerLabels = []) { $this->templateName = $templateName; $this->extensionKey = $extensionKey; $this->markers = $markers; $this->markerLabels = $markerLabels; $this->registerService = GeneralUtility::makeInstance(RegisterService::class); - $this->resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); - $this->mailMessage = GeneralUtility::makeInstance(MailMessage::class); - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0')) { $this->objectManager = GeneralUtility::makeInstance(ObjectManager::class); /** @var TypoScriptSettingsService $typoScriptSettingsService */ $typoScriptSettingsService = $this->objectManager->get(TypoScriptSettingsService::class); - /** @var TemplateRepository templateRepository */ - $this->templateRepository = $this->objectManager->get(TemplateRepository::class); - /** @var LayoutRepository layoutRepository */ - $this->layoutRepository = $this->objectManager->get(LayoutRepository::class); } else { $typoScriptSettingsService = GeneralUtility::makeInstance(TypoScriptSettingsService::class); - $this->templateRepository = GeneralUtility::makeInstance(TemplateRepository::class); - $this->layoutRepository = GeneralUtility::makeInstance(LayoutRepository::class); } $tsSettings = $typoScriptSettingsService->getSettings(0, 'tx_sgmail'); // use defaultMailFromAddress if it is provided in LocalConfiguration.php; use the sg_mail TS setting as fallback - if (\filter_var($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'], FILTER_VALIDATE_EMAIL)) { + if (filter_var($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'], FILTER_VALIDATE_EMAIL)) { $this->fromAddress = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']; - $this->defaultFromAddress = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']; + } else if (!filter_var($tsSettings['mail']['default']['from'], FILTER_VALIDATE_EMAIL)) { + $this->fromAddress = 'noreply@example.org'; } else { - if (!\filter_var($tsSettings['mail']['default']['from'], FILTER_VALIDATE_EMAIL)) { - $this->fromAddress = 'noreply@example.org'; - $this->defaultFromAddress = 'noreply@example.org'; - } else { - $this->fromAddress = $tsSettings['mail']['default']['from']; - $this->defaultFromAddress = $tsSettings['mail']['default']['from']; - } + $this->fromAddress = $tsSettings['mail']['default']['from']; } if ($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']) { $this->fromName = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']; - $this->defaultFromName = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']; } - $this->mailMessage->setFrom($this->fromAddress, $this->fromName); $this->bccAddresses = GeneralUtility::trimExplode(',', $tsSettings['mail']['default']['bcc']); $this->ccAddresses = GeneralUtility::trimExplode(',', $tsSettings['mail']['default']['cc']); - foreach ($this->bccAddresses as $index => $email) { - if (!\filter_var($email, FILTER_VALIDATE_EMAIL)) { + if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { unset($this->bccAddresses[$index]); } } @@ -247,38 +260,6 @@ class MailTemplateService { unset($this->ccAddresses[$index]); } } - - if (\count($this->bccAddresses) > 0) { - $this->mailMessage->setBcc($this->bccAddresses); - } - - if (\count($this->ccAddresses) > 0) { - $this->mailMessage->setCc($this->ccAddresses); - } - } - - /** - * 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; - case self::MARKER_TYPE_FILE: - LocalizationUtility::translate('backend.marker.type.file', 'sg_mail'); - break; - default: - LocalizationUtility::translate('backend.marker.type.mixed', 'sg_mail'); - } } /** @@ -289,10 +270,10 @@ class MailTemplateService { * @param string $extensionKey * @return array */ - public static function getDefaultTemplateMarker($translationKey, array $marker, $extensionKey = 'sg_mail'): array { + public static function getDefaultTemplateMarker(string $translationKey, array $marker, $extensionKey = 'sg_mail'): array { $languagePath = 'LLL:EXT:' . $extensionKey . '/Resources/Private/Language/locallang.xlf:' . $translationKey; // Need the key for translations - if (\trim($extensionKey) === '') { + if (trim($extensionKey) === '') { return []; } @@ -310,78 +291,16 @@ class MailTemplateService { return $generatedMarker; } - /** - * @param string $language - * @return MailTemplateService - */ - public function setLanguage($language): MailTemplateService { - $this->language = $language; - return $this; - } - - /** - * @param string $templateName - * @return MailTemplateService - */ - public function setTemplateName($templateName): MailTemplateService { - $this->templateName = $templateName; - return $this; - } - - /** - * @param string $extensionKey - * @return MailTemplateService - */ - public function setExtensionKey($extensionKey): MailTemplateService { - $this->extensionKey = $extensionKey; - return $this; - } - - /** - * @param array $markers - * @return MailTemplateService - */ - public function addMarkers(array $markers): MailTemplateService { - $this->setMarkers(\array_merge($this->markers, $markers)); - return $this; - } - - /** - * @param array $markers - * @return MailTemplateService - */ - public function setMarkers(array $markers): MailTemplateService { - $this->markers = $markers; - foreach ($markers as $key => $currentMarker) { - if (!\is_array($currentMarker) || !isset($currentMarker['markerLabel'])) { - continue; - } - $this->markerLabels[$key] = $currentMarker['markerLabel']; - } - - return $this; - } - - /** - * @param int $priority - * @return MailTemplateService - */ - public function setPriority($priority): MailTemplateService { - $this->priority = $priority; - return $this; - } - /** * Adds a file resource as attachment * - * @param FileReference $fileReference - * @param File $file + * @param FileReference|null $fileReference + * @param File|null $file * * @return MailTemplateService - * @throws \TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException */ public function addFileResourceAttachment( - FileReference $fileReference = NULL, File $file = NULL + FileReference $fileReference = NULL, FileInterface $file = NULL ): MailTemplateService { if (!$file) { if (!$fileReference) { @@ -399,7 +318,8 @@ class MailTemplateService { } } - $coreFileReferenceMailFile = $this->resourceFactory->createFileReferenceObject( + $coreFileReferenceMailFile = GeneralUtility::makeInstance(ResourceFactory::class) + ->createFileReferenceObject( [ 'uid_local' => $file->getUid(), 'table_local' => 'sys_file', @@ -414,53 +334,20 @@ class MailTemplateService { return $this; } - /** - * @return MailMessage - */ - public function getMailMessage(): MailMessage { - return $this->mailMessage; - } - - /** - * set the page id from which this was called - * - * @param int $pid - * @return MailTemplateService - */ - public function setPid($pid): MailTemplateService { - $this->pid = (int) $pid; - return $this; - } - - /** - * @return string - */ - public function getSubject(): string { - return $this->subject; - } - - /** - * @param string $subject - */ - public function setSubject(string $subject) { - $this->subject = $subject; - } - /** * Set preview markers for the template editor * - * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException + * @throws NoSuchCacheException */ - public function setPreviewMarkers() { - $previewMarker = []; + public function setPreviewMarkers(): void { + $previewMarkers = []; /** @var array $markerArray */ $markerArray = $this->registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['marker']; - foreach ($markerArray as $marker) { $markerPath = GeneralUtility::trimExplode('.', $marker['marker']); $temporaryMarkerArray = []; - foreach (\array_reverse($markerPath) as $index => $markerPathSegment) { + foreach (array_reverse($markerPath) as $index => $markerPathSegment) { if ($index === 0) { if ($marker['markerLabel']) { $markerPathSegment = $marker['markerLabel']; @@ -477,34 +364,27 @@ class MailTemplateService { $temporaryMarkerArray = [$markerPathSegment => $temporaryMarkerArray]; } } - /** @noinspection SlowArrayOperationsInLoopInspection */ - $previewMarker = \array_merge_recursive($previewMarker, $temporaryMarkerArray); + + $previewMarkers[] = $temporaryMarkerArray; } - $this->setMarkers($previewMarker); + + $this->setMarkers(array_merge_recursive(...$previewMarkers)); } /** * Send the Email * * @param bool $isPreview - * @param Template|null $template + * @param bool $isNewsletter * @return bool email was sent or added to mail queue successfully? - * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException - * @throws \TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException - */ - public function sendEmail($isPreview = FALSE, $isNewsletter = FALSE): bool { - if ($isPreview) { //TODO: remove this from here - $this->setIgnoreMailQueue(TRUE); - } - $success = FALSE; - - // Get page ID - // TODO: this doesn't belong here. The API user needs to provide the UID - $siteRootId = $this->getSiteRootId(); + * @throws NoSuchCacheException + * @throws ResourceDoesNotExistException + * @throws IllegalObjectTypeException + * @throws UnknownObjectException + */ + public function sendEmail(bool $isPreview = FALSE, bool $isNewsletter = FALSE): bool { try { - $template = $this->getTemplate($siteRootId); + $template = $this->getTemplate(); } catch (\Exception $e) { return FALSE; } @@ -519,136 +399,63 @@ class MailTemplateService { // set the ToAddress if there are no placeholders in it // TODO: does this belong here? - if ($template !== NULL && \filter_var($template->getToAddress(), FILTER_VALIDATE_EMAIL)) { - $this->setToAddresses(\trim($template->getToAddress())); + if ($template !== NULL && filter_var($template->getToAddress(), FILTER_VALIDATE_EMAIL)) { + $this->setToAddresses(trim($template->getToAddress())); } - $this->parseValuesForMail($template, $defaultTemplateContent, $siteRootId); + $this->parseValuesForMail($template, $defaultTemplateContent); - $mail = $this->addMailToMailQueue( - $this->extensionKey, $this->templateName, $this->getSubjectToSend(), $this->getMailBodyToSend(), - $this->priority, - 0, 0, $this->language, $siteRootId - ); + $mail = $this->addMailToMailQueue(); self::$mailObjectCache[$mail->getUid()] = $mail; // add it to cache to avoid extra DB queries + $success = FALSE; if ($this->ignoreMailQueue) { $success = $this->sendMailFromQueue($mail->getUid()); } - //TODO: this can be avoided if the sending logic is decoupled from this function - if ($isPreview) { - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { - /** @var MailRepository $mailRepository */ - $mailRepository = $this->objectManager->get(MailRepository::class); - } else { - $mailRepository = GeneralUtility::makeInstance(MailRepository::class); - } - - $mailRepository->remove($mail); - $mailRepository->persist(); - } - return $success; } - /** - * @param boolean $ignoreMailQueue - * @return MailTemplateService - */ - public function setIgnoreMailQueue($ignoreMailQueue): MailTemplateService { - $this->ignoreMailQueue = $ignoreMailQueue; - return $this; - } - - /** - * Get site root ID - * - * @return int - */ - public function getSiteRootId(): int { - $pageUid = $this->getPageUid(); - return BackendService::getSiteRoot($pageUid); - } - - /** - * Gets the current PageUid - * - * @return int - */ - protected function getPageUid(): int { - if (TYPO3_MODE === 'FE') { - $pageUid = (int) $GLOBALS['TSFE']->id; - } else { - $pageUid = (int) GeneralUtility::_GP('id'); - } - - if ($this->pid) { - $pageUid = $this->pid; - } - - if ($pageUid === 0) { - $pageUid = $this->getAnyRootPageUid(); - } - return $pageUid; - } - - /** - * Gets the page uid of any root page in the page tree - * - * @return int - */ - private function getAnyRootPageUid() { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable( - 'pages' - ); - $rootPageRows = $queryBuilder->select('*') - ->from('pages') - ->where( - $queryBuilder->expr()->eq( - 'is_siteroot', 1 - ) - ) - ->andWhere( - $queryBuilder->expr()->eq( - 'hidden', 0 - ) - ) - ->execute()->fetchAll(); - - if ($rootPageRows && \count($rootPageRows)) { - $pageUid = (int) $rootPageRows[0]['uid']; - } - return $pageUid; - } - /** * Get the template object * - * @param int $siteRootId - * @return null|object|Template|FALSE + * @return null|Template * @throws \Exception */ - private function getTemplate($siteRootId) { - $isTemplateBlacklisted = $this->registerService->isTemplateBlacklisted($this->extensionKey, $this->templateName, $siteRootId); + private function getTemplate(): ?Template { + $isTemplateBlacklisted = $this->registerService->isTemplateBlacklisted( + $this->extensionKey, + $this->templateName, + $this->pid + ); if ($isTemplateBlacklisted) { throw new \Exception('The template is blacklisted'); } - $templateHash = $this->getTemplateHash($this->extensionKey, $this->templateName, $siteRootId, $this->language); - if (isset(self::$templateObjectCache[$templateHash]) - && self::$templateObjectCache[$templateHash] instanceof Template) { + $templateHash = $this->getTemplateHash(); + if ( + isset(self::$templateObjectCache[$templateHash]) + && self::$templateObjectCache[$templateHash] instanceof Template + ) { return self::$templateObjectCache[$templateHash]; } + /** @var Template $template */ - $template = $this->templateRepository->findOneByTemplate( - $this->extensionKey, $this->templateName, $this->language, $siteRootId - ); + $template = $this->getTemplateRepository()->findByTemplateProperties( + $this->extensionKey, $this->templateName, [$this->siteLanguage], $this->pid + )->getFirst(); if ($template === NULL) { - $template = $this->templateRepository->findOneByTemplate( - $this->extensionKey, $this->templateName, 'default', $siteRootId - ); + $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($this->pid); + $fallbackLanguages = []; + foreach ($this->siteLanguage->getFallbackLanguageIds() as $fallbackLanguageId) { + $fallbackLanguages[] = $site->getLanguageById($fallbackLanguageId); + } + + $template = $this->getTemplateRepository()->findByTemplateProperties( + $this->extensionKey, $this->templateName, $fallbackLanguages, $this->pid + )->getFirst(); } + self::$templateObjectCache[$templateHash] = $template; return $template; } @@ -656,14 +463,15 @@ class MailTemplateService { /** * Get the hash for the object cache * - * @param $extensionKey - * @param $templateName - * @param $siteRootId - * @param $languageId * @return string */ - private function getTemplateHash($extensionKey, $templateName, $siteRootId, $languageId) { - return md5($extensionKey . '_' . $templateName . '_' . $siteRootId . '_' . $languageId); + private function getTemplateHash(): string { + return md5( + $this->extensionKey . '_' . + $this->templateName . '_' . + $this->pid . '_' . + $this->siteLanguage->getLanguageId() + ); } /** @@ -671,16 +479,21 @@ class MailTemplateService { * * @param Template $template */ - private function loadTemplateValues(Template $template) { - $fromName = \trim($template->getFromName()); + private function loadTemplateValues(Template $template): void { + $this->resetTemplate(); + $this->extensionKey = $template->getExtensionKey(); + $this->templateName = $template->getTemplateName(); + + $fromName = trim($template->getFromName()); if ($fromName === '') { $fromName = $this->fromName; } + if ($fromName === '' && $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']) { $fromName = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']; } - $fromMail = $this->getValidFromMail(\trim($template->getFromMail())); + $fromMail = $this->getValidFromMail(trim($template->getFromMail())); // The setters check if the value is empty or not $this->setFromAddress($fromMail, $fromName); $this->setCcAddresses($template->getCc()); @@ -696,14 +509,15 @@ class MailTemplateService { * @param string $fromMail * @return string */ - private function getValidFromMail($fromMail): string { - $fromMail = \trim($fromMail); - if (!\filter_var($fromMail, FILTER_VALIDATE_EMAIL)) { + private function getValidFromMail(string $fromMail): string { + $fromMail = trim($fromMail); + if (!filter_var($fromMail, FILTER_VALIDATE_EMAIL)) { $fromMail = $this->fromAddress; } - if (!\filter_var($fromMail, FILTER_VALIDATE_EMAIL)) { + + if (!filter_var($fromMail, FILTER_VALIDATE_EMAIL)) { $fromMail = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']; - if (!\filter_var($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'], FILTER_VALIDATE_EMAIL)) { + if (!filter_var($GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'], FILTER_VALIDATE_EMAIL)) { $fromMail = 'noreply@example.com'; } } @@ -711,74 +525,17 @@ class MailTemplateService { return $fromMail; } - /** - * @param string $fromAddress - * @param string $fromName - * @return MailTemplateService - */ - public function setFromAddress($fromAddress, $fromName = ''): MailTemplateService { - if ($fromAddress) { - $this->fromAddress = $fromAddress; - $this->mailMessage->setFrom($fromAddress, $fromName); - } - - return $this; - } - - /** - * @param string $ccAddresses - * @return MailTemplateService - */ - public function setCcAddresses($ccAddresses): MailTemplateService { - if ($ccAddresses) { - $this->ccAddresses = $ccAddresses; - $this->mailMessage->setCc(GeneralUtility::trimExplode(',', $this->ccAddresses)); - } - - return $this; - } - - /** - * @param string $bccAddresses - * @return MailTemplateService - */ - public function setBccAddresses($bccAddresses): MailTemplateService { - if ($bccAddresses) { - $this->bccAddresses = $bccAddresses; - $this->mailMessage->setBcc(GeneralUtility::trimExplode(',', $this->bccAddresses)); - } - - return $this; - } - - /** - * @param string $replyToAddress - * @return MailTemplateService - */ - public function setReplyToAddress($replyToAddress): MailTemplateService { - if ($replyToAddress) { - $this->replyToAddress = $replyToAddress; - $this->mailMessage->setReplyTo($replyToAddress); - } - - return $this; - } - /** - * @param string $fromName - */ - public function setFromName($fromName) { - $this->fromName = $fromName; - } /** * Get the default content for this template * * @param Template|null $template - * @return bool|false|string - * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException + * @return bool|string + * @throws Exception + * @throws NoSuchCacheException */ - protected function getDefaultTemplateContent($template) { + protected function getDefaultTemplateContent(Template $template = NULL) { $defaultTemplateContent = $this->registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['templateContent']; @@ -789,8 +546,8 @@ class MailTemplateService { // only standard template file is considered since version 4.1 $defaultTemplateFile = $templatePath . 'template.html'; - if (\file_exists($defaultTemplateFile)) { - $defaultTemplateContent = \file_get_contents($defaultTemplateFile); + if (file_exists($defaultTemplateFile)) { + $defaultTemplateContent = file_get_contents($defaultTemplateFile); } else { // use configured default html template if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { @@ -805,13 +562,14 @@ class MailTemplateService { $tsSettings['mail']['defaultHtmlTemplate'] ); - if (\file_exists($defaultTemplateFile)) { - $defaultTemplateContent = \file_get_contents($defaultTemplateFile); + if (file_exists($defaultTemplateFile)) { + $defaultTemplateContent = file_get_contents($defaultTemplateFile); } else { return FALSE; } } } + return $defaultTemplateContent; } @@ -819,15 +577,9 @@ class MailTemplateService { * @param string $toAddresses * @return MailTemplateService */ - public function setToAddresses($toAddresses): MailTemplateService { + public function setToAddresses(string $toAddresses): MailTemplateService { $normalizedToAddresses = trim(preg_replace('~\x{00a0}~iu', ' ', $toAddresses)); $this->toAddresses = $normalizedToAddresses; - - $addressesArray = GeneralUtility::trimExplode(',', $normalizedToAddresses, TRUE); - if (\count($addressesArray) > 1) { - $normalizedToAddresses = $addressesArray; - } - $this->mailMessage->setTo($normalizedToAddresses); return $this; } @@ -836,14 +588,12 @@ class MailTemplateService { * * @param Template|null $template * @param string $defaultTemplateContent - * @param int $siteRootId - * @param boolean $isNewsletter - * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException + * @throws Exception + * @throws NoSuchCacheException */ protected function parseValuesForMail( - $template, $defaultTemplateContent, - $siteRootId - ) { + Template $template = NULL, string $defaultTemplateContent = '' + ): void { if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { /** @var StandaloneView $emailView */ $emailView = $this->objectManager->get(StandaloneView::class); @@ -868,18 +618,18 @@ class MailTemplateService { trim(empty($overwrittenSubject) ? $template->getSubject() : $overwrittenSubject), $emailView ); - $layoutId = $template->getLayout(); $templateContent = $template->getContent(); $this->setSubjectToSend($subject); } else { $subject = $this->registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['subject']; - if (\is_array($subject)) { - $subject = \trim( + if (is_array($subject)) { + $subject = trim( $this->registerService->getRegisterArray() - [$this->extensionKey][$this->templateName]['subject'][$this->language] + [$this->extensionKey][$this->templateName]['subject'][$this->siteLanguage->getTypo3Language()] ); } + $subject = $this->parseMarkers( (empty($overwrittenSubject) ? $subject : $overwrittenSubject), $emailView @@ -890,7 +640,6 @@ class MailTemplateService { } $this->setSubjectToSend($subject); - $this->mailMessage->setSubject($subject); // Parse the markers if ($this->fromName) { @@ -924,15 +673,20 @@ class MailTemplateService { // insert <br> tags, but replace every instance of three or more successive breaks with just two. $emailBody = $emailView->render(); - $emailBody = \nl2br($emailBody); - $emailBody = \preg_replace('/(<br[\s]?[\/]?>[\s]*){3,}/', '<br><br>', $emailBody); + $emailBody = nl2br($emailBody); + $emailBody = preg_replace('/(<br[\s]?[\/]?>[\s]*){3,}/', '<br><br>', $emailBody); - $layout = $this->getLayoutSource($layoutId, $siteRootId); + $layout = $this->getLayoutRepository()->findByUidOrDefault( + $layoutId, + $this->pid, + $this->siteLanguage->getLanguageId() + ); $emailHTMLHead = ''; if ($layout) { $emailHTMLHead = $layout->getHeadContent(); - $emailBody = \str_replace('###CONTENT###', $emailBody, $layout->getContent()); + $emailBody = str_replace('###CONTENT###', $emailBody, $layout->getContent()); } + $this->mailBodyToSend = '<html><head>' . $emailHTMLHead . '</head><body>' . $emailBody . '</body></html>'; } @@ -944,23 +698,22 @@ class MailTemplateService { */ private function getAllMarker(array $markers): string { $allMarker = ''; - foreach ($markers as $key => $value) { - if (\array_key_exists($key, $this->markerLabels) && $this->markerLabels[$key] !== NULL) { + if (array_key_exists($key, $this->markerLabels) && $this->markerLabels[$key] !== NULL) { $key = $this->markerLabels[$key]; } - if (\is_string($value)) { + if (is_string($value)) { $allMarker .= $key . ': ' . $value . PHP_EOL; - } elseif (\is_array($value)) { + } elseif (is_array($value)) { foreach ($value as $innerKey => $innerValue) { $allMarker .= $key . '.' . $innerKey . ': ' . $innerValue . PHP_EOL; } - } elseif (\is_bool($value)) { + } elseif (is_bool($value)) { $valueAsString = $value ? 'true' : 'false'; $allMarker .= $key . ': ' . $valueAsString . PHP_EOL; - } elseif (\is_object($value)) { - if (\method_exists($value, '__toString')) { + } elseif (is_object($value)) { + if (method_exists($value, '__toString')) { $allMarker .= $key . ': ' . $value->__toString() . PHP_EOL; } } @@ -978,57 +731,39 @@ class MailTemplateService { private function getAllMarkerHTML(array $markers): string { $allMarker = '<table>'; $allMarker .= '<style> table { text-align: left; } table tr th, table tr td { border-bottom: 1px solid rgba(0,0,0,0.2); padding: 2px 6px 4px;} </style>'; - foreach ($markers as $key => $value) { - if (\array_key_exists($key, $this->markerLabels) && $this->markerLabels[$key] !== NULL) { + if (array_key_exists($key, $this->markerLabels) && $this->markerLabels[$key] !== NULL) { $key = $this->markerLabels[$key]; } - if (\is_string($value)) { + if (is_string($value)) { $allMarker .= '<tr><th>' . $key . ' </th><td> ' . $value . '</td></tr>'; - } elseif (\is_array($value)) { + } elseif (is_array($value)) { foreach ($value as $innerKey => $innerValue) { $allMarker .= '<tr><th>' . $key . '.' . $innerKey . ' </th><td> ' . $innerValue . '</td></tr>'; } - } elseif (\is_bool($value)) { + } elseif (is_bool($value)) { $valueAsString = $value ? 'true' : 'false'; $allMarker .= '<tr><th>' . $key . ' </th><td> ' . $valueAsString . '</td></tr>'; - } elseif (\is_object($value)) { - if (\method_exists($value, '__toString')) { + } elseif (is_object($value)) { + if (method_exists($value, '__toString')) { $allMarker .= '<tr><th>' . $key . ' </th><td> ' . $value->__toString() . '</td></tr>'; } } } - $allMarker .= '</table>'; - - return $allMarker; + return $allMarker . '</table>'; } /** + * Parses markers in an email View. + * !!! CHANGES THE SOURCE PATH AND IT SHOULD BE RESET BACK TO THE ORIGINAL!!! + * + * @param string $text + * @param StandaloneView $emailView * @return string */ - public function getOverwrittenEmailBody(): string { - return $this->overwrittenEmailBody; - } - - /** - * @param string $overwrittenEmailBody - */ - public function setOverwrittenEmailBody(string $overwrittenEmailBody) { - $this->overwrittenEmailBody = $overwrittenEmailBody; - } - - /** - * Parses markers in an email View. - * !!! CHANGES THE SOURCE PATH AND IT SHOULD BE RESET BACK TO THE ORIGINAL!!! - * - * @param string $text - * @param StandaloneView $emailView - * @return mixed - */ - protected function parseMarkers($text, $emailView) { - $text = (string) $text; + protected function parseMarkers(string $text, StandaloneView $emailView): string { if (strpos($text, '{') !== FALSE) { $emailView->setTemplateSource($text); return $emailView->render(); @@ -1037,107 +772,100 @@ class MailTemplateService { return $text; } - /** - * Returns the layout. - * - * @param int $layoutUid - * @param int $siteRootId - * @return Layout|NULL - */ - private function getLayoutSource(int $layoutUid, int $siteRootId) { - $languageUid = 0; - if ($this->language !== self::DEFAULT_LANGUAGE) { - $languageUid = (int) array_search($this->language, $this->getAvailableLanguages(), TRUE); - } - - return $this->layoutRepository->findByUidOrDefault($layoutUid, $siteRootId, $languageUid); - } - - /** - * Returns the list of available translation languages - * - * @return array - */ - private function getAvailableLanguages(): array { - $out = [0 => '']; - try { - $site = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId(0); - } catch (\Exception $exception) { - return [0 => '']; - } - $availableLanguages = $site->getLanguages(); - $out = []; - foreach ($availableLanguages as $language) { - $languageId = $language->getLanguageId(); - if ($languageId < 0) { - continue; - } - $out[$language->getLanguageId()] = strtolower($language->getTwoLetterIsoCode()); - } - return $out; - } - /** * 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 * @return Mail - * @throws \InvalidArgumentException - * @throws \BadFunctionCallException - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException - * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException - */ - private function addMailToMailQueue( - $extensionKey, $templateName, $subject, $emailBody, $priority, $sendingTime = 0, - $lastSendingTime = 0, $language = self::DEFAULT_LANGUAGE, $pid = 0 - ): Mail { - $mail = new Mail(); - $mail->setPid($pid); - $mail->setExtensionKey($extensionKey); - $mail->setTemplateName($templateName); - $mail->setLanguage($language); - $mail->setBlacklisted($this->registerService->isTemplateBlacklisted($extensionKey, $templateName, $pid)); - + * @throws Exception + * @throws IllegalObjectTypeException + * @throws NoSuchCacheException + */ + private function addMailToMailQueue(): Mail { + $mail = GeneralUtility::makeInstance(Mail::class); + $mail->setPid($this->pid); + $mail->setExtensionKey($this->extensionKey); + $mail->setTemplateName($this->templateName); + $mail->setLanguage(explode('.', $this->siteLanguage->getLocale())[0]); + $mail->setBlacklisted( + $this->registerService->isTemplateBlacklisted( + $this->extensionKey, + $this->templateName, + $this->pid + ) + ); $mail->setFromAddress($this->fromAddress); $mail->setFromName($this->fromName); - $mail->setToAddress($this->toAddresses); - $mail->setMailSubject($subject); - $mail->setMailBody($emailBody); - $mail->setPriority($priority); + $mail->setMailSubject($this->getSubjectToSend()); + $mail->setMailBody($this->getMailBodyToSend()); + $mail->setPriority($this->priority); $mail->setBccAddresses($this->bccAddresses); $mail->setCcAddresses($this->ccAddresses); - $mail->setSendingTime($sendingTime); - $mail->setLastSendingTime($lastSendingTime); + $mail->setSendingTime(0); + $mail->setLastSendingTime(0); $mail->setReplyTo($this->replyToAddress); foreach ($this->markers as $marker) { if ($marker instanceof FileReference) { // we need to create proper copies of the attachment so that the original file reference does not get // moved over to the mail model and worst case, the original model loses the reference because of this $originalResource = $marker->getOriginalResource(); - if ($originalResource instanceof \TYPO3\CMS\Core\Resource\FileReference) { - $coreFileReferenceMailFile = $this->resourceFactory->createFileReferenceObject( + if ($originalResource instanceof CoreFileReference) { + $coreFileReferenceMailFile = GeneralUtility::makeInstance(ResourceFactory::class) + ->createFileReferenceObject( [ 'uid_local' => $originalResource->getOriginalFile()->getUid(), 'table_local' => 'sys_file', 'uid' => uniqid('NEW_MAIL', TRUE) ] ); - $newFileReference = new FileReference(); + $newFileReference = GeneralUtility::makeInstance(FileReference::class); $newFileReference->setOriginalResource($coreFileReferenceMailFile); $mail->addAttachment($newFileReference); } } } + $mailRepository = $this->getMailRepository(); + $mailRepository->add($mail); + $mailRepository->persist(); + return $mail; + } + + /** + * Send a Mail from the queue, identified by its id + * + * @param int $uid + * @return bool + * @throws Exception + */ + public function sendMailFromQueue(int $uid): bool { + if (!isset(self::$mailObjectCache[$uid]) || !self::$mailObjectCache[$uid] instanceof Mail) { + $mailToSend = $this->getMailObjectByUid($uid); + if ($mailToSend === FALSE) { + return FALSE; + } + } else { + $mailToSend = self::$mailObjectCache[$uid]; + } + + $this->sendMailsFromQueue([$mailToSend]); + $success = FALSE; + if ($mailToSend->getStatus() === Mail::STATUS_SENT) { + $success = TRUE; + } + + unset(self::$mailObjectCache[$uid]); // free the memory + return $success; + } + + /** + * Get the mail object by uid and check if it's blacklisted + * + * @param int $uid + * @return bool|object + * @throws Exception + */ + protected function getMailObjectByUid(int $uid): ?Mail { if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { /** @var MailRepository $mailRepository */ $mailRepository = $this->objectManager->get(MailRepository::class); @@ -1145,155 +873,375 @@ class MailTemplateService { $mailRepository = GeneralUtility::makeInstance(MailRepository::class); } - $mailRepository->add($mail); - $mailRepository->persist(); - return $mail; + $mailObject = $mailRepository->findOneByUid($uid); + if (!$mailObject || $mailObject->getBlacklisted()) { + return NULL; + } + + return $mailObject; } /** - * @return string + * Add html and plain body text to the mail message object + * + * @param MailMessage $mailMessage + * @param string $htmlBody + * @param string $plainBody */ - public function getSubjectToSend(): string { - return $this->subjectToSend; + protected static function addBodyToMailMessage(MailMessage $mailMessage, string $htmlBody = '', string $plainBody = ''): void { + if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { + $mailMessage->setBody($htmlBody, 'text/html'); + $mailMessage->addPart($plainBody, 'text/plain'); + } else { + $mailMessage->html($htmlBody); + $mailMessage->text($plainBody); + } } /** - * @param string $subjectToSend + * Attach a file + * @param MailMessage $mailMessage + * @param FileInterface $file */ - public function setSubjectToSend(string $subjectToSend) { - $this->subjectToSend = $subjectToSend; + protected static function attachToMailMessage(MailMessage $mailMessage, FileInterface $file): void { + if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { + $mailMessage->attach( + Swift_Attachment::newInstance($file->getContents(), $file->getName(), $file->getMimeType()) + ); + } else { + $mailMessage->attach( + $file->getContents(), $file->getName(), $file->getMimeType() + ); + } } /** - * @return string|string[]|null + * + * @param Mail[] $mails + * @throws Exception + * @throws IllegalObjectTypeException + * @throws UnknownObjectException + */ + public function sendMailsFromQueue(array $mails): void { + foreach ($mails as $mail) { + $mailMessage = GeneralUtility::makeInstance(MailMessage::class); + $toAddresses = trim($mail->getToAddress()); + $addressesArray = GeneralUtility::trimExplode(',', $mail->getToAddress(), TRUE); + if (count($addressesArray) > 1) { + $toAddresses = $addressesArray; + } + + $mailMessage->setTo($toAddresses); + $mailMessage->setFrom($mail->getFromAddress(), $mail->getFromName()); + $mailMessage->setCc( + GeneralUtility::trimExplode(',', $mail->getCcAddresses(), TRUE) + ); + $mailMessage->setBcc( + GeneralUtility::trimExplode(',', $mail->getBccAddresses(), TRUE) + ); + $mailMessage->setSubject($mail->getMailSubject()); + $plaintextService = GeneralUtility::makeInstance(PlaintextService::class); + $plaintextBody = $plaintextService->makePlain($mail->getMailBody()); + self::addBodyToMailMessage($mailMessage, $mail->getMailBody(), $plaintextBody); + + if ($mail->getBccAddresses()) { + $mailMessage->setBcc(GeneralUtility::trimExplode(',', $mail->getBccAddresses())); + } + + if ($mail->getCcAddresses()) { + $mailMessage->setCc(GeneralUtility::trimExplode(',', $mail->getCcAddresses())); + } + + if ($mail->getReplyTo()) { + $mailMessage->setReplyTo($mail->getReplyTo()); + } + + $attachments = $mail->getAttachments(); + if ($attachments->count() > 0) { + foreach ($attachments as $attachment) { + /** + * @var FileReference $attachment + */ + $originalResource = $attachment->getOriginalResource(); + if ($originalResource === NULL) { + continue; + } + + $file = $originalResource->getOriginalFile(); + self::attachToMailMessage($mailMessage, $file); + } + } + + $dateTime = new DateTime(); + if ($mail->getSendingTime() === 0) { + $mail->setSendingTime($dateTime->getTimestamp()); + } + + $mail->setLastSendingTime($dateTime->getTimestamp()); + try { + $success = $mailMessage->send(); + if (!$success) { + $mail->setStatus(Mail::STATUS_ERROR); + $mail->setErrorMessage(LocalizationUtility::translate('backend.success_mail_queue', 'sg_mail')); + } + $mail->setStatus(Mail::STATUS_SENT); + } catch (TransportException $exception) { + $mail->setStatus(Mail::STATUS_ERROR); + $mail->setErrorMessage($exception->getMessage()); + } + + $this->getMailRepository()->update($mail); + } + + $this->getMailRepository()->persist(); + } + + /** + * @param SiteLanguage $siteLanguage + * @return $this */ - public function getMailBodyToSend() { - return $this->mailBodyToSend; + public function setSiteLanguage(SiteLanguage $siteLanguage): MailTemplateService { + $this->siteLanguage = $siteLanguage; + return $this; + } + + /** + * @param string $templateName + * @return MailTemplateService + */ + public function setTemplateName(string $templateName): MailTemplateService { + $this->templateName = $templateName; + return $this; } /** - * @param string|string[]|null $mailBodyToSend + * @param string $extensionKey + * @return MailTemplateService */ - public function setMailBodyToSend($mailBodyToSend) { - $this->mailBodyToSend = $mailBodyToSend; + public function setExtensionKey(string $extensionKey): MailTemplateService { + $this->extensionKey = $extensionKey; + return $this; } /** - * Send a Mail from the queue, identified by its id - * - * @param int $uid - * @return bool|NULL - * @throws \TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException - * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException + * @param array $markers + * @return MailTemplateService */ - public function sendMailFromQueue($uid): bool { - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { - /** @var MailRepository $mailRepository */ - $mailRepository = $this->objectManager->get(MailRepository::class); - } else { - $mailRepository = GeneralUtility::makeInstance(MailRepository::class); - } + public function addMarkers(array $markers): MailTemplateService { + $this->setMarkers(array_merge($this->markers, $markers)); + return $this; + } - /** @var Mail $mailToSend */ - if (!isset(self::$mailObjectCache[$uid]) || !self::$mailObjectCache[$uid] instanceof Mail) { - $mailToSend = $this->getMailObjectByUid($uid); - if ($mailToSend === FALSE) { - return FALSE; + /** + * @param array $markers + * @return MailTemplateService + */ + public function setMarkers(array $markers): MailTemplateService { + $this->markers = $markers; + foreach ($markers as $key => $currentMarker) { + if (!is_array($currentMarker) || !isset($currentMarker['markerLabel'])) { + continue; } - } else { - $mailToSend = self::$mailObjectCache[$uid]; + $this->markerLabels[$key] = $currentMarker['markerLabel']; } - $plaintextService = GeneralUtility::makeInstance(PlaintextService::class); - $plaintextBody = $plaintextService->makePlain($mailToSend->getMailBody()); - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { - $this->mailMessage->setBody($mailToSend->getMailBody(), 'text/html'); - $this->mailMessage->addPart($plaintextBody, 'text/plain'); - } else { - $this->mailMessage->html($mailToSend->getMailBody()); - $this->mailMessage->text($plaintextBody); - } + return $this; + } - $toAddresses = \trim($mailToSend->getToAddress()); - $addressesArray = GeneralUtility::trimExplode(',', $toAddresses, TRUE); - if (\count($addressesArray) > 1) { - $toAddresses = $addressesArray; - } + /** + * @param int $priority + * @return MailTemplateService + */ + public function setPriority(int $priority): MailTemplateService { + $this->priority = $priority; + return $this; + } - $this->mailMessage->setTo($toAddresses); - $this->mailMessage->setFrom($mailToSend->getFromAddress(), $mailToSend->getFromName()); - $this->mailMessage->setSubject($mailToSend->getMailSubject()); - if ($mailToSend->getBccAddresses()) { - $this->mailMessage->setBcc(GeneralUtility::trimExplode(',', $mailToSend->getBccAddresses())); + /** + * @param string $fromAddress + * @param string $fromName + * @return MailTemplateService + */ + public function setFromAddress(string $fromAddress, string $fromName = ''): MailTemplateService { + if ($fromAddress) { + $this->fromAddress = $fromAddress; } - if ($mailToSend->getCcAddresses()) { - $this->mailMessage->setCc(GeneralUtility::trimExplode(',', $mailToSend->getCcAddresses())); - } + return $this; + } - if ($mailToSend->getReplyTo()) { - $this->mailMessage->setReplyTo($mailToSend->getReplyTo()); + /** + * @param string $ccAddresses + * @return MailTemplateService + */ + public function setCcAddresses(string $ccAddresses): MailTemplateService { + if ($ccAddresses) { + $this->ccAddresses = $ccAddresses; } - $attachments = $mailToSend->getAttachments(); - if ($attachments->count() > 0) { - foreach ($attachments as $attachment) { - /** - * @var FileReference $attachment - */ - $file = $attachment->getOriginalResource()->getOriginalFile(); - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { - $this->mailMessage->attach( - \Swift_Attachment::newInstance($file->getContents(), $file->getName(), $file->getMimeType()) - ); - } else { - $this->mailMessage->attach( - $file->getContents(), $file->getName(), $file->getMimeType() - ); - } - } - } + return $this; + } - $dateTime = new DateTime(); - if ($mailToSend->getSendingTime() === 0) { - $mailToSend->setSendingTime($dateTime->getTimestamp()); + /** + * @param string $bccAddresses + * @return MailTemplateService + */ + public function setBccAddresses(string $bccAddresses): MailTemplateService { + if ($bccAddresses) { + $this->bccAddresses = $bccAddresses; } - $mailToSend->setLastSendingTime($dateTime->getTimestamp()); - try { - $success = $this->mailMessage->send(); - } catch (TransportException $exception) { - $success = FALSE; - } + return $this; + } - if ($success) { - $mailRepository->update($mailToSend); - $mailRepository->persist(); + /** + * @param string $replyToAddress + * @return MailTemplateService + */ + public function setReplyToAddress(string $replyToAddress): MailTemplateService { + if ($replyToAddress) { + $this->replyToAddress = $replyToAddress; } - unset(self::$mailObjectCache[$uid]); // free the memory - return $success; + return $this; } /** - * Get the mail object by uid and check if it's blacklisted + * @param string $fromName + * @return MailTemplateService + */ + public function setFromName(string $fromName): MailTemplateService { + $this->fromName = $fromName; + return $this; + } + + /** + * @param bool $ignoreMailQueue + * @return MailTemplateService + */ + public function setIgnoreMailQueue(bool $ignoreMailQueue): MailTemplateService { + $this->ignoreMailQueue = $ignoreMailQueue; + return $this; + } + + /** + * @return string + */ + public function getSubjectToSend(): string { + return $this->subjectToSend; + } + + /** + * @param string $subjectToSend + * @return MailTemplateService + */ + public function setSubjectToSend(string $subjectToSend): MailTemplateService { + $this->subjectToSend = $subjectToSend; + return $this; + } + + /** + * @return string + */ + public function getMailBodyToSend(): string { + return $this->mailBodyToSend; + } + + /** + * @param string $mailBodyToSend + * @return MailTemplateService + */ + public function setMailBodyToSend(string $mailBodyToSend): MailTemplateService { + $this->mailBodyToSend = $mailBodyToSend; + return $this; + } + + /** + * @return string + */ + public function getOverwrittenEmailBody(): string { + return $this->overwrittenEmailBody; + } + + /** + * @param string $overwrittenEmailBody + * @return MailTemplateService + */ + public function setOverwrittenEmailBody(string $overwrittenEmailBody): MailTemplateService { + $this->overwrittenEmailBody = $overwrittenEmailBody; + return $this; + } + + /** + * set the page id from which this was called * - * @param int $uid - * @return bool|object + * @param int $pid + * @return MailTemplateService */ - public function getMailObjectByUid($uid) { - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0', '<')) { - /** @var MailRepository $mailRepository */ - $mailRepository = $this->objectManager->get(MailRepository::class); - } else { - $mailRepository = GeneralUtility::makeInstance(MailRepository::class); + public function setPid(int $pid): MailTemplateService { + $this->pid = $pid; + return $this; + } + + /** + * @return string + */ + public function getSubject(): string { + return $this->subject; + } + + /** + * @param string $subject + */ + public function setSubject(string $subject): void { + $this->subject = $subject; + } + + /** + * @return LayoutRepository + * @throws Exception + */ + protected function getLayoutRepository(): LayoutRepository { + if ($this->layoutRepository === NULL) { + if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0')) { + $this->layoutRepository = $this->objectManager->get(LayoutRepository::class); + } else { + $this->layoutRepository = GeneralUtility::makeInstance(LayoutRepository::class); + } } - $mailObject = $mailRepository->findOneByUid($uid); - if (!$mailObject || $mailObject->getBlacklisted()) { - return FALSE; + return $this->layoutRepository; + } + + /** + * @return TemplateRepository + * @throws Exception + */ + protected function getTemplateRepository(): TemplateRepository { + if ($this->templateRepository === NULL) { + if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0')) { + $this->templateRepository = $this->objectManager->get(TemplateRepository::class); + } else { + $this->templateRepository = GeneralUtility::makeInstance(TemplateRepository::class); + } } - return $mailObject; + + return $this->templateRepository; + } + + /** + * @return MailRepository + * @throws Exception + */ + protected function getMailRepository(): MailRepository { + if ($this->mailRepository === NULL) { + if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '10.4.0')) { + $this->mailRepository = $this->objectManager->get(MailRepository::class); + } else { + $this->mailRepository = GeneralUtility::makeInstance(MailRepository::class); + } + } + + return $this->mailRepository; } } diff --git a/Classes/Updates/LanguageMigrationUpdate.php b/Classes/Updates/LanguageMigrationUpdate.php new file mode 100644 index 0000000000000000000000000000000000000000..c9e23fb63f0d748609f41da8714d7c8c23ef83f8 --- /dev/null +++ b/Classes/Updates/LanguageMigrationUpdate.php @@ -0,0 +1,101 @@ +<?php +/******************************************************************************* + * 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! + ******************************************************************************/ + +namespace SGalinski\SgMail\Updates; + +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Site\SiteFinder; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite; +use TYPO3\CMS\Install\Updates\UpgradeWizardInterface; + +class LanguageMigrationUpdate implements UpgradeWizardInterface { + public const IDENTIFIER = 'sgmail_languagemigrationupdate'; + + /** + * @return string + */ + public function getIdentifier(): string { + return self::IDENTIFIER; + } + + /** + * @return string + */ + public function getTitle(): string { + return 'Language migration wizard'; + } + + /** + * @return string + */ + public function getDescription(): string { + return 'This wizard migrates the language values of mails and templates to more reasonable values then two letter isocodes'; + } + + /** + * @return bool + */ + public function executeUpdate(): bool { + $sites = GeneralUtility::makeInstance(SiteFinder::class)->getAllSites(); + $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); + foreach ($sites as $site) { + $languages = $site->getAllLanguages(); + foreach ($languages as $language) { + $queryBuilder = $connectionPool->getQueryBuilderForTable('tx_sgmail_domain_model_mail'); + $queryBuilder->update('tx_sgmask_domain_model_mail') + ->set('language', explode('.', $language->getLocale())) + ->where( + $queryBuilder->expr()->like('language', $language->getTypo3Language()) + )->execute(); + + $queryBuilder = $connectionPool->getQueryBuilderForTable('tx_sgmail_domain_model_template'); + $queryBuilder->update('tx_sgmail_domain_model_template') + ->set('sys_language_uid', $language->getLanguageId()) + ->where( + $queryBuilder->expr()->like('language', $language->getTypo3Language()) + )->execute(); + } + } + + return TRUE; + } + + /** + * @return bool + */ + public function updateNecessary(): bool { + return TRUE; + } + + /** + * @return string[] + */ + public function getPrerequisites(): array { + return [ + DatabaseUpdatedPrerequisite::class + ]; + } +} diff --git a/Classes/Updates/SendStatusUpdate.php b/Classes/Updates/SendStatusUpdate.php new file mode 100644 index 0000000000000000000000000000000000000000..44034c6893add982bc088657e90b5a57440d879a --- /dev/null +++ b/Classes/Updates/SendStatusUpdate.php @@ -0,0 +1,99 @@ +<?php +/******************************************************************************* + * 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! + ******************************************************************************/ + +namespace SGalinski\SgMail\Updates; + +use SGalinski\SgMail\Domain\Model\Mail; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite; +use TYPO3\CMS\Install\Updates\UpgradeWizardInterface; + +/** + * Class SendStatusUpdate + * + * @package SGalinski\SgMail\Updates + */ +class SendStatusUpdate implements UpgradeWizardInterface { + public const IDENTIFIER = 'sgmail_sendstatusupdate'; + + /** + * @inheritDoc + */ + public function getIdentifier(): string { + return self::IDENTIFIER; + } + + /** + * @inheritDoc + */ + public function getTitle(): string { + return 'Update the send status of mails'; + } + + /** + * @inheritDoc + */ + public function getDescription(): string { + return 'This wizard updates the status of mails that have a sending_time set to sent appropriately.'; + } + + /** + * @inheritDoc + */ + public function executeUpdate(): bool { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_sgmail_domain_model_mail'); + $queryBuilder->update('tx_sgmail_domain_model_mail') + ->set('status', Mail::STATUS_SENT) + ->where( + $queryBuilder->expr()->gt('sending_time', 0), + $queryBuilder->expr()->eq('status', Mail::STATUS_PENDING) + )->execute(); + return TRUE; + } + + /** + * @inheritDoc + */ + public function updateNecessary(): bool { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_sgmail_domain_model_mail'); + $count = $queryBuilder->count('*') + ->from('tx_sgmail_domain_model_mail') + ->where( + $queryBuilder->expr()->gt('sending_time', 0), + $queryBuilder->expr()->eq('status', Mail::STATUS_PENDING) + )->execute()->fetchOne(); + return $count > 0; + } + + /** + * @inheritDoc + */ + public function getPrerequisites(): array { + return [ + DatabaseUpdatedPrerequisite::class + ]; + } +} diff --git a/Classes/Updates/UpdateGermanAsDefault.php b/Classes/Updates/UpdateGermanAsDefault.php deleted file mode 100644 index 1ef546aa4b92ff59b780cd35fa31c9bae903ecc2..0000000000000000000000000000000000000000 --- a/Classes/Updates/UpdateGermanAsDefault.php +++ /dev/null @@ -1,135 +0,0 @@ -<?php -/*************************************************************** - * 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! - ***************************************************************/ - -namespace SGalinski\SgMail\Updates; - -use TYPO3\CMS\Core\Database\Connection; -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite; -use TYPO3\CMS\Install\Updates\UpgradeWizardInterface; - -/** - * Makes german templates the default and former default as english templates - */ -class UpdateGermanAsDefault implements UpgradeWizardInterface { - /** - * The wizard identifier - */ - public const IDENTIFIER = 'tx_sgmail_update_german_as_default'; - - /** - * @var string - */ - protected $table = 'tx_sgmail_domain_model_template'; - - /** - * @return string - */ - public function getIdentifier(): string { - return self::IDENTIFIER; - } - - /** - * @return string - */ - public function getTitle(): string { - return 'Makes german templates the default and former default as english templates. WARNING: ONLY EXECUTE THIS IF IT MAKES SENSE FOR YOUR TYPO3 INSTANCE'; - } - - /** - * @return string - */ - public function getDescription(): string { - return ''; - } - - /** - * @return bool - */ - public function executeUpdate(): bool { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table); - $queryBuilder->getRestrictions()->removeAll(); - $resultGerman = $queryBuilder->select('uid') - ->from($this->table) - ->where( - $queryBuilder->expr()->eq('language', $queryBuilder->createNamedParameter('de')) - ) - ->execute()->fetchAllAssociative(); - - $resultDefault = $queryBuilder->select('uid') - ->from($this->table) - ->where( - $queryBuilder->expr()->eq('language', $queryBuilder->createNamedParameter('default')) - ) - ->execute()->fetchAllAssociative(); - - /** @var array $resultGerman */ - foreach ($resultGerman as $row) { - $queryBuilder->update($this->table) - ->where( - $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($row[0], Connection::PARAM_INT)) - ) - ->set('language', 'default', TRUE) - ->execute(); - } - - /** @var array $resultGerman */ - foreach ($resultDefault as $row) { - $queryBuilder->update($this->table) - ->where( - $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($row[0], Connection::PARAM_INT)) - ) - ->set('language', 'en', TRUE) - ->execute(); - } - - return TRUE; - } - - /** - * @return bool - */ - public function updateNecessary(): bool { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table); - $queryBuilder->getRestrictions()->removeAll(); - $rowCount = $queryBuilder->select('*') - ->from($this->table) - ->where( - $queryBuilder->expr()->eq('language', $queryBuilder->createNamedParameter('de')) - ) - ->execute()->rowCount(); - return $rowCount > 0; - } - - /** - * @return array|string[] - */ - public function getPrerequisites(): array { - return [ - DatabaseUpdatedPrerequisite::class - ]; - } -} diff --git a/Classes/Updates/UpdateLanguages.php b/Classes/Updates/UpdateLanguages.php deleted file mode 100644 index 34a11e7ec470b7661cecdb6fadb47dbe21dc427a..0000000000000000000000000000000000000000 --- a/Classes/Updates/UpdateLanguages.php +++ /dev/null @@ -1,147 +0,0 @@ -<?php -/*************************************************************** - * 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! - ***************************************************************/ - -namespace SGalinski\SgMail\Updates; - -use SGalinski\SgMail\Service\BackendService; -use TYPO3\CMS\Core\Database\Connection; -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite; -use TYPO3\CMS\Install\Updates\UpgradeWizardInterface; - -/** - * Fix all incorrect / deprecated language codes (be languages instead of sys languages) in the database - */ -class UpdateLanguages implements UpgradeWizardInterface { - /** - * The wizard identifier - */ - public const IDENTIFIER = 'tx_sgmail_update_languages'; - - /** - * @var array - */ - protected $tables = [ - 'tx_sgmail_domain_model_mail', 'tx_sgmail_domain_model_template' - ]; - - /** - * is used to map language codes. If empty the updatewizard will ignore this update - * example: you want to change en-us to en - * [ - * 'en-us' => 'en' - * ] - * - * @var array - */ - protected $languageMap = [ - - ]; - - /** - * @return string - */ - public function getIdentifier(): string { - return self::IDENTIFIER; - } - - /** - * @return string - */ - public function getTitle(): string { - return 'Find all templates & queue entries with an incorrect (be languages instead of sys languages) language code and fix it'; - } - - /** - * @return string - */ - public function getDescription(): string { - return ''; - } - - /** - * @return bool - */ - public function executeUpdate(): bool { - foreach ($this->tables as $table) { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); - $queryBuilder->getRestrictions()->removeAll(); - foreach ($this->languageMap as $origin => $target) { - $queryBuilder->update($table) - ->where( - $queryBuilder->expr()->eq('language', $queryBuilder->createNamedParameter($origin)) - ) - ->set('language', $target, TRUE) - ->execute(); - } - } - - return TRUE; - } - - /** - * @return bool - */ - public function updateNecessary(): bool { - $upgradeNecessary = FALSE; - - if (count($this->languageMap) > 0) { - $languages = BackendService::getLanguages(); - - foreach ($this->tables as $table) { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); - $queryBuilder->getRestrictions()->removeAll(); - $rowCount = $queryBuilder->select('language') - ->from($table) - ->where( - $queryBuilder->expr()->notIn( - 'language', - $queryBuilder->createNamedParameter( - array_column($languages, 'isocode'), - Connection::PARAM_STR_ARRAY - ) - ) - ) - ->execute()->rowCount(); - if ($rowCount > 0) { - $upgradeNecessary = TRUE; - break; - } - } - } - - return $upgradeNecessary; - } - - /** - * @return array|string[] - */ - public function getPrerequisites(): array { - return [ - DatabaseUpdatedPrerequisite::class - ]; - } -} diff --git a/Configuration/TCA/tx_sgmail_domain_model_layout.php b/Configuration/TCA/tx_sgmail_domain_model_layout.php index 040a8b38ad8af92a76f624188f547c5a811a1599..03a1e0419b56f27dec48f5d638422d83b1302e9d 100644 --- a/Configuration/TCA/tx_sgmail_domain_model_layout.php +++ b/Configuration/TCA/tx_sgmail_domain_model_layout.php @@ -32,10 +32,10 @@ $columns = [ 'crdate' => 'crdate', 'cruser_id' => 'cruser_id', 'searchFields' => 'name, content', - 'dividers2tabs' => TRUE, 'delete' => 'deleted', 'languageField' => 'sys_language_uid', 'transOrigPointerField' => 'l10n_parent', + 'translationSource' => 'l10n_source', 'transOrigDiffSourceField' => 'l10n_diffsource', 'enablecolumns' => [ 'disabled' => 'hidden', @@ -82,9 +82,9 @@ $columns = [ 'default' => 0, 'fieldWizard' => [ 'selectIcons' => [ - 'disabled' => FALSE, - ], - ], + 'disabled' => FALSE + ] + ] ] ], 'l10n_parent' => [ diff --git a/Configuration/TCA/tx_sgmail_domain_model_mail.php b/Configuration/TCA/tx_sgmail_domain_model_mail.php index 12fe86e4b7344d3cafd1b912b613ef5e183b3dad..7992e211811adde9ed9ce51d9fba8063ad202201 100644 --- a/Configuration/TCA/tx_sgmail_domain_model_mail.php +++ b/Configuration/TCA/tx_sgmail_domain_model_mail.php @@ -32,8 +32,7 @@ $columns = [ 'tstamp' => 'tstamp', 'crdate' => 'crdate', 'cruser_id' => 'cruser_id', - 'searchFields' => 'blacklisted, mail_subject, mail_body, to_address, from_address, from_name, bcc_addresses, cc_addresses, extension_key, template_name, sending_time, last_sending_time, language', - 'dividers2tabs' => TRUE, + 'searchFields' => 'status, error_message, blacklisted, mail_subject, mail_body, to_address, from_address, from_name, bcc_addresses, cc_addresses, extension_key, template_name, sending_time, last_sending_time, language', 'delete' => 'deleted', 'enablecolumns' => [ 'disabled' => 'hidden', @@ -44,10 +43,32 @@ $columns = [ 'interface' => [], 'types' => [ '1' => [ - 'showitem' => 'hidden;;1, blacklisted, priority, to_address, from_address, mail_subject, mail_body, from_name, bcc_addresses, cc_addresses, extension_key, template_name, sending_time, last_sending_time, language, attachments' + 'showitem' => 'hidden;;1, status, error_message, blacklisted, priority, to_address, from_address, mail_subject, mail_body, from_name, bcc_addresses, cc_addresses, extension_key, template_name, sending_time, last_sending_time, language, attachments' ], ], 'columns' => [ + 'status' => [ + 'exclude' => TRUE, + 'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_mail.status', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => [ + ['LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_mail.status.pending', \SGalinski\SgMail\Domain\Model\Mail::STATUS_PENDING], + ['LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_mail.status.sent', \SGalinski\SgMail\Domain\Model\Mail::STATUS_SENT], + ['LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_mail.status.error', \SGalinski\SgMail\Domain\Model\Mail::STATUS_ERROR], + ] + ] + ], + 'error_message' => [ + 'exclude' => TRUE, + 'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_mail.error_message', + 'config' => [ + 'type' => 'text', + 'readOnly' => TRUE + ], + 'displayCond' => 'FIELD:status:=:' . \SGalinski\SgMail\Domain\Model\Mail::STATUS_ERROR + ], 'hidden' => [ 'exclude' => TRUE, 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:hidden.I.0', diff --git a/Configuration/TCA/tx_sgmail_domain_model_template.php b/Configuration/TCA/tx_sgmail_domain_model_template.php index 7bf38f6fa2911fbc53ba7c7338198314e0862d55..171a03e7752e611f131b34fc2861347cd9114829 100644 --- a/Configuration/TCA/tx_sgmail_domain_model_template.php +++ b/Configuration/TCA/tx_sgmail_domain_model_template.php @@ -34,8 +34,11 @@ $columns = [ 'crdate' => 'crdate', 'cruser_id' => 'cruser_id', 'searchFields' => 'extension_key, template_name, language, subject, fromName, fromMail, replyTo, to_address', - 'dividers2tabs' => TRUE, 'delete' => 'deleted', + 'languageField' => 'sys_language_uid', + 'transOrigPointerField' => 'l18n_parent', + 'translationSource' => 'l10n_source', + 'transOrigDiffSourceField' => 'l18n_diffsource', 'enablecolumns' => [ 'disabled' => 'hidden', ], @@ -45,7 +48,7 @@ $columns = [ 'interface' => [], 'types' => [ '1' => [ - 'showitem' => 'hidden;;1, extension_key, template_name, language, content, subject, fromName, fromMail, cc, bcc, replyTo, to_address' + 'showitem' => 'hidden;;1, extension_key, template_name, sys_language_uid, content, subject, fromName, fromMail, cc, bcc, replyTo, to_address' ], ], 'columns' => [ @@ -95,14 +98,6 @@ $columns = [ 'eval' => 'required, trim' ], ], - 'language' => [ - 'exclude' => TRUE, - 'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_template.language', - 'config' => [ - 'type' => 'input', - 'eval' => 'required, trim' - ], - ], 'subject' => [ 'exclude' => TRUE, 'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_template.subject', @@ -156,7 +151,7 @@ $columns = [ ] ]; if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '10.3.0', '<')) { - $columns['interface']['showRecordFieldList'] = 'layout, extension_key, template_name, language, content, subject, fromName, fromMail, cc, bcc, replyTo, to_address'; + $columns['interface']['showRecordFieldList'] = 'layout, extension_key, template_name, content, subject, fromName, fromMail, cc, bcc, replyTo, to_address'; } return $columns; diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index 2564d56ee4fb592a8f87e7d58aea4db9d3df35fe..40b0d1416b8353b283dba48c515e9daa90f3a1a6 100644 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -613,6 +613,10 @@ Die Templates declined und approved der Extension sg_comments sind für alle Dom <source><![CDATA[BCC]]></source> <target><![CDATA[BCC]]></target> </trans-unit> + <trans-unit id="backend.preview.error"> + <source><![CDATA[Preview could not be generated]]></source> + <target><![CDATA[Vorschau konnte nicht generiert werden]]></target> + </trans-unit> </body> </file> </xliff> diff --git a/Resources/Private/Language/de.locallang_db.xlf b/Resources/Private/Language/de.locallang_db.xlf index 8e082d7f5462c9f75b1ef64fb4b5b10ebb5f0eed..b2f202ecab246ddbabb4c31b7f170df352df1f3c 100644 --- a/Resources/Private/Language/de.locallang_db.xlf +++ b/Resources/Private/Language/de.locallang_db.xlf @@ -45,6 +45,26 @@ Kann bspw. für CSS verwendet werden.]]></target> <source><![CDATA[Mail Queue Entry]]></source> <target><![CDATA[Mail-Queue-Eintrag]]></target> </trans-unit> + <trans-unit id="tx_sgmail_domain_model_mail.status"> + <source><![CDATA[Status]]></source> + <target><![CDATA[Status]]></target> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_mail.status.pending"> + <source><![CDATA[Pending]]></source> + <target><![CDATA[Wartend]]></target> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_mail.status.error"> + <source><![CDATA[Error]]></source> + <target><![CDATA[Fehler]]></target> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_mail.status.sent"> + <source><![CDATA[Sent]]></source> + <target><![CDATA[Gesendet]]></target> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_mail.error_message"> + <source><![CDATA[Error message]]></source> + <target><![CDATA[Fehlermeldung]]></target> + </trans-unit> <trans-unit id="tx_sgmail_domain_model_mail.bcc_addresses" approved="yes"> <source><![CDATA[BCC Addresses]]></source> <target><![CDATA[BCC-Adressen]]></target> @@ -179,4 +199,4 @@ Kann bspw. für CSS verwendet werden.]]></target> </trans-unit> </body> </file> -</xliff> \ No newline at end of file +</xliff> diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index 5a720d077859d626c6826dedaf422e3778284557..d585f2c5a4215d85edac42060a77b558ee0eec0a 100644 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -459,6 +459,9 @@ The templates declined and approved of the sg_comments extension are blacklisted <trans-unit id="backend.preview.bcc"> <source><![CDATA[BCC]]></source> </trans-unit> + <trans-unit id="backend.preview.error"> + <source><![CDATA[Preview could not be generated]]></source> + </trans-unit> </body> </file> </xliff> diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf index 757ac26970770849122e2f204caed5fa588aca8f..a41b0813792ab9c9e103010938381f7fd44eec57 100644 --- a/Resources/Private/Language/locallang_db.xlf +++ b/Resources/Private/Language/locallang_db.xlf @@ -35,6 +35,21 @@ Can be used e.g. for CSS.]]></source> <trans-unit id="tx_sgmail_domain_model_mail"> <source><![CDATA[Mail Queue Entry]]></source> </trans-unit> + <trans-unit id="tx_sgmail_domain_model_mail.status"> + <source><![CDATA[Status]]></source> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_mail.status.pending"> + <source><![CDATA[Pending]]></source> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_mail.status.error"> + <source><![CDATA[Error]]></source> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_mail.status.sent"> + <source><![CDATA[Sent]]></source> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_mail.error_message"> + <source><![CDATA[Error message]]></source> + </trans-unit> <trans-unit id="tx_sgmail_domain_model_mail.bcc_addresses"> <source><![CDATA[BCC Addresses]]></source> </trans-unit> @@ -136,4 +151,4 @@ Can be used e.g. for CSS.]]></source> </trans-unit> </body> </file> -</xliff> \ No newline at end of file +</xliff> diff --git a/Resources/Private/Partials/ButtonBar.html b/Resources/Private/Partials/ButtonBar.html index b63090afaf97f180ac634edb5cf59a9b09c090a8..430943650907fd00df2a0ad74742717f2dc7a95d 100644 --- a/Resources/Private/Partials/ButtonBar.html +++ b/Resources/Private/Partials/ButtonBar.html @@ -1,14 +1,14 @@ - <f:for each="{buttons}" as="buttonGroup"> - <f:if condition="{buttonGroup -> f:count()} > 1"> - <f:then> - <div class="btn-group" role="group" aria-label=""> - <f:for each="{buttonGroup}" as="button"> - {button -> f:format.raw()} - </f:for> - </div> - </f:then> - <f:else> - {buttonGroup.0 -> f:format.raw()} - </f:else> - </f:if> - </f:for> +<f:for each="{buttons}" as="buttonGroup"> + <f:if condition="{buttonGroup -> f:count()} > 1"> + <f:then> + <div class="btn-group" role="group" aria-label=""> + <f:for each="{buttonGroup}" as="button"> + {button -> f:format.raw()} + </f:for> + </div> + </f:then> + <f:else> + {buttonGroup.0 -> f:format.raw()} + </f:else> + </f:if> +</f:for> diff --git a/Resources/Private/Partials/Layout/Empty.html b/Resources/Private/Partials/Layout/Empty.html index ecceff62b936325a2c1d6c89b0229d3bcbb51a53..33eeda0bff3262c2e084834a5b90e1a49aaf14cb 100644 --- a/Resources/Private/Partials/Layout/Empty.html +++ b/Resources/Private/Partials/Layout/Empty.html @@ -1,3 +1,3 @@ <p> - {f:translate(key:'backend.no_layout_entries')} + <f:translate key="backend.no_layout_entries" /> </p> diff --git a/Resources/Private/Partials/Mail/Empty.html b/Resources/Private/Partials/Mail/Empty.html index 00da31387f53280c02abe166cd4b380ffef57fc6..4700fbbc4c8c57338e9913306c8a349c582a7c2b 100644 --- a/Resources/Private/Partials/Mail/Empty.html +++ b/Resources/Private/Partials/Mail/Empty.html @@ -1,5 +1,5 @@ <div class="row"> <p> - <h3>{f:translate(key:'backend.no_site_root')}</h3> + <h3><f:translate key="backend.no_site_root" /></h3> </p> </div> diff --git a/Resources/Private/Partials/Module/DocHeader.html b/Resources/Private/Partials/Module/DocHeader.html index 549a53ade7d49d868fe93729d983c4f785974671..64b85c11219362947c4d5869ae79667be3052d3f 100644 --- a/Resources/Private/Partials/Module/DocHeader.html +++ b/Resources/Private/Partials/Module/DocHeader.html @@ -1,29 +1,3 @@ -<f:comment><!-- - ~ - ~ 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! - --></f:comment> - -<!DOCTYPE html> <html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" xmlns:mail="http://typo3.org/ns/SGalinski/SgMail/ViewHelpers" diff --git a/Resources/Private/Partials/Queue/Empty.html b/Resources/Private/Partials/Queue/Empty.html index 99a38fcd2506bf4d0656839e1259f10fc55fed5c..bd76ddc0c37c9e264b559a7c6012dfc36f05e53e 100644 --- a/Resources/Private/Partials/Queue/Empty.html +++ b/Resources/Private/Partials/Queue/Empty.html @@ -1,3 +1,3 @@ <p> - {f:translate(key:'backend.no_queue_entries')} + <f:translate key="backend.no_queue_entries" /> </p> diff --git a/Resources/Private/Partials/Queue/Filter.html b/Resources/Private/Partials/Queue/Filter.html index e5a5b5071c025c5b8799ae29a7c7c13917392bb5..f6f78d0013ca6e077e71a0fb84f6ca10d6af4727 100644 --- a/Resources/Private/Partials/Queue/Filter.html +++ b/Resources/Private/Partials/Queue/Filter.html @@ -14,18 +14,9 @@ <f:then> <sgm:be.menus.actionMenuOptionGroup label="{extensionKey}"> <f:for each="{extension}" as="template"> - <f:if condition="{selectedTemplateFilter} == {template.name} && {selectedExtensionFilter} == {extensionKey}"> - <f:then> - <option value="{extensionKey}###{template.name}" selected="selected"> - {f:if(condition: '{template.is_manual}', then:'* ')}{template.name} - </option> - </f:then> - <f:else> - <option value="{extensionKey}###{template.name}"> - {f:if(condition: '{template.is_manual}', then:'* ')}{template.name} - </option> - </f:else> - </f:if> + <option value="{extensionKey}###{template.name}"{f:if(condition:'{selectedTemplateFilter} == {template.name} && {selectedExtensionFilter} == {extensionKey}',then:' selected="selected"')}> + {f:if(condition: '{template.is_manual}', then:'* ')}{template.name} + </option> </f:for> </sgm:be.menus.actionMenuOptionGroup> </f:then> @@ -54,7 +45,13 @@ <f:translate key="backend.filters.fields" /> <f:translate key="backend.filter.fields.description" /> </label> - <f:form.select class="form-control" multiple="1" size="9" property="filterFields" optionValueField="value" options="{filterFields}" id="filter-fields" /> + <f:form.select class="form-control" + multiple="1" + size="9" + property="filterFields" + optionValueField="value" + options="{filterFields}" + id="filter-fields" /> </div> </div> <div class="col-xs-12 col-md-4"> @@ -64,7 +61,10 @@ <f:translate key="backend.filter.date_from" /> </label> <div class="form-control-clearable"> - <f:form.textfield property="filterFromDate" id="filter-from-date" data="{date-type: 'datetime'}" class="reset-me form-control t3js-datetimepicker t3js-clearable hasDefaultValue" /> + <f:form.textfield property="filterFromDate" + id="filter-from-date" + data="{date-type: 'datetime'}" + class="reset-me form-control t3js-datetimepicker t3js-clearable hasDefaultValue" /> <button type="button" class="close" tabindex="-1" aria-hidden="true" style="display: none;"> <span class="fa fa-times"></span> </button> @@ -80,7 +80,10 @@ <f:translate key="backend.filter.date_to" /> </label> <div class="form-control-clearable"> - <f:form.textfield property="filterToDate" id="filter-to-date" data="{date-type: 'datetime'}" class="reset-me form-control t3js-datetimepicker t3js-clearable hasDefaultValue" /> + <f:form.textfield property="filterToDate" + id="filter-to-date" + data="{date-type: 'datetime'}" + class="reset-me form-control t3js-datetimepicker t3js-clearable hasDefaultValue" /> <button type="button" class="close" tabindex="-1" aria-hidden="true" style="display: none;"> <span class="fa fa-times"></span> </button> @@ -93,32 +96,50 @@ </div> <div class="form-group"> <label class="radio-inline"> - <f:form.radio property="filterSent" id="filters-all" value="0" checked="{f:if(condition: '{filters.filterSent} == \'0\'', then: '1')}" /> + <f:form.radio property="filterSent" + id="filters-all" + value="0" + checked="{f:if(condition: '{filters.filterSent} == \'0\'', then: '1')}" /> <f:translate key="backend.all" /> </label> <label class="radio-inline"> - <f:form.radio property="filterSent" id="filters-sent" value="1" checked="{f:if(condition: '{filters.filterSent} == \'1\'', then: '1')}" /> + <f:form.radio property="filterSent" + id="filters-sent" + value="1" + checked="{f:if(condition: '{filters.filterSent} == \'1\'', then: '1')}" /> <f:translate key="backend.sent" /> </label> <label class="radio-inline"> - <f:form.radio property="filterSent" id="filters-notsent" value="2" checked="{f:if(condition: '{filters.filterSent} == \'2\'', then: '1')}" /> + <f:form.radio property="filterSent" + id="filters-notsent" + value="2" + checked="{f:if(condition: '{filters.filterSent} == \'2\'', then: '1')}" /> <f:translate key="backend.not_sent" /> </label> </div> <div class="form-group"> - <f:form.checkbox property="filterBlacklist" id="filters-blacklisted" value="1" checked="{f:if(condition: '{filters.filterBlacklist} == \'1\'', then: '1')}" /> + <f:form.checkbox property="filterBlacklist" + id="filters-blacklisted" + value="1" + checked="{f:if(condition: '{filters.filterBlacklist} == \'1\'', then: '1')}" /> <f:translate key="backend.blacklisted" /> </div> </div> <div class="form-group"> <div class="col-md-12"> - <f:form.button class="filter-btn btn btn-success form-group col-xs-12 col-md-12" type="submit"> + <f:form.button class="filter-btn btn btn-success form-group col-xs-12 col-md-12" + type="submit"> <f:translate key="backend.filter.filter" /> </f:form.button> - <f:form.button class="filter-btn btn btn-info form-group col-xs-12 col-md-12" type="submit" name="action" value="export"> + <f:form.button class="filter-btn btn btn-info form-group col-xs-12 col-md-12" + type="submit" + name="action" + value="export"> <f:translate key="backend.button_download_csv" /> </f:form.button> - <f:form.button id="filter-reset-btn" class="filter-btn btn btn-danger form-group col-xs-12 col-md-12" type="reset"> + <f:form.button id="filter-reset-btn" + class="filter-btn btn btn-danger form-group col-xs-12 col-md-12" + type="reset"> <f:translate key="backend.button_reset_filter" /> </f:form.button> </div> diff --git a/Resources/Private/Templates/Configuration/Index.html b/Resources/Private/Templates/Configuration/Index.html index dfeb25ab19cf9d84cb2bbdb23a9de3b2d42cfe37..7f50ed97cf90ba5c92eabf6abcca052c44f6608e 100644 --- a/Resources/Private/Templates/Configuration/Index.html +++ b/Resources/Private/Templates/Configuration/Index.html @@ -15,15 +15,17 @@ <f:translate key="backend.create.info_header" /> </div> <div class="panel-body"> - <f:format.html> - <f:translate key="backend.create.info" /> - </f:format.html> + <f:format.html><f:translate key="backend.create.info" /></f:format.html> </div> </div> </div> </div> - <f:form action="{f:if(condition: '{editMode}', then: 'edit', else: 'create')}" controller="Configuration" method="post" objectName="configuration" object="{configuration}"> + <f:form action="{f:if(condition: '{editMode}', then: 'edit', else: 'create')}" + controller="Configuration" + method="post" + objectName="configuration" + object="{configuration}"> <div class="row"> <div class="col-xs-12 col-md-10 col-md-offset-1"> <f:form.hidden name="extensionKey" value="{selectedExtensionKey}"/> @@ -31,25 +33,45 @@ <f:form.hidden name="oldExtensionKey" property="oldExtensionKey" value="{selectedExtensionKey}"/> <div class="form-group"> <label for="extensionKey"><f:translate key="backend.create.extensionKey" /></label> - <f:form.textfield class="form-control" property="extensionKey" id="extensionKey" required="TRUE" value="{extensionKey}" /> + <f:form.textfield class="form-control" + property="extensionKey" + id="extensionKey" + required="TRUE" + value="{extensionKey}" /> </div> <div class="form-group"> <label for="templateName"><f:translate key="backend.create.templateName" /></label> - <f:form.textfield class="form-control" property="templateName" id="templateName" required="TRUE" value="{templateName}" /> + <f:form.textfield class="form-control" + property="templateName" + id="templateName" + required="TRUE" + value="{templateName}" /> </div> <div class="form-group"> <label for="csv"><f:translate key="backend.create.csv" /></label> - <f:form.textarea rows="5" class="form-control" property="csv" id="csv" value="{csv}" /> + <f:form.textarea rows="5" + class="form-control" + property="csv" + id="csv" + value="{csv}" /> </div> <div class="form-group"> <label for="subject"><f:translate key="backend.create.subject" /></label> - <f:form.textfield class="form-control" property="subject" id="subject" value="{subject}" /> + <f:form.textfield class="form-control" + property="subject" + id="subject" + value="{subject}" /> </div> <div class="form-group"> <label for="description"><f:translate key="backend.create.description" /></label> - <f:form.textarea rows="5" class="form-control" property="description" id="description" value="{description}" /> + <f:form.textarea rows="5" + class="form-control" + property="description" + id="description" + value="{description}" /> </div> - <f:form.submit class="btn-primary btn form-group col-xs-12 col-md-2 col-md-offset-10" value="{f:translate(key:'backend.create.save')}" /> + <f:form.submit class="btn-primary btn form-group col-xs-12 col-md-2 col-md-offset-10" + value="{f:translate(key:'backend.create.save')}" /> </div> </div> </f:form> diff --git a/Resources/Private/Templates/Layout/Index.html b/Resources/Private/Templates/Layout/Index.html index 635d48c2893512ad5e4ee12be7b7bc7f9a1589b9..2742a994e0031eff98f26f730c512abfc900a1ed 100644 --- a/Resources/Private/Templates/Layout/Index.html +++ b/Resources/Private/Templates/Layout/Index.html @@ -3,7 +3,10 @@ <f:layout name="Default" /> <f:section name="iconButtons"> - <be:link.newRecord table="tx_sgmail_domain_model_layout" pid="{pageUid}" class="btn btn-default btn-sm" title="{f:translate(key: 'backend.button_create_layout')}"> + <be:link.newRecord table="tx_sgmail_domain_model_layout" + pid="{pageUid}" + class="btn btn-default btn-sm" + title="{f:translate(key: 'backend.button_create_layout')}"> <core:icon identifier="actions-document-new" /> </be:link.newRecord> <f:if condition="{pasteButton}"> @@ -27,7 +30,8 @@ <table data-table="tx_sgmail_domain_model_layout" class="table table-striped table-hover"> <tbody> <f:for each="{layouts}" as="layout"> - <tr data-uid="{layout.uid}" class="{f:if(condition: '{layout.default}', then: 'success', else: '')}"> + <tr data-uid="{layout.uid}" + class="{f:if(condition: '{layout.default}', then: 'success', else: '')}"> <td nowrap="nowrap" class="col-icon"> <core:iconForRecord row="{layout}" table="tx_sgmail_domain_model_layout" /> </td> @@ -39,9 +43,7 @@ </be:link.editRecord> </td> <td nowrap="nowrap" class="col-control"> - <f:format.raw> - <sg:backend.control table="tx_sgmail_domain_model_layout" row="{layout}" clipboard="1" /> - </f:format.raw> + <f:format.raw><sg:backend.control table="tx_sgmail_domain_model_layout" row="{layout}" clipboard="1" /></f:format.raw> </td> </tr> </f:for> @@ -65,7 +67,8 @@ <f:for each="{pages}" as="page"> <tr data-uid="{page.pid}"> <td nowrap="nowrap" class="col-title"> - <f:link.action action="index" additionalParams="{id: page.uid, returnUrl: returnUrl}"> + <f:link.action action="index" + additionalParams="{id: page.uid, returnUrl: returnUrl}"> <core:iconForRecord row="{page}" table="pages" /> {page._thePathFull} </f:link.action> diff --git a/Resources/Private/Templates/Mail/Empty.html b/Resources/Private/Templates/Mail/Empty.html index c39bf8639ddeb268eb99722aa1d9e5fd0e764c19..f58331a5fd546b79cb9510ce801b282359cf9fe9 100644 --- a/Resources/Private/Templates/Mail/Empty.html +++ b/Resources/Private/Templates/Mail/Empty.html @@ -2,6 +2,6 @@ <f:section name="content"> <div class="alert alert-warning"> - {f:translate(key:'backend.no_extensions')} + <f:translate key="backend.no_extensions" /> </div> </f:section> diff --git a/Resources/Private/Templates/Newsletter/Empty.html b/Resources/Private/Templates/Newsletter/Empty.html index c39bf8639ddeb268eb99722aa1d9e5fd0e764c19..f58331a5fd546b79cb9510ce801b282359cf9fe9 100644 --- a/Resources/Private/Templates/Newsletter/Empty.html +++ b/Resources/Private/Templates/Newsletter/Empty.html @@ -2,6 +2,6 @@ <f:section name="content"> <div class="alert alert-warning"> - {f:translate(key:'backend.no_extensions')} + <f:translate key="backend.no_extensions" /> </div> </f:section> diff --git a/Resources/Private/Templates/Newsletter/Index.html b/Resources/Private/Templates/Newsletter/Index.html index b52c9989b4f34faa969531fa26283aa84dac746c..06cd88939b20cac6e346d53095ec40c51c2a1112 100644 --- a/Resources/Private/Templates/Newsletter/Index.html +++ b/Resources/Private/Templates/Newsletter/Index.html @@ -256,37 +256,79 @@ </h3> <div class="col-md-12"> <div class="row form-group"> - <label for="parameters-templates-{key}-layout" class="">{f:translate(key:'backend.layout')}</label> - <f:form.select id="parameters-templates-{key}-layout" class="form-control" - value="{languageTemplate.layout}" options="{layoutOptions}" name="parameters[templates][{key}][layout]"/> + <label for="parameters-templates-{key}-layout"> + <f:translate key="backend.layout" /> + </label> + <f:form.select id="parameters-templates-{key}-layout" + class="form-control" + value="{languageTemplate.layout}" + options="{layoutOptions}" + name="parameters[templates][{key}][layout]"/> </div> <div class="row form-group"> - <label for="parameters[templates][{key}][fromName]" class="">{f:translate(key:'backend.fromName')}</label> - <f:form.textfield type="text" class="form-control" value="{languageTemplate.fromName}" name="parameters[templates][{key}][fromName]" /> + <label for="parameters-templates-{key}-fromName"> + <f:translate key="backend.fromName" /> + </label> + <f:form.textfield id="parameters-templates-{key}-fromName" + class="form-control" + value="{languageTemplate.fromName}" + name="parameters[templates][{key}][fromName]" /> </div> <div class="row form-group"> - <label for="parameters[templates][{key}][fromMail]" class="">{f:translate(key:'backend.fromMail')}</label> - <f:form.textfield type="email" class="form-control" value="{languageTemplate.fromMail}" name="parameters[templates][{key}][fromMail]" /> + <label for="parameters-templates-{key}-fromMail"> + <f:translate key="backend.fromMail" /> + </label> + <f:form.textfield id="parameters-templates-{key}-fromMail" + type="email" + class="form-control" + value="{languageTemplate.fromMail}" + name="parameters[templates][{key}][fromMail]" /> </div> <div class="row form-group"> - <label for="parameters[templates][{key}][cc]" class="">{f:translate(key:'backend.cc')}</label> - <f:form.textfield type="text" class="form-control" value="{languageTemplate.cc}" name="parameters[templates][{key}][cc]" /> + <label for="parameters-templates-{key}-cc"> + <f:translate key="backend.cc" /> + </label> + <f:form.textfield id="parameters-templates-{key}-cc" + class="form-control" + value="{languageTemplate.cc}" + name="parameters[templates][{key}][cc]" /> </div> <div class="row form-group"> - <label for="parameters[templates][{key}][bcc]" class="">{f:translate(key:'backend.bcc')}</label> - <f:form.textfield type="text" class="form-control" value="{languageTemplate.bcc}" name="parameters[templates][{key}][bcc]" /> + <label for="parameters-templates-{key}-bcc"> + <f:translate key="backend.bcc" /> + </label> + <f:form.textfield id="parameters-templates-{key}-bcc" + class="form-control" + value="{languageTemplate.bcc}" + name="parameters[templates][{key}][bcc]" /> </div> <div class="row form-group"> - <label for="parameters[templates][{key}][replyTo]" class="">{f:translate(key:'backend.replyTo')}</label> - <f:form.textfield type="text" class="form-control" value="{languageTemplate.replyTo}" name="parameters[templates][{key}][replyTo]" /> + <label for="parameters-templates-{key}-replyTo"> + <f:translate key="backend.replyTo" /> + </label> + <f:form.textfield id="parameters-templates-{key}-replyTo" + class="form-control" + value="{languageTemplate.replyTo}" + name="parameters[templates][{key}][replyTo]" /> </div> <div class="row form-group"> - <label for="parameters[templates][{key}][subject]" class="">{f:translate(key:'backend.subject')}</label> - <f:form.textfield type="text" class="form-control" value="{languageTemplate.subject}" name="parameters[templates][{key}][subject]" /> + <label for="parameters-templates-{key}-subject"> + <f:translate key="backend.subject" /> + </label> + <f:form.textfield id="parameters-templates-{key}-subject" + class="form-control" + value="{languageTemplate.subject}" + name="parameters[templates][{key}][subject]" /> </div> <div class="row form-group"> - <label for="parameters[templates][{key}][content]" class="">{f:translate(key:'backend.content')}</label> - <f:form.textarea class="form-control" rows="15" name="parameters[templates][{key}][content]" value="{languageTemplate.content}" /> + <label for="parameters-templates-{key}-content"> + <f:translate key="backend.content" /> + </label> + <f:form.textarea id="parameters-templates-{key}-content" + class="form-control" + rows="15" + name="parameters[templates][{key}][content]" + value="{languageTemplate.content}" /> </div> </div> </div> @@ -294,10 +336,19 @@ </div> </f:for> <div class="form-group"> - <f:form.submit name="sendDirectly" id="newsletter-send-real-emails-button" class="btn-success btn form-group" value="{f:translate(key:'backend.send_newsletter')}" /> - <f:form.submit class="btn-primary btn form-group" id="newsletter-send-preview-emails-button" value="{f:translate(key:'backend.send_test_newsletter')}" /> - <f:form.textfield name="parameters[emailAddress]" class="email-input form-group" value="{beUserMail}" /> - <f:form.hidden name="sendRealEmails" id="newsletter-send-real-emails-hidden-field" value="0" /> + <f:form.submit name="sendDirectly" + id="newsletter-send-real-emails-button" + class="btn-success btn form-group" + value="{f:translate(key:'backend.send_newsletter')}" /> + <f:form.submit class="btn-primary btn form-group" + id="newsletter-send-preview-emails-button" + value="{f:translate(key:'backend.send_test_newsletter')}" /> + <f:form.textfield name="parameters[emailAddress]" + class="email-input form-group" + value="{beUserMail}" /> + <f:form.hidden name="sendRealEmails" + id="newsletter-send-real-emails-hidden-field" + value="0" /> <f:form.hidden name="parameters[selectedLanguage]" value="{selectedLanguage}" /> <f:form.hidden name="parameters[selectedTemplate]" value="{selectedTemplateKey}" /> <f:form.hidden name="parameters[selectedExtensionKey]" value="{selectedTemplate.extension}" /> @@ -320,7 +371,10 @@ <f:for each="{pages}" as="page"> <tr data-uid="{page.pid}"> <td nowrap="nowrap" class="col-title"> - <f:link.action class="sg-mail_pageswitch" action="index" additionalParams="{id: page.uid, returnUrl: returnUrl}" additionalAttributes="{data-page: page.uid, data-path: page.path}"> + <f:link.action class="sg-mail_pageswitch" + action="index" + additionalParams="{id: page.uid, returnUrl: returnUrl}" + additionalAttributes="{data-page: page.uid, data-path: page.path}"> <core:iconForRecord table="pages" row="{page}" /> {page._thePathFull} </f:link.action> @@ -336,14 +390,24 @@ </f:section> <f:section name="iconButtons"> - <f:link.action class="btn btn-default btn-sm" controller="Configuration" action="index" arguments="{mode: 'new', selectedTemplate: selectedTemplateKey, selectedExtension: selectedTemplate.extension}"> + <f:link.action class="btn btn-default btn-sm" + controller="Configuration" + action="index" + arguments="{mode: 'new', selectedTemplate: selectedTemplateKey, selectedExtension: selectedTemplate.extension}"> <core:icon identifier="actions-document-new" /> </f:link.action> <f:if condition="{isManual}"> - <f:link.action class="btn btn-default btn-sm" controller="Configuration" action="index" arguments="{mode: 'edit', selectedTemplate: selectedTemplateKey, selectedExtension: selectedTemplate.extension}"> + <f:link.action class="btn btn-default btn-sm" + controller="Configuration" + action="index" + arguments="{mode: 'edit', selectedTemplate: selectedTemplateKey, selectedExtension: selectedTemplate.extension}"> <core:icon identifier="actions-document-open" /> </f:link.action> - <f:link.action class="btn btn-default btn-sm" id="delete-template-btn" controller="Configuration" action="delete" arguments="{selectedTemplate: selectedTemplateKey, selectedExtension: selectedTemplate.extension}"> + <f:link.action class="btn btn-default btn-sm" + id="delete-template-btn" + controller="Configuration" + action="delete" + arguments="{selectedTemplate: selectedTemplateKey, selectedExtension: selectedTemplate.extension}"> <core:icon identifier="actions-edit-delete" /> </f:link.action> </f:if> diff --git a/Resources/Private/Templates/Queue/Index.html b/Resources/Private/Templates/Queue/Index.html index 90dbe3c67c239cdb6e3c507235bb0bd9b2e499d8..104e3058fb1910673685f0ed65f25b6cf16a6358 100644 --- a/Resources/Private/Templates/Queue/Index.html +++ b/Resources/Private/Templates/Queue/Index.html @@ -90,15 +90,16 @@ </f:then> <f:else> <f:link.action class="btn btn-default btn-send-now" - controller="Queue" action="sendMail" - arguments="{uid: mail.uid, selectedTemplate: selectedTemplateKey, selectedExtension: selectedExtensionKey}"> + controller="Queue" + action="sendMail" + arguments="{mail: mail, selectedTemplate: selectedTemplateKey, selectedExtension: selectedExtensionKey}"> <core:icon identifier="actions-document-import-t3d"/> <f:translate key="backend.send_now"/> </f:link.action> </f:else> </f:if> <button class="btn btn-default btn-preview" - onClick="MailPreviewWindow{mail.uid}=window.open('{f:uri.action( controller: 'Queue', action: 'preview', noCacheHash: true, arguments: {uid: mail.uid, selectedTemplate: selectedTemplateKey, selectedExtension: selectedExtensionKey})}','MailPreviewWindow{mail.uid}','width=1200,height=768'); return false;"> + onClick="MailPreviewWindow{mail.uid}=window.open('{f:uri.action( controller: 'Queue', action: 'preview', noCacheHash: true, arguments: {mail: mail})}','MailPreviewWindow{mail.uid}','width=1200,height=768'); return false;"> <core:icon identifier="actions-view-page"/> </button> </td> diff --git a/Resources/Private/Templates/Queue/Preview.html b/Resources/Private/Templates/Queue/Preview.html index ee57f58fde17f7d903aa2afe96641b35b1e57bec..877412fa9848c895b905a4d92e185e83868b554e 100644 --- a/Resources/Private/Templates/Queue/Preview.html +++ b/Resources/Private/Templates/Queue/Preview.html @@ -1,74 +1,81 @@ <f:layout name="Preview"/> <f:section name="mailPreview"> - <div class="mail-header"> - <table> - <tr> - <th> - <f:translate key="backend.preview.date"/> - </th> - <td> - <f:format.date format="d.m.Y H:i"> - <f:format.stripTags>{mail.sendingTime}</f:format.stripTags> - </f:format.date> - </td> - </tr> + <f:if condition="{mail} && !{mail.blacklisted}"> + <f:then> + <div class="mail-header"> + <table> + <tr> + <th> + <f:translate key="backend.preview.date"/> + </th> + <td> + <f:format.date format="d.m.Y H:i"> + <f:format.stripTags>{mail.sendingTime}</f:format.stripTags> + </f:format.date> + </td> + </tr> - <tr> - <th> - <f:translate key="backend.preview.from"/> - </th> - <td> - <f:format.stripTags>{mail.fromName}</f:format.stripTags> - <<f:format.stripTags>{mail.fromAddress}</f:format.stripTags>> - </td> - </tr> + <tr> + <th> + <f:translate key="backend.preview.from"/> + </th> + <td> + <f:format.stripTags>{mail.fromName}</f:format.stripTags> + <<f:format.stripTags>{mail.fromAddress}</f:format.stripTags>> + </td> + </tr> - <tr> - <th> - <f:translate key="backend.preview.subject"/> - </th> - <td> - <strong> - <f:format.stripTags>{mail.mailSubject}</f:format.stripTags> - </strong> - </td> - </tr> + <tr> + <th> + <f:translate key="backend.preview.subject"/> + </th> + <td> + <strong> + <f:format.stripTags>{mail.mailSubject}</f:format.stripTags> + </strong> + </td> + </tr> - <tr> - <th> - <f:translate key="backend.preview.to"/> - </th> - <td class="ng-binding"> - <f:format.stripTags>{mail.toAddress}</f:format.stripTags> - </td> - </tr> + <tr> + <th> + <f:translate key="backend.preview.to"/> + </th> + <td class="ng-binding"> + <f:format.stripTags>{mail.toAddress}</f:format.stripTags> + </td> + </tr> - <f:if condition="{mail.ccAddresses}"> - <tr> - <th> - <f:translate key="backend.preview.cc"/> - </th> - <td class="ng-binding"> - <f:format.stripTags>{mail.ccAddresses}</f:format.stripTags> - </td> - </tr> - </f:if> + <f:if condition="{mail.ccAddresses}"> + <tr> + <th> + <f:translate key="backend.preview.cc"/> + </th> + <td class="ng-binding"> + <f:format.stripTags>{mail.ccAddresses}</f:format.stripTags> + </td> + </tr> + </f:if> - <f:if condition="{mail.bccAddresses}"> - <tr> - <th> - <f:translate key="backend.preview.bcc"/> - </th> - <td class="ng-binding"> - <f:format.stripTags>{mail.bccAddresses}</f:format.stripTags> - </td> - </tr> - </f:if> - </table> - </div> + <f:if condition="{mail.bccAddresses}"> + <tr> + <th> + <f:translate key="backend.preview.bcc"/> + </th> + <td class="ng-binding"> + <f:format.stripTags>{mail.bccAddresses}</f:format.stripTags> + </td> + </tr> + </f:if> + </table> + </div> - <div class="mail-body"> - <iframe class="mail-body-iframe" srcdoc="{mail.mailBody}" sandbox></iframe> - </div> + <div class="mail-body"> + <iframe class="mail-body-iframe" srcdoc="{mail.mailBody}" sandbox></iframe> + </div> + </f:then> + <f:else> + <f:translate key="backend.preview.error" /> + </f:else> + </f:if> </f:section> diff --git a/ext_localconf.php b/ext_localconf.php index e9be793e768259e05c179b3aa5e8983829756df0..82f7125e32946d80fbe25caab7b53dc90e1c8207 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -28,10 +28,10 @@ call_user_func( // add upgrade wizard for moving all db entries to their respected siteroot $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\UpdatePidToSiteRoot::IDENTIFIER] = \SGalinski\SgMail\Updates\UpdatePidToSiteRoot::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\UpdateSendingTimes::IDENTIFIER] = \SGalinski\SgMail\Updates\UpdateSendingTimes::class; - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\UpdateLanguages::IDENTIFIER] = \SGalinski\SgMail\Updates\UpdateLanguages::class; - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\UpdateGermanAsDefault::IDENTIFIER] = \SGalinski\SgMail\Updates\UpdateGermanAsDefault::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\MigrateSchedulerTasks::IDENTIFIER] = \SGalinski\SgMail\Updates\MigrateSchedulerTasks::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\MigrateFinishersUpgrade::IDENTIFIER] = \SGalinski\SgMail\Updates\MigrateFinishersUpgrade::class; + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\SendStatusUpdate::IDENTIFIER] = \SGalinski\SgMail\Updates\SendStatusUpdate::class; + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgMail\Updates\LanguageMigrationUpdate::IDENTIFIER] = \SGalinski\SgMail\Updates\LanguageMigrationUpdate::class; if (TYPO3_MODE === 'BE') { \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScriptSetup( diff --git a/ext_tables.sql b/ext_tables.sql index c8b4ccf5be61092e4be69fbbaf9c8c5729fea475..04dc4fae6fdb1066553b1c7e8216a654b2ac1576 100644 --- a/ext_tables.sql +++ b/ext_tables.sql @@ -14,7 +14,9 @@ CREATE TABLE tx_sgmail_domain_model_mail ( last_sending_time int(11) unsigned DEFAULT '0' NOT NULL, language varchar(255) DEFAULT '' NOT NULL, blacklisted tinyint(4) unsigned DEFAULT '0' NOT NULL, - attachments int(11) unsigned DEFAULT '0' NOT NULL + attachments int(11) unsigned DEFAULT '0' NOT NULL, + status varchar(255) DEFAULT 'pending' NOT NULL, + error_message text ); CREATE TABLE tx_sgmail_domain_model_template ( @@ -28,7 +30,6 @@ CREATE TABLE tx_sgmail_domain_model_template ( cc varchar(255) DEFAULT '' NOT NULL, bcc varchar(255) DEFAULT '' NOT NULL, reply_to varchar(255) DEFAULT '' NOT NULL, - language varchar(30) DEFAULT '' NOT NULL, content text NOT NULL );