1<?php 2declare(strict_types = 1); 3namespace TYPO3\CMS\Core\Utility; 4 5/* 6 * This file is part of the TYPO3 CMS project. 7 * 8 * It is free software; you can redistribute it and/or modify it under 9 * the terms of the GNU General Public License, either version 2 10 * of the License, or any later version. 11 * 12 * For the full copyright and license information, please read the 13 * LICENSE.txt file that was distributed with this source code. 14 * 15 * The TYPO3 project - inspiring people to share! 16 */ 17 18/** 19 * Class with helper functions for permuting items. 20 */ 21class PermutationUtility 22{ 23 /** 24 * Combines string items of multiple arrays as cross-product into flat items. 25 * 26 * Example: 27 * + meltStringItems([['a', 'b'], ['c', 'd'], ['e', 'f']]) 28 * + results into ['ace', 'acf', 'ade', 'adf', 'bce', 'bcf', 'bde', 'bdf'] 29 * 30 * @param array[] $payload Distinct array that should be melted 31 * @param string $previousResult Previous item results 32 * @return array 33 */ 34 public static function meltStringItems(array $payload, string $previousResult = ''): array 35 { 36 $results = []; 37 $items = static::nextItems($payload); 38 foreach ($items as $item) { 39 $resultItem = $previousResult . static::asString($item); 40 if (!empty($payload)) { 41 $results = array_merge( 42 $results, 43 static::meltStringItems($payload, $resultItem) 44 ); 45 continue; 46 } 47 $results[] = $resultItem; 48 } 49 return $results; 50 } 51 52 /** 53 * Combines arbitrary items of multiple arrays as cross-product into flat items. 54 * 55 * Example: 56 * + meltArrayItems(['a','b'], ['c','e'], ['f','g']) 57 * + results into ['a', 'c', 'e'], ['a', 'c', 'f'], ['a', 'd', 'e'], ['a', 'd', 'f'], 58 * ['b', 'c', 'e'], ['b', 'c', 'f'], ['b', 'd', 'e'], ['b', 'd', 'f'], 59 * 60 * @param array[] $payload Distinct items that should be melted 61 * @param array $previousResult Previous item results 62 * @return array 63 */ 64 public static function meltArrayItems(array $payload, array $previousResult = []): array 65 { 66 $results = []; 67 $items = static::nextItems($payload); 68 foreach ($items as $item) { 69 $resultItems = $previousResult; 70 $resultItems[] = $item; 71 if (!empty($payload)) { 72 $results = array_merge( 73 $results, 74 static::meltArrayItems($payload, $resultItems) 75 ); 76 continue; 77 } 78 $results[] = $resultItems; 79 } 80 return $results; 81 } 82 83 protected static function nextItems(array &$payload): iterable 84 { 85 $items = array_shift($payload); 86 if (is_iterable($items)) { 87 return $items; 88 } 89 throw new \LogicException( 90 sprintf('Expected iterable, got %s', gettype($items)), 91 1578164101 92 ); 93 } 94 95 protected static function asString($item): string 96 { 97 if (is_string($item)) { 98 return $item; 99 } 100 if (is_object($item) && method_exists($item, '__toString')) { 101 return (string)$item; 102 } 103 throw new \LogicException( 104 sprintf('Expected string, got %s', gettype($item)), 105 1578164102 106 ); 107 } 108} 109