PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/cake/libs/string.php

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