Commit d08d1b5d authored by Paul Ilea's avatar Paul Ilea
Browse files

[FEATURE] Add Mail Layouts

parent 133606f5
<?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)),