diff --git a/Classes/Controller/MailController.php b/Classes/Controller/MailController.php index 1d099bd9f4f437f07c1b8e5b79aa61d0aef9a626..2e21e11d8bdc3f9e06062beb9afcf6b3c60e0c5c 100644 --- a/Classes/Controller/MailController.php +++ b/Classes/Controller/MailController.php @@ -77,6 +77,7 @@ class MailController extends ActionController { * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException * @throws \BadFunctionCallException * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException + * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException */ public function indexAction(array $parameters = []) { $pid = (int) GeneralUtility::_GP('id'); @@ -84,24 +85,22 @@ class MailController extends ActionController { if (!($this->session instanceof PhpSession)) { $this->session = $this->objectManager->get(PhpSession::class); $this->session->setSessionKey('sg_mail_controller_session'); + } else { + $this->session->setSessionKey('sg_mail_controller_session'); } - $registerArray = MailTemplateService::getRegisterArray(); - $extensionConfiguration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['sg_mail']); - if (isset($extensionConfiguration['excludeTemplates']) && $extensionConfiguration['excludeTemplates'] !== '') { - $excludedTemplates = GeneralUtility::trimExplode(',', $extensionConfiguration['excludeTemplates'], TRUE); - if ($excludedTemplates && count($excludedTemplates)) { - foreach ($excludedTemplates as $excludedTemplate) { - list($extensionKey, $templateName) = GeneralUtility::trimExplode('.', $excludedTemplate); - if ($extensionKey && $templateName && isset($registerArray[$extensionKey][$templateName])) { - unset($registerArray[$extensionKey][$templateName]); - } - } - } + if ($this->request->hasArgument('controller')) { + $this->session->setDataByKey('mode', $this->request->getArgument('controller')); + } + if ($this->session->getDataByKey('mode') !== BackendService::BACKEND_MODE_EDITOR_CONTROLLER) { + $this->redirect('index', $this->session->getDataByKey('mode')); } + + $registerArray = BackendService::getNonBlacklistedTemplates($pid); + $removeExtensionKeys = []; foreach ($registerArray as $extensionKey => $extensionTemplates) { - if (count($extensionTemplates) === 0) { + if (\count($extensionTemplates) === 0) { $removeExtensionKeys[] = $extensionKey; } } @@ -115,11 +114,29 @@ class MailController extends ActionController { $this->redirect('empty'); } + // if no template & extensionKey is selected look for them in the session if ($parameters['selectedTemplate'] === NULL || $parameters['selectedTemplate'] === '') { - $parameters['selectedExtension'] = key($registerArray); - $parameters['selectedTemplate'] = key($registerArray[$parameters['selectedExtension']]); + if ( + $this->session->getDataByKey('selectedTemplate') !== NULL && + $this->session->getDataByKey('selectedExtension') !== NULL && + !MailTemplateService::isTemplateBlacklisted( + $this->session->getDataByKey('selectedExtension'), $this->session->getDataByKey('selectedTemplate'), + $pid + ) + ) { + $parameters['selectedTemplate'] = $this->session->getDataByKey('selectedTemplate'); + $parameters['selectedExtension'] = $this->session->getDataByKey('selectedExtension'); + } else { + // if nothing is set in the session, use the first entries from the register array + $parameters['selectedExtension'] = key($registerArray); + $parameters['selectedTemplate'] = key($registerArray[$parameters['selectedExtension']]); + } } + // store selected template & extension key in the session + $this->session->setDataByKey('selectedTemplate', $parameters['selectedTemplate']); + $this->session->setDataByKey('selectedExtension', $parameters['selectedExtension']); + $languages = BackendService::getLanguages(); $templatesFromDb = BackendService::getSelectedTemplates( @@ -141,13 +158,10 @@ class MailController extends ActionController { $templateFromFile->setLanguage($key); $templates[$key] = $templateFromFile; + $templateFromFile->setSubject($subject); if (file_exists($defaultTemplateFile)) { $templateFromFile->setContent(file_get_contents($defaultTemplateFile)); - $templateFromFile->setSubject($subject); } else { - // set subject from register array - $templateFromFile->setSubject(LocalizationUtility::translate($subject, $this->extensionName)); - if (file_exists($fallbackTemplateFile)) { $templateFromFile->setContent(file_get_contents($fallbackTemplateFile)); } @@ -160,7 +174,7 @@ class MailController extends ActionController { // calculating optimal column width for the view $colspace = 4; - $templateCount = count($templates); + $templateCount = \count($templates); if ($templateCount % 2 === 0 && $templateCount <= 4) { $colspace = 6; } elseif ($templateCount === 1) { @@ -174,7 +188,7 @@ class MailController extends ActionController { $templateDescription = $registerArray[$parameters['selectedExtension']][$parameters['selectedTemplate']]['description']; - if (is_array($templateDescription)) { + if (\is_array($templateDescription)) { if ($languages[0]['isocode']) { $templateDescription = $templateDescription[$languages[0]['isocode']]; } @@ -245,7 +259,7 @@ class MailController extends ActionController { public function sendTestMailAction(array $parameters = []) { foreach ((array) $parameters['templates'] as $parameter) { $ccAddresses = GeneralUtility::trimExplode(',', $parameter['cc']); - if (count($ccAddresses) > 0) { + if (\count($ccAddresses) > 0) { foreach ($ccAddresses as $ccAddress) { if (!filter_var($ccAddress, FILTER_VALIDATE_EMAIL) && trim($ccAddress) !== '') { @@ -259,7 +273,7 @@ class MailController extends ActionController { } $bccAddresses = GeneralUtility::trimExplode(',', $parameter['bcc']); - if (count($bccAddresses) > 0) { + if (\count($bccAddresses) > 0) { foreach ($bccAddresses as $bccAddress) { if (!filter_var($bccAddress, FILTER_VALIDATE_EMAIL) && trim($bccAddress) !== '') { $message = LocalizationUtility::translate('backend.error_bcc', 'sg_mail'); @@ -282,35 +296,36 @@ class MailController extends ActionController { $message = LocalizationUtility::translate('backend.success', 'sg_mail'); $this->addFlashMessage($message, '', FlashMessage::OK); - if (!filter_var($parameters['emailAddress'], FILTER_VALIDATE_EMAIL)) { - $arguments = $this->request->getArguments(); - $this->redirect('index', NULL, NULL, $arguments); - } - - $objectManager = GeneralUtility::makeInstance(ObjectManager::class); - /** @var \SGalinski\SgMail\Service\MailTemplateService $mailTemplateService */ - $mailTemplateService = $objectManager->get( - MailTemplateService::class, $parameters['selectedTemplate'], $parameters['selectedExtension'] - ); - $mailIsSend = FALSE; + if (!$this->request->hasArgument('saveOnly')) { + if (!filter_var($parameters['emailAddress'], FILTER_VALIDATE_EMAIL)) { + $arguments = $this->request->getArguments(); + $this->redirect('index', NULL, NULL, $arguments); + } - foreach ((array) $parameters['templates'] as $key => $template) { - $mailTemplateService->setLanguage($key); - $mailTemplateService->setToAddresses($parameters['emailAddress']); - $mailTemplateService->setFromAddress($template['fromMail']); - $mailTemplateService->setTemplateName($parameters['selectedTemplate']); - $mailTemplateService->setExtensionKey($parameters['selectedExtension']); - $mailIsSend = $mailTemplateService->sendEmail(TRUE); - } + $objectManager = GeneralUtility::makeInstance(ObjectManager::class); + /** @var \SGalinski\SgMail\Service\MailTemplateService $mailTemplateService */ + $mailTemplateService = $objectManager->get( + MailTemplateService::class, $parameters['selectedTemplate'], $parameters['selectedExtension'] + ); + $mailIsSend = FALSE; + + foreach ((array) $parameters['templates'] as $key => $template) { + $mailTemplateService->setLanguage($key); + $mailTemplateService->setToAddresses($parameters['emailAddress']); + $mailTemplateService->setFromAddress($template['fromMail']); + $mailTemplateService->setTemplateName($parameters['selectedTemplate']); + $mailTemplateService->setExtensionKey($parameters['selectedExtension']); + $mailIsSend = $mailTemplateService->sendEmail(TRUE); + } - if ($mailIsSend) { - $message = LocalizationUtility::translate('backend.success_mail', 'sg_mail'); - $this->addFlashMessage($message, '', FlashMessage::OK); - } else { - $message = LocalizationUtility::translate('backend.failure_mail', 'sg_mail'); - $this->addFlashMessage($message, '', FlashMessage::ERROR); + if ($mailIsSend) { + $message = LocalizationUtility::translate('backend.success_mail', 'sg_mail'); + $this->addFlashMessage($message, '', FlashMessage::OK); + } else { + $message = LocalizationUtility::translate('backend.failure_mail', 'sg_mail'); + $this->addFlashMessage($message, '', FlashMessage::ERROR); + } } - $arguments = $this->request->getArguments(); $this->redirect('index', NULL, NULL, $arguments); } diff --git a/Classes/Controller/QueueController.php b/Classes/Controller/QueueController.php index 8a9f8142f67630ccf1841d023de05acb45ca4a50..f3c0ce25bff94a694bcbfb8db4bfdc66bc4f1992 100644 --- a/Classes/Controller/QueueController.php +++ b/Classes/Controller/QueueController.php @@ -28,6 +28,7 @@ namespace SGalinski\SgMail\Controller; use SGalinski\SgMail\Service\BackendService; use SGalinski\SgMail\Service\MailTemplateService; +use SGalinski\SgMail\Session\PhpSession; use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Messaging\FlashMessage; @@ -67,8 +68,22 @@ class QueueController extends ActionController { * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException * @throws \BadFunctionCallException * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException + * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException */ public function indexAction($selectedTemplate = NULL, $selectedExtension = NULL, array $filters = []) { + $pageUid = (int) GeneralUtility::_GP('id'); + + if (!($this->session instanceof PhpSession)) { + $this->session = $this->objectManager->get(PhpSession::class); + $this->session->setSessionKey('sg_mail_controller_session'); + } else { + $this->session->setSessionKey('sg_mail_controller_session'); + } + + if ($this->request->hasArgument('controller')) { + $this->session->setDataByKey('mode', $this->request->getArgument('controller')); + } + $filterTemplate = $_POST['filterTemplate']; $filters['filterExtension'] = $filterTemplate; $filters['filterTemplate'] = $filterTemplate; @@ -82,13 +97,12 @@ class QueueController extends ActionController { $this->view->assign('selectedTemplateFilter', $filters['filterTemplate']); $this->view->assign('selectedExtensionFilter', $filters['filterExtension']); - $registerArray = MailTemplateService::getRegisterArray(); + $registerArray = BackendService::getNonBlacklistedTemplates($pageUid); if ($selectedTemplate === NULL || $selectedTemplate === '') { $selectedExtension = key($registerArray); $selectedTemplate = key($registerArray[$selectedExtension]); } - $pageUid = (int) GeneralUtility::_GP('id'); $queue = $this->mailRepository->findAllEntries($pageUid, 0, $filters); // create doc header component @@ -98,7 +112,7 @@ class QueueController extends ActionController { $this->view->assign('selectedExtensionKey', $selectedExtension); $this->view->assign('templates', $registerArray); - $this->view->assign('templatesFilter', BackendService::getTemplatesForFilter()); + $this->view->assign('templatesFilter', BackendService::getTemplatesForFilter($pageUid)); $this->view->assign('languages', BackendService::getLanguagesForFilter()); $this->view->assign('mode', 'queue'); diff --git a/Classes/Domain/Model/Mail.php b/Classes/Domain/Model/Mail.php index b3e346c9b12e1b6195c6218e3eea06acdb16bcac..82a20b16408fab96ecad4b5b2e7edb4a7a078637 100644 --- a/Classes/Domain/Model/Mail.php +++ b/Classes/Domain/Model/Mail.php @@ -109,6 +109,11 @@ class Mail extends AbstractEntity { */ protected $lastSendingTime = 0; + /** + * @var boolean + */ + protected $blacklisted = FALSE; + /** * @return string */ @@ -309,4 +314,18 @@ class Mail extends AbstractEntity { public function setLanguage($language) { $this->language = $language; } + + /** + * @return bool + */ + public function getBlacklisted() { + return $this->blacklisted; + } + + /** + * @param bool $blacklisted + */ + public function setBlacklisted($blacklisted) { + $this->blacklisted = (bool) $blacklisted; + } } diff --git a/Classes/Domain/Repository/MailRepository.php b/Classes/Domain/Repository/MailRepository.php index 15f88970e9d79471aae0099177c944367c8ef96a..42e966bc2b59970ffda077505b271fb074786abc 100644 --- a/Classes/Domain/Repository/MailRepository.php +++ b/Classes/Domain/Repository/MailRepository.php @@ -51,7 +51,10 @@ class MailRepository extends AbstractRepository { $query->setOrderings(['priority' => Query::ORDER_DESCENDING]); - return $query->matching($query->equals('sending_time', 0))->execute(); + // ignore blacklisted templates + $constraintsAnd[] = $query->equals('blacklisted', FALSE); + $constraintsAnd[] = $query->equals('sending_time', 0); + return $query->matching($query->logicalAnd($constraintsAnd))->execute(); } /** @@ -148,6 +151,10 @@ class MailRepository extends AbstractRepository { $constraintsAnd[] = $query->lessThanOrEqual('last_sending_time', $toTime); } + if ((int) $filters['filterBlacklist'] !== 1) { + $constraintsAnd[] = $query->equals('blacklisted', 0); + } + if ($filters['filterSent']) { switch ($filters['filterSent']) { case self::SENT: diff --git a/Classes/Domain/Repository/TemplateRepository.php b/Classes/Domain/Repository/TemplateRepository.php index f93b06252102416dc23e6e412936dff434215d13..4c2b6d414541af12feff0d67b94c0e9d8b7a0249 100644 --- a/Classes/Domain/Repository/TemplateRepository.php +++ b/Classes/Domain/Repository/TemplateRepository.php @@ -40,7 +40,7 @@ class TemplateRepository extends AbstractRepository { * @param string $language * @param int $pid * - * @return Template + * @return Object */ public function findOneByTemplate($extensionKey, $templateName, $language, $pid = 0) { $query = $this->createQuery(); @@ -57,9 +57,7 @@ class TemplateRepository extends AbstractRepository { $query->logicalAnd($constraintsAnd) ); - /** @var Template $template */ - $template = $query->setLimit(1)->execute()->getFirst(); - return $template; + return $query->setLimit(1)->execute()->getFirst(); } /** diff --git a/Classes/Service/BackendService.php b/Classes/Service/BackendService.php index b505e39f61233a2336734bd1be4eb9fb396b55bf..fc7eb062b61ea12f735e987d449f2b503aed8232 100644 --- a/Classes/Service/BackendService.php +++ b/Classes/Service/BackendService.php @@ -39,6 +39,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository; use TYPO3\CMS\Extbase\Mvc\Request; use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; @@ -57,6 +58,12 @@ class BackendService { const FROM_NAME_FILTER_OPTION = 6; const REPLY_TO_NAME_FILTER_OPTION = 7; + // constants for deetermining the backend mode + const BACKEND_MODE_EDITOR = 'editor'; + const BACKEND_MODE_EDITOR_CONTROLLER = 'Mail'; + const BACKEND_MODE_QUEUE = 'queue'; + const BACKEND_MODE_QUEUE_CONTROLLER = 'Queue'; + /** * Get all pages the be user has access to * @@ -76,10 +83,10 @@ class BackendService { foreach ($rows as $row) { $pageInfo = BackendUtility::readPageAccess($row['uid'], $GLOBALS['BE_USER']->getPagePermsClause(1)); if ($pageInfo) { - $rootline = BackendUtility::BEgetRootLine($pageInfo['uid'], '', true); + $rootline = BackendUtility::BEgetRootLine($pageInfo['uid'], '', TRUE); ksort($rootline); $path = '/root'; - foreach($rootline as $page) { + foreach ($rootline as $page) { $path .= '/p' . dechex($page['uid']); } $pageInfo['path'] = $path; @@ -245,10 +252,15 @@ class BackendService { /** * Get the template keys in an array suitable for filtering * + * @param int $pageUid * @return array + * @throws \InvalidArgumentException + * @throws \BadFunctionCallException + * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException */ - public static function getTemplatesForFilter() { - $registerArray = MailTemplateService::getRegisterArray(); + public static function getTemplatesForFilter($pageUid): array { + $pageUid = (int) $pageUid; + $registerArray = self::getNonBlacklistedTemplates($pageUid); $templates = []; foreach ($registerArray as $extensions) { foreach ($extensions as $template => $key) { @@ -308,6 +320,10 @@ class BackendService { $templateRepository->add($template); } + $objectManager = GeneralUtility::makeInstance(ObjectManager::class); + $persistenceManager = $objectManager->get(PersistenceManager::class); + $persistenceManager->persistAll(); + return $template; } @@ -382,4 +398,52 @@ class BackendService { return trim(preg_replace('/\s\s+/', ' ', strip_tags($exportString))); } + + /** + * Filter the register array to have only whitelisted templates for this domain + * + * @param int $siteRootId + * @throws \InvalidArgumentException + * @throws \BadFunctionCallException + * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException + * @return array + */ + public static function getNonBlacklistedTemplates($siteRootId): array { + $siteRootId = (int) $siteRootId; + $registerArray = MailTemplateService::getRegisterArray(); + $extensionConfiguration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['sg_mail'], []); + + if (isset($extensionConfiguration['excludeTemplates']) && $extensionConfiguration['excludeTemplates'] !== '') { + $excludedTemplatesWithSiteId = GeneralUtility::trimExplode( + ';', $extensionConfiguration['excludeTemplates'], TRUE + ); + + foreach ($excludedTemplatesWithSiteId as $currentSite) { + $currentSiteBlacklist = GeneralUtility::trimExplode(',', $currentSite, TRUE); + if ((int) $currentSiteBlacklist[0] === $siteRootId) { + foreach ($currentSiteBlacklist as $excludedTemplate) { + list($extensionKey, $templateName) = GeneralUtility::trimExplode('.', $excludedTemplate); + if ($extensionKey && $templateName && isset($registerArray[$extensionKey][$templateName])) { + unset($registerArray[$extensionKey][$templateName]); + } + } + } + } + } + + // filter out excluded templates from all domains + if (isset($extensionConfiguration['excludeTemplatesAllDomains']) && $extensionConfiguration['excludeTemplatesAllDomains'] !== '') { + $excludedTemplates = GeneralUtility::trimExplode( + ',', $extensionConfiguration['excludeTemplatesAllDomains'], TRUE + ); + foreach ($excludedTemplates as $excludedTemplate) { + list($extensionKey, $templateName) = GeneralUtility::trimExplode('.', $excludedTemplate); + if ($extensionKey && $templateName && isset($registerArray[$extensionKey][$templateName])) { + unset($registerArray[$extensionKey][$templateName]); + } + } + } + + return $registerArray; + } } diff --git a/Classes/Service/FormhandlerFinisherService.php b/Classes/Service/FormhandlerFinisherService.php index 319fc75b8fd66309789214880483a024e822a506..c1cfdd48ebc530352ab3f6b4cb54c419caa13232 100644 --- a/Classes/Service/FormhandlerFinisherService.php +++ b/Classes/Service/FormhandlerFinisherService.php @@ -69,8 +69,10 @@ class FormhandlerFinisherService extends AbstractFinisher { * Needed to hook into Formhandler * * @return array $gp + * @throws \BadFunctionCallException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException * @throws \InvalidArgumentException + * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException */ public function process() { if (!isset($this->settings['to_address'])) { diff --git a/Classes/Service/MailTemplateService.php b/Classes/Service/MailTemplateService.php index df4be76b82762aceb7a5d906ff1396ce0a699d18..33eec50c2a52a7bfc2ae81c3949d507a6893d76a 100644 --- a/Classes/Service/MailTemplateService.php +++ b/Classes/Service/MailTemplateService.php @@ -245,7 +245,7 @@ class MailTemplateService { * @throws \BadFunctionCallException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException */ - public function sendEmail($isPreview = FALSE) { + public function sendEmail($isPreview = FALSE): bool { if (TYPO3_MODE === 'FE') { /** @var TypoScriptFrontendController $tsfe */ $tsfe = $GLOBALS['TSFE']; @@ -331,11 +331,6 @@ class MailTemplateService { if (is_array($subject)) { $subject = self::getRegisterArray( )[$this->extensionKey][$this->templateName]['subject'][$this->language]; - } else { - $subject = LocalizationUtility::translate( - self::getRegisterArray()[$this->extensionKey][$this->templateName]['subject'], - $this->extensionKey - ); } } $this->mailMessage->setSubject($subject); @@ -346,7 +341,10 @@ class MailTemplateService { // insert <br /> tags, but replace every instance of three or more successive breaks with just two. $emailBody = nl2br($emailBody); $emailBody = preg_replace('/(<br[\s]?[\/]?>[\s]*){3,}/', '<br /><br />', $emailBody); - if ($this->ignoreMailQueue) { + $isTemplateBlacklisted = self::isTemplateBlacklisted( + $this->extensionKey, $this->templateName, $siteRootId + ); + if ($this->ignoreMailQueue && $isTemplateBlacklisted) { $this->mailMessage->setBody($emailBody, 'text/html'); $this->mailMessage->send(); @@ -384,7 +382,10 @@ class MailTemplateService { * @param int $lastSendingTime * @param string $language * @param int $pid + * @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, @@ -395,6 +396,7 @@ class MailTemplateService { $mail->setExtensionKey($extensionKey); $mail->setTemplateName($templateName); $mail->setLanguage($language); + $mail->setBlacklisted(self::isTemplateBlacklisted($extensionKey, $templateName, $pid)); $mail->setFromAddress($this->fromAddress); $mail->setFromName($this->fromName); @@ -426,7 +428,7 @@ class MailTemplateService { /** @var Mail $mailToSend */ $mailToSend = $mailRepository->findOneByUid($uid); - if ($mailToSend) { + if ($mailToSend && !$mailToSend->getBlacklisted()) { $this->mailMessage->setBody($mailToSend->getMailBody(), 'text/html'); $this->mailMessage->setTo(trim($mailToSend->getToAddress())); $this->mailMessage->setFrom($mailToSend->getFromAddress(), $mailToSend->getFromName()); @@ -456,7 +458,7 @@ class MailTemplateService { * @return MailTemplateService */ public function setToAddresses($toAddresses) { - $toAddresses = preg_replace('~\x{00a0}~siu',' ', $toAddresses); + $toAddresses = preg_replace('~\x{00a0}~siu', ' ', $toAddresses); $this->toAddresses = trim($toAddresses); $this->mailMessage->setTo(trim($toAddresses)); return $this; @@ -692,7 +694,7 @@ class MailTemplateService { * @throws \BadFunctionCallException * @return array */ - public static function registerExtensions() { + public static function registerExtensions(): array { // clear registerArray $registerArray = []; @@ -740,4 +742,25 @@ class MailTemplateService { return $registerArray; } + + /** + * Checks if a template is blacklisted for a given siterootId + * + * @param string $extensionKey + * @param string $templateName + * @param int $siteRootId + * @return boolean + * @throws \InvalidArgumentException + * @throws \BadFunctionCallException + * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException + */ + public static function isTemplateBlacklisted($extensionKey, $templateName, $siteRootId): bool { + $nonBlacklistedTemplates = BackendService::getNonBlacklistedTemplates($siteRootId); + + if ($nonBlacklistedTemplates[$extensionKey]) { + return $nonBlacklistedTemplates[$extensionKey][$templateName] ? FALSE : TRUE; + } + + return TRUE; + } } diff --git a/Classes/UserFunc/ExtensionConfiguration.php b/Classes/UserFunc/ExtensionConfiguration.php new file mode 100644 index 0000000000000000000000000000000000000000..3e01d938b00b6e82398dab43472c00c9a41eca47 --- /dev/null +++ b/Classes/UserFunc/ExtensionConfiguration.php @@ -0,0 +1,57 @@ +<?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! + ***************************************************************/ + +/** + * Class ExtensionConfiguration + * + * @package SGalinski\SgMail\UserFunc + */ +class ExtensionConfiguration { + + /** + * Displays all registered sg mail templates for easy use with the blacklist feature + * + * @return string + */ + public function displayTemplates(): string { + $result = ''; + + try { + $registerArray = \SGalinski\SgMail\Service\MailTemplateService::getRegisterArray(); + foreach ($registerArray as $extensionKey => $extension) { + /** @var array $extension */ + foreach ($extension as $templateKey => $template) { + $result .= $extensionKey . '.' . $templateKey . '<br>'; + } + } + + } catch (Exception $exception) { + return 'TODO EXCEPTION MSG'; + } + + return $result; + } +} diff --git a/Configuration/TCA/tx_sgmail_domain_model_mail.php b/Configuration/TCA/tx_sgmail_domain_model_mail.php index 0c73381011312149e03b027a3c3836b9d687a330..2d66dd6789955bc1e7e823621fa10f2164647d09 100644 --- a/Configuration/TCA/tx_sgmail_domain_model_mail.php +++ b/Configuration/TCA/tx_sgmail_domain_model_mail.php @@ -32,7 +32,7 @@ return [ 'tstamp' => 'tstamp', 'crdate' => 'crdate', 'cruser_id' => 'cruser_id', - 'searchFields' => 'mail_subject, mail_body, to_address, from_address, from_name, bcc_addresses, cc_addresses, extension_key, template_name, sending_time, last_sending_time, language', + '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, 'delete' => 'deleted', 'enablecolumns' => [ @@ -42,11 +42,11 @@ return [ 'iconfile' => 'EXT:sg_mail/Resources/Public/Icons/ModuleIconTCA.svg' ], 'interface' => [ - 'showRecordFieldList' => 'hidden, mail_subject, mail_body, to_address, from_address, priority, from_name, bcc_addresses, cc_addresses, extension_key, template_name, sending_time, last_sending_time, language', + 'showRecordFieldList' => 'hidden, blacklisted, mail_subject, mail_body, to_address, from_address, priority, from_name, bcc_addresses, cc_addresses, extension_key, template_name, sending_time, last_sending_time, language', ], 'types' => [ '1' => [ - 'showitem' => 'hidden;;1, 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' + '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' ], ], 'columns' => [ @@ -57,6 +57,13 @@ return [ 'type' => 'check', ], ], + 'blacklisted' => [ + 'exclude' => TRUE, + 'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_mail.blacklisted', + 'config' => [ + 'type' => 'check', + ], + ], 'mail_subject' => [ 'exclude' => TRUE, 'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_mail.mail_subject', diff --git a/README.md b/README.md index 8aad1be20a4a8e62860556d12f519f25b46552b6..8894b84dad1bc3418cd6d5bf1572fbfb381d9b51 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,38 @@ With the **Mail Queue** mode, you can see the current content of your mailing qu Additionally you can now filter the mail queue or export it to a csv file. +## Blacklisting templates +It is possible to exlude certain templates for all or specific domains. Excluded templates are not shown in the backend module +and their mails are never send. +Mails from these templates are still logged and you can search for them in the backend module. + +### Blacklisting templates for all domains +In the extension configuration setting **general.excludeTemplatesAllDomains**, you can specify which templates should be excluded for all domains with a comma seperated list. + +Example: + + sg_comments.approved, sg_comments.declined + +The templates "approved" and "declined" of the extension sg_comments are blacklisted for every domain. + +### Blacklisting templates for certain domains +In the extension configuration setting **general.excludeTemplates**, ou can specify which templates should be excluded for which domains with a Semicolon separated list of comma separated list. + +The comma seperated lists contain the page id and the templates to be excluded. + +Example: + + 1, sg_comments.approved, sg_example.welcome;10, sg_comments.declined + +The template "approved" of the extension sg_comments and the template "welcome" of the extension sg_example are blacklisted for the domain with the page id 1. + +The template "declied" of the extension sg_comments is blacklisted for the domain with the page id 10. + +If the page ids are missing or not correspond to a site root, the configuration has simply no effect. + +### Searching for emails from blacklisted templates +In the backend module mode "Queue" you can filter for "Blacklisted" mails. Note: you shouldn't select a template filter to see the blacklisted mails. + ## Known Facts ### Countries aren't respected yet. Currently just languages are used. diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index 9cf5de2650c702ec97a5d31f893fd715b81626b3..70924b73ad49c0275cf3c1765c3dde9e991d02a9 100644 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -17,6 +17,10 @@ <source>BCC (Blind Carbon Copy Receiver, comma separated)</source> <target>BCC (Blindempfänger, komma-separiert)</target> </trans-unit> + <trans-unit id="backend.blacklisted" approved="yes"> + <source>Show mails from blacklisted templates</source> + <target>Mails basierend auf gesperrten Templates anzeigen</target> + </trans-unit> <trans-unit id="backend.button_download_csv" approved="yes"> <source>Export CSV</source> <target>CSV exportieren</target> @@ -183,7 +187,7 @@ </trans-unit> <trans-unit id="backend.marker.type.string" approved="yes"> <source>String</source> - <target>String</target> + <target>Zeichenkette</target> </trans-unit> <trans-unit id="backend.no_extension" approved="yes"> <source>No template was registered.</source> @@ -213,6 +217,10 @@ <source>Priority</source> <target>Priorität</target> </trans-unit> + <trans-unit id="backend.queue.blacklisted" approved="yes"> + <source>Blacklisted</source> + <target>Auf der schwarzen Liste</target> + </trans-unit> <trans-unit id="backend.replyTo" approved="yes"> <source>Reply to</source> <target>Antwort-Adresse</target> @@ -221,6 +229,10 @@ <source>Save</source> <target>Speichern</target> </trans-unit> + <trans-unit id="backend.save_template" approved="yes"> + <source>Save</source> + <target>Speichern</target> + </trans-unit> <trans-unit id="backend.select_language" approved="yes"> <source>Language (reloads the page):</source> <target>Sprache (lädt die Seite neu):</target> @@ -285,10 +297,6 @@ <source>The template was resetted successfully.</source> <target>Das Template erfolgreich zurückgesetzt.</target> </trans-unit> - <trans-unit id="backend.to_form" approved="yes"> - <source>To (If set, this overwrites the recipient everytime!) </source> - <target>Empfänger (Falls angegeben, wird der Empfänger immer überschrieben!)</target> - </trans-unit> <trans-unit id="backend.to" approved="yes"> <source>To</source> <target>Empfänger</target> @@ -297,6 +305,10 @@ <source>Receiver</source> <target>Empfänger</target> </trans-unit> + <trans-unit id="backend.to_form" approved="yes"> + <source>To (If set, this overwrites the recipient everytime!) </source> + <target>Empfänger (Falls angegeben, wird der Empfänger immer überschrieben!)</target> + </trans-unit> <trans-unit id="backend.type" approved="yes"> <source>Type</source> <target>Typ</target> @@ -309,9 +321,47 @@ <source>Example</source> <target>Beispiel</target> </trans-unit> - <trans-unit id="configuration.excludeTemplates"> - <source>Exclude Mail Templates:Comma-separated list of {extension_key}.{template_name}</source> - <target>Mail-Templates ausschließen:Kommagetrennte Liste von {extension_key}.{template_name}</target> + <trans-unit id="configuration.excludeTemplates" approved="yes" xml:space="preserve"> + <source>Exclude Mail Templates for certain Domains + +Example: + +1, sg_mail.exampleA, sg_mail.exampleB;10, sg_mail.exampleB + +In this example the templates sg_mail.exampleA, sg_mail.exampleB are excluded for the page with id = 1 and the template sg_mail.exampleB is excluded for the page with id = 2. + +If the given page ids do not exist or are not site roots, the configuration is ignored.</source> + <target>Ausschließen von Mail Templates für bestimmte Domains + +Beispiel: + +1, sg_mail.exampleA, sg_mail.exampleB;10, sg_mail.exampleB + +Hier sind die Templates sg_mail.exampleA, sg_mail.exampleB ausgeschlossen für die Seite mit der id = 1 und das Template sg_mail.exampleB ist ausgeschlossen für die Seite mit der page id = 2. + +Existiert die angegebene page id nicht oder sollte die Seite keine Wurzelseite sein, dann wird dieser Teil der Konfiguration nicht berücksichtigt.</target> + </trans-unit> + <trans-unit id="configuration.excludeTemplatesAllDomains" approved="yes" xml:space="preserve"> + <source>Exclude Mail Templates for all domains:Comma-separated list of {extension_key}.{template_name} + +Example: + +sg_comments.declined, sg_comments.approved + +The templates declined and approved of the sg_comments extension are blacklisted for all domains. + +</source> + <target>Mail-Templates für alle Domains ausschließen:Kommagetrennte Liste von {extension_key}.{template_name} + +Example: + +sg_comments.declined, sg_comments.approved + +Die Templates declined und approved der Extension sg_comments sind für alle Domains auf der schwarzen Liste</target> + </trans-unit> + <trans-unit id="configuration.templateList" approved="yes"> + <source>List of templates</source> + <target>Liste aller templates</target> </trans-unit> <trans-unit id="mlang_labels_tabdescr" approved="yes"> <source>Mail Templates</source> diff --git a/Resources/Private/Language/de.locallang_db.xlf b/Resources/Private/Language/de.locallang_db.xlf index 373333d319a51a3ca12385cebdea3d4e5163e6be..b3079145760a429cef98705e40b8396d6b313fcd 100644 --- a/Resources/Private/Language/de.locallang_db.xlf +++ b/Resources/Private/Language/de.locallang_db.xlf @@ -17,6 +17,10 @@ <source>BCC Addresses</source> <target>BCC-Adressen</target> </trans-unit> + <trans-unit id="tx_sgmail_domain_model_mail.blacklisted" approved="yes"> + <source>blacklisted</source> + <target>auf der schwarzen liste</target> + </trans-unit> <trans-unit id="tx_sgmail_domain_model_mail.cc_addresses" approved="yes"> <source>CC Addresses</source> <target>CC-Adressen</target> diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index 61ea244b2b218d5de3e9b0f2ec48f73dca470a7b..8a556f9e24656625496d7522bcc2dee7bb70fded 100644 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -15,6 +15,9 @@ <trans-unit id="backend.bcc"> <source>BCC (Blind Carbon Copy Receiver, comma separated)</source> </trans-unit> + <trans-unit id="backend.blacklisted"> + <source>Show mails from blacklisted templates</source> + </trans-unit> <trans-unit id="backend.button_download_csv"> <source>Export CSV</source> </trans-unit> @@ -162,12 +165,18 @@ <trans-unit id="backend.priority"> <source>Priority</source> </trans-unit> + <trans-unit id="backend.queue.blacklisted"> + <source>Blacklisted</source> + </trans-unit> <trans-unit id="backend.replyTo"> <source>Reply to</source> </trans-unit> <trans-unit id="backend.save"> <source>Save</source> </trans-unit> + <trans-unit id="backend.save_template"> + <source>Save</source> + </trans-unit> <trans-unit id="backend.select_language"> <source>Language (reloads the page):</source> </trans-unit> @@ -216,15 +225,15 @@ <trans-unit id="backend.template_reset"> <source>The template was resetted successfully.</source> </trans-unit> - <trans-unit id="backend.to_form"> - <source>To (If set, this overwrites the recipient everytime!) </source> - </trans-unit> <trans-unit id="backend.to"> <source>To</source> </trans-unit> <trans-unit id="backend.toAddress"> <source>Receiver</source> </trans-unit> + <trans-unit id="backend.to_form"> + <source>To (If set, this overwrites the recipient everytime!) </source> + </trans-unit> <trans-unit id="backend.type"> <source>Type</source> </trans-unit> @@ -234,8 +243,30 @@ <trans-unit id="backend.value"> <source>Example</source> </trans-unit> - <trans-unit id="configuration.excludeTemplates"> - <source>Exclude Mail Templates:Comma-separated list of {extension_key}.{template_name}</source> + <trans-unit id="configuration.excludeTemplates" xml:space="preserve"> + <source>Exclude Mail Templates for certain Domains + +Example: + +1, sg_mail.exampleA, sg_mail.exampleB;10, sg_mail.exampleB + +In this example the templates sg_mail.exampleA, sg_mail.exampleB are excluded for the page with id = 1 and the template sg_mail.exampleB is excluded for the page with id = 2. + +If the given page ids do not exist or are not site roots, the configuration is ignored.</source> + </trans-unit> + <trans-unit id="configuration.excludeTemplatesAllDomains" xml:space="preserve"> + <source>Exclude Mail Templates for all domains:Comma-separated list of {extension_key}.{template_name} + +Example: + +sg_comments.declined, sg_comments.approved + +The templates declined and approved of the sg_comments extension are blacklisted for all domains. + +</source> + </trans-unit> + <trans-unit id="configuration.templateList"> + <source>List of templates</source> </trans-unit> <trans-unit id="mlang_labels_tabdescr"> <source>Mail Templates</source> diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf index 7412be39c6f0b975ad35fcbee83f922ecae5c883..515d0f6db6b95ecfc1f37ee0b7d12847460b0424 100644 --- a/Resources/Private/Language/locallang_db.xlf +++ b/Resources/Private/Language/locallang_db.xlf @@ -15,6 +15,9 @@ <trans-unit id="tx_sgmail_domain_model_mail.bcc_addresses"> <source>BCC Addresses</source> </trans-unit> + <trans-unit id="tx_sgmail_domain_model_mail.blacklisted"> + <source>blacklisted</source> + </trans-unit> <trans-unit id="tx_sgmail_domain_model_mail.cc_addresses"> <source>CC Addresses</source> </trans-unit> diff --git a/Resources/Private/Layouts/Default.html b/Resources/Private/Layouts/Default.html index 31f7f7e13502c23542d08077739dbdab31cfef35..124ce7a70c43bbe445cae0937409f887912c2d82 100644 --- a/Resources/Private/Layouts/Default.html +++ b/Resources/Private/Layouts/Default.html @@ -58,25 +58,47 @@ <f:else> <div class="module-docheader-bar module-docheader-bar-buttons t3js-module-docheader-bar t3js-module-docheader-bar-buttons"> <div class="module-docheader-bar-column-left"> - <div class="btn-toolbar" role="toolbar" aria-label=""> - <f:if condition="{templates}"> - <f:be.menus.actionMenu> - <f:for each="{templates}" as="template" key="extensionKey"> - <f:if condition="{mode} == 'queue'"> + <f:if condition="{templates}"> + <f:be.menus.actionMenu> + <f:for each="{templates}" as="template" key="extensionKey"> + <f:if condition="{mode} == 'queue'"> + <sgm:be.menus.actionMenuOptionGroup label="{extensionKey}"> + <f:for each="{template}" as="currentTemplate" key="templateKey"> + <sgm:extendedIf condition="{selectedTemplateKey} == {templateKey}" + and="{selectedExtensionKey} == {extensionKey}"> + <f:then> + <sgm:be.menus.actionMenuItem label="{currentTemplate.templateName}" + controller="Queue" + action="index" + arguments="{parameters: {selectedTemplate: templateKey, selectedExtension: extensionKey}}" + additionalAttributes="{selected: 'selected'}" /> + </f:then> + <f:else> + <sgm:be.menus.actionMenuItem label="{currentTemplate.templateName}" + controller="Queue" + action="index" + arguments="{parameters: {selectedTemplate: templateKey, selectedExtension: extensionKey}}" /> + </f:else> + </sgm:extendedIf> + </f:for> + </sgm:be.menus.actionMenuOptionGroup> + </f:if> + <f:else> + <f:if condition="{mode} == 'editor'"> <sgm:be.menus.actionMenuOptionGroup label="{extensionKey}"> <f:for each="{template}" as="currentTemplate" key="templateKey"> <sgm:extendedIf condition="{selectedTemplateKey} == {templateKey}" and="{selectedExtensionKey} == {extensionKey}"> <f:then> <sgm:be.menus.actionMenuItem label="{currentTemplate.templateName}" - controller="Queue" + controller="Mail" action="index" arguments="{parameters: {selectedTemplate: templateKey, selectedExtension: extensionKey}}" additionalAttributes="{selected: 'selected'}" /> </f:then> <f:else> <sgm:be.menus.actionMenuItem label="{currentTemplate.templateName}" - controller="Queue" + controller="Mail" action="index" arguments="{parameters: {selectedTemplate: templateKey, selectedExtension: extensionKey}}" /> </f:else> @@ -84,34 +106,10 @@ </f:for> </sgm:be.menus.actionMenuOptionGroup> </f:if> - <f:else> - <f:if condition="{mode} == 'editor'"> - <sgm:be.menus.actionMenuOptionGroup label="{extensionKey}"> - <f:for each="{template}" as="currentTemplate" key="templateKey"> - <sgm:extendedIf condition="{selectedTemplateKey} == {templateKey}" - and="{selectedExtensionKey} == {extensionKey}"> - <f:then> - <sgm:be.menus.actionMenuItem label="{currentTemplate.templateName}" - controller="Mail" - action="index" - arguments="{parameters: {selectedTemplate: templateKey, selectedExtension: extensionKey}}" - additionalAttributes="{selected: 'selected'}" /> - </f:then> - <f:else> - <sgm:be.menus.actionMenuItem label="{currentTemplate.templateName}" - controller="Mail" - action="index" - arguments="{parameters: {selectedTemplate: templateKey, selectedExtension: extensionKey}}" /> - </f:else> - </sgm:extendedIf> - </f:for> - </sgm:be.menus.actionMenuOptionGroup> - </f:if> - </f:else> - </f:for> - </f:be.menus.actionMenu> - </f:if> - </div> + </f:else> + </f:for> + </f:be.menus.actionMenu> + </f:if> </div> <div class="module-docheader-bar-column-right"> <f:render partial="ButtonBar" arguments="{buttons:docHeader.buttons.right}" /> diff --git a/Resources/Private/Partials/Queue/Filter.html b/Resources/Private/Partials/Queue/Filter.html index eb7a405a97ab4ebbba61bf99f8c55831bd9e801e..0ff9a44e929a54964517f41df82eb3ef769005f3 100644 --- a/Resources/Private/Partials/Queue/Filter.html +++ b/Resources/Private/Partials/Queue/Filter.html @@ -112,18 +112,22 @@ <f:translate key="backend.not_sent" /> </label> </div> - <div class="form-group row"> - <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: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: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:translate key="backend.button_reset_filter" /> - </f:form.button> - </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: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: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: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:translate key="backend.button_reset_filter" /> + </f:form.button> </div> </div> </div> diff --git a/Resources/Private/Templates/Mail/Index.html b/Resources/Private/Templates/Mail/Index.html index 2404e8e704754aad37363e629b90455411087ea4..6057c40715fa1312f6e0b9f340a26260b7308825 100644 --- a/Resources/Private/Templates/Mail/Index.html +++ b/Resources/Private/Templates/Mail/Index.html @@ -6,15 +6,14 @@ </f:section> <f:section name="content"> <f:flashMessages /> - <br /> <f:if condition="{selectedTemplate}"> <f:then> <div class="row form-group col-md-12"> - <div class=" col-md-10"> + <div class="editor-description col-md-9"> <p>{templateDescription}</p> </div> - <div class=" col-md-2"> - <f:link.action class="reset-btn reset-all-btn btn-danger btn" style="width: 100%;" action="reset" arguments="{template: selectedTemplateKey, extensionKey: selectedTemplate.extension}">{f:translate(key:'backend.button_reset_all')}</f:link.action> + <div class=" col-md-3"> + <f:link.action class="reset-btn reset-all-btn btn-danger btn col-md-12" action="reset" arguments="{template: selectedTemplateKey, extensionKey: selectedTemplate.extension}">{f:translate(key:'backend.button_reset_all')}</f:link.action> </div> </div> <div class="col-md-12 row"> @@ -26,7 +25,6 @@ <th><f:translate key="backend.marker" /></th> <th><f:translate key="backend.type" /></th> <th><f:translate key="backend.value" /></th> - <th><f:translate key="backend.usage" /></th> <th><f:translate key="backend.description" /></th> </tr> </thead> @@ -56,16 +54,6 @@ </f:else> </f:if> </td> - <td> - <f:if condition="{marker.usage}"> - <f:then> - {marker.usage} - </f:then> - <f:else> - <![CDATA[{]]>{marker.marker}<![CDATA[}]]> - </f:else> - </f:if> - </td> <td> <f:translate key="{marker.description}">{marker.description}</f:translate> </td> @@ -78,6 +66,7 @@ <div class="row col-md-12 form-group"> <f:form method="post" controller="Mail" action="sendTestMail"> <div class="col-md-12 form-group"> + <f:form.submit name="saveOnly" class="btn-success btn form-group" value="{f:translate(key:'backend.save_template')}" /> <f:form.submit class="btn-primary btn form-group" value="{f:translate(key:'backend.send_test')}" /> <f:form.textfield name="parameters[emailAddress]" class="email-input form-group" value="{beUserMail}" /> <f:form.hidden name="parameters[selectedTemplate]" value="{selectedTemplateKey}" /> diff --git a/Resources/Private/Templates/Queue/Index.html b/Resources/Private/Templates/Queue/Index.html index e8dd4c830f6b4dc004645ebc11ffd8bb18978056..1d3c191effd2c5f6e5048b6adfe0e11fab126ffc 100644 --- a/Resources/Private/Templates/Queue/Index.html +++ b/Resources/Private/Templates/Queue/Index.html @@ -6,113 +6,124 @@ <f:section name="content"> <f:flashMessages /> - <f:render partial="Queue/Filter" arguments="{filterFields: filterFields, filters: filters, languages: languages, templatesFilter: templatesFilter, selectedTemplateFilter: selectedTemplateFilter, selectedExtensionFilter: selectedExtensionFilter}" /> + <f:if condition="!{pages}"> + <f:render partial="Queue/Filter" arguments="{filterFields: filterFields, filters: filters, languages: languages, templatesFilter: templatesFilter, selectedTemplateFilter: selectedTemplateFilter, selectedExtensionFilter: selectedExtensionFilter}" /> + <f:if condition="{queue -> f:count()} > 0"> + <f:then> + <div class="panel panel-default recordlist"> + <div class="table-fit"> + <table data-table="tx_sgmail_domain_model_mail" class="table table-striped table-hover"> + <sgm:backend.widget.paginate objects="{queue}" as="paginatedMails" configuration="{insertAbove: 1, itemsPerPage: 20}"> + <thead> + <tr> + <th></th> + <th><f:translate key="backend.from" /> <br> <f:translate key="backend.to" /> + </th> + <th><f:translate key="backend.filter.extension" />: + <f:translate key="backend.filter.template" /> <br> + <f:translate key="backend.subject" /></th> + <th><f:translate key="backend.entry_date" /> <br> + <f:translate key="backend.last_sent" /></th> + <th></th> + <th></th> + </tr> + </thead> + <tbody> + <f:for each="{paginatedMails}" as="mail"> + {sgm:backend.editOnClick(table: 'tx_sgmail_domain_model_mail', uid: mail.uid) -> sgm:set(name: 'editOnClick')} + <tr data-uid="{mail.uid}"> + <td nowrap="nowrap" class="col-icon"> + <sgm:backend.icon table="tx_sgmail_domain_model_mail" row="{mail}" /> + </td> + <td> + <span>{mail.from_address}</span> + <hr> + <span>{mail.to_address}</span> + </td> + <td> + <span>{mail.extension_key}: {mail.template_name}</span> + <hr> + <f:if condition="{mail.mail_subject}"> + <f:then> + <span><f:format.crop maxCharacters="40" append="...">{mail.mail_subject}</f:format.crop></span> + </f:then> + <f:else> + + </f:else> + </f:if> - <f:if condition="{queue -> f:count()} > 0"> - <f:then> - <div class="panel panel-default recordlist"> - <div class="table-fit"> - <table data-table="tx_sgmail_domain_model_mail" class="table table-striped table-hover"> - <sgm:backend.widget.paginate objects="{queue}" as="paginatedMails" configuration="{insertAbove: 1, itemsPerPage: 20}"> - <thead> - <tr> - <th></th> - <th><f:translate key="backend.from" /> <br> <f:translate key="backend.to" /></th> - <th><f:translate key="backend.filter.extension" />: - <f:translate key="backend.filter.template" /> <br> - <f:translate key="backend.subject" /></th> - <th><f:translate key="backend.entry_date" /> <br> - <f:translate key="backend.last_sent" /></th> - <th></th> - <th></th> - </tr> - </thead> - <tbody> - <f:for each="{paginatedMails}" as="mail"> - {sgm:backend.editOnClick(table: 'tx_sgmail_domain_model_mail', uid: mail.uid) -> sgm:set(name: 'editOnClick')} - <tr data-uid="{mail.uid}"> - <td nowrap="nowrap" class="col-icon"> - <sgm:backend.icon table="tx_sgmail_domain_model_mail" row="{mail}" /> - </td> - <td> - <span>{mail.from_address}</span> - <hr> - <span>{mail.to_address}</span> - </td> - <td> - <span>{mail.extension_key}: {mail.template_name}</span> - <hr> - <f:if condition="{mail.mail_subject}"> - <f:then> - <span><f:format.crop maxCharacters="40" append="...">{mail.mail_subject}</f:format.crop></span> - </f:then> - <f:else> - - </f:else> - </f:if> - - </td> - <td> - <span><f:format.date format="d.m.Y H:i">{mail.crdate}</f:format.date></span> - <hr> - <f:if condition="{mail.last_sending_time} != 0"> - <f:then> - <span><f:format.date format="d.m.Y H:i">{mail.last_sending_time}</f:format.date></span> - </f:then> - <f:else> - <f:translate key="backend.not_sent" /> - </f:else> - </f:if> - </td> - <td nowrap="nowrap" class="col-control"> - <sgm:backend.control table="tx_sgmail_domain_model_mail" row="{mail}" /> - </td> - <td> - <f:link.action class="btn btn-default btn-send-now" controller="Queue" action="sendMail" arguments="{uid: mail.uid, selectedTemplate: selectedTemplateKey, selectedExtension: selectedExtensionKey}"> - <span class="t3js-icon icon icon-size-small icon-state-default actions-document-import-t3d"> - <span class="icon-markup"> - <img src="/typo3/sysext/core/Resources/Public/Icons/T3Icons/actions/actions-document-import-t3d.svg" width="16" height="16"> - </span> - </span> - <f:translate key="backend.send_now" /> - </f:link.action> - <a class="btn btn-default btn-toggle" data-uid="{mail.uid}"> - <span class="t3js-icon icon icon-size-small icon-state-default actions-document-view"> - <span class="icon-markup"> - <img src="/typo3/sysext/core/Resources/Public/Icons/T3Icons/actions/actions-document-view.svg" width="16" height="16"> - </span> - </span> - <f:translate key="backend.showBody" /> - </a> - </td> - <div class="modal fade" id="toggle-{mail.uid}" tabindex="-1" role="dialog" aria-labelledby="login-modal-label"> - <div class="modal-dialog" role="document"> - <div class="modal-content"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal" aria-label="Close"> - <span aria-hidden="true">×</span></button> - <h4 class="modal-title" id="login-modal-label">{mail.mail_subject}</h4> - </div> - <div class="modal-body" id="login-modal-body"> - <div class="modalcol modalcol-left"> - <f:format.html>{mail.mail_body}</f:format.html> + </td> + <td> + <span><f:format.date format="d.m.Y H:i">{mail.crdate}</f:format.date></span> + <hr> + <f:if condition="{mail.last_sending_time} != 0"> + <f:then> + <span><f:format.date format="d.m.Y H:i">{mail.last_sending_time}</f:format.date></span> + </f:then> + <f:else> + <f:translate key="backend.not_sent" /> + </f:else> + </f:if> + </td> + <td nowrap="nowrap" class="col-control"> + <sgm:backend.control table="tx_sgmail_domain_model_mail" row="{mail}" /> + </td> + <td> + <f:if condition="{mail.blacklisted}"> + <f:then> + <b><f:translate key="backend.queue.blacklisted" /></b> + </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}"> + <span class="t3js-icon icon icon-size-small icon-state-default actions-document-import-t3d"> + <span class="icon-markup"> + <img src="/typo3/sysext/core/Resources/Public/Icons/T3Icons/actions/actions-document-import-t3d.svg" width="16" height="16"> + </span> + </span> + <f:translate key="backend.send_now" /> + </f:link.action> + <a class="btn btn-default btn-toggle" data-uid="{mail.uid}"> + <span class="t3js-icon icon icon-size-small icon-state-default actions-document-view"> + <span class="icon-markup"> + <img src="/typo3/sysext/core/Resources/Public/Icons/T3Icons/actions/actions-document-view.svg" width="16" height="16"> + </span> + </span> + <f:translate key="backend.showBody" /> + </a> + </f:else> + </f:if> + </td> + <div class="modal fade" id="toggle-{mail.uid}" tabindex="-1" role="dialog" aria-labelledby="login-modal-label"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="login-modal-label">{mail.mail_subject}</h4> + </div> + <div class="modal-body" id="login-modal-body"> + <div class="modalcol modalcol-left"> + <f:format.html>{mail.mail_body}</f:format.html> + </div> </div> </div> </div> </div> - </div> - </f:for> - </tbody> - </sgm:backend.widget.paginate> - </table> + </f:for> + </tbody> + </sgm:backend.widget.paginate> + </table> + </div> </div> - </div> - </f:then> - <f:else> - <f:render partial="Queue/Empty" /> - </f:else> + </f:then> + <f:else> + <f:render partial="Queue/Empty" /> + </f:else> + </f:if> </f:if> + <f:if condition="{pages}"> + <f:render partial="Mail/Empty" /> <div class="panel panel-default recordlist"> <div class="table-fit"> <table data-table="pages" class="table table-striped table-hover"> @@ -121,7 +132,8 @@ <tr data-uid="{page.pid}"> <td nowrap="nowrap" class="col-title"> <a href="#" onclick="sgMailGoToPage({page.uid}, '{page.path}'); return false;"> - <sgm:backend.icon table="pages" row="{page}" clickMenu="0" /> {page._thePathFull} + <sgm:backend.icon table="pages" row="{page}" clickMenu="0" /> + {page._thePathFull} </a> </td> </tr> diff --git a/Resources/Public/Scripts/Backend.js b/Resources/Public/Scripts/Backend.js index debbeb10a92d15e90aa2a0d80f0c8b96a8efd989..190cff67399863314ae5893d4dad5b223c1f0ab5 100644 --- a/Resources/Public/Scripts/Backend.js +++ b/Resources/Public/Scripts/Backend.js @@ -78,18 +78,23 @@ function setHighlight(id) { // } /** - * Switches to the spefied page in the BE + * Switches to the specified page in the BE * * @param {number} uid * @param {string} path */ function sgMailGoToPage(uid, path) { if (top.nav) { - top.nav.invokePageId(uid,gotToPageCallback); + top.nav.invokePageId(uid, gotToPageCallback); } else { var tree = top.Ext.getCmp('typo3-pagetree'); if (tree) { + var elements = path.split('/'); + var pageNode = tree.activeTree.getNodeById(elements[elements.length - 1]); tree.activeTree.selectPath(path); + if (pageNode) { + tree.activeTree.commandProvider.singleClick(pageNode, tree.activeTree); + } } var separator = '?'; if (top.currentSubScript.indexOf('?') !== -1) { diff --git a/Resources/Public/StyleSheets/backend.css b/Resources/Public/StyleSheets/backend.css index cd2d7c1587000fb46173348afa91fabb85194645..a59f419336f65a77db915b9955f5c4ae6a5a8012 100644 --- a/Resources/Public/StyleSheets/backend.css +++ b/Resources/Public/StyleSheets/backend.css @@ -6,6 +6,10 @@ margin-top: 10px; } +.editor-description { + padding: 10px; +} + .email-input { padding: 5px 6px; vertical-align: top; diff --git a/composer.json b/composer.json index 537879cd7f59b05c2b90f4232bd91c210839871e..25e924bdafe68f642acccd3cec894d80277b6749 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "license": [ "GPL-2.0+" ], - "version": "4.2.1", + "version": "4.3.1", "repositories": [ { "type": "composer", diff --git a/ext_conf_template.txt b/ext_conf_template.txt index 5eee4dc177e0146d29cb88e4e209a21d4c086193..3d817b3221fe2982d4be8238c076ad2a8a383f30 100644 --- a/ext_conf_template.txt +++ b/ext_conf_template.txt @@ -1,2 +1,8 @@ +# cat=general; type=string; label=LLL:EXT:sg_mail/Resources/Private/Language/locallang.xlf:configuration.excludeTemplatesAllDomains +excludeTemplatesAllDomains = + # cat=general; type=string; label=LLL:EXT:sg_mail/Resources/Private/Language/locallang.xlf:configuration.excludeTemplates excludeTemplates = + +# cat=general; type=user[EXT:sg_mail/Classes/UserFunc/ExtensionConfiguration.php:ExtensionConfiguration->displayTemplates]; label=LLL:EXT:sg_mail/Resources/Private/Language/locallang.xlf:configuration.templateList +templates = \ No newline at end of file diff --git a/ext_emconf.php b/ext_emconf.php index dc0a0108785d093b2c5e393d5f56939d58aea833..e615fb9729d84bd1e3e986bbf6707f8d62b8f105 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -8,7 +8,7 @@ $EM_CONF['sg_mail'] = array ( 'title' => 'Mail Templates', 'description' => 'Mail Templates', 'category' => 'module', - 'version' => '4.2.1', + 'version' => '4.3.1', 'state' => 'stable', 'uploadfolder' => false, 'createDirs' => '', diff --git a/ext_tables.sql b/ext_tables.sql index e56a5c475b33e19fb5d603a390249566147bf72c..5a4de506b40ef4d8d7273d1a99963052e4d3526b 100644 --- a/ext_tables.sql +++ b/ext_tables.sql @@ -16,6 +16,7 @@ CREATE TABLE tx_sgmail_domain_model_mail ( sending_time int(11) unsigned DEFAULT '0' NOT NULL, last_sending_time int(11) unsigned DEFAULT '0' NOT NULL, language varchar(255) DEFAULT '' NOT NULL, + blacklisted tinyint(4) unsigned DEFAULT '0' NOT NULL, tstamp int(11) unsigned DEFAULT '0' NOT NULL, crdate int(11) unsigned DEFAULT '0' NOT NULL,