diff --git a/Classes/Controller/LayoutController.php b/Classes/Controller/LayoutController.php new file mode 100644 index 0000000000000000000000000000000000000000..8a580475d16c59d435d6622618f0c3c3757c1683 --- /dev/null +++ b/Classes/Controller/LayoutController.php @@ -0,0 +1,196 @@ +<?php + +namespace SGalinski\SgMail\Controller; + +/*************************************************************** + * Copyright notice + * + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +use SGalinski\SgMail\Domain\Repository\LayoutRepository; +use SGalinski\SgMail\Service\BackendService; +use SGalinski\SgMail\Session\PhpSession; +use TYPO3\CMS\Backend\Clipboard\Clipboard; +use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent; +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Page\PageRenderer; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\VersionNumberUtility; +use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; +use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException; +use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; + +/** + * Controller for the mail templating service module + */ +class LayoutController extends ActionController { + /** + * DocHeaderComponent + * + * @var DocHeaderComponent + */ + protected $docHeaderComponent; + + /** + * @var LayoutRepository + */ + protected $layoutRepository; + + /** + * Inject the LayoutRepository + * + * @param LayoutRepository $layoutRepository + */ + public function injectLayoutRepository(LayoutRepository $layoutRepository) { + $this->layoutRepository = $layoutRepository; + } + + /** + * @var PhpSession + */ + protected $session; + + /** + * Command array on the form [tablename][uid][command] = value. + * This array may get additional data set internally based on clipboard commands send in clipboardCommandArray var! + * + * @var array + */ + protected $command; + + /** + * Clipboard command array. May trigger changes in "command" + * + * @var array + */ + protected $clipboardCommandArray; + + /** + * @var Clipboard + */ + protected $clipObj; + + /** + * Initializes the Action calls + * + * @return void + */ + public function initializeAction() { + $this->command = GeneralUtility::_GP('cmd'); + $this->clipboardCommandArray = GeneralUtility::_GP('CB'); + } + + /** + * @param ViewInterface $view + */ + public function initializeView(ViewInterface $view) { + parent::initializeView($view); + $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); + $pageRenderer->addJsInlineCode( + 'typo3_version', 'TYPO3.version=' + . VersionNumberUtility::convertVersionNumberToInteger(VersionNumberUtility::getCurrentTypo3Version()) + . ';' + ); + if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '9.0.0', '<')) { + $pageRenderer->loadExtJS(); + } + $this->initClipboard(); + $view->assign('controller', 'Layout'); + } + + /** + * @throws NoSuchArgumentException + */ + public function indexAction() { + $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')); + } + + // create doc header component + $pageInfo = BackendUtility::readPageAccess($pageUid, $GLOBALS['BE_USER']->getPagePermsClause(1)); + if ($pageInfo && (int) $pageInfo['is_siteroot'] === 1) { + $layouts = $this->layoutRepository->findByPidForModule($pageUid); + $this->view->assign('layouts', $layouts); + $pasteData = $this->clipObj->elFromTable('tx_sgmail_domain_model_layout'); + if (\count($pasteData)) { + $pasteButton = [ + 'message' => $this->clipObj->confirmMsgText('pages', $pageInfo, 'into', $pasteData), + 'url' => $this->clipObj->pasteUrl('', $pageUid) + ]; + $this->view->assign('pasteButton', $pasteButton); + } + } else { + $this->view->assign('pages', BackendService::getPages()); + } + $this->docHeaderComponent = GeneralUtility::makeInstance(DocHeaderComponent::class); + if ($pageInfo === FALSE) { + $pageInfo = ['uid' => $pageUid]; + } + $this->docHeaderComponent->setMetaInformation($pageInfo); + BackendService::makeButtons($this->docHeaderComponent, $this->request); + $this->view->assign('pageUid', $pageUid); + $this->view->assign('docHeader', $this->docHeaderComponent->docHeaderContent()); + $this->view->assign('typo3Version', VersionNumberUtility::convertVersionNumberToInteger(TYPO3_version)); + } + + /** + * Clipboard pasting and deleting. + * + * @return void + * @throws \InvalidArgumentException + */ + protected function initClipboard() { + if (!$this->clipObj) { + $this->clipObj = GeneralUtility::makeInstance(Clipboard::class); + } + $this->clipObj->initializeClipboard(); + if (\is_array($this->clipboardCommandArray)) { + if ($this->clipboardCommandArray['paste']) { + $this->clipObj->setCurrentPad($this->clipboardCommandArray['pad']); + $this->command = $this->clipObj->makePasteCmdArray( + $this->clipboardCommandArray['paste'], + $this->command, + $this->clipboardCommandArray['update'] ?? NULL + ); + } + if ($this->clipboardCommandArray['delete']) { + $this->clipObj->setCurrentPad($this->clipboardCommandArray['pad']); + $this->command = $this->clipObj->makeDeleteCmdArray($this->command); + } + if ($this->clipboardCommandArray['el']) { + $this->clipboardCommandArray['setP'] = 'normal'; + $this->clipObj->setCmd($this->clipboardCommandArray); + $this->clipObj->cleanCurrent(); + $this->clipObj->endClipboard(); + } + } + } +} diff --git a/Classes/Controller/MailController.php b/Classes/Controller/MailController.php index 2d9a357c1a7e3b1af14e542849efd3c43e83ab01..4891dc7269821cf22428ca03e4c6cb98ac5676be 100644 --- a/Classes/Controller/MailController.php +++ b/Classes/Controller/MailController.php @@ -69,6 +69,20 @@ class MailController extends ActionController { $this->templateRepository = $templateRepository; } + /** + * @var LayoutRepository + */ + protected $layoutRepository; + + /** + * Inject the LayoutRepository + * + * @param LayoutRepository $layoutRepository + */ + public function injectLayoutRepository(LayoutRepository $layoutRepository) { + $this->layoutRepository = $layoutRepository; + } + /** * @var \SGalinski\SgMail\Session\PhpSession */ @@ -248,6 +262,15 @@ class MailController extends ActionController { $this->view->assign('selectedTemplateKey', $parameters['selectedTemplate']); $this->view->assign('selectedExtensionKey', $parameters['selectedExtension']); $this->view->assign('mode', 'editor'); + $layouts = $this->layoutRepository->findByPidForModule($pageUid); + $layoutOptions = [ + 0 => LocalizationUtility::translate('backend.layout.default', 'SgMail'), + -1 => LocalizationUtility::translate('backend.layout.none', 'SgMail') + ]; + foreach ($layouts as $layout) { + $layoutOptions[(int) $layout['uid']] = $layout['name']; + } + $this->view->assign('layoutOptions', $layoutOptions); } else { $this->view->assign('pages', BackendService::getPages()); } diff --git a/Classes/Domain/Model/Layout.php b/Classes/Domain/Model/Layout.php new file mode 100644 index 0000000000000000000000000000000000000000..53e5c6ac0d549485a88196076b156f39c2907d9b --- /dev/null +++ b/Classes/Domain/Model/Layout.php @@ -0,0 +1,73 @@ +<?php + +namespace SGalinski\SgMail\Domain\Model; + +/*************************************************************** + * Copyright notice + * + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; + +/** + * Template domain model + */ +class Layout extends AbstractEntity { + + /** + * @var string + */ + protected $name = ''; + + /** + * @var string + */ + protected $content = ''; + + /** + * @return string + */ + public function getName(): string { + return $this->name; + } + + /** + * @param string $name + */ + public function setName($name) { + $this->name = $name; + } + + /** + * @return string + */ + public function getContent(): string { + return $this->content; + } + + /** + * @param string $content + */ + public function setContent($content) { + $this->content = $content; + } +} diff --git a/Classes/Domain/Model/Template.php b/Classes/Domain/Model/Template.php index 993cc472f44e099fd9a815dbf6bb91c440d2d90b..b44f7582aaa93c14307e151abb9f57570a51eb26 100644 --- a/Classes/Domain/Model/Template.php +++ b/Classes/Domain/Model/Template.php @@ -37,6 +37,11 @@ class Template extends AbstractEntity { */ protected $extensionKey = ''; + /** + * @var int + */ + protected $layout = 0; + /** * @var string */ @@ -259,4 +264,18 @@ class Template extends AbstractEntity { public function setToAddress($toAddress) { $this->toAddress = $toAddress; } + + /** + * @return int + */ + public function getLayout(): int { + return $this->layout; + } + + /** + * @param int $layout + */ + public function setLayout(int $layout) { + $this->layout = $layout; + } } diff --git a/Classes/Domain/Repository/LayoutRepository.php b/Classes/Domain/Repository/LayoutRepository.php new file mode 100644 index 0000000000000000000000000000000000000000..0155f3e39a8617fec2003ffa6a755ddf53ee7502 --- /dev/null +++ b/Classes/Domain/Repository/LayoutRepository.php @@ -0,0 +1,111 @@ +<?php + +namespace SGalinski\SgMail\Domain\Repository; + +/*************************************************************** + * Copyright notice + * + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +use TYPO3\CMS\Core\Database\Connection; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; +use TYPO3\CMS\Extbase\Persistence\Repository; + +/** + * Repository for the Template object + */ +class LayoutRepository extends Repository { + const LAYOUT_TABLE_NAME = 'tx_sgmail_domain_model_layout'; + + /** + * Initializes the repository default settings + * + * @return void + */ + public function initializeObject() { + /** @var $querySettings Typo3QuerySettings */ + $querySettings = $this->objectManager->get(Typo3QuerySettings::class); + $querySettings->setRespectStoragePage(FALSE); + $querySettings->setLanguageOverlayMode(TRUE); + $querySettings->setLanguageMode('content_fallback'); + $querySettings->setRespectSysLanguage(FALSE); + $this->setDefaultQuerySettings($querySettings); + } + + /** + * Fetches the layout by uid or the default by pid + * + * @param int $uid + * @param int $pid + * @param int $languageUid + * @return array|NULL + */ + public function findByUidOrDefault(int $uid, int $pid, int $languageUid = 0) { + $query = $this->createQuery(); + $querySettings = $query->getQuerySettings(); + $querySettings->setLanguageUid($languageUid); + $query->setQuerySettings($querySettings); + $query->setLimit(1); + + if ($uid > 0) { + $result = $query->matching($query->equals('uid', $uid))->execute(TRUE)[0] ?? NULL; + if ($result) { + return $result; + } + } + + return $query->matching( + $query->logicalAnd([ + $query->equals('pid', $pid), + $query->equals('default', 1) + ]) + )->execute(TRUE)[0] ?? NULL; + } + + /** + * Returns the layout records for the given page uid + * + * @param int $pageUid + * @return array + */ + public function findByPidForModule(int $pageUid): array { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable( + self::LAYOUT_TABLE_NAME + ); + $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class)); + return $queryBuilder->selectLiteral('l.*')->from(self::LAYOUT_TABLE_NAME, 'l') + ->where( + $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq( + 'l.pid', $queryBuilder->createNamedParameter($pageUid, Connection::PARAM_INT) + ), + $queryBuilder->expr()->in( + 'l.sys_language_uid', $queryBuilder->createNamedParameter([0, -1], Connection::PARAM_INT_ARRAY) + ) + ) + ) + ->orderBy('l.name')->execute()->fetchAll(); + } +} diff --git a/Classes/Form/NodeExpansion/FieldInformation.php b/Classes/Form/NodeExpansion/FieldInformation.php new file mode 100644 index 0000000000000000000000000000000000000000..08a44f250a3b1223c8df643ccf48984f4b5fa2da --- /dev/null +++ b/Classes/Form/NodeExpansion/FieldInformation.php @@ -0,0 +1,81 @@ +<?php + +namespace SGalinski\SgMail\Form\NodeExpansion; + +/*************************************************************** + * Copyright notice + * + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +use TYPO3\CMS\Backend\Form\AbstractNode; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Utility\LocalizationUtility; + +/** + * Renders additional TCA field information. + */ +class FieldInformation extends AbstractNode { + + /** + * @return array Result array + */ + public function render(): array { + $result = $this->initializeResultArray(); + $options = $this->data['renderData']['fieldInformationOptions'] + ?? $this->data['renderData']['fieldWizardOptions']; + + if ( + !isset($options['text']) + && (!isset($options['parentFields'], $options['parentTable'], $options['parentUidField'])) + ) { + return $result; + } + + $text = \trim($options['text'] ?? ''); + + if ($text === '') { + return $result; + } + + if (\strpos($text, 'LLL') === 0) { + $text = LocalizationUtility::translate($text); + } + + $tagOpen = '<span>'; + $tagClose = '</span>'; + + if (isset($options['tag'])) { + $tag = \trim(\str_replace(['<', '>'], '', $options['tag'])); + $tagSplit = GeneralUtility::trimExplode(' ', $tag); + $tagName = $tagSplit[0]; + + if ($tagName !== '') { + $tagOpen = '<' . $tag . '>'; + $tagClose = '</' . $tagName . '>'; + } + } + + $result['html'] = '<div>' . $tagOpen . $text . $tagClose . '</div>'; + + return $result; + } +} diff --git a/Classes/Hooks/ProcessDatamap.php b/Classes/Hooks/ProcessDatamap.php new file mode 100644 index 0000000000000000000000000000000000000000..9937139ee139340a91bacc75960df9c3ecbf3f80 --- /dev/null +++ b/Classes/Hooks/ProcessDatamap.php @@ -0,0 +1,88 @@ +<?php + +namespace SGalinski\SgMail\Hooks; + +/*************************************************************** + * Copyright notice + * + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\DataHandling\DataHandler; +use TYPO3\CMS\Core\Utility\GeneralUtility; + +/** + * Hooks for synchronize urls directly on-the-fly while editing + */ +class ProcessDatamap { + + /** + * Hook function for handling the enabling and disabling of FE users from the BE + * + * @param string $status + * @param string $table + * @param int $id + * @param array $fieldArray + * @param DataHandler $dataHandler + * @return void + */ + public function processDatamap_afterDatabaseOperations($status, $table, $id, array $fieldArray, $dataHandler) { + if ( + $table === 'tx_sgmail_domain_model_layout' && isset($fieldArray['default']) && + in_array($status, ['update', 'new'], TRUE) + ) { + if (!(bool) $fieldArray['default']) { + return; + } + + if ($status === 'update') { + $updatedRow = BackendUtility::getRecord('tx_sgmail_domain_model_layout', $id, 'pid, sys_language_uid'); + if ($updatedRow === NULL || (int) $updatedRow['sys_language_uid'] > 0) { + return; + } + + $pid = (int) $updatedRow['pid']; + } else { + if ((int) $fieldArray['sys_language_uid'] > 0) { + return; + } + $id = (int) $dataHandler->substNEWwithIDs[$id]; + $pid = (int) $fieldArray['pid']; + } + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable( + 'tx_sgmail_domain_model_layout' + ); + $queryBuilder->getRestrictions()->removeAll(); + $queryBuilder->update('tx_sgmail_domain_model_layout') + ->where( + $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid)), + $queryBuilder->expr()->neq('l10n_parent', $queryBuilder->createNamedParameter($id)), + $queryBuilder->expr()->neq('uid', $queryBuilder->createNamedParameter($id)) + ) + ) + ->set('default', 0) + ->execute(); + } + } +} diff --git a/Classes/Service/BackendService.php b/Classes/Service/BackendService.php index 08e9d7ef5f2a14564a9b7fe2449c6f7f24f00310..afd3a00caf08f9e4501683096f13490e9828e04f 100644 --- a/Classes/Service/BackendService.php +++ b/Classes/Service/BackendService.php @@ -331,6 +331,7 @@ class BackendService { $template->setExtensionKey($selectedExtension); $template->setTemplateName($selectedTemplate); $template->setLanguage($language); + $template->setLayout($templateData['layout']); $template->setContent($templateData['content']); $template->setSubject($templateData['subject']); $template->setFromName($templateData['fromName']); diff --git a/Classes/Service/MailTemplateService.php b/Classes/Service/MailTemplateService.php index 1ae7146371a57fc338457bdf416becb1c852cbf8..bd41f47d369021d8ab68e24de3d7bcb9c211e11c 100644 --- a/Classes/Service/MailTemplateService.php +++ b/Classes/Service/MailTemplateService.php @@ -29,6 +29,7 @@ namespace SGalinski\SgMail\Service; use DateTime; 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; @@ -37,7 +38,9 @@ use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Mail\MailMessage; use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\ResourceFactory; +use TYPO3\CMS\Core\Routing\SiteMatcher; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\VersionNumberUtility; use TYPO3\CMS\Extbase\Domain\Model\FileReference; use TYPO3\CMS\Extbase\Object\ObjectManager; use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; @@ -150,6 +153,11 @@ class MailTemplateService { */ protected $templateRepository; + /** + * @var \SGalinski\SgMail\Domain\Repository\LayoutRepository + */ + protected $layoutRepository; + /** * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager */ @@ -186,6 +194,7 @@ class MailTemplateService { $typoScriptSettingsService = $this->objectManager->get(TypoScriptSettingsService::class); $tsSettings = $typoScriptSettingsService->getSettings(0, 'tx_sgmail'); $this->templateRepository = $this->objectManager->get(TemplateRepository::class); + $this->layoutRepository = $this->objectManager->get(LayoutRepository::class); $this->persistenceManager = $this->objectManager->get(PersistenceManager::class); $this->resourceFactory = $this->objectManager->get(ResourceFactory::class); @@ -710,7 +719,10 @@ class MailTemplateService { $subject = $emailView->render(); $emailView->setTemplateSource( - empty($overwrittenEmailBody) ? $template->getContent() : $overwrittenEmailBody + $this->getTemplateSource( + empty($overwrittenEmailBody) ? $template->getContent() : $overwrittenEmailBody, + $template->getLayout(), $siteRootId + ) ); } else { $subject = $registerService->getRegisterArray()[$this->extensionKey][$this->templateName]['subject']; @@ -725,7 +737,10 @@ class MailTemplateService { $subject = $emailView->render(); $emailView->setTemplateSource( - empty($overwrittenEmailBody) ? $defaultTemplateContent : $overwrittenEmailBody + $this->getTemplateSource( + empty($overwrittenEmailBody) ? $defaultTemplateContent : $overwrittenEmailBody, + 0, $siteRootId + ) ); } @@ -753,6 +768,78 @@ class MailTemplateService { return $success; } + /** + * Combines the template content with the layout and returns the result + * + * @param string $content + * @param int $layoutUid + * @param int $siteRootId + * @return string + */ + private function getTemplateSource(string $content, int $layoutUid, int $siteRootId): string { + if ($layoutUid === -1) { + return $content; + } + + $languageUid = 0; + if ($this->language !== self::DEFAULT_LANGUAGE) { + $languageUid = (int) array_search($this->language, $this->getAvailableLanguages(), TRUE); + } + + $frontendSimulated = FALSE; + if (!isset($GLOBALS['TSFE'])) { + $frontendSimulated = TRUE; + $GLOBALS['TSFE'] = new TypoScriptFrontendController(NULL, $siteRootId, 0); + } + /** @var array $layout */ + $layout = $this->layoutRepository->findByUidOrDefault($layoutUid, $siteRootId, $languageUid); + if ($frontendSimulated) { + unset($GLOBALS['TSFE']); + } + + if ($layout === NULL) { + return $content; + } + + return str_replace('###CONTENT###', $content, $layout['content']); + } + + /** + * Returns the list of avalilable translation languages + * + * @return array + */ + private function getAvailableLanguages(): array { + $out = [0 => '']; + if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '9.0.0', '<')) { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable( + 'sys_language' + ); + $rows = $queryBuilder->select('*') + ->from('sys_language')->execute()->fetchAll(); + + foreach ($rows as $row) { + $out[(int) $row['uid']] = $row['language_isocode']; + } + } else { + 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. * diff --git a/Classes/ViewHelpers/Backend/ControlViewHelper.php b/Classes/ViewHelpers/Backend/ControlViewHelper.php index 843cbb8232701f3dff9e87a305a947a5943b73f6..4b20c204e3718ef9b3ab68fd829ebaffa8486a9b 100644 --- a/Classes/ViewHelpers/Backend/ControlViewHelper.php +++ b/Classes/ViewHelpers/Backend/ControlViewHelper.php @@ -27,6 +27,7 @@ namespace SGalinski\SgMail\ViewHelpers\Backend; ***************************************************************/ use SGalinski\SgMail\ViewHelpers\AbstractViewHelper; +use TYPO3\CMS\Backend\Clipboard\Clipboard; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList; @@ -43,6 +44,7 @@ class ControlViewHelper extends AbstractViewHelper { parent::initializeArguments(); $this->registerArgument('table', 'string', 'The table to control', TRUE); $this->registerArgument('row', 'array', 'The row of the record', TRUE); + $this->registerArgument('clipboard', 'bool', 'If true, renders the clipboard controls', FALSE); } /** @@ -55,10 +57,19 @@ class ControlViewHelper extends AbstractViewHelper { public function render() { $table = $this->arguments['table']; $row = $this->arguments['row']; + $clipboard = (bool) $this->arguments['clipboard']; /** @var DatabaseRecordList $databaseRecordList */ $databaseRecordList = GeneralUtility::makeInstance(DatabaseRecordList::class); $pageInfo = BackendUtility::readPageAccess($row['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1)); $databaseRecordList->calcPerms = $GLOBALS['BE_USER']->calcPerms($pageInfo); - return $databaseRecordList->makeControl($table, $row); + $out = $databaseRecordList->makeControl($table, $row); + if ($clipboard) { + $databaseRecordList->MOD_SETTINGS['clipBoard'] = TRUE; + $databaseRecordList->clipObj = GeneralUtility::makeInstance(Clipboard::class); + $databaseRecordList->clipObj->initializeClipboard(); + $GLOBALS['SOBE'] = $databaseRecordList; + $out .= $databaseRecordList->makeClip($table, $row); + } + return $out; } } diff --git a/Configuration/TCA/tx_sgmail_domain_model_layout.php b/Configuration/TCA/tx_sgmail_domain_model_layout.php new file mode 100644 index 0000000000000000000000000000000000000000..53127a061dd471cd6056f83afa8ffd4dc72f39de --- /dev/null +++ b/Configuration/TCA/tx_sgmail_domain_model_layout.php @@ -0,0 +1,143 @@ +<?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! + ***************************************************************/ + +return [ + 'ctrl' => [ + 'title' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_layout', + 'label' => 'name', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + 'searchFields' => 'name, content', + 'dividers2tabs' => TRUE, + 'delete' => 'deleted', + 'languageField' => 'sys_language_uid', + 'transOrigPointerField' => 'l10n_parent', + 'transOrigDiffSourceField' => 'l10n_diffsource', + 'enablecolumns' => [ + 'disabled' => 'hidden', + ], + 'default_sortby' => 'name', + 'hideTable' => TRUE, + 'iconfile' => 'EXT:sg_mail/Resources/Public/Icons/ModuleIconTCA.svg' + ], + 'interface' => [ + 'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, name, content, default' + ], + 'types' => [ + '1' => [ + 'showitem' => 'hidden, --palette--;;name, content, ' + ], + ], + 'palettes' => [ + 'name' => [ + 'showitem' => 'name, default' + ], + ], + 'columns' => [ + 'hidden' => [ + 'exclude' => TRUE, + 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:hidden.I.0', + 'config' => [ + 'type' => 'check', + ], + ], + 'sys_language_uid' => [ + 'exclude' => true, + 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.language', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'foreign_table' => 'sys_language', + 'foreign_table_where' => 'ORDER BY sys_language.title', + 'items' => [ + ['LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', -1], + ['LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.default_value', 0] + ], + 'default' => 0, + 'fieldWizard' => [ + 'selectIcons' => [ + 'disabled' => false, + ], + ], + ] + ], + 'l10n_parent' => [ + 'displayCond' => 'FIELD:sys_language_uid:>:0', + 'exclude' => true, + 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => [ + ['', 0] + ], + 'foreign_table' => 'tx_sgmail_domain_model_layout', + 'foreign_table_where' => 'AND tx_sgmail_domain_model_layout.uid=###REC_FIELD_l10n_parent### AND tx_sgmail_domain_model_layout.sys_language_uid IN (-1,0)', + 'default' => 0 + ] + ], + 'l10n_diffsource' => [ + 'config' => [ + 'type' => 'passthrough', + 'default' => '' + ] + ], + 'default' => [ + 'exclude' => TRUE, + 'l10n_mode' => 'exclude', + 'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_layout.default', + 'config' => [ + 'type' => 'check', + ], + ], + 'name' => [ + 'exclude' => TRUE, + 'l10n_display' => 'defaultAsReadonly', + 'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_layout.name', + 'config' => [ + 'type' => 'input', + 'eval' => 'required, trim' + ], + ], + 'content' => [ + 'exclude' => TRUE, + 'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_layout.content', + 'config' => [ + 'type' => 'text', + 'renderType' => 't3editor', + 'fieldInformation' => [ + 'info' => [ + 'renderType' => 'sgMailFieldInformation', + 'options' => [ + 'text' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_layout.content.info' + ] + ], + ], + ], + ], + ] +]; diff --git a/Configuration/TCA/tx_sgmail_domain_model_template.php b/Configuration/TCA/tx_sgmail_domain_model_template.php index 3ff152ab419f62a45d411122ef19b704e374cdbf..9b42cee13069c2d877bb326631c03efd7cb14b47 100644 --- a/Configuration/TCA/tx_sgmail_domain_model_template.php +++ b/Configuration/TCA/tx_sgmail_domain_model_template.php @@ -43,7 +43,7 @@ return [ 'iconfile' => 'EXT:sg_mail/Resources/Public/Icons/ModuleIconTCA.svg' ], 'interface' => [ - 'showRecordFieldList' => 'extension_key, template_name, language, content, subject, fromName, fromMail, cc, bcc, replyTo, to_address' + 'showRecordFieldList' => 'layout, extension_key, template_name, language, content, subject, fromName, fromMail, cc, bcc, replyTo, to_address' ], 'types' => [ '1' => [ @@ -58,6 +58,20 @@ return [ 'type' => 'check', ], ], + 'layout' => [ + 'exclude' => TRUE, + 'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_template.layout', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => [ + ['', 0] + ], + 'foreign_table' => 'tx_sgmail_domain_model_layout', + 'foreign_table_where' => 'AND tx_sgmail_domain_model_layout.pid=###CURRENT_PID### AND tx_sgmail_domain_model_layout.sys_language_uid IN (-1,0)', + 'default' => 0 + ], + ], 'extension_key' => [ 'exclude' => TRUE, 'label' => 'LLL:EXT:sg_mail/Resources/Private/Language/locallang_db.xlf:tx_sgmail_domain_model_template.extension_key', diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index cb1be9f1344eab1daa23b32cc6b9a460410c55b6..54e4a6f72fbf535f563721afcf408820dd83366b 100644 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -33,10 +33,18 @@ <source><![CDATA[Register new template]]></source> <target><![CDATA[Neues Template registrieren]]></target> </trans-unit> + <trans-unit id="backend.button_create_layout" approved="yes"> + <source><![CDATA[Add new layout]]></source> + <target><![CDATA[Neues Layout hinzufügen]]></target> + </trans-unit> <trans-unit id="backend.button_download_csv" approved="yes"> <source><![CDATA[Export CSV]]></source> <target><![CDATA[CSV exportieren]]></target> </trans-unit> + <trans-unit id="backend.button_paste_layout"> + <source><![CDATA[Paste Layout]]></source> + <target><![CDATA[Layout einfügen]]></target> + </trans-unit> <trans-unit id="backend.button_reset" approved="yes"> <source><![CDATA[Reset Template]]></source> <target><![CDATA[Zurücksetzen]]></target> @@ -252,6 +260,22 @@ Bitte registrieren Sie Ihre Templates in den entsprechenden ext_localconf.php Da <source><![CDATA[Last Sent]]></source> <target><![CDATA[Zuletzt gesendet]]></target> </trans-unit> + <trans-unit id="backend.layout"> + <source><![CDATA[Layout]]></source> + <target><![CDATA[Layout]]></target> + </trans-unit> + <trans-unit id="backend.layout.default"> + <source><![CDATA[Default]]></source> + <target><![CDATA[Default]]></target> + </trans-unit> + <trans-unit id="backend.layout.none"> + <source><![CDATA[None]]></source> + <target><![CDATA[Keine]]></target> + </trans-unit> + <trans-unit id="backend.layouts"> + <source><![CDATA[Template Layouts]]></source> + <target><![CDATA[Template-Layouts]]></target> + </trans-unit> <trans-unit id="backend.mail_queue" approved="yes"> <source><![CDATA[Mail Queue]]></source> <target><![CDATA[Mail-Queue]]></target> @@ -292,6 +316,10 @@ Bitte registrieren Sie Ihre Templates in den entsprechenden ext_localconf.php Da <source><![CDATA[Your filter criteria didn't match any entries.]]></source> <target><![CDATA[Es wurden keine Einträge für Ihre Filtereinstellungen gefunden.]]></target> </trans-unit> + <trans-unit id="backend.no_layout_entries"> + <source><![CDATA[Your filter criteria didn't match any entries.]]></source> + <target><![CDATA[Es wurden keine Einträge für Ihre Filtereinstellungen gefunden.]]></target> + </trans-unit> <trans-unit id="backend.no_site_root" approved="yes"> <source><![CDATA[Please select one of the following website roots:]]></source> <target><![CDATA[Bitte wählen Sie eine der folgenden Webseiten:]]></target> diff --git a/Resources/Private/Language/de.locallang_db.xlf b/Resources/Private/Language/de.locallang_db.xlf index fd01b7596fb3082326cef0e8e695a25505024287..693b6a07e436bb6b36a02dcc68db2a299c075166 100644 --- a/Resources/Private/Language/de.locallang_db.xlf +++ b/Resources/Private/Language/de.locallang_db.xlf @@ -9,6 +9,26 @@ <authorEmail>torsten@sgalinski.de</authorEmail> </header> <body> + <trans-unit id="tx_sgmail_domain_model_layout"> + <source>Mail Layout</source> + <target>Mail-Layout</target> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_layout.content"> + <source>Layout</source> + <target>Layout</target> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_layout.content.info"> + <source>To include the Mail Template content, use the '###CONTENT###' marker.</source> + <target>Verwenden Sie die Markierung "###CONTENT###", um den Inhalt des Mail-Templates einzuschließen.</target> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_layout.default"> + <source>Default</source> + <target>Default</target> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_layout.name"> + <source>Name</source> + <target>Name</target> + </trans-unit> <trans-unit id="tx_sgmail_domain_model_mail" approved="yes"> <source>Mail Queue Entry</source> <target>Mail-Queue-Eintrag</target> @@ -125,6 +145,10 @@ <source>Language</source> <target>Sprache</target> </trans-unit> + <trans-unit id="tx_sgmail_domain_model_template.layout"> + <source>Layout</source> + <target>Layout</target> + </trans-unit> <trans-unit id="tx_sgmail_domain_model_template.replyTo" approved="yes"> <source>Reply To</source> <target>Antwort an</target> diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index 45d2ccaabe77b2aef290ff780e35853019825730..d6f598ef1321b1bf234e57e7479c30b0ff7f990d 100644 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -27,9 +27,15 @@ <trans-unit id="backend.button_create"> <source><![CDATA[Register new template]]></source> </trans-unit> + <trans-unit id="backend.button_create_layout" approved="yes"> + <source><![CDATA[Add new layout]]></source> + </trans-unit> <trans-unit id="backend.button_download_csv"> <source><![CDATA[Export CSV]]></source> </trans-unit> + <trans-unit id="backend.button_paste_layout"> + <source><![CDATA[Paste Layout]]></source> + </trans-unit> <trans-unit id="backend.button_reset"> <source><![CDATA[Reset Template]]></source> </trans-unit> @@ -194,6 +200,18 @@ Please register your configurations in the according ext_localconf.php.]]></sour <trans-unit id="backend.last_sent"> <source><![CDATA[Last Sent]]></source> </trans-unit> + <trans-unit id="backend.layout"> + <source><![CDATA[Layout]]></source> + </trans-unit> + <trans-unit id="backend.layout.default"> + <source><![CDATA[Default]]></source> + </trans-unit> + <trans-unit id="backend.layout.none"> + <source><![CDATA[None]]></source> + </trans-unit> + <trans-unit id="backend.layouts"> + <source><![CDATA[Template Layouts]]></source> + </trans-unit> <trans-unit id="backend.mail_queue"> <source><![CDATA[Mail Queue]]></source> </trans-unit> @@ -224,6 +242,9 @@ Please register your configurations in the according ext_localconf.php.]]></sour <trans-unit id="backend.no_queue_entries"> <source><![CDATA[Your filter criteria didn't match any entries.]]></source> </trans-unit> + <trans-unit id="backend.no_layout_entries"> + <source><![CDATA[Your filter criteria didn't match any entries.]]></source> + </trans-unit> <trans-unit id="backend.no_site_root"> <source><![CDATA[Please select one of the following website roots:]]></source> </trans-unit> diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf index 0c8fb92484929ea34ef476e970ffc51ba4e0efe7..0592bb867ba44793373ae618e37beedb5ff3dd1a 100644 --- a/Resources/Private/Language/locallang_db.xlf +++ b/Resources/Private/Language/locallang_db.xlf @@ -9,6 +9,21 @@ <authorEmail>torsten@sgalinski.de</authorEmail> </header> <body> + <trans-unit id="tx_sgmail_domain_model_layout"> + <source>Mail Layout</source> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_layout.content"> + <source>Layout</source> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_layout.content.info"> + <source>To include the Mail Template content, use the '###CONTENT###' marker.</source> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_layout.default"> + <source>Default</source> + </trans-unit> + <trans-unit id="tx_sgmail_domain_model_layout.name"> + <source>Name</source> + </trans-unit> <trans-unit id="tx_sgmail_domain_model_mail"> <source>Mail Queue Entry</source> </trans-unit> @@ -96,6 +111,9 @@ <trans-unit id="tx_sgmail_domain_model_template.language"> <source>Language</source> </trans-unit> + <trans-unit id="tx_sgmail_domain_model_template.layout"> + <source>Layout</source> + </trans-unit> <trans-unit id="tx_sgmail_domain_model_template.replyTo"> <source>Reply To</source> </trans-unit> diff --git a/Resources/Private/Partials/Layout/Empty.html b/Resources/Private/Partials/Layout/Empty.html new file mode 100644 index 0000000000000000000000000000000000000000..ecceff62b936325a2c1d6c89b0229d3bcbb51a53 --- /dev/null +++ b/Resources/Private/Partials/Layout/Empty.html @@ -0,0 +1,3 @@ +<p> + {f:translate(key:'backend.no_layout_entries')} +</p> diff --git a/Resources/Private/Partials/Module/DocHeader.html b/Resources/Private/Partials/Module/DocHeader.html index 09cffd21f8c0aea96a164122d5240e6d54446853..09bde8ebe777850ac523091e02839b786143b7e1 100644 --- a/Resources/Private/Partials/Module/DocHeader.html +++ b/Resources/Private/Partials/Module/DocHeader.html @@ -71,6 +71,10 @@ partial="Module/DocHeader" section="actionMenuItem" arguments="{controller:'Queue', action: 'index', label: '{f:translate(key:\'backend.mail_queue\')}', selectedTemplate: selectedTemplateKey, selectedExtension: selectedExtensionKey, simpleActionItem: 1}" /> + <f:render + partial="Module/DocHeader" + section="actionMenuItem" + arguments="{controller:'Layout', action: 'index', label: '{f:translate(key:\'backend.layouts\')}', selectedTemplate: selectedTemplateKey, selectedExtension: selectedExtensionKey, simpleActionItem: 1}" /> </f:be.menus.actionMenu> </div> </f:else> diff --git a/Resources/Private/Templates/Layout/Index.html b/Resources/Private/Templates/Layout/Index.html new file mode 100644 index 0000000000000000000000000000000000000000..1a97fbbd3b40026a1fc2aeda9f96c1b3c70eea34 --- /dev/null +++ b/Resources/Private/Templates/Layout/Index.html @@ -0,0 +1,81 @@ +{namespace sg=SGalinski\SgMail\ViewHelpers} +<f:layout name="Default" /> + +<f:section name="iconButtons"> + <a href="#" class="btn btn-default btn-sm" title="{f:translate(key: 'backend.button_create_layout')}" onclick="{sg:backend.editOnClick(table: 'tx_sgmail_domain_model_layout', uid: pageUid, new: 1)}"> + <core:icon identifier="actions-document-new" /> + </a> + <f:if condition="{pasteButton}"> + <a href="{pasteButton.url}" class="btn btn-sm btn-default t3js-modal-trigger" data-severity="warning" + data-content="{pasteButton.message}" + data-title="{f:translate(key: 'backend.button_paste_layout')}" + title="{f:translate(key: 'backend.button_paste_layout')}"> + <core:icon identifier="actions-document-paste-into" /> + </a> + </f:if> +</f:section> + +<f:section name="content"> + <f:flashMessages /> + <f:if condition="!{pages}"> + <h1><f:translate key="backend.layouts" /></h1> + <f:if condition="{layouts -> f:count()} > 0"> + <f:then> + <div class="panel panel-default recordlist"> + <div class="table-fit"> + <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: '')}"> + <td nowrap="nowrap" class="col-icon"> + <f:format.raw> + <sg:backend.icon table="tx_sgmail_domain_model_layout" row="{layout}" /> + </f:format.raw> + </td> + <td nowrap="nowrap"> + <a href="#" onclick="{sg:backend.editOnClick(table: 'tx_sgmail_domain_model_layout', uid: layout.uid)}"> + <span> + {layout.name} + </span> + </a> + </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> + </td> + </tr> + </f:for> + </tbody> + </table> + </div> + </div> + </f:then> + <f:else> + <f:render partial="Layout/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"> + <tbody> + <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}"> + <sg:backend.icon table="pages" row="{page}" clickMenu="0" /> + {page._thePathFull} + </f:link.action> + </td> + </tr> + </f:for> + </tbody> + </table> + </div> + </div> + </f:if> +</f:section> diff --git a/Resources/Private/Templates/Mail/Index.html b/Resources/Private/Templates/Mail/Index.html index f7249ecd850a8ac6c78d222a1a633d61777b521a..eccce1a7cda32b493302da63c8f1547e97ea79fe 100644 --- a/Resources/Private/Templates/Mail/Index.html +++ b/Resources/Private/Templates/Mail/Index.html @@ -150,6 +150,11 @@ </f:for> <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]"/> + </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]" /> diff --git a/ext_localconf.php b/ext_localconf.php index 59a1e56bb3edaea80fb4cb420fbada104fe872f1..a78784e2f1c4a62f30752da2f80344fb616c4e72 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -51,6 +51,16 @@ call_user_func( 'className' => \SGalinski\SgMail\XClass\Form\FormManagerController::class, ]; + // Register FormEngine node type resolvers + $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry']['sgMailFieldInformation'] = [ + 'nodeName' => 'sgMailFieldInformation', + 'priority' => 10, + 'class' => \SGalinski\SgMail\Form\NodeExpansion\FieldInformation::class, + ]; + + // Datamap process hook + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = \SGalinski\SgMail\Hooks\ProcessDatamap::class; + // Cache registration $registerService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( \SGalinski\SgMail\Service\RegisterService::class diff --git a/ext_tables.php b/ext_tables.php index 5080e408340b43d1a13858268517374cd016c641..9895715542f3feae2ea4152b2cdbdabb1d467204 100644 --- a/ext_tables.php +++ b/ext_tables.php @@ -34,6 +34,7 @@ call_user_func( 'Mail' => 'index, sendTestMail, empty, reset', 'Queue' => 'index, sendMail, export', 'Configuration' => 'index, create, edit, delete', + 'Layout' => 'index', ], [ 'access' => 'user,group', @@ -46,5 +47,6 @@ call_user_func( \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages( 'tx_sgmail_domain_model_template' ); + \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages('tx_sgmail_domain_model_layout'); }, 'sg_mail' ); diff --git a/ext_tables.sql b/ext_tables.sql index 52b2c71ef5dcd92f7ac209b7fad7fb9e15e013f7..aee2329b4226350bbb2f90e1390b40fb2251f884 100644 --- a/ext_tables.sql +++ b/ext_tables.sql @@ -35,6 +35,7 @@ CREATE TABLE tx_sgmail_domain_model_template ( uid int(11) NOT NULL auto_increment, pid int(11) DEFAULT '0' NOT NULL, + layout int(11) DEFAULT '0' NOT NULL, subject text NOT NULL, extension_key varchar(255) DEFAULT '' NOT NULL, template_name varchar(255) DEFAULT '' NOT NULL, @@ -57,3 +58,24 @@ CREATE TABLE tx_sgmail_domain_model_template ( PRIMARY KEY (uid), KEY parent (pid) ); + +CREATE TABLE tx_sgmail_domain_model_layout ( + uid int(11) NOT NULL auto_increment, + pid int(11) DEFAULT '0' NOT NULL, + tstamp int(11) DEFAULT '0' NOT NULL, + crdate int(11) DEFAULT '0' NOT NULL, + cruser_id int(11) DEFAULT '0' NOT NULL, + deleted tinyint(4) DEFAULT '0' NOT NULL, + hidden tinyint(4) DEFAULT '0' NOT NULL, + default tinyint(4) DEFAULT '0' NOT NULL, + + sys_language_uid int(11) DEFAULT '0' NOT NULL, + l10n_parent int(11) DEFAULT '0' NOT NULL, + l10n_diffsource mediumblob, + + name tinytext NOT NULL, + content text, + + PRIMARY KEY (uid), + KEY layout_list (pid,deleted,sys_language_uid) +);