$typoScriptArray for example `['foo' => 'TEXT', 'foo.' => ['bar' => 'baz']]` * @return array for example `['foo' => ['_typoScriptNodeValue' => 'TEXT', 'bar' => 'baz']]` * @internal Avoid using this method. This has been invented for Extbase, which decided to move TypoScript * arrays around in just another different way. */ public function convertTypoScriptArrayToPlainArray(array $typoScriptArray): array { foreach ($typoScriptArray as $key => $value) { if (str_ends_with((string)$key, '.')) { $keyWithoutDot = substr((string)$key, 0, -1); $typoScriptNodeValue = $typoScriptArray[$keyWithoutDot] ?? null; if (is_array($value)) { $typoScriptArray[$keyWithoutDot] = $this->convertTypoScriptArrayToPlainArray($value); if ($typoScriptNodeValue !== null) { $typoScriptArray[$keyWithoutDot]['_typoScriptNodeValue'] = $typoScriptNodeValue; } unset($typoScriptArray[$key]); } else { $typoScriptArray[$keyWithoutDot] = null; } } } return $typoScriptArray; } /** * Returns an array with Typoscript the old way (with dot). * * Extbase converts the "classical" TypoScript (with trailing dot) to a format without trailing dot, * to be more future-proof and not to have any conflicts with Fluid object accessor syntax. * However, if you want to call legacy TypoScript objects, you somehow need the "old" syntax (because this is what TYPO3 is used to). * With this method, you can convert the extbase TypoScript to classical TYPO3 TypoScript which is understood by the rest of TYPO3. * * @param array $plainArray A TypoScript Array with Extbase Syntax (without dot but with _typoScriptNodeValue) * @return array Array with TypoScript as usual (with dot) * @internal Avoid using this method. This has been invented for Extbase, which decided to move TypoScript * arrays around in just another different way. */ public function convertPlainArrayToTypoScriptArray(array $plainArray): array { $typoScriptArray = []; foreach ($plainArray as $key => $value) { if (is_array($value)) { if (isset($value['_typoScriptNodeValue'])) { $typoScriptArray[$key] = $value['_typoScriptNodeValue']; unset($value['_typoScriptNodeValue']); } $typoScriptArray[$key . '.'] = $this->convertPlainArrayToTypoScriptArray($value); } else { $typoScriptArray[$key] = $value ?? ''; } } return $typoScriptArray; } /** * Implementation of the "optionSplit" feature in TypoScript (used eg. for MENU objects) * What it does is to split the incoming TypoScript array so that the values are exploded by certain * strings ("||" and "|*|") and each part distributed into individual TypoScript arrays with a similar structure, * but individualized values. * The concept is known as "optionSplit" and is rather advanced to handle but quite powerful, in particular * for creating menus in TYPO3. * * @param array $originalConfiguration A TypoScript array * @param int $splitCount The number of items for which to generate individual TypoScript arrays * @return array The individualized TypoScript array. */ public function explodeConfigurationForOptionSplit(array $originalConfiguration, int $splitCount): array { $finalConfiguration = []; if (!$splitCount) { return $finalConfiguration; } // Initialize output to carry at least the keys for ($aKey = 0; $aKey < $splitCount; $aKey++) { $finalConfiguration[$aKey] = []; } // Recursive processing of array keys foreach ($originalConfiguration as $cKey => $val) { if (is_array($val)) { $tempConf = $this->explodeConfigurationForOptionSplit($val, $splitCount); foreach ($tempConf as $aKey => $val2) { $finalConfiguration[$aKey][$cKey] = $val2; } } elseif (is_string($val)) { // Splitting of all values on this level of the TypoScript object tree: if ($cKey === 'noTrimWrap' || (!str_contains($val, '|*|') && !str_contains($val, '||'))) { for ($aKey = 0; $aKey < $splitCount; $aKey++) { $finalConfiguration[$aKey][$cKey] = $val; } } else { $main = explode('|*|', $val); $lastC = 0; $middleC = 0; $firstC = 0; if ($main[0]) { $first = explode('||', $main[0]); $firstC = count($first); } $middle = []; if (!empty($main[1])) { $middle = explode('||', $main[1]); $middleC = count($middle); } $last = []; $value = ''; if (!empty($main[2])) { $last = explode('||', $main[2]); $lastC = count($last); $value = $last[0]; } for ($aKey = 0; $aKey < $splitCount; $aKey++) { if ($firstC && isset($first[$aKey])) { $value = $first[$aKey]; } elseif ($middleC) { $value = $middle[($aKey - $firstC) % $middleC]; } if ($lastC && $lastC >= $splitCount - $aKey) { $value = $last[$lastC - ($splitCount - $aKey)]; } $finalConfiguration[$aKey][$cKey] = trim($value); } } } } return $finalConfiguration; } /** * Flatten TypoScript label array; converting a hierarchical array into a flat * array with the keys separated by dots. * * Example Input: array('k1' => array('subkey1' => 'val1')) * Example Output: array('k1.subkey1' => 'val1') * * @param array $labelValues Hierarchical array of labels * @param string $parentKey the name of the parent key in the recursion; is only needed for recursion. * @return array flattened array of labels. */ public function flattenTypoScriptLabelArray(array $labelValues, string $parentKey = ''): array { $result = []; foreach ($labelValues as $key => $labelValue) { if (!empty($parentKey)) { if ($key === '_typoScriptNodeValue') { $key = $parentKey; } else { $key = $parentKey . '.' . $key; } } if (is_array($labelValue)) { $labelValue = $this->flattenTypoScriptLabelArray($labelValue, $key); $result = array_merge($result, $labelValue); } else { $result[$key] = $labelValue; } } return $result; } }