<?php namespace SGalinski\SgMail\Service; /*************************************************************** * 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\Model\Template; use SGalinski\SgMail\Domain\Repository\MailRepository; use SGalinski\SgMail\Domain\Repository\TemplateRepository; use TYPO3\CMS\Backend\Template\Components\ButtonBar; use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Database\DatabaseConnection; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Request; use TYPO3\CMS\Extbase\Object\ObjectManager; use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; /** * Backend Service class */ class BackendService { // options for the queue search filter const SENDER_FILTER_OPTION = 0; const RECIPIENT_FILTER_OPTION = 1; const SUBJECT_FILTER_OPTION = 2; const MAILTEXT_FILTER_OPTION = 3; const CC_FILTER_OPTION = 4; const BCC_FILTER_OPTION = 5; const FROM_NAME_FILTER_OPTION = 6; const REPLY_TO_NAME_FILTER_OPTION = 7; // constants for deetermining the backend mode const BACKEND_MODE_EDITOR = 'editor'; const BACKEND_MODE_EDITOR_CONTROLLER = 'Mail'; const BACKEND_MODE_QUEUE = 'queue'; const BACKEND_MODE_QUEUE_CONTROLLER = 'Queue'; /** * Get all pages the be user has access to * * @return array * @throws \InvalidArgumentException */ public static function getPages(): array { $out = []; /** @var $databaseConnection DatabaseConnection */ $databaseConnection = $GLOBALS['TYPO3_DB']; $rows = $databaseConnection->exec_SELECTgetRows( '*', 'pages', 'deleted = 0 AND is_siteroot = 1' ); foreach ($rows as $row) { $pageInfo = BackendUtility::readPageAccess($row['uid'], $GLOBALS['BE_USER']->getPagePermsClause(1)); if ($pageInfo) { $rootline = BackendUtility::BEgetRootLine($pageInfo['uid'], '', TRUE); ksort($rootline); $path = '/root'; foreach ($rootline as $page) { $path .= '/p' . dechex($page['uid']); } $pageInfo['path'] = $path; $out[] = $pageInfo; } } return $out; } /** * create buttons for the backend module header * * @param DocHeaderComponent $docHeaderComponent * @param Request $request * @throws \InvalidArgumentException * @throws \UnexpectedValueException */ public static function makeButtons($docHeaderComponent, $request) { /** @var ButtonBar $buttonBar */ $buttonBar = $docHeaderComponent->getButtonBar(); /** @var IconFactory $iconFactory */ $iconFactory = GeneralUtility::makeInstance(IconFactory::class); // Refresh $refreshButton = $buttonBar->makeLinkButton() ->setHref(GeneralUtility::getIndpEnv('REQUEST_URI')) ->setTitle(LocalizationUtility::translate('LLL:EXT:lang/locallang_core.xlf:labels.reload', '')) ->setIcon($iconFactory->getIcon('actions-refresh', Icon::SIZE_SMALL)); $buttonBar->addButton($refreshButton, ButtonBar::BUTTON_POSITION_RIGHT); // shortcut button $shortcutButton = $buttonBar->makeShortcutButton() ->setModuleName($request->getPluginName()) ->setGetVariables( [ 'id', 'M' ] ) ->setSetVariables([]); $buttonBar->addButton($shortcutButton, ButtonBar::BUTTON_POSITION_RIGHT); $docHeaderComponent->getButtonBar(); } /** * Retrieves the next site root in the page hierarchy from the current page * * @param int $currentPid * @return int */ public static function getSiteRoot($currentPid): int { $rootLine = BackendUtility::BEgetRootLine((int) $currentPid); $siteRoot = ['uid' => 0]; foreach ($rootLine as $page) { if ((int) $page['is_siteroot'] === 1) { $siteRoot = $page; break; } } return $siteRoot['uid']; } /** * Get the selected templates for the selected language * * @param string $selectedExtension * @param string $selectedTemplate * @param array $languages * @param int $pid * @return array * @throws \InvalidArgumentException */ public static function getSelectedTemplates( $selectedExtension, $selectedTemplate, array $languages, $pid ): array { $selectedTemplates = []; $objectManager = GeneralUtility::makeInstance(ObjectManager::class); /** @var TemplateRepository $templateRepository */ $templateRepository = $objectManager->get(TemplateRepository::class); foreach ($languages as $language) { $selectedTemplates[$language['isocode']] = $templateRepository->findOneByTemplate( $selectedExtension, $selectedTemplate, $language['isocode'], $pid ); } return $selectedTemplates; } /** * get an array of all the locales for the activated languages * * @return array * @throws \InvalidArgumentException */ public static function getLanguages(): array { /** @var $databaseConnection DatabaseConnection */ $databaseConnection = $GLOBALS['TYPO3_DB']; /** @var QueryResultInterface $rows */ $rows = $databaseConnection->exec_SELECTgetRows( '*', 'sys_language', 'hidden = 0' ); $languages = []; // adding default language $languages[] = ['isocode' => MailTemplateService::DEFAULT_LANGUAGE, 'name' => LocalizationUtility::translate( 'backend.language_default', 'SgMail' )]; foreach ($rows as $language) { $languages[] = ['isocode' => $language['language_isocode'], 'name' => $language['title']]; } return $languages; } /** * get an array of all the labels for the activated languages * * @param array $languages * @return array * @throws \InvalidArgumentException */ public static function getLanguageLabels(array $languages): array { $languageLabels = []; foreach ($languages as $language) { $languageLabels[$language['isocode']] = $language['name']; } return $languageLabels; } /** * Get the languages in an array suitable for filtering * * @return array * @throws \InvalidArgumentException */ public static function getLanguagesForFilter(): array { $languages = self::getLanguages(); array_unshift($languages, ['isocode' => '', 'name' => '']); $filterLanguages = []; if (\count($languages) > 0) { foreach ($languages as $language) { $filterLanguages[$language['isocode']] = $language['name']; } } return $filterLanguages; } /** * Get the template keys in an array suitable for filtering * * @param int $pageUid * @return array * @throws \InvalidArgumentException * @throws \BadFunctionCallException * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException */ public static function getTemplatesForFilter($pageUid): array { $pageUid = (int) $pageUid; $registerArray = self::getNonBlacklistedTemplates($pageUid); $templates = []; foreach ($registerArray as $extensions) { foreach ($extensions as $template => $key) { $templates[$key['extension']][] = $key['templateName']; } } array_unshift($templates, ''); return $templates; } /** * Save or update the template in the DB, depending if it already exists or not * * @param int $pid * @param string $selectedExtension * @param string $selectedTemplate * @param string $language * @param array $templateData * @return Template $template * @throws \InvalidArgumentException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException */ public static function saveTemplate($pid, $selectedExtension, $selectedTemplate, $language, $templateData ): Template { $objectManager = GeneralUtility::makeInstance(ObjectManager::class); $templateRepository = $objectManager->get(TemplateRepository::class); /** @var Template $template */ $template = $templateRepository->findOneByTemplate( $selectedExtension, $selectedTemplate, $language, $pid ); $templateAlreadyExists = TRUE; $objectManager = GeneralUtility::makeInstance(ObjectManager::class); if ($template === NULL) { $templateAlreadyExists = FALSE; $template = $objectManager->get(Template::class); } $template->setExtensionKey($selectedExtension); $template->setTemplateName($selectedTemplate); $template->setLanguage($language); $template->setContent($templateData['content']); $template->setSubject($templateData['subject']); $template->setFromName($templateData['fromName']); $template->setFromMail($templateData['fromMail']); $template->setCc($templateData['cc']); $template->setBcc($templateData['bcc']); $template->setReplyTo($templateData['replyTo']); $template->setToAddress($templateData['toAddress']); if ($templateAlreadyExists) { $templateRepository->update($template); } else { $templateRepository->add($template); } $objectManager = GeneralUtility::makeInstance(ObjectManager::class); $persistenceManager = $objectManager->get(PersistenceManager::class); $persistenceManager->persistAll(); return $template; } /** * Generate a csv string from the queues, respecting the given filters * * @param array $filters * @return string * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException * @throws \InvalidArgumentException */ public static function getCsvFromQueue(array $filters = []): string { $objectManager = GeneralUtility::makeInstance(ObjectManager::class); /** @var MailRepository $mailRepository */ $mailRepository = $objectManager->get(MailRepository::class); $pageUid = (int) GeneralUtility::_GP('id'); /** @var array $queue */ $queue = $mailRepository->findAllEntries($pageUid, 0, $filters); $totalQueueSize = \count($queue); $exportString = ''; if ($totalQueueSize && $queue) { $ignoreFields = ['uid', 'pid', 'tstamp', 'password', 'starttime', 'endtime', 'deleted', 'sent', 'priority', 'crdate', 'cruser_id', 'hidden']; $dateFields = ['tstamp', 'starttime', 'endtime', 'crdate']; $export = [[]]; $first = TRUE; /** @var array $mail */ foreach ($queue as $mail) { if ($first) { $first = FALSE; foreach ($mail as $field => $value) { if (!\in_array($field, $ignoreFields, TRUE)) { $label = isset($GLOBALS['TCA']['tx_sgmail_domain_model_mail']['columns'][$field]) ? $GLOBALS['TCA']['fe_users']['columns'][$field]['label'] : ''; if (strpos($label, 'LLL:') === 0) { $label = $GLOBALS['LANG']->sL($label); } $export[0][] = $label ?: $field; } } } } $line = 1; /** @var array $mail */ foreach ($queue as $mail) { foreach ($mail as $field => $value) { if (!\in_array($field, $ignoreFields, TRUE)) { if (\in_array($field, $dateFields, TRUE)) { $export[$line][] = $value ? date('d.m.Y', $value) : ''; } else { $export[$line][] = (string) $value; } } } $line++; } foreach ($export as $line) { /** @var array $line */ $fields = []; foreach ($line as $field) { $fields[] = '"' . $field . '"'; } $exportString .= implode(',', $fields) . ';' . LF; } } return trim(preg_replace('/\s\s+/', ' ', strip_tags($exportString))); } /** * Filter the register array to have only whitelisted templates for this domain * * @param int $siteRootId * @throws \InvalidArgumentException * @throws \BadFunctionCallException * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException * @return array */ public static function getNonBlacklistedTemplates($siteRootId): array { $siteRootId = (int) $siteRootId; $registerService = GeneralUtility::makeInstance(RegisterService::class); $registerArray = $registerService->getRegisterArray(); $extensionConfiguration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['sg_mail'], ['array']); if (isset($extensionConfiguration['excludeTemplates']) && $extensionConfiguration['excludeTemplates'] !== '') { $excludedTemplatesWithSiteId = GeneralUtility::trimExplode( ';', $extensionConfiguration['excludeTemplates'], TRUE ); foreach ($excludedTemplatesWithSiteId as $currentSite) { $currentSiteBlacklist = GeneralUtility::trimExplode(',', $currentSite, TRUE); if ((int) $currentSiteBlacklist[0] === $siteRootId) { foreach ($currentSiteBlacklist as $excludedTemplate) { list($extensionKey, $templateName) = GeneralUtility::trimExplode('.', $excludedTemplate); if ($extensionKey && $templateName && isset($registerArray[$extensionKey][$templateName])) { unset($registerArray[$extensionKey][$templateName]); } } } } } // filter out excluded templates from all domains if (isset($extensionConfiguration['excludeTemplatesAllDomains']) && $extensionConfiguration['excludeTemplatesAllDomains'] !== '' ) { $excludedTemplates = GeneralUtility::trimExplode( ',', $extensionConfiguration['excludeTemplatesAllDomains'], TRUE ); foreach ($excludedTemplates as $excludedTemplate) { list($extensionKey, $templateName) = GeneralUtility::trimExplode('.', $excludedTemplate); if ($extensionKey && $templateName && isset($registerArray[$extensionKey][$templateName])) { unset($registerArray[$extensionKey][$templateName]); } } } return $registerArray; } }