FileOverrideService.php 7.32 KB
Newer Older
1 2 3 4 5 6 7
<?php

namespace SGalinski\Lfeditor\Service;

/***************************************************************
 *  Copyright notice
 *
Stefan Galinski's avatar
Stefan Galinski committed
8
 *  (c) sgalinski Internet Services (https://www.sgalinski.de)
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 *
 *  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\Lfeditor\Exceptions\LFException;
use SGalinski\Lfeditor\Utility\SgLib;
use SGalinski\Lfeditor\Utility\Typo3Lib;

33 34 35
/**
 * FileOverrideService
 */
Damjan's avatar
Damjan committed
36
class FileOverrideService extends FileBaseXMLService {
37 38 39 40 41 42 43 44 45 46 47 48 49
	/**
	 * Object which represents original (overridden) language file.
	 *
	 * @var \SGalinski\Lfeditor\Service\FileService
	 */
	protected $originalFileObject;

	/**
	 * Initialises fileObject of override language file.
	 *
	 * @param FileService $originalFileObject
	 * @return void
	 */
50
	public function init($originalFileObject, $path, $metaFile) {
51 52 53 54 55 56 57
		try {
			$typo3ExtRelativeFilePath = Typo3Lib::transTypo3File($originalFileObject->getAbsFile(), FALSE);
		} catch (\Exception $e) {
			$typo3ExtRelativeFilePath = '';
		}
		$overrideFileAbsolutePath = Typo3Lib::fixFilePath(
			PATH_site . '/' .
Damjan's avatar
Damjan committed
58
			$GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride'][$typo3ExtRelativeFilePath][0]
59 60 61 62
		);

		if (!is_file($overrideFileAbsolutePath)) {
			$extRelativeFilePath = SgLib::trimPath('EXT:', $typo3ExtRelativeFilePath);
Damjan's avatar
Damjan committed
63
			$extRelativeFilePath = substr($extRelativeFilePath, 0, strrpos($extRelativeFilePath, '.')) . '.xml';
64 65 66

			/** @var ConfigurationService $configurationService */
			$configurationService = $this->objectManager->get('SGalinski\Lfeditor\Service\ConfigurationService');
Damjan's avatar
Damjan committed
67 68
			$extConfig = $configurationService->getExtConfig();
			$overrideFileAbsolutePath = $extConfig['pathOverrideFiles']
69 70 71 72
				. $extRelativeFilePath;
		}

		$this->originalFileObject = $originalFileObject;
73
		parent::init(basename($overrideFileAbsolutePath), dirname($overrideFileAbsolutePath), $metaFile);
74 75 76 77 78 79 80 81 82 83
	}

	/**
	 * Calls the parent function and convert all values from utf-8 to the original charset
	 *
	 * @throws LFException raised if the parent read file method fails
	 * @return void
	 */
	public function readFile() {
		if (is_file($this->absFile)) {
Damjan's avatar
Damjan committed
84
			parent::readFile();
85
			if (!Typo3Lib::isTypo3BackendInUtf8Mode()) {
86
				$this->localLang = Typo3Lib::utf8($this->localLang, FALSE, array('default'));
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
			}
		}

		$this->originalFileObject->readFile();
		$this->mergeOriginalWidthOverrideLangData();
	}

	/**
	 * Merges Language data from original and override files, so all data can e presented to user.
	 *
	 * @return void
	 */
	protected function mergeOriginalWidthOverrideLangData() {
		foreach ($this->originalFileObject->getLocalLang() as $lang => $langData) {
			if (empty($langData)) {
				continue;
			}
104

105 106 107 108
			foreach ($langData as $costKey => $constValue) {
				if (isset($this->localLang[$lang][$costKey]) && $this->localLang[$lang][$costKey] !== $constValue) {
					continue;
				}
109 110 111 112 113

				if (!is_array($this->localLang[$lang])) {
					$this->localLang[$lang] = [];
				}

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
				$this->localLang[$lang][$costKey] = $constValue;
			}
		}

		foreach ($this->originalFileObject->getMeta() as $metaTag => $metaTagValue) {
			if ($metaTag === '@attributes') {
				foreach ($metaTagValue as $attributeKey => $attributeValue) {
					if (isset($this->meta[$metaTag][$attributeKey])
						&& $this->meta[$metaTag][$attributeKey] !== $attributeValue
					) {
						continue;
					}
					$this->meta[$metaTag][$attributeKey] = $attributeValue;
				}
			} else {
				if (isset($this->meta[$metaTag]) && $this->meta[$metaTag] !== $metaTagValue) {
					continue;
				}
				$this->meta[$metaTag] = $metaTagValue;
			}
		}
	}

