<?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 TYPO3\CMS\Core\Cache\CacheManager; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Object\ObjectManager; /** * Provides an api for registering your mail templates */ class RegisterService implements \TYPO3\CMS\Core\SingletonInterface { const CACHE_NAME = 'sg_mail_registerArrayCache'; const CACHE_LIFETIME_IN_SECONDS = 86400; const DEFAULT_TEMPLATE_PATH = 'Resources/Private/Templates/SgMail/'; const CONFIG_PATH = 'Configuration/MailTemplates/Forms'; /** * contains the actual registration data * * @var array */ private $registerArray = []; /** * Get all registered templates from the cache. if the cache expired, the entries are generated * * @return array * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException * @throws \BadFunctionCallException * @throws \InvalidArgumentException */ public function getRegisterArray(): array { if (\count($this->registerArray) > 1) { return $this->registerArray; } $cacheManager = GeneralUtility::makeInstance(CacheManager::class); $cache = $cacheManager->getCache(self::CACHE_NAME); $registerArray = $cache->get('sg_mail'); if (!$registerArray || !\is_array($registerArray)) { $registerArray = $this->registerExtensions(); if (\is_array($registerArray)) { $cache->set('sg_mail', $registerArray, [], self::CACHE_LIFETIME_IN_SECONDS); } } if (!\is_array($registerArray)) { $registerArray = []; } return $registerArray; } /** * Read every registered file and create a registration entry in the registerArray if possible * * @return array */ private function registerExtensions(): array { $this->registerArray = []; // @TODO remove in version 5.0.0 $extensionConfiguration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['sg_mail'], ['array']); if (((int) $extensionConfiguration['supportOldRegistrations']) === 0) { MailTemplateService::registerExtensions(); } foreach ($GLOBALS['sg_mail'] as $extensionName => $templates) { foreach ($templates as $templateKey => $registerFile) { // already registered in the new way? Then don't load the old one again. // @TODO remove in version 5.0.0 $insecureRegistration = FALSE; if (strpos($templateKey, '.php')) { $insecureRegistration = TRUE; $registerFileTest = str_replace('.php', '', $templateKey); $registerFileTest = GeneralUtility::camelCaseToLowerCaseUnderscored($registerFileTest); if (isset($GLOBALS['sg_mail'][$extensionName][$registerFileTest]) || isset($GLOBALS['sg_mail']['sg_mail'][$registerFileTest]) ) { continue; } } $registerFile = GeneralUtility::getFileAbsFileName($registerFile); if (!\is_file($registerFile)) { continue; } $configArray = (include $registerFile); $extensionKey = $configArray['extension_key']; $templateKey = $configArray['template_key']; if ($extensionKey === NULL) { continue; } $this->writeRegisterArrayEntry($extensionKey, $templateKey, $configArray, $insecureRegistration); } } // read automatically created extensionName registrations and write the entries $configurationLocation = $this->getRegistrationPath(); $registerFolder = GeneralUtility::getFileAbsFileName($configurationLocation); if (\is_dir($registerFolder)) { $configFiles = GeneralUtility::getFilesInDir($registerFolder); foreach ($configFiles as $configFile) { $pathToRegistrationFile = $registerFolder . '/' . $configFile; if (!\is_file($pathToRegistrationFile)) { continue; } // get file name without folders $pathAsArray = GeneralUtility::trimExplode('/', $pathToRegistrationFile); $filename = $pathAsArray[\count($pathAsArray) - 1]; $filenameWithoutHash = GeneralUtility::trimExplode('_', $filename, FALSE, 2)[1]; $hash = md5($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . '|' . $filenameWithoutHash); // if the filename doesn't start with the hash value, ignore it if (strpos($filename, $hash) !== 0) { continue; } $configArray = (include $pathToRegistrationFile); $extensionKey = $configArray['extension_key']; $templateKey = $configArray['template_key']; if ($extensionKey === NULL || $templateKey === NULL) { continue; } $this->writeRegisterArrayEntry($extensionKey, $templateKey, $configArray, FALSE); } } return $this->registerArray; } /** * write a single entry into the register array * * @param string $extensionKey * @param string $templateKey * @param array $configArray * @param bool $insecureRegistration */ private function writeRegisterArrayEntry( $extensionKey, $templateKey, array $configArray, $insecureRegistration = FALSE ) { // template_path means where to find the mail body content (usually it's set directly in the registration // as template_content) if ($configArray['template_path']) { $templatePath = $configArray['template_path']; } else { if (!ExtensionManagementUtility::isLoaded($extensionKey)) { return; } // transform template directory name: your_templates => YourTemplates/ $templateDirectoryParts = GeneralUtility::trimExplode('_', $templateKey); $templateDirectory = ''; foreach ($templateDirectoryParts as $part) { $templateDirectory .= \ucfirst($part); } $templateDirectory .= '/'; $templatePath = ExtensionManagementUtility::extPath($extensionKey) . self::DEFAULT_TEMPLATE_PATH . $templateDirectory; } if (!\is_dir($templatePath)) { $templatePath = ''; } $description = $configArray['description']; $subject = $configArray['subject']; $marker = $configArray['markers']; $templateContent = $configArray['templateContent']; $this->registerArray[$extensionKey][$templateKey] = [ 'templatePath' => $templatePath, 'description' => $description, 'marker' => $marker, 'extension' => $extensionKey, 'templateName' => $templateKey, 'subject' => $subject, 'templateContent' => $templateContent, 'insecureRegistration' => $insecureRegistration ]; } /** * Returns the path to the configured location where automatic mail template registrations should be * * @return string */ private function getRegistrationPath(): string { // get typoscript settings from sg mail /** @var TypoScriptSettingsService $typoScriptSettingsService */ $typoScriptSettingsService = GeneralUtility::makeInstance(TypoScriptSettingsService::class); $tsSettings = $typoScriptSettingsService->getSettings(0, 'tx_sgmail'); // get the location where automatic registrations should be stored return 'EXT:' . $tsSettings['mail']['configurationLocation'] . '/' . self::CONFIG_PATH; } /** * Clear the sgmail register cache * * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException */ public function clearCaches() { $objectManager = GeneralUtility::makeInstance(ObjectManager::class); $cacheManager = $objectManager->get(CacheManager::class); /** @var FrontendInterface $cache */ $cache = $cacheManager->getCache(self::CACHE_NAME); /** @var FrontendInterface $cache */ $cache->flush(); } /** * Write the mail registration file * * @param string $templateKey * @param string $extensionKey * @param array $markers * @param string $subject * @param string $description * @return string */ public function writeRegisterFile($templateKey, $extensionKey, $markers, $subject = '', $description = ''): string { $configurationLocation = $this->getRegistrationPath(); $registerFolder = GeneralUtility::getFileAbsFileName($configurationLocation); GeneralUtility::mkdir_deep($registerFolder); $hashPrefix = md5($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . '|' . $templateKey . '.php'); $registerFile = GeneralUtility::getFileAbsFileName( $registerFolder . '/' . $hashPrefix . '_' . $templateKey . '.php' ); $newRegisterArray = [ 'extension_key' => $extensionKey, 'template_key' => $templateKey, 'description' => $description, 'subject' => $subject, 'markers' => [] ]; foreach ($markers as $marker) { $markerName = $marker['identifier']; $newRegisterArray['markers'][] = [ 'marker' => $markerName, 'type' => MailTemplateService::MARKER_TYPE_STRING, 'value' => $marker['value'], 'description' => $marker['description'] ]; } file_put_contents($registerFile, '<?php return ' . var_export($newRegisterArray, TRUE) . ';'); return $registerFile; } /** * Trims non-allowed characters from the form field marker name * * @param string $markerName * @return string */ public static function normalizeFormFieldMarkerName($markerName = '') { return \preg_replace('/[^a-z0-9\-_]/i', '', $markerName); } }