Subversion-Projekte lars-tiefland.cakephp

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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