Skip to content
Snippets Groups Projects
Commit c14fbf09 authored by Paul Ilea's avatar Paul Ilea
Browse files

Merge branch 'feature_mail_layouts' into 'master'

[FEATURE] Add Mail Layouts

See merge request !17
parents 133606f5 62cd5dec
No related branches found
No related tags found
1 merge request!17[FEATURE] Add Mail Layouts
Showing
with 1035 additions and 4 deletions
<?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();
}
}
}
}
......@@ -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());
}
......
<?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;
}
}
......@@ -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;
}
}
<?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();
}
}
<?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;
}
}
<?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();
}
}
}
......@@ -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']);
......
......@@ -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.
*
......
......@@ -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;
}
}
<?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'
]
],
],
],
],
]
];
......@@ -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',
......
......@@ -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>
......
......@@ -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>
......
......@@ -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>
......
......@@ -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>
......
<p>
{f:translate(key:'backend.no_layout_entries')}
</p>
......@@ -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>
......
{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>
......@@ -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]" />
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment