root/trunk/server/www/cake/libs/string.php @ 310

Revision 310, 8.9 KB (checked in by sander, 6 months ago)

Do not assign the return of 'new' by reference or PHP 5.3 will yell

Line 
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 20:16:01 -0600 (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 */
33class 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?>
Note: See TracBrowser for help on using the browser.