ArrayUtils.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Stdlib;
  7. /**
  8. * Class ArrayUtils
  9. *
  10. * @api
  11. * @since 100.0.2
  12. */
  13. class ArrayUtils
  14. {
  15. /**
  16. * Sorts array with multibyte string keys
  17. *
  18. * @param array $sort
  19. * @param string $locale
  20. * @return array|bool
  21. */
  22. public function ksortMultibyte(array &$sort, $locale)
  23. {
  24. if (empty($sort)) {
  25. return false;
  26. }
  27. $oldLocale = setlocale(LC_COLLATE, "0");
  28. // use fallback locale if $localeCode is not available
  29. if (strpos($locale, '.UTF8') === false) {
  30. $locale .= '.UTF8';
  31. }
  32. setlocale(LC_COLLATE, $locale, 'C.UTF-8', 'en_US.utf8');
  33. ksort($sort, SORT_LOCALE_STRING);
  34. setlocale(LC_COLLATE, $oldLocale);
  35. return $sort;
  36. }
  37. /**
  38. * Decorate a plain array of arrays or objects
  39. * The array actually can be an object with Iterator interface
  40. *
  41. * Keys with prefix_* will be set:
  42. * *_is_first - if the element is first
  43. * *_is_odd / *_is_even - for odd/even elements
  44. * *_is_last - if the element is last
  45. *
  46. * The respective key/attribute will be set to element, depending on object it is or array.
  47. * \Magento\Framework\DataObject is supported.
  48. *
  49. * $forceSetAll true will cause to set all possible values for all elements.
  50. * When false (default), only non-empty values will be set.
  51. *
  52. * @param array $array
  53. * @param string $prefix
  54. * @param bool $forceSetAll
  55. * @return array
  56. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  57. * @SuppressWarnings(PHPMD.NPathComplexity)
  58. */
  59. public function decorateArray($array, $prefix = 'decorated_', $forceSetAll = false)
  60. {
  61. // check if array or an object to be iterated given
  62. if (!(is_array($array) || is_object($array))) {
  63. return $array;
  64. }
  65. $keyIsFirst = "{$prefix}is_first";
  66. $keyIsOdd = "{$prefix}is_odd";
  67. $keyIsEven = "{$prefix}is_even";
  68. $keyIsLast = "{$prefix}is_last";
  69. $count = count($array);
  70. // this will force Iterator to load
  71. $index = 0;
  72. $isEven = false;
  73. foreach ($array as $key => $element) {
  74. if (is_object($element)) {
  75. $this->_decorateArrayObject($element, $keyIsFirst, 0 === $index, $forceSetAll || 0 === $index);
  76. $this->_decorateArrayObject($element, $keyIsOdd, !$isEven, $forceSetAll || !$isEven);
  77. $this->_decorateArrayObject($element, $keyIsEven, $isEven, $forceSetAll || $isEven);
  78. $isEven = !$isEven;
  79. $index++;
  80. $this->_decorateArrayObject(
  81. $element,
  82. $keyIsLast,
  83. $index === $count,
  84. $forceSetAll || $index === $count
  85. );
  86. } elseif (is_array($element)) {
  87. if ($forceSetAll || 0 === $index) {
  88. $array[$key][$keyIsFirst] = 0 === $index;
  89. }
  90. if ($forceSetAll || !$isEven) {
  91. $array[$key][$keyIsOdd] = !$isEven;
  92. }
  93. if ($forceSetAll || $isEven) {
  94. $array[$key][$keyIsEven] = $isEven;
  95. }
  96. $isEven = !$isEven;
  97. $index++;
  98. if ($forceSetAll || $index === $count) {
  99. $array[$key][$keyIsLast] = $index === $count;
  100. }
  101. }
  102. }
  103. return $array;
  104. }
  105. /**
  106. * Mark passed object with specified flag and appropriate value.
  107. *
  108. * @param \Magento\Framework\DataObject $element
  109. * @param string $key
  110. * @param bool $value
  111. * @param bool $isSkipped
  112. * @return void
  113. */
  114. private function _decorateArrayObject($element, $key, $value, $isSkipped)
  115. {
  116. if ($isSkipped && $element instanceof \Magento\Framework\DataObject) {
  117. $element->setData($key, $value);
  118. }
  119. }
  120. /**
  121. * Expands multidimensional array into flat structure.
  122. *
  123. * Example:
  124. *
  125. * ```php
  126. * [
  127. * 'default' => [
  128. * 'web' => 2
  129. * ]
  130. * ]
  131. * ```
  132. *
  133. * Expands to:
  134. *
  135. * ```php
  136. * [
  137. * 'default/web' => 2,
  138. * ]
  139. * ```
  140. *
  141. * @param array $data The data to be flatten
  142. * @param string $path The leading path
  143. * @param string $separator The path parts separator
  144. * @return array
  145. * @since 101.0.0
  146. */
  147. public function flatten(array $data, $path = '', $separator = '/')
  148. {
  149. $result = [];
  150. $path = $path ? $path . $separator : '';
  151. foreach ($data as $key => $value) {
  152. $fullPath = $path . $key;
  153. if (!is_array($value)) {
  154. $result[$fullPath] = $value;
  155. continue;
  156. }
  157. $result = array_merge(
  158. $result,
  159. $this->flatten($value, $fullPath, $separator)
  160. );
  161. }
  162. return $result;
  163. }
  164. /**
  165. * Search for array differences recursively.
  166. *
  167. * @param array $originalArray The array to compare from
  168. * @param array $newArray The array to compare with
  169. * @return array Diff array
  170. * @since 101.0.0
  171. */
  172. public function recursiveDiff(array $originalArray, array $newArray)
  173. {
  174. $diff = [];
  175. foreach ($originalArray as $key => $value) {
  176. if (array_key_exists($key, $newArray)) {
  177. if (is_array($value)) {
  178. $valueDiff = $this->recursiveDiff($value, $newArray[$key]);
  179. if (count($valueDiff)) {
  180. $diff[$key] = $valueDiff;
  181. }
  182. } else {
  183. if ($value != $newArray[$key]) {
  184. $diff[$key] = $value;
  185. }
  186. }
  187. } else {
  188. $diff[$key] = $value;
  189. }
  190. }
  191. return $diff;
  192. }
  193. }