Skip to content
Snippets Groups Projects
RegisterService.php 9.64 KiB
Newer Older
<?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);
	 * Read every registered file and create a registration entry in the registerArray if possible
	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'];
				$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)) {
				// 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) {
				$configArray = (include $pathToRegistrationFile);
				$extensionKey = $configArray['extension_key'];
				$templateKey = $configArray['template_key'];
				if ($extensionKey === NULL || $templateKey === NULL) {
					continue;
				}

				$this->writeRegisterArrayEntry($extensionKey, $templateKey, $configArray, FALSE);
	 * @param string $extensionKey
	 * @param string $templateKey
		$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 (!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
	 */
Torsten Oppermann's avatar
Torsten Oppermann committed
	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();
	}
Torsten Oppermann's avatar
Torsten Oppermann committed

	/**
	 * Write the mail registration file
	 *
	 * @param string $templateKey
	 * @param string $extensionKey
	 * @param array $markers
	 * @param string $subject
	 * @param string $description
Torsten Oppermann's avatar
Torsten Oppermann committed
	 */
	public function writeRegisterFile($templateKey, $extensionKey, $markers, $subject = '', $description = ''): string {
Torsten Oppermann's avatar
Torsten Oppermann committed
		$configurationLocation = $this->getRegistrationPath();
		$registerFolder = GeneralUtility::getFileAbsFileName($configurationLocation);
		GeneralUtility::mkdir_deep($registerFolder);
Torsten Oppermann's avatar
Torsten Oppermann committed

		$hashPrefix = md5($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . '|' . $templateKey . '.php');
		$registerFile = GeneralUtility::getFileAbsFileName(
			$registerFolder . '/' . $hashPrefix . '_' . $templateKey . '.php'
		);

Torsten Oppermann's avatar
Torsten Oppermann committed
		$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) . ';');
Torsten Oppermann's avatar
Torsten Oppermann committed
	}

	/**
	 * 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);
	}