StringUtils.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. * Magento methods to work with string
  9. *
  10. * @api
  11. * @since 100.0.2
  12. */
  13. class StringUtils
  14. {
  15. /**
  16. * Default charset
  17. */
  18. const ICONV_CHARSET = 'UTF-8';
  19. /**
  20. * Capitalize first letters and convert separators if needed
  21. *
  22. * @param string $str
  23. * @param string $sourceSeparator
  24. * @param string $destinationSeparator
  25. * @return string
  26. */
  27. public function upperCaseWords($str, $sourceSeparator = '_', $destinationSeparator = '_')
  28. {
  29. return str_replace(' ', $destinationSeparator, ucwords(str_replace($sourceSeparator, ' ', $str)));
  30. }
  31. /**
  32. * Split string and appending $insert string after $needle
  33. *
  34. * @param string $str
  35. * @param integer $length
  36. * @param string $needle
  37. * @param string $insert
  38. * @return string
  39. */
  40. public function splitInjection($str, $length = 50, $needle = '-', $insert = ' ')
  41. {
  42. $str = $this->split($str, $length);
  43. $newStr = '';
  44. foreach ($str as $part) {
  45. if ($this->strlen($part) >= $length) {
  46. $lastDelimiter = $this->strpos($this->strrev($part), $needle);
  47. $tmpNewStr = $this->substr($this->strrev($part), 0, $lastDelimiter) . $insert
  48. . $this->substr($this->strrev($part), $lastDelimiter);
  49. $newStr .= $this->strrev($tmpNewStr);
  50. } else {
  51. $newStr .= $part;
  52. }
  53. }
  54. return $newStr;
  55. }
  56. /**
  57. * Binary-safe variant of strSplit()
  58. * + option not to break words
  59. * + option to trim spaces (between each word)
  60. * + option to set character(s) (pcre pattern) to be considered as words separator
  61. *
  62. * @param string $value
  63. * @param int $length
  64. * @param bool $keepWords
  65. * @param bool $trim
  66. * @param string $wordSeparatorRegex
  67. * @return string[]
  68. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  69. * @SuppressWarnings(PHPMD.NPathComplexity)
  70. */
  71. public function split($value, $length = 1, $keepWords = false, $trim = false, $wordSeparatorRegex = '\s')
  72. {
  73. $result = [];
  74. $strLen = $this->strlen($value);
  75. if (!$strLen || !is_int($length) || $length <= 0) {
  76. return $result;
  77. }
  78. if ($trim) {
  79. $value = trim(preg_replace('/\s{2,}/siu', ' ', $value));
  80. }
  81. // do a usual str_split, but safe for our encoding
  82. if (!$keepWords || $length < 2) {
  83. for ($offset = 0; $offset < $strLen; $offset += $length) {
  84. $result[] = $this->substr($value, $offset, $length);
  85. }
  86. } else {
  87. // split smartly, keeping words
  88. $split = preg_split('/(' . $wordSeparatorRegex . '+)/siu', $value, null, PREG_SPLIT_DELIM_CAPTURE);
  89. $index = 0;
  90. $space = '';
  91. $spaceLen = 0;
  92. foreach ($split as $key => $part) {
  93. if ($trim) {
  94. // ignore spaces (even keys)
  95. if ($key % 2) {
  96. continue;
  97. }
  98. $space = ' ';
  99. $spaceLen = 1;
  100. }
  101. if (empty($result[$index])) {
  102. $currentLength = 0;
  103. $result[$index] = '';
  104. $space = '';
  105. $spaceLen = 0;
  106. } else {
  107. $currentLength = $this->strlen($result[$index]);
  108. }
  109. $partLength = $this->strlen($part);
  110. // add part to current last element
  111. if ($currentLength + $spaceLen + $partLength <= $length) {
  112. $result[$index] .= $space . $part;
  113. } elseif ($partLength <= $length) {
  114. // add part to new element
  115. $index++;
  116. $result[$index] = $part;
  117. } else {
  118. // break too long part recursively
  119. foreach ($this->split($part, $length, false, $trim, $wordSeparatorRegex) as $subPart) {
  120. $index++;
  121. $result[$index] = $subPart;
  122. }
  123. }
  124. }
  125. }
  126. // remove last element, if empty
  127. $count = count($result);
  128. if ($count) {
  129. if ($result[$count - 1] === '') {
  130. unset($result[$count - 1]);
  131. }
  132. }
  133. // remove first element, if empty
  134. if (isset($result[0]) && $result[0] === '') {
  135. array_shift($result);
  136. }
  137. return $result;
  138. }
  139. /**
  140. * Retrieve string length using default charset
  141. *
  142. * @param string $string
  143. * @return int
  144. */
  145. public function strlen($string)
  146. {
  147. return mb_strlen($string, self::ICONV_CHARSET);
  148. }
  149. /**
  150. * Clean non UTF-8 characters
  151. *
  152. * @param string $string
  153. * @return string
  154. */
  155. public function cleanString($string)
  156. {
  157. return mb_convert_encoding($string, self::ICONV_CHARSET);
  158. }
  159. /**
  160. * Pass through to mb_substr()
  161. *
  162. * @param string $string
  163. * @param int $offset
  164. * @param int $length
  165. * @return string
  166. */
  167. public function substr($string, $offset, $length = null)
  168. {
  169. $string = $this->cleanString($string);
  170. if ($length === null) {
  171. $length = $this->strlen($string) - $offset;
  172. }
  173. return mb_substr($string, $offset, $length, self::ICONV_CHARSET);
  174. }
  175. /**
  176. * Binary-safe strrev()
  177. *
  178. * @param string $str
  179. * @return string
  180. */
  181. public function strrev($str)
  182. {
  183. $result = '';
  184. $strLen = $this->strlen($str);
  185. if (!$strLen) {
  186. return $result;
  187. }
  188. for ($i = $strLen - 1; $i >= 0; $i--) {
  189. $result .= $this->substr($str, $i, 1);
  190. }
  191. return $result;
  192. }
  193. /**
  194. * Find position of first occurrence of a string
  195. *
  196. * @param string $haystack
  197. * @param string $needle
  198. * @param int $offset
  199. * @return int|bool
  200. */
  201. public function strpos($haystack, $needle, $offset = null)
  202. {
  203. return mb_strpos($haystack, $needle, $offset, self::ICONV_CHARSET);
  204. }
  205. }