PageRenderTime 27ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/cake/libs/string.php

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