$extPaths) { if (!is_array($extPaths) || !count($extPaths)) { continue; } unset($prepArray); foreach ($extPaths as $extPath) { $prepArray[$extPath] = basename($extPath); } ksort($prepArray); $myArray = array_merge($myArray, ['###extensionGroup###' . $header => $header], $prepArray); } return $myArray; } /** * searches extensions in a given path * * Modes for $state: * 0 - loaded and unloaded * 1 - only loaded * 2 - only unloaded * * @param string $path path * @param integer $state optional: extension state to ignore (see above) * @param string $extIgnoreRegExp optional: directories to ignore (regular expression; pcre with slashes) * @param string $extWhitelistRegExp optional: keep only those directories (regular expression; pcre with slashes) * @return array result of the search * @throws Exception raised, if the given path cant be opened for reading */ public static function searchExtensions($path, $state = 0, $extIgnoreRegExp = '', $extWhitelistRegExp = '') { if (!@$fhd = opendir($path)) { throw new Exception('cant open "' . $path . '"'); } $path = rtrim($path, '/'); $extArray = []; while ($extDir = readdir($fhd)) { $extDirPath = $path . '/' . $extDir; // ignore all unless the file is a directory and no point dir if (!is_dir($extDirPath) || preg_match('/^\.{1,2}$/', $extDir)) { continue; } // check, if the directory/extension should be saved if (preg_match($extIgnoreRegExp, $extDir)) { continue; } // check, if the directory/extension should be saved if ($extWhitelistRegExp !== '' && !preg_match($extWhitelistRegExp, $extDir)) { continue; } // state filter if ($state) { $extState = (int) ExtensionManagementUtility::isLoaded($extDir); if (($extState && $state == 2) || (!$extState && $state == 1)) { continue; } } $extArray[] = $extDirPath; } closedir($fhd); return $extArray; } /** * prepares a given language string for section output * * @param string $value language string * @return string prepared output in sections */ public static function prepareSectionName($value) { return html_entity_decode(LocalizationUtility::translate($value, 'lfeditor')); } /** * checks and returns given languages or TYPO3 language list if the given content was empty * * @param array $languages optional: some language shortcuts * @return array language list */ public static function buildLangArray($languages = NULL) { if (!is_array($languages) || !count($languages)) { return SgLib::getSystemLanguages(); } else { return $languages; } } /** * generates output for a diff between the backup and original file * * Note that the generated diff will be an array with a normal structure like * any language content array. * * Modes of diffType: * - all changes at the original since the backup was done (0) * - only changes at the original (1) * - only changes at the backup (2) * * @param integer $diffType see above for available modes * @param array $origLang original language data * @param array $backupLocalLang backup language data * @return mixed generated diff */ public static function getBackupDiff($diffType, $origLang, $backupLocalLang) { // get all languages and generate the diff $langKeys = array_merge(array_keys($origLang), array_keys($backupLocalLang)); $diff = []; foreach ($langKeys as $langKey) { // prevent warnings if (!is_array($origLang[$langKey])) { $origLang[$langKey] = []; } if (!is_array($backupLocalLang[$langKey])) { $backupLocalLang[$langKey] = []; } $origDiff[$langKey] = []; $backupDiff[$langKey] = []; // generate diff if (!$diffType || $diffType == 1) { $origDiff[$langKey] = array_diff_assoc($origLang[$langKey], $backupLocalLang[$langKey]); } if (!$diffType || $diffType == 2) { $backupDiff[$langKey] = array_diff_assoc( $backupLocalLang[$langKey], $origLang[$langKey] ); } $diff[$langKey] = array_merge($origDiff[$langKey], $backupDiff[$langKey]); } return $diff; } /** * generates output for a meta diff between the backup and original file * * Note that the generated diff will be an array with a normal structure like * any meta content array. * * Modes of diffType: * - all changes at the original since the backup was done (0) * - only changes at the original (1) * - only changes at the backup (2) * * @param integer $diffType see above for available modes * @param array $origMeta original meta data * @param array $backupMeta backup meta data * @return mixed generated diff */ public static function getMetaDiff($diffType, $origMeta, $backupMeta) { $origDiff = []; $backupDiff = []; if (!$diffType || $diffType == 1) { $origDiff = array_diff_assoc($origMeta, $backupMeta); } if (!$diffType || $diffType == 2) { $backupDiff = array_diff_assoc($backupMeta, $origMeta); } if ($diffType == 1) { return $origDiff; } elseif ($diffType == 2) { return $backupDiff; } else { return array_merge($origDiff, $backupDiff); } } /** * generates a general information array * * @param string $refLang reference language * @param array $languages language key array * @param FileBasePHPService $fileObj file object * @return array general information array * @see outputGeneral() */ public static function genGeneralInfoArray($refLang, $languages, $fileObj) { $numTranslated = []; // reference language data information $localRefLangData = $fileObj->getLocalLangData($refLang); // generate needed data $infos = []; foreach ($languages as $langKey) { // get origin data and meta information $origin = $fileObj->getOriginLangData($langKey); $infos['default']['meta'] = $fileObj->getMetaData(); // language data $localLangData = $fileObj->getLocalLangData($langKey); // detailed constants information $infos[$langKey]['numUntranslated'] = count(array_diff_key($localRefLangData, $localLangData)); $infos[$langKey]['numUnknown'] = count(array_diff_key($localLangData, $localRefLangData)); $infos[$langKey]['numTranslated'] = count(array_intersect_key($localLangData, $localRefLangData)); // set origin try { $infos[$langKey]['origin'] = '[-]'; if (!empty($origin)) { $infos[$langKey]['origin'] = Typo3Lib::transTypo3File($origin, FALSE); } } catch (Exception $e) { $pathSite = Environment::getPublicPath() . '/'; $infos[$langKey]['origin'] = SgLib::trimPath($pathSite, $origin); } } // Sort by numTranslated DESC foreach ($infos as $key => $row) { $numTranslated[$key] = $row['numTranslated']; } array_multisort($numTranslated, SORT_DESC, $infos); return $infos; } /** * generates a tree information array * * structure: * tree[dimension][branch]['name'] = name of constant * tree[dimension][branch]['type'] = type of constant (0=>normal;1=>untranslated;2=>unknown) * tree[dimension][branch]['parent'] = parentOfBranch (absConstName) * tree[dimension][branch]['childs'] = amount of children * * @param array $langData language data (only one language) * @param array $refLang reference data (only reference language) * @param string $expToken explode token * @return array tree information array */ public static function genTreeInfoArray($langData, $refLang, $expToken) { // reference language $refConsts = []; if (is_array($refLang) && count($refLang)) { $refConsts = array_keys($refLang); } $langConsts = array_merge(array_keys($langData), $refConsts); // generate tree information array $curAbsName = ''; $tree = []; foreach ($langConsts as $constant) { // add root $tree[0]['Root']['name'] = 'Root'; // get type $type = 0; // normal if (!in_array($constant, $refConsts)) { $type = 2; } // unknown elseif (empty($langData[$constant])) { $type = 1; } // untranslated $branches = explode($expToken, $constant); $numBranches = is_countable($branches) ? count($branches) : 0; for ($i = 0, $curDim = 1; $i < $numBranches; ++$i, ++$curDim) { // get current absolute constant name if (!$i) { $curAbsName = $branches[$i]; } else { $curAbsName .= $expToken . $branches[$i]; } if (isset($tree[$curDim][$curAbsName]['name'])) { continue; } // add branch $tree[$curDim][$curAbsName]['name'] = $branches[$i]; $tree[$curDim][$curAbsName]['type'] = $type; // set parent if ($i > 0) { $parentAbsName = substr($curAbsName, 0, strrpos($curAbsName, (string) $expToken)); } else { $parentAbsName = 'Root'; } $tree[$curDim][$curAbsName]['parent'] = $parentAbsName; if (array_key_exists('childs', $tree[$curDim - 1][$parentAbsName])) { ++$tree[$curDim - 1][$parentAbsName]['childs']; } else { $tree[$curDim - 1][$parentAbsName]['childs'] = 1; } } } return $tree; } /** * get best explode token of a given language data * * @param string $curToken current token * @param array $langData some test language data * @return string new token */ public static function getExplodeToken($curToken, $langData) { $ascii = []; // get current token if (!empty($curToken)) { return $curToken; } // return default token, if no test data found if (!is_array($langData) || !count($langData)) { return '.'; } // get ascii codes (possible explode values) $ascii['.'] = ord('.'); $ascii['_'] = ord('_'); // get best possible character of the default language $defKeys = array_keys($langData); $numKeys = count($defKeys); $maxTestCount = ($numKeys >= 10) ? 10 : $numKeys; $counts = []; for ($i = 0; $i < $maxTestCount; ++$i) { $curCounts = count_chars($defKeys[$i], 1); foreach ($ascii as $sign) { $counts[$sign] += $curCounts[$sign]; } } // get curToken foreach ($counts as $sign => $curCounts) { if ($curCounts > $counts[$curToken]) { $curToken = $sign; } } return chr($curToken); } }