	/**
	 * Writes language override files.
	 *
140
	 * @param array|null $editedLanguages
141
	 * @throws LFException raised if a file cant be written
142
	 * @throws \Exception
143 144
	 * @return void
	 */
145
	public function writeFile($editedLanguages = NULL) {
146 147 148 149 150 151 152
		$this->deleteDuplicates();
		if (!$this->langDataExists() && !is_file($this->absFile)) {
			return;
		}

		try {
			SgLib::createDir($this->absPath, PATH_site);
153 154
		} catch (\Exception $exception) {
			throw new LFException('failure.failure', 0, '(' . $exception->getMessage() . ')');
155 156 157
		}

		parent::writeFile();
Damjan's avatar
Damjan committed
158

159 160 161
		// Set only new values in GlobalConfiguration if something changed
		$typo3ExtRelativeFilePath = Typo3Lib::transTypo3File($this->originalFileObject->getAbsFile(), FALSE);
		$relativeOverrideFilePath = SgLib::trimPath(PATH_site, $this->absFile);
Damjan's avatar
Damjan committed
162 163
		$locallangXMLOverride = &$GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride'];
		if ($locallangXMLOverride[$typo3ExtRelativeFilePath][0] === $relativeOverrideFilePath) {
164 165 166 167 168 169 170 171 172
			return;
		}

		try {
			$addLine = '$GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'locallangXMLOverride\'][\''
				. $typo3ExtRelativeFilePath . '\'][0] = \'' . $relativeOverrideFilePath . '\';';
			Typo3Lib::writeLineToAdditionalConfiguration($addLine);
			$GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride'][$typo3ExtRelativeFilePath][0]
				= $relativeOverrideFilePath;
173 174
		} catch (\Exception $exception) {
			throw new LFException('failure.failure', 0, '(' . $exception->getMessage() . ')');
175 176 177 178 179 180 181 182 183 184
		}
	}

	/**
	 * Deletes duplicated language data (data that exist in both files - original file and override file),
	 * so that only changed data will be saved in override file.
	 *
	 * @return void
	 */
	public function deleteDuplicates() {
185 186 187 188 189 190
		foreach ($this->localLang as $language => $languageData) {
			if (!is_array($languageData)) {
				continue;
			}
			foreach ($languageData as $constKey => $constValue) {
				$localLangData = $this->originalFileObject->getLocalLangData($language);
191
				if (SgLib::strCmpIgnoreCR($constValue, $localLangData[$constKey])) {
192
					unset($this->localLang[$language][$constKey]);
193 194 195 196 197
				}
			}
		}

		foreach ($this->meta as $metaTag => $metaValue) {
198
			if (SgLib::strCmpIgnoreCR($metaValue, $this->originalFileObject->getMetaData($metaTag))) {
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
				unset($this->meta[$metaTag]);
			}
		}
	}

	/**
	 * Checks is there any lang data (constants in $localLang and meta data).
	 *
	 * @return bool Returns true if any constant or meta data exist.
	 */
	protected function langDataExists() {
		foreach ($this->meta as $metaTag => $metaValue) {
			if (isset($this->meta[$metaTag]) && $metaTag !== '@attributes') {
				return TRUE;
			}
		}

216 217 218 219 220 221
		foreach ($this->localLang as $language => $languageData) {
			if (!is_array($languageData)) {
				continue;
			}
			foreach ($languageData as $constKey => $constValue) {
				if (isset($languageData[$constKey])) {
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
					return TRUE;
				}
			}
		}
		return FALSE;
	}

	/**
	 * Writes generator meta tag.
	 *
	 * @return void
	 */
	protected function addGeneratorString() {
		if ($this->originalFileObject->getMetaData('generator') !== 'LFEditor') {
			$this->meta['generator'] = 'LFEditor';
		}
	}
Stefan Galinski's avatar
Stefan Galinski committed
239
}