PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/cake/libs/string.php

https://github.com/msadouni/cakephp2x
PHP | 332 lines | 248 code | 18 blank | 66 comment | 44 complexity | 68e07b805c854acf72784908dc393b23 MD5 | raw file
  1. <?php
  2. /**
  3. * String handling methods.
  4. *
  5. *
  6. * PHP Version 5.x
  7. *
  8. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  9. * Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  10. *
  11. * Licensed under The MIT License
  12. * Redistributions of files must retain the above copyright notice.
  13. *
  14. * @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  15. * @link http://cakephp.org CakePHP(tm) Project
  16. * @package cake
  17. * @subpackage cake.cake.libs
  18. * @since CakePHP(tm) v 1.2.0.5551
  19. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  20. */
  21. /**
  22. * String handling methods.
  23. *
  24. *
  25. * @package cake
  26. * @subpackage cake.cake.libs
  27. */
  28. <<<<<<< HEAD
  29. final class String {
  30. =======
  31. class String {
  32. >>>>>>> cakephp/1.3
  33. /**
  34. * Generate a random UUID
  35. *
  36. * @see http://www.ietf.org/rfc/rfc4122.txt
  37. * @return RFC 4122 UUID
  38. * @static
  39. */
  40. public static function uuid() {
  41. $node = env('SERVER_ADDR');
  42. $pid = null;
  43. if (strpos($node, ':') !== false) {
  44. if (substr_count($node, '::')) {
  45. $node = str_replace(
  46. '::', str_repeat(':0000', 8 - substr_count($node, ':')) . ':', $node
  47. );
  48. }
  49. $node = explode(':', $node) ;
  50. $ipv6 = '' ;
  51. foreach ($node as $id) {
  52. $ipv6 .= str_pad(base_convert($id, 16, 2), 16, 0, STR_PAD_LEFT);
  53. }
  54. $node = base_convert($ipv6, 2, 10);
  55. if (strlen($node) < 38) {
  56. $node = null;
  57. } else {
  58. $node = crc32($node);
  59. }
  60. } elseif (empty($node)) {
  61. $host = env('HOSTNAME');
  62. if (empty($host)) {
  63. $host = env('HOST');
  64. }
  65. if (!empty($host)) {
  66. $ip = gethostbyname($host);
  67. if ($ip === $host) {
  68. $node = crc32($host);
  69. } else {
  70. $node = ip2long($ip);
  71. }
  72. }
  73. } elseif ($node !== '127.0.0.1') {
  74. $node = ip2long($node);
  75. } else {
  76. $node = null;
  77. }
  78. if (empty($node)) {
  79. $node = crc32(Configure::read('Security.salt'));
  80. }
  81. if (function_exists('zend_thread_id')) {
  82. $pid = zend_thread_id();
  83. } else {
  84. $pid = getmypid();
  85. }
  86. if (!$pid || $pid > 65535) {
  87. $pid = mt_rand(0, 0xfff) | 0x4000;
  88. }
  89. list($timeMid, $timeLow) = explode(' ', microtime());
  90. $uuid = sprintf(
  91. "%08x-%04x-%04x-%02x%02x-%04x%08x", (int)$timeLow, (int)substr($timeMid, 2) & 0xffff,
  92. mt_rand(0, 0xfff) | 0x4000, mt_rand(0, 0x3f) | 0x80, mt_rand(0, 0xff), $pid, $node
  93. );
  94. return $uuid;
  95. }
  96. /**
  97. * Tokenizes a string using $separator, ignoring any instance of $separator that appears between
  98. * $leftBound and $rightBound
  99. *
  100. * @param string $data The data to tokenize
  101. * @param string $separator The token to split the data on
  102. * @return array
  103. * @access public
  104. * @static
  105. */
  106. public static function tokenize($data, $separator = ',', $leftBound = '(', $rightBound = ')') {
  107. if (empty($data) || is_array($data)) {
  108. return $data;
  109. }
  110. $depth = 0;
  111. $offset = 0;
  112. $buffer = '';
  113. $results = array();
  114. $length = strlen($data);
  115. $open = false;
  116. while ($offset <= $length) {
  117. $tmpOffset = -1;
  118. $offsets = array(
  119. strpos($data, $separator, $offset),
  120. strpos($data, $leftBound, $offset),
  121. strpos($data, $rightBound, $offset)
  122. );
  123. for ($i = 0; $i < 3; $i++) {
  124. if ($offsets[$i] !== false && ($offsets[$i] < $tmpOffset || $tmpOffset == -1)) {
  125. $tmpOffset = $offsets[$i];
  126. }
  127. }
  128. if ($tmpOffset !== -1) {
  129. $buffer .= substr($data, $offset, ($tmpOffset - $offset));
  130. if ($data{$tmpOffset} == $separator && $depth == 0) {
  131. $results[] = $buffer;
  132. $buffer = '';
  133. } else {
  134. $buffer .= $data{$tmpOffset};
  135. }
  136. if ($leftBound != $rightBound) {
  137. if ($data{$tmpOffset} == $leftBound) {
  138. $depth++;
  139. }
  140. if ($data{$tmpOffset} == $rightBound) {
  141. $depth--;
  142. }
  143. } else {
  144. if ($data{$tmpOffset} == $leftBound) {
  145. if (!$open) {
  146. $depth++;
  147. $open = true;
  148. } else {
  149. $depth--;
  150. $open = false;
  151. }
  152. }
  153. }
  154. $offset = ++$tmpOffset;
  155. } else {
  156. $results[] = $buffer . substr($data, $offset);
  157. $offset = $length + 1;
  158. }
  159. }
  160. if (empty($results) && !empty($buffer)) {
  161. $results[] = $buffer;
  162. }
  163. if (!empty($results)) {
  164. $data = array_map('trim', $results);
  165. } else {
  166. $data = array();
  167. }
  168. return $data;
  169. }
  170. /**
  171. * Replaces variable placeholders inside a $str with any given $data. Each key in the $data array
  172. * corresponds to a variable placeholder name in $str.
  173. * Example: `String::insert(':name is :age years old.', array('name' => 'Bob', '65'));`
  174. * Returns: Bob is 65 years old.
  175. *
  176. * Available $options are:
  177. *
  178. * - before: The character or string in front of the name of the variable placeholder (Defaults to `:`)
  179. * - after: The character or string after the name of the variable placeholder (Defaults to null)
  180. * - escape: The character or string used to escape the before character / string (Defaults to `\`)
  181. * - format: A regex to use for matching variable placeholders. Default is: `/(?<!\\)\:%s/`
  182. * (Overwrites before, after, breaks escape / clean)
  183. * - clean: A boolean or array with instructions for String::cleanInsert
  184. *
  185. * @param string $str A string containing variable placeholders
  186. * @param string $data A key => val array where each key stands for a placeholder variable name
  187. * to be replaced with val
  188. * @param string $options An array of options, see description above
  189. * @return string
  190. * @access public
  191. * @static
  192. */
  193. public static function insert($str, $data, $options = array()) {
  194. $defaults = array(
  195. 'before' => ':', 'after' => null, 'escape' => '\\', 'format' => null, 'clean' => false
  196. );
  197. $options += $defaults;
  198. $format = $options['format'];
  199. $data = (array)$data;
  200. if (empty($data)) {
  201. return ($options['clean']) ? String::cleanInsert($str, $options) : $str;
  202. }
  203. if (!isset($format)) {
  204. $format = sprintf(
  205. '/(?<!%s)%s%%s%s/',
  206. preg_quote($options['escape'], '/'),
  207. str_replace('%', '%%', preg_quote($options['before'], '/')),
  208. str_replace('%', '%%', preg_quote($options['after'], '/'))
  209. );
  210. }
  211. if (strpos($str, '?') !== false && is_numeric(key($data))) {
  212. $offset = 0;
  213. while (($pos = strpos($str, '?', $offset)) !== false) {
  214. $val = array_shift($data);
  215. $offset = $pos + strlen($val);
  216. $str = substr_replace($str, $val, $pos, 1);
  217. }
  218. return ($options['clean']) ? self::cleanInsert($str, $options) : $str;
  219. } else {
  220. asort($data);
  221. $hashKeys = array();
  222. foreach ($data as $key => $value) {
  223. $hashKeys[] = crc32($key);
  224. }
  225. $tempData = array_combine(array_keys($data), array_values($hashKeys));
  226. foreach ($tempData as $key => $hashVal) {
  227. $key = sprintf($format, preg_quote($key, '/'));
  228. $str = preg_replace($key, $hashVal, $str);
  229. }
  230. $dataReplacements = array_combine($hashKeys, array_values($data));
  231. foreach ($dataReplacements as $tmpHash => $tmpValue) {
  232. $tmpValue = (is_array($tmpValue)) ? '' : $tmpValue;
  233. $str = str_replace($tmpHash, $tmpValue, $str);
  234. }
  235. }
  236. if (!isset($options['format']) && isset($options['before'])) {
  237. $str = str_replace($options['escape'].$options['before'], $options['before'], $str);
  238. }
  239. return ($options['clean']) ? self::cleanInsert($str, $options) : $str;
  240. }
  241. /**
  242. * Cleans up a Set::insert formated string with given $options depending on the 'clean' key in
  243. * $options. The default method used is text but html is also available. The goal of this function
  244. * is to replace all whitespace and uneeded markup around placeholders that did not get replaced
  245. * by Set::insert.
  246. *
  247. * @param string $str
  248. * @param string $options
  249. * @return string
  250. * @access public
  251. * @static
  252. * @see Set::insert()
  253. */
  254. public static function cleanInsert($str, $options) {
  255. $clean = $options['clean'];
  256. if (!$clean) {
  257. return $str;
  258. }
  259. if ($clean === true) {
  260. $clean = array('method' => 'text');
  261. }
  262. if (!is_array($clean)) {
  263. $clean = array('method' => $options['clean']);
  264. }
  265. switch ($clean['method']) {
  266. case 'html':
  267. $clean = array_merge(array(
  268. 'word' => '[\w,.]+',
  269. 'andText' => true,
  270. 'replacement' => '',
  271. ), $clean);
  272. $kleenex = sprintf(
  273. '/[\s]*[a-z]+=(")(%s%s%s[\s]*)+\\1/i',
  274. preg_quote($options['before'], '/'),
  275. $clean['word'],
  276. preg_quote($options['after'], '/')
  277. );
  278. $str = preg_replace($kleenex, $clean['replacement'], $str);
  279. if ($clean['andText']) {
  280. $options['clean'] = array('method' => 'text');
  281. $str = self::cleanInsert($str, $options);
  282. }
  283. break;
  284. case 'text':
  285. $clean = array_merge(array(
  286. 'word' => '[\w,.]+',
  287. 'gap' => '[\s]*(?:(?:and|or)[\s]*)?',
  288. 'replacement' => '',
  289. ), $clean);
  290. $kleenex = sprintf(
  291. '/(%s%s%s%s|%s%s%s%s)/',
  292. preg_quote($options['before'], '/'),
  293. $clean['word'],
  294. preg_quote($options['after'], '/'),
  295. $clean['gap'],
  296. $clean['gap'],
  297. preg_quote($options['before'], '/'),
  298. $clean['word'],
  299. preg_quote($options['after'], '/')
  300. );
  301. $str = preg_replace($kleenex, $clean['replacement'], $str);
  302. break;
  303. }
  304. return $str;
  305. }
  306. }
  307. ?>