setVar(['metaFile' => $metaFile]); parent::init($file, $path, $metaFile); // read meta file try { if (is_file($this->metaFile)) { $this->readMetaFile(); } } catch (LFException $e) { throw $e; } } ##################### ###### Set/Get ###### ##################### /** * sets information * * structure: * $infos["metaFile"] = absolute path to the meta file (includes filename) * $infos["extPath"] = extension path * $infos["langFile"] = language file * * @param array $informations information (see above) * @return void */ public function setVar($informations) { if (!empty($informations['metaFile'])) { $this->metaFile = Typo3Lib::fixFilePath($informations['metaFile']); } if (!empty($informations['extPath'])) { $this->extPath = Typo3Lib::fixFilePath($informations['extPath']); $this->extName = basename($informations['extPath']); } if (!empty($informations['langFile'])) { $this->langFile = Typo3Lib::fixFilePath($informations['langFile']); } parent::setVar($informations); } /** * returns requested information * * @param string $info * @return mixed */ public function getVar($info) { if ($info == 'metaFile') { return $this->metaFile; } elseif ($info == 'extName') { return $this->extName; } elseif ($info == 'extPath') { return $this->extPath; } elseif ($info == 'langFile') { return $this->langFile; } else { return parent::getVar($info); } } /** * returns meta information about backup files * * Modes: * - 0 => full meta information (default) * - 1 => only meta information of given extension key * - 2 => only meta information of given extension key and workspace * - 3 => only meta information of given extension key, workspace and language file * * @param integer $mode * @param string $extName extension Name (default = $this->extName) * @param string $workspace (default = $this->workspace) * @param string $langFile language file (default = $this->langFile) * @return array */ public function getMetaInfos($mode = 0, $extName = '', $workspace = '', $langFile = '') { $extName = empty($extName) ? $this->extName : $extName; $langFile = empty($langFile) ? $this->langFile : $langFile; $workspace = empty($workspace) ? $this->workspace : $workspace; // build return value if (!$mode) { return $this->metaArray; } elseif ($mode == 1) { return $this->metaArray[$extName] ?? []; } elseif ($mode == 2) { return $this->metaArray[$extName][$workspace] ?? []; } elseif ($mode == 3) { return $this->metaArray[$extName][$workspace][$langFile] ?? []; } else { return []; } } /** * rewrites current meta information array with the given equivalent * * Modes: * - 0 => full meta information (default) * - 1 => only meta information of given extension key * - 2 => only meta information of given extension key and workspace * - 3 => only meta information of given extension key, workspace and language file * * @param array $metaArray meta information * @param integer $mode * @param string $extName extension Name (default = $this->extName) * @param string $workspace (default = $this->workspace) * @param string $langFile language file (default = $this->langFile) * @return void */ private function setMetaInfos($metaArray, $mode = 0, $extName = '', $workspace = '', $langFile = '') { $extName = empty($extName) ? $this->extName : $extName; $langFile = empty($langFile) ? $this->langFile : $langFile; $workspace = empty($workspace) ? $this->workspace : $workspace; // build new meta information array if (is_array($metaArray) && count($metaArray)) { if (!$mode) { $this->metaArray = $metaArray; } elseif ($mode == 1) { $this->metaArray[$extName] = $metaArray; } elseif ($mode == 2) { $this->metaArray[$extName][$workspace] = $metaArray; } elseif ($mode == 3) { $this->metaArray[$extName][$workspace][$langFile] = $metaArray; } } else { if (!$mode) { unset($this->metaArray); } elseif ($mode == 1) { unset($this->metaArray[$extName]); } elseif ($mode == 2) { unset($this->metaArray[$extName][$workspace]); } elseif ($mode == 3) { unset($this->metaArray[$extName][$workspace][$langFile]); } } } ############################### ###### Meta FileService Methods ###### ############################### /** * reads the meta information file and parses the content into $this->metaArray * * @throws LFException raised if no meta content was generated * @return void */ private function readMetaFile() { // read file and parse xml to array $metaArray = GeneralUtility::xml2array(file_get_contents($this->metaFile)); if (!is_array($metaArray)) { throw new LFException('failure.backup.metaFile.notRead'); } $this->metaArray = $metaArray; } /** * generate meta XML * * @return string meta information (xml) */ private function genMetaXML() { $options = []; // define assocTagNames $options['parentTagMap'] = [ '' => 'extKey', 'extKey' => 'workspace', 'workspace' => 'langFile', 'langFile' => 'file', ]; return GeneralUtility::array2xml($this->getMetaInfos(), '', 0, 'LFBackupMeta', 0, $options); } /** * writes the meta information file * * @throws LFException raised if the meta file cant be written * @return void */ private function writeMetaFile() { $metaXML = $this->genMetaXML(); if (empty($metaXML)) { throw new LFException('failure.backup.metaFile.notWritten'); } if (!GeneralUtility::writeFile($this->metaFile, $this->getXMLHeader() . $metaXML)) { throw new LFException('failure.backup.metaFile.notWritten'); } } ################################# ###### Backup FileService Methods ###### ################################# /** * generates the xml header * * @return string xml header */ private function getXMLHeader() { return '' . "\n"; } /** * removes the meta information entry and the backup file * * @param string $filename * @param string $extName (default = $this->extName) * @param string $langFile (default = $this->langFile) * @throws Exception|LFException * @throws LFException * @return void */ public function deleteSpecFile($filename, $extName = '', $langFile = '') { // get needed meta information $extName = empty($extName) ? $this->extName : $extName; $langFile = empty($langFile) ? $this->langFile : $langFile; $metaArray = $this->getMetaInfos(3, $extName, '', $langFile); // check backup file if (!isset($metaArray[$filename])) { throw new LFException('failure.backup.notDeleted'); } // get file $backupPath = $metaArray[$filename]['pathBackup']; $pathSite = Environment::getPublicPath() . '/'; $file = GeneralUtility::fixWindowsFilePath($pathSite . $backupPath . '/' . $filename); // build new meta information file unset($metaArray[$filename]); if (!count($metaArray)) { $metaArray = NULL; } $this->setMetaInfos($metaArray, 3, $extName, '', $langFile); $extMetaArray = $this->getMetaInfos(2, $extName); if (!count($extMetaArray)) { $extMetaArray = NULL; } $this->setMetaInfos($extMetaArray, 2, $extName); // write meta information try { $this->writeMetaFile(); } catch (LFException $e) { throw $e; } // delete backup file try { SgLib::deleteFiles([$file]); } catch (Exception $e) { throw new LFException( 'failure.backup.notDeleted', 0, '(' . $e->getMessage() . ')', ); } } /** * wrapper for deleteSpecFile() * * @throws LFException raised if the backup or meta file cant be written * @return void */ public function deleteFile() { try { $this->deleteSpecFile($this->relFile); } catch (LFException $e) { throw $e; } } /** * reads a backup file * * @throws LFException raised if the backup file can't be read * @return void */ public function readFile() { if (!is_file($this->absFile)) { throw new LFException('failure.backup.notRead'); } // read file and transform from xml to array $phpArray = GeneralUtility::xml2array(file_get_contents($this->absFile)); if (!is_array($phpArray)) { throw new LFException('failure.backup.notRead'); } $pathSite = Environment::getPublicPath() . '/'; // read array $localLang = $originLang = []; foreach ($phpArray['data'] as $langKey => $informations) { // read origin try { $originLang[$langKey] = Typo3Lib::transTypo3File($informations['meta']['origin'], TRUE); } catch (Exception $e) { $originLang[$langKey] = $pathSite . $informations['meta']['origin']; } // read data if (is_array($informations['langData'])) { foreach ($informations['langData'] as $const => $value) { $localLang[$langKey][$const] = $value; } } } // check if (!count($localLang) || !count($originLang)) { throw new LFException('failure.backup.notRead'); } $this->localLang = $localLang; $this->originLang = $originLang; $this->meta = $phpArray['meta']; } /** * prepares the final Content * * @return string prepared content (xml) */ private function prepareBackupContent() { $phpArray = []; $options = []; // set meta $phpArray['meta'] = $this->meta; $pathSite = Environment::getPublicPath() . '/'; // set array foreach ($this->originLang as $lang => $origin) { // set origin try { $phpArray['data'][$lang]['meta']['origin'] = Typo3Lib::transTypo3File($origin, FALSE); } catch (Exception $e) { $phpArray['data'][$lang]['meta']['origin'] = substr($origin, strlen($pathSite)); } // set data if (\array_key_exists($lang, $this->localLang) && \is_array($this->localLang[$lang])) { foreach ($this->localLang[$lang] as $labelKey => $labelVal) { $phpArray['data'][$lang]['langData'][$labelKey] = $labelVal; } } } // define assocTagNames $options['parentTagMap'] = [ 'data' => 'languageKey', 'langData' => 'label' ]; // get xml return GeneralUtility::array2xml($phpArray, '', 0, 'LFBackup', 0, $options); } /** * prepares the backup file and writes the new meta information * * @param array | NULL $editedLanguages * @return array raised if meta file cant be written * @throws Exception * @throws LFException * @return array */ protected function prepareFileContents($editedLanguages = NULL) { $backupFiles = []; // get content $xml = $this->prepareBackupContent(); // get and set name of backup $backupName = 'locallang_' . substr(md5(md5($xml)), 0, 10) . '.bak'; $this->setVar(['relFile' => $backupName]); $pathSite = Environment::getPublicPath() . '/'; // get new meta information $metaArray = $this->getMetaInfos(3); $metaArray[$this->relFile]['createdAt'] = time(); $metaArray[$this->relFile]['pathBackup'] = str_replace($pathSite, '', $this->absPath); $this->setMetaInfos($metaArray, 3); // write meta information file try { $this->writeMetaFile(); } catch (LFException $e) { throw $e; } $backupFiles[$this->absPath . $this->relFile] = $this->getXMLHeader() . $xml; return $backupFiles; } }