Commit 74b4f85e authored by Rémy DANIEL's avatar Rémy DANIEL Committed by Kevin Ditscheid
Browse files

[FEATURE] Add option for configuration file location

This commit adds the possibilty to set a different path than
AdditionalConfiguration.php to store the lfeditor language file
overrides.
parent 170f1c69
Pipeline #16 canceled with stages
<?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!
*/
namespace SGalinski\Lfeditor\Exceptions;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
/**
* DirectoryAccessRightsException can be thrown for exceptions relating to file access and write permissions
* in directories
*
* @package SGalinski\Lfeditor\Exceptions
* @author Kevin Ditscheid <kevin.ditscheid@sgalinski.de>
*/
class DirectoryAccessRightsException extends \Exception {
/**
* DirectoryAccessRightsException constructor.
*
* @param string $message
* @param int $code
* @param \Exception|NULL $previous
*/
public function __construct($message = '', $code = 0, $previous = NULL) {
if (\strpos($message, 'LLL:') === 0) {
$locallizedMessage = LocalizationUtility::translate($message, 'lfeditor');
$message = $locallizedMessage !== NULL ? $locallizedMessage : $message;
}
if ($message === '') {
$message = 'LFExeption: no error message given !!!';
}
parent::__construct($message, $code, $previous);
}
}
...@@ -27,6 +27,7 @@ namespace SGalinski\Lfeditor\Service; ...@@ -27,6 +27,7 @@ namespace SGalinski\Lfeditor\Service;
***************************************************************/ ***************************************************************/
use Exception; use Exception;
use SGalinski\Lfeditor\Exceptions\DirectoryAccessRightsException;
use SGalinski\Lfeditor\Exceptions\LFException; use SGalinski\Lfeditor\Exceptions\LFException;
use SGalinski\Lfeditor\Utility\Functions; use SGalinski\Lfeditor\Utility\Functions;
use SGalinski\Lfeditor\Utility\SgLib; use SGalinski\Lfeditor\Utility\SgLib;
...@@ -82,20 +83,20 @@ class ConfigurationService extends AbstractService { ...@@ -82,20 +83,20 @@ class ConfigurationService extends AbstractService {
* Note that the default value will be set, if a option check fails. * Note that the default value will be set, if a option check fails.
* *
* @return array * @return array
* @throws \InvalidArgumentException * @throws DirectoryAccessRightsException
*/ */
public function prepareConfig() { public function prepareConfig() {
if (!empty($this->extConfig)) { if (!empty($this->extConfig)) {
return $this->extConfig; return $this->extConfig;
} }
$this->extConfig = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['lfeditor'], []); $this->extConfig = \unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['lfeditor'], []);
// regular expressions // regular expressions
if (!preg_match('/^\/.*\/.*$/', $this->extConfig['searchRegex'])) { if (!\preg_match('/^\/.*\/.*$/', $this->extConfig['searchRegex'])) {
$this->extConfig['searchRegex'] = '/^([a-z0-9_]*locallang[a-z0-9_-]*\.(php|xml)|[^\.]*\.xlf)$/i'; $this->extConfig['searchRegex'] = '/^([a-z0-9_]*locallang[a-z0-9_-]*\.(php|xml)|[^\.]*\.xlf)$/i';
} }
if (!preg_match('/^\/.*\/.*$/', $this->extConfig['extIgnore'])) { if (!\preg_match('/^\/.*\/.*$/', $this->extConfig['extIgnore'])) {
$this->extConfig['extIgnore'] = '/^csh_.*$/'; $this->extConfig['extIgnore'] = '/^csh_.*$/';
} }
...@@ -183,6 +184,22 @@ class ConfigurationService extends AbstractService { ...@@ -183,6 +184,22 @@ class ConfigurationService extends AbstractService {
unset($this->availabledEditingModes['l10n']); unset($this->availabledEditingModes['l10n']);
} }
if (isset($this->extConfig['pathAdditionalConfiguration']) && $this->extConfig['pathAdditionalConfiguration']) {
$pathAdditionalConfiguration = Typo3Lib::fixFilePath($this->extConfig['pathAdditionalConfiguration']);
$this->extConfig['pathAdditionalConfiguration'] = \realpath(PATH_site . $pathAdditionalConfiguration);
$additionalConfigurationDirectory = \dirname($this->extConfig['pathAdditionalConfiguration']);
if (!\is_writable($additionalConfigurationDirectory)) {
$message = 'Directory ' . $additionalConfigurationDirectory . ' is not writable.'
. 'This directory should be writable in order to write the language override configuration '
. 'file ' . $pathAdditionalConfiguration;
throw new DirectoryAccessRightsException($message);
}
} else {
/** @var \TYPO3\CMS\Core\Configuration\ConfigurationManager $configurationManager */
$configurationManager = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class);
$this->extConfig['pathAdditionalConfiguration'] = $configurationManager->getAdditionalConfigurationFileLocation();
}
return $this->extConfig; return $this->extConfig;
} }
...@@ -212,7 +229,7 @@ class ConfigurationService extends AbstractService { ...@@ -212,7 +229,7 @@ class ConfigurationService extends AbstractService {
} }
// global extensions // global extensions
if ($this->extConfig['viewGlobalExt'] && is_dir(Typo3Lib::PATH_GLOBAL_EXT)) { if ($this->extConfig['viewGlobalExt'] && \is_dir(Typo3Lib::PATH_GLOBAL_EXT)) {
if (\count( if (\count(
$content = Functions::searchExtensions( $content = Functions::searchExtensions(
PATH_site . Typo3Lib::PATH_GLOBAL_EXT, $this->extConfig['viewStateExt'], PATH_site . Typo3Lib::PATH_GLOBAL_EXT, $this->extConfig['viewStateExt'],
...@@ -248,7 +265,7 @@ class ConfigurationService extends AbstractService { ...@@ -248,7 +265,7 @@ class ConfigurationService extends AbstractService {
// create list // create list
/** @var array $extList */ /** @var array $extList */
$extList = Functions::prepareExtList($tmpExtList); $extList = Functions::prepareExtList($tmpExtList);
$extList = array_merge([PATH_site . 'fileadmin' => 'fileadmin/', ''], $extList); $extList = \array_merge([PATH_site . 'fileadmin' => 'fileadmin/', ''], $extList);
foreach ($extList as $extAddress => $extLabel) { foreach ($extList as $extAddress => $extLabel) {
unset ($extList[$extAddress]); unset ($extList[$extAddress]);
...@@ -286,9 +303,9 @@ class ConfigurationService extends AbstractService { ...@@ -286,9 +303,9 @@ class ConfigurationService extends AbstractService {
} }
$fileArray = []; $fileArray = [];
if (count($files)) { if (\count($files)) {
foreach ($files as $file) { foreach ($files as $file) {
$filename = substr($file, strlen($extensionAddress) + 1); $filename = \substr($file, \strlen($extensionAddress) + 1);
$fileArray[$filename] = $filename; $fileArray[$filename] = $filename;
} }
} else { } else {
...@@ -316,8 +333,8 @@ class ConfigurationService extends AbstractService { ...@@ -316,8 +333,8 @@ class ConfigurationService extends AbstractService {
$languageList = []; $languageList = [];
foreach ($languageArray as $language) { foreach ($languageArray as $language) {
$constCount = 0; $constCount = 0;
if (is_array($langData[$language])) { if (\is_array($langData[$language])) {
$constCount = count($langData[$language]); $constCount = \count($langData[$language]);
} }
if ($translatedLanguagesOnly && $constCount <= 0) { if ($translatedLanguagesOnly && $constCount <= 0) {
continue; continue;
...@@ -332,7 +349,7 @@ class ConfigurationService extends AbstractService { ...@@ -332,7 +349,7 @@ class ConfigurationService extends AbstractService {
// add default value // add default value
if (!empty($default)) { if (!empty($default)) {
$languageList = array_merge(['###default###' => $default], $languageList); $languageList = \array_merge(['###default###' => $default], $languageList);
} }
return $languageList; return $languageList;
} }
...@@ -349,20 +366,20 @@ class ConfigurationService extends AbstractService { ...@@ -349,20 +366,20 @@ class ConfigurationService extends AbstractService {
$constList = []; $constList = [];
$languages = Functions::buildLangArray(); $languages = Functions::buildLangArray();
foreach ($languages as $language) { foreach ($languages as $language) {
if (!is_array($langData[$language]) || !count($langData[$language])) { if (!\is_array($langData[$language]) || !\count($langData[$language])) {
continue; continue;
} }
/** @var array $constants */ /** @var array $constants */
$constants = array_keys($langData[$language]); $constants = \array_keys($langData[$language]);
foreach ($constants as $constant) { foreach ($constants as $constant) {
$constList[str_replace('#', '$*-*$', $constant)] = $constant; $constList[\str_replace('#', '$*-*$', $constant)] = $constant;
} }
} }
// sorting and default entry // sorting and default entry
asort($constList); \asort($constList);
$constList = array_merge(['###default###' => $default], $constList); $constList = \array_merge(['###default###' => $default], $constList);
return $constList; return $constList;
} }
...@@ -381,8 +398,8 @@ class ConfigurationService extends AbstractService { ...@@ -381,8 +398,8 @@ class ConfigurationService extends AbstractService {
*/ */
public function initFileObject($langFile, $extPath, $flagReadFile = TRUE) { public function initFileObject($langFile, $extPath, $flagReadFile = TRUE) {
$fileType = SgLib::getFileExtension($langFile); $fileType = SgLib::getFileExtension($langFile);
$className = __NAMESPACE__ . '\FileBase' . strtoupper($fileType) . 'Service'; $className = __NAMESPACE__ . '\FileBase' . \strtoupper($fileType) . 'Service';
if (!class_exists($className)) { if (!\class_exists($className)) {
throw new LFException('failure.langfile.unknownType'); throw new LFException('failure.langfile.unknownType');
} }
/** @var \SGalinski\Lfeditor\Service\FileService $originalFileObject */ /** @var \SGalinski\Lfeditor\Service\FileService $originalFileObject */
...@@ -422,7 +439,7 @@ class ConfigurationService extends AbstractService { ...@@ -422,7 +439,7 @@ class ConfigurationService extends AbstractService {
*/ */
public function execWrite($modArray, $modMetaArray = [], $forceDel = FALSE, $editedLanguages = NULL) { public function execWrite($modArray, $modMetaArray = [], $forceDel = FALSE, $editedLanguages = NULL) {
// checks // checks
if (!is_array($modArray)) { if (!\is_array($modArray)) {
throw new LFException('failure.file.notWritten'); throw new LFException('failure.file.notWritten');
} }
...@@ -448,7 +465,7 @@ class ConfigurationService extends AbstractService { ...@@ -448,7 +465,7 @@ class ConfigurationService extends AbstractService {
} }
// set new language data // set new language data
foreach ($modArray as $langKey => $data) { foreach ($modArray as $langKey => $data) {
if (is_array($data)) { if (\is_array($data)) {
foreach ($data as $const => $value) { foreach ($data as $const => $value) {
$fileObject->setLocalLangData($const, $value, $langKey, $forceDel); $fileObject->setLocalLangData($const, $value, $langKey, $forceDel);
} }
...@@ -468,19 +485,19 @@ class ConfigurationService extends AbstractService { ...@@ -468,19 +485,19 @@ class ConfigurationService extends AbstractService {
$originLang = $fileObject->getOriginLangData(); $originLang = $fileObject->getOriginLangData();
$emptyFiles = []; $emptyFiles = [];
foreach ($originLang as $lang => $origin) { foreach ($originLang as $lang => $origin) {
if ($origin == $absFile || !is_file($origin)) { if ($origin == $absFile || !\is_file($origin)) {
continue; continue;
} }
$langData = $fileObject->getLocalLangData($lang); $langData = $fileObject->getLocalLangData($lang);
if (is_array($langData) && !count($langData)) { if (\is_array($langData) && !\count($langData)) {
$emptyFiles[] = $origin; $emptyFiles[] = $origin;
} }
} }
// delete all empty language files // delete all empty language files
try { try {
if (count($emptyFiles)) { if (\count($emptyFiles)) {
SgLib::deleteFiles($emptyFiles); SgLib::deleteFiles($emptyFiles);
} }
} catch (Exception $e) { } catch (Exception $e) {
...@@ -502,7 +519,7 @@ class ConfigurationService extends AbstractService { ...@@ -502,7 +519,7 @@ class ConfigurationService extends AbstractService {
*/ */
public function execSplitFile(array $langModes) { public function execSplitFile(array $langModes) {
// check // check
if (!is_array($langModes) || !count($langModes)) { if (!\is_array($langModes) || !\count($langModes)) {
throw new LFException('failure.langfile.notSplittedOrMerged'); throw new LFException('failure.langfile.notSplittedOrMerged');
} }
...@@ -520,22 +537,22 @@ class ConfigurationService extends AbstractService { ...@@ -520,22 +537,22 @@ class ConfigurationService extends AbstractService {
if ($mode === 1) { if ($mode === 1) {
// nothing to do if the file is already a normal splitted file // nothing to do if the file is already a normal splitted file
if (Typo3Lib::checkFileLocation($origin) != 'l10n') { if (Typo3Lib::checkFileLocation($origin) != 'l10n') {
if ($this->fileObj->checkLocalizedFile(basename($origin), $langKey)) { if ($this->fileObj->checkLocalizedFile(\basename($origin), $langKey)) {
continue; continue;
} }
} }
// delete file if was it a l10n file // delete file if was it a l10n file
if ($this->fileObj->checkLocalizedFile(basename($origin), $langKey)) { if ($this->fileObj->checkLocalizedFile(\basename($origin), $langKey)) {
$delLangFiles[] = $origin; $delLangFiles[] = $origin;
} }
$origin = Typo3Lib::fixFilePath( $origin = Typo3Lib::fixFilePath(
dirname($this->fileObj->getVar('absFile')) . \dirname($this->fileObj->getVar('absFile')) .
'/' . $this->fileObj->nameLocalizedFile($langKey) '/' . $this->fileObj->nameLocalizedFile($langKey)
); );
} elseif ($mode === 2) { } elseif ($mode === 2) {
if ($this->fileObj->checkLocalizedFile(basename($origin), $langKey)) { if ($this->fileObj->checkLocalizedFile(\basename($origin), $langKey)) {
$delLangFiles[] = $origin; $delLangFiles[] = $origin;
} }
$origin = $this->fileObj->getVar('absFile'); $origin = $this->fileObj->getVar('absFile');
...@@ -550,7 +567,7 @@ class ConfigurationService extends AbstractService { ...@@ -550,7 +567,7 @@ class ConfigurationService extends AbstractService {
// delete old localized files, if single mode was selected // delete old localized files, if single mode was selected
try { try {
if (count($delLangFiles)) { if (\count($delLangFiles)) {
SgLib::deleteFiles($delLangFiles); SgLib::deleteFiles($delLangFiles);
} }
} catch (Exception $e) { } catch (Exception $e) {
...@@ -584,8 +601,8 @@ class ConfigurationService extends AbstractService { ...@@ -584,8 +601,8 @@ class ConfigurationService extends AbstractService {
// localized or merged language origin // localized or merged language origin
$newFile = SgLib::setFileExtension($type, $file); $newFile = SgLib::setFileExtension($type, $file);
if ($this->convObj->getVar('workspace') == 'base') { if ($this->convObj->getVar('workspace') == 'base') {
if ($this->convObj->checkLocalizedFile(basename($file), $langKey)) { if ($this->convObj->checkLocalizedFile(\basename($file), $langKey)) {
$newFile = dirname($file) . '/' . $this->fileObj->nameLocalizedFile($langKey); $newFile = \dirname($file) . '/' . $this->fileObj->nameLocalizedFile($langKey);
} }
} }
$this->fileObj->setOriginLangData(Typo3Lib::fixFilePath($newFile), $langKey); $this->fileObj->setOriginLangData(Typo3Lib::fixFilePath($newFile), $langKey);
...@@ -604,7 +621,7 @@ class ConfigurationService extends AbstractService { ...@@ -604,7 +621,7 @@ class ConfigurationService extends AbstractService {
// delete all old files // delete all old files
try { try {
$delFiles = $this->convObj->getOriginLangData(); $delFiles = $this->convObj->getOriginLangData();
if (is_array($delFiles) && count($delFiles)) { if (\is_array($delFiles) && \count($delFiles)) {
SgLib::deleteFiles($delFiles); SgLib::deleteFiles($delFiles);
} }
} catch (Exception $e) { } catch (Exception $e) {
...@@ -707,11 +724,11 @@ class ConfigurationService extends AbstractService { ...@@ -707,11 +724,11 @@ class ConfigurationService extends AbstractService {
$languages = Functions::buildLangArray($this->extConfig['viewLanguages']); $languages = Functions::buildLangArray($this->extConfig['viewLanguages']);
$languages = $this->narrowToUserLanguages($languages, $backendUser); $languages = $this->narrowToUserLanguages($languages, $backendUser);
if (!in_array('default', $languages)) { if (!\in_array('default', $languages)) {
$languages = array_merge(['default'], $languages); $languages = \array_merge(['default'], $languages);
} }
if (!in_array($this->extConfig['defaultLanguage'], $languages)) { if (!\in_array($this->extConfig['defaultLanguage'], $languages)) {
$languages = array_merge([$this->extConfig['defaultLanguage']], $languages); $languages = \array_merge([$this->extConfig['defaultLanguage']], $languages);
} }
$this->langArray = $languages; $this->langArray = $languages;
} }
...@@ -725,6 +742,15 @@ class ConfigurationService extends AbstractService { ...@@ -725,6 +742,15 @@ class ConfigurationService extends AbstractService {
$this->langArray = $langArray; $this->langArray = $langArray;
} }
/**
* Return the path to the configured AdditionalConfiguration.php file
*
* @return string
*/
public function getAdditionalConfigurationFilePath() {
return $this->extConfig['pathAdditionalConfiguration'];
}
/** /**
* Narrows $languages to user languages if user is not admin. * Narrows $languages to user languages if user is not admin.
* *
......
...@@ -161,10 +161,14 @@ class FileOverrideService extends FileBaseXMLService { ...@@ -161,10 +161,14 @@ class FileOverrideService extends FileBaseXMLService {
return; return;
} }
/** @var ConfigurationService $configurationService */
$configurationService = $this->objectManager->get( ConfigurationService::class );
$additionalConfigurationFilePath = $configurationService->getAdditionalConfigurationFilePath();
try { try {
$addLine = '$GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'locallangXMLOverride\'][\'' $addLine = '$GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'locallangXMLOverride\'][\''
. $typo3ExtRelativeFilePath . '\'][0] = \'' . $relativeOverrideFilePath . '\';'; . $typo3ExtRelativeFilePath . '\'][0] = \'' . $relativeOverrideFilePath . '\';';
Typo3Lib::writeLineToAdditionalConfiguration($addLine); Typo3Lib::writeLineToAdditionalConfiguration( $addLine, $additionalConfigurationFilePath );
$GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride'][$typo3ExtRelativeFilePath][0] $GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride'][$typo3ExtRelativeFilePath][0]
= $relativeOverrideFilePath; = $relativeOverrideFilePath;
} catch (\Exception $exception) { } catch (\Exception $exception) {
......
...@@ -124,16 +124,14 @@ class Typo3Lib { ...@@ -124,16 +124,14 @@ class Typo3Lib {
} }
/** /**
* Adds configuration line to AdditionalConfiguration.php. * Adds configuration line to AdditionalConfiguration file.
* *
* @param string $configLine line to be added. * @param string $configLine line to be added.
* @param string $additionalConfigurationFilePath
*
* @return void * @return void
* @throws \InvalidArgumentException
*/ */
public static function writeLineToAdditionalConfiguration($configLine) { public static function writeLineToAdditionalConfiguration($configLine, $additionalConfigurationFilePath) {
/** @var ConfigurationManager $configurationManager */
$configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
$additionalConfigurationFilePath = $configurationManager->getAdditionalConfigurationFileLocation();
SgLib::appendToPHPFile($additionalConfigurationFilePath, $configLine); SgLib::appendToPHPFile($additionalConfigurationFilePath, $configLine);
} }
} }
...@@ -20,3 +20,6 @@ editModeExtension = 1 ...@@ -20,3 +20,6 @@ editModeExtension = 1
# cat=basic; type=boolean; label=Allow edit mode "l10n" # cat=basic; type=boolean; label=Allow edit mode "l10n"
editModeL10n = 1 editModeL10n = 1
# cat=basic; type=string; label=Path to AdditionalConfiguration.php file: It is possible to change the file where locallangXMLOverride will be declared. Relative to the document root. If modified, don't forget then to include the custom file path from the AdditionalConfiguration.php.
pathAdditionalConfiguration = typo3conf/AdditionalConfiguration.php
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment