RSI helpers  0.1
RSI helpers
Str.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Rsi;
4 
5 /**
6  * String helpers.
7  */
8 class Str{
9 
10  const TRANSFORM_HTMLCHARS = 'htmlchars';
11  const TRANSFORM_LCFIRST = 'lcfirst';
12  const TRANSFORM_LOWER = 'lower';
13  const TRANSFORM_NL2BR = 'nl2br';
14  const TRANSFORM_NL2P = 'nl2p';
15  const TRANSFORM_NL2PBR = 'nl2pbr';
16  const TRANSFORM_TRIM = 'trim';
17  const TRANSFORM_UCFIRST = 'ucfirst';
18  const TRANSFORM_UCWORDS = 'ucwords';
19  const TRANSFORM_UPPER = 'upper';
20  const TRANSFORM_URLENCODE = 'urlencode';
21  const TRANSFORM_URLIFY = 'urlify';
22 
23  const ATTRIBUTES_PATTERN = '\\s+(?<key>[\\w\\-]+)(?<value>=(\'([^\']*)\'|"([^"]*)"|(\\w+)))?';
24 
25  const PASSWORD_CHARS = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
26  const MAX_TIME = 20000000000;
27 
28  /**
29  * Returns literally 'true' or 'false'.
30  * @param bool $value
31  * @return string
32  */
33  public static function bool($value){
34  return $value ? 'true' : 'false';
35  }
36  /**
37  * Generate a random string.
38  * @param int $length Length of the resulting string.
39  * @param string $chars Characters to use. Ranges can be indicated as [{from}-{to}]. E.g. '[0-9][a-f]' for the hexadecimal
40  * range. Special cases: '*' all digits + letter (upper + lower case); '+': all digits + lower case letters; '@': all easy
41  * distinguishable characters (no 0/1/l/o).
42  * @param int|bool $time Start the string with the time encoded in the available characters (makes them sequential). When
43  * true, the current time will be taken.
44  * @return string
45  */
46  public static function random($length = 32,$chars = null,$time = null){
47  switch($chars ?: '*'){
48  case '*': $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; break;
49  case '+': $chars = '0123456789abcdefghijklmnopqrstuvwxyz'; break;
50  case '@': $chars = '23456789abcdefghjklmnpqrstuvwxyz'; break;
51  default:
52  if(preg_match_all('/\\[(.)\\-(.)\\]/',$chars,$matches,PREG_SET_ORDER))
53  foreach($matches as list($full,$min,$max)) $chars = str_replace($full,implode(range($min,$max)),$chars);
54  }
55  $max = strlen($chars) - 1;
56  $result = '';
57  if($time){
58  if(($time_length = ceil(log(self::MAX_TIME,$max))) > $length)
59  throw new \Exception("Not enough characters to encode time (need $time_length, have $length)");
60  $length -= $time_length;
61  if($time === true) $time = time();
62  while($time_length--){
63  $result = $chars[$time % $max] . $result;
64  $time = floor($time / $max);
65  }
66  }
67  while($length--) $result .= $chars[random_int(0,$max)];
68  return $result;
69  }
70  /**
71  * Generate a code-name, based on the index.
72  * @param int $index
73  * @return string
74  */
75  public static function codeName($index){
76  $animals = require(__DIR__ . '/../../data/animals.php');
77  $letter = strtolower(substr($animal = $animals[$index % count($animals)],0,1));
78  $adjectives = array_values(array_filter(require(__DIR__ . '/../../data/adjectives.php'),function($adjective) use ($letter){
79  return strtolower(substr($adjective,0,1)) == $letter;
80  }));
81  return $adjectives[$index % count($adjectives)] . ' ' . $animal;
82  }
83  /**
84  * Transform an empty string to a null.
85  * @param string $str
86  * @return string
87  */
88  public static function nullify($str){
89  return $str === '' ? null : $str;
90  }
91  /**
92  * Remove accents from a string.
93  * @param string $str
94  * @return string
95  */
96  public static function normalize($str){
97  return str_replace(["'",'"'],'',iconv('UTF-8','ASCII//TRANSLIT//IGNORE',$str));
98  }
99  /**
100  * Transform a string to a URL-friendly version.
101  * @param string $str Original string.
102  * @param string $replace Character to replace non 'word' characters by.
103  * @return string URL-friendly string.
104  */
105  public static function urlify($str,$replace = '-'){
106  return strtolower(trim(preg_replace('/\\W+/',$replace,self::normalize($str)),$replace));
107  }
108  /**
109  * Replace ASCII emoji's by their Unicode equivalent.
110  * @param string $str String with ASCII emoji's (e.g. ';-)').
111  * @return string String with Unicode emoji's (e.g. '😉').
112  */
113  public static function emojify($str){
114  return strtr($str,require(__DIR__ . '/../../data/emoji.php'));
115  }
116  /**
117  * Remove leet-speak (1337 5p33k) from a string.
118  * @param string $str String with leet-speak characters.
119  * @param bool $upper Replace with uppercase letters.
120  * @return string String with leet-speak symbols replaced by their normal letter. This is near from perfect, since '13'
121  * could be 'LE' or 'B', '1' could be 'I' or 'L', etc).
122  */
123  public static function unleet($str,$upper = false){
124  $leet = require(__DIR__ . '/../../data/leet.php');
125  $length = 0;
126  foreach($leet as $chars) $length = max($length,max(array_map('strlen',$chars)));
127  do foreach($leet as $char => $chars) $str = str_replace(
128  array_filter($chars,function($char) use ($length){
129  return strlen($char) == $length;
130  }),
131  $upper ? $char : strtolower($char),
132  $str
133  );
134  while(--$length);
135  return $str;
136  }
137  /**
138  * Case insesitive string comparison.
139  * @param string $str1 First string.
140  * @param string $str2 Second string.
141  * @return Returns < 0 if str1 is less than str2, > 0 if str1 is greater than str2, and 0 if they are equal.
142  *
143  */
144  public static function icompare($str1,$str2){
145  return strcmp(mb_strtolower($str1),mb_strtolower($str2));
146  }
147  /**
148  * Pad function that defaults to left padding with zeros.
149  * @param string $str
150  * @param int $length
151  * @param string $pad
152  * @param int $type
153  * @return string
154  */
155  public static function pad($str,$length,$pad = '0',$type = STR_PAD_LEFT){
156  return str_pad($str,$length + strlen($str) - mb_strlen($str),$pad,$type);
157  }
158  /**
159  * Format a string.
160  * @param string $str Base string (without formatting).
161  * @param string $format Format, $replace characters are replaced with characters from the $str.
162  * @param string $pad Optional padding (to number of $replace characters in $format).
163  * @param int $type Padding type.
164  * @param string $replace Characters to replace in the $format.
165  * @return string Format with
166  */
167  public static function format($str,$format,$pad = null,$type = STR_PAD_LEFT,$replace = '*'){
168  if($pad !== null) $str = str_pad($str,substr_count($format,$replace),$pad,$type);
169  $result = '';
170  foreach(str_split($format) as $format) if($format === $replace){
171  if($str === '') break;
172  $result .= mb_substr($str,0,1);
173  $str = mb_substr($str,1);
174  }
175  else $result .= $format;
176  return $result;
177  }
178  /**
179  * Converts a delimited string to CamelCase.
180  * @param string $str Delimited string.
181  * @param string $delimiters Word delimiters.
182  * @return string
183  */
184  public static function camel($str,$delimiters = ' -_'){
185  return str_replace(str_split($delimiters),'',ucwords($str,$delimiters));
186  }
187  /**
188  * Converts a CamelCased string to snake_case.
189  * @param string $str CamelCased string.
190  * @param string $delimiter Delimiter to put between the words.
191  * @return string
192  */
193  public static function snake($str,$delimiter = '_'){
194  return strtolower(preg_replace('/([A-Z])([A-Z][a-z])/',"\$1$delimiter\$2",preg_replace('/([a-z\\d])([A-Z])/',"\$1$delimiter\$2",$str)));
195  }
196  /**
197  * Limit a string to a number of characters.
198  * @param string $str Original string.
199  * @param int $length Maximum length (including delimiter).
200  * @param bool $words Break at a word boundary.
201  * @param string $delimiter Character to indicate a limited string.
202  * @return string
203  */
204  public static function limit($str,$length,$words = false,$delimiter = '…'){
205  if(mb_strlen($str) > $length){
206  $str = mb_substr($str,0,$length - mb_strlen($delimiter));
207  if($words && ($i = strrpos($str,' '))) $str = substr($str,0,$i + 1);
208  $str .= $delimiter;
209  }
210  return $str;
211  }
212  /**
213  * Parse a string into variables.
214  * Basicly parse_str() but with a returned array instead of by reference.
215  * @param string $str
216  * @return array
217  */
218  public static function parse($str){
219  parse_str($str,$data);
220  return $data;
221  }
222  /**
223  * Return part of a string until a needle. Shorten the string including the needle.
224  * @param string $haystack String to search in.
225  * @param string $needle Needle to look for (not found = return string until end).
226  * @return string Part of string until the needle.
227  */
228  public static function strip(&$haystack,$needle){
229  $result = substr($haystack,0,$i = strpos($haystack . $needle,$needle));
230  $haystack = substr($haystack,$i + 1);
231  return $result;
232  }
233  /**
234  * Return part of a string after a needle. Shorten the string including the needle.
235  * @param string $haystack String to search in.
236  * @param string $needle Needle to look for (not found = return string until end).
237  * @return string Part of string after the needle (false if needle not found).
238  */
239  public static function pop(&$haystack,$needle){
240  $i = strrpos($haystack,$needle);
241  if($i === false) return false;
242  $result = substr($haystack,$i + 1);
243  $haystack = substr($haystack,0,$i);
244  return $result;
245  }
246  /**
247  * Return part of a string until a needle.
248  * @param string $haystack String to search in.
249  * @param string $needle Needle to look for.
250  * @param int $index Number of parts/needles to skip.
251  * @return string Part of string until the needle (false = index not found).
252  */
253  public static function part($haystack,$needle,$index = 0){
254  $parts = explode($needle,$haystack);
255  return $index < count($parts) ? $parts[$index] : false;
256  }
257  /**
258  * Insert a string at a certain position in another string.
259  * @param string $str String to insert to.
260  * @param string $insert String to insert into $str.
261  * @param int $position Position to insert at (negative = relative to end).
262  * @param int $length Length of the part to replace with the insertion.
263  * @return string
264  */
265  public static function insert($str,$insert,$position,$length = 0){
266  return substr($str,0,$position) . $insert . substr($str,$position + $length);
267  }
268  /**
269  * Remove optinal quotes from a string.
270  * Quotes are only removed if they appear on both ends of the string.
271  * @param string $str String to remove quotes from.
272  * @param array $quotes Possible quote characters.
273  * @return string String without quotes.
274  */
275  public static function stripQuotes($str,$quotes = ["'",'"']){
276  return in_array($quote = substr($str,0,1),$quotes) && (substr($str,-1) == $quote) ? substr($str,1,-1) : $str;
277  }
278  /**
279  * Wrap a string into multiple lines (better wordwrap()).
280  * @param string $str String to wrap.
281  * @param int $width Maximum width.
282  * @return array Wrapped lines.
283  */
284  public static function wrap($str,$width){
285  $lines = [];
286  foreach(explode("\n",strtr($str,["\r" => '',"\t" => ' '])) as $line) while($line){
287  if(($length = mb_strlen($line)) > $width){
288  preg_match("/^.{0,$width}\\s/u",$line,$space);
289  preg_match('/^.{0,' . ($width - 1) . '}-/u',$line,$hyphen);
290  $length = ($space || $hyphen) ? max($space ? mb_strlen($space[0]) : 0,$hyphen ? mb_strlen($hyphen[0]) : 0) : $width;
291  }
292  $lines[] = rtrim(mb_substr($line,0,$length));
293  $line = mb_substr($line,$length);
294  }
295  return $lines;
296  }
297  /**
298  * Replace all newlines with HTML paragraph tags
299  * @param string $str String to format.
300  * @return string String with paragraphs (null on effective empty string).
301  */
302  public static function nl2p($str){
303  return ($str = trim($str)) ? '<p>' . preg_replace('/\\s*\\n\\s*/','</p><p>',str_replace("\r",'',$str)) . '</p>' : null;
304  }
305  /**
306  * Replace all multi newlines with HTML paragraph tags, and single newlines with line breaks.
307  * @param string $str String to format.
308  * @return string String with paragraphs and line breaks (null on effective empty string).
309  */
310  public static function nl2pbr($str){
311  return ($str = trim($str)) ? '<p>' . nl2br(preg_replace('/\\s*\\n\\s*\\n\\s*/','</p><p>',str_replace("\r",'',$str))) . '</p>' : null;
312  }
313  /**
314  * Transforms a string according to a certain function.
315  * @param string $str String to format.
316  * @param string|array $methods One or more format function(s).
317  * @param int $count Number of format functions applied (> 0 = ok; 0 = unknown function).
318  * @return string Tranformed string.
319  */
320  public static function transform($str,$methods,&$count = null){
321  if(!is_array($methods)) $methods = [$methods];
322  $count = count($methods);
323  foreach($methods as $method) switch($method){
324  case self::TRANSFORM_HTMLCHARS: $str = htmlspecialchars($str); break;
325  case self::TRANSFORM_LCFIRST: $str = lcfirst($str); break;
326  case self::TRANSFORM_LOWER: $str = strtolower($str); break;
327  case self::TRANSFORM_NL2BR: $str = nl2br($str); break;
328  case self::TRANSFORM_NL2P: $str = self::nl2p($str); break;
329  case self::TRANSFORM_NL2PBR: $str = self::nl2pbr($str); break;
330  case self::TRANSFORM_TRIM: $str = trim($str); break;
331  case self::TRANSFORM_UCFIRST: $str = ucfirst($str); break;
332  case self::TRANSFORM_UCWORDS: $str = ucwords($str); break;
333  case self::TRANSFORM_UPPER: $str = strtoupper($str); break;
334  case self::TRANSFORM_URLENCODE: $str = rawurlencode($str); break;
335  case self::TRANSFORM_URLIFY: $str = self::urlify($str); break;
336  default:
337  $replaced = 0;
338  if($i = strpos($method,'=')) $str = str_replace(substr($method,0,$i),substr($method,$i + 1),$str,$replaced);
339  if(!$replaced) $count--;
340  }
341  return $str;
342  }
343  /**
344  * Check if a string starts with a specific value.
345  * @param string $haystack String to search in.
346  * @param string $needle Value to look for at the start of the haystack.
347  * @result bool True if the haystack starts with the needle.
348  */
349  public static function startsWith($haystack,$needle){
350  return substr($haystack,0,strlen($needle)) == $needle;
351  }
352  /**
353  * Make sure a string starts with a specific value.
354  * @param string $haystack Base string.
355  * @param string $needle Value to check for at the start of the haystack.
356  * @return string Base string with the needle added if not present.
357  */
358  public static function startWith($haystack,$needle){
359  return self::startsWith($haystack,$needle) ? $haystack : $needle . $haystack;
360  }
361  /**
362  * Check if a string ends with a specific value.
363  * @param string $haystack String to search in.
364  * @param string $needle Value to look for at the end of the haystack.
365  * @result bool True if the haystack ends with the needle.
366  */
367  public static function endsWith($haystack,$needle){
368  return substr($haystack,-strlen($needle)) == $needle;
369  }
370  /**
371  * Make sure a string ends with a specific value.
372  * @param string $haystack Base string.
373  * @param string $needle Value to check for at the end of the haystack.
374  * @return string Base string with the needle added if not present.
375  */
376  public static function endWith($haystack,$needle){
377  return self::endsWith($haystack,$needle) ? $haystack : $haystack . $needle;
378  }
379  /**
380  * Numeric detection.
381  * Works only on decimal numbers, plus signs and exponential parts are not allowed.
382  * @param mixed $value Value to check.
383  * @return bool True if the value is a numeric.
384  */
385  public static function numeric($value){
386  return is_string($value) && preg_match('/^(\\-?[1-9]\\d*|0)(\\.\\d+)?$/',$value);
387  }
388  /**
389  * Evaluate an operator between a value and a reference value.
390  * Besides the usual '==', '!=', '>', '>=', '<', '<=', en '%' operators there are also some specific operators::
391  * - '*-' : Reference starts with the value.
392  * - '*-' : Reference ends with the value.
393  * - '*' : Reference contains the value.
394  * - '//' : Reference matches the regular expression in the value.
395  * @param string $ref Reference value. The value to look at.
396  * @param string $operator Operator.
397  * @param string $value Value sought after in the reference.
398  * @param bool $default Default result (unknown operator).
399  * @return bool True if the value matches the reference according to the operator.
400  */
401  public static function operator($ref,$operator,$value,$default = false){
402  switch($operator){
403  case '==': return $ref == $value;
404  case '!=': return $ref != $value;
405  case '>': return $ref > $value;
406  case '>=': return $ref >= $value;
407  case '<': return $ref < $value;
408  case '<=': return $ref <= $value;
409  case '%': return $ref % $value;
410  case '=%': return $ref % $value == 0;
411  case '*-': return self::startsWith($ref,$value);
412  case '-*': return self::endsWith($ref,$value);
413  case '*': return strpos($ref,$value) !== false;
414  case '//': return preg_match(substr($value,0,1) == '/' ? $value : '/' . $value . '/',$ref);
415  }
416  return $default;
417  }
418  /**
419  * Convert an array to a list.
420  * @param array $array Array with list items.
421  * @param string $last_delimiter Delimiter for the last item (same as delimiter when empty).
422  * @param string $delimiter Delimiter for the items.
423  * @return string
424  */
425  public static function implode($array,$last_delimiter = null,$delimiter = ', '){
426  $last = array_pop($array);
427  return $array ? implode($delimiter,$array) . ($last_delimiter ?: $delimiter) . $last : $last;
428  }
429  /**
430  * Show ranges from a numerical array.
431  * For example [1,2,3,5,6,8,9,10] becomes '1 - 3, 5, 6, 8 - 10'.
432  * @param array $array Array with numbers.
433  * @param string $delimiter Delimiter to use between ranges.
434  * @param string $separator Seperator to use between boundaries of a range.
435  * @return string
436  */
437  public static function ranges($array,$delimiter = ', ',$separator = ' - '){
438  $result = [];
439  foreach(Record::ranges($array) as $start => $end)
440  if($end > $start + 1) $result[] = $start . $separator . $end;
441  else{
442  $result[] = $start;
443  if($start != $end) $result[] = $end;
444  }
445  return implode($delimiter,$result);
446  }
447  /**
448  * Replace date tags in a string.
449  * @param string $str String with date tags.
450  * @param int $time Timestamp to use (empty = now).
451  * @param string $open Open tag.
452  * @param string $close Close tag.
453  * @return string String with tags replaced.
454  */
455  public static function replaceDate($str,$time = null,$open = '[',$close = ']'){
456  if(preg_match_all('/' . preg_quote($open,'/') . '(\w+)' . preg_quote($close,'/') . '/',$str,$matches,PREG_SET_ORDER)){
457  if(!$time) $time = time();
458  foreach($matches as $match) $str = str_replace($match[0],date($match[1],$time),$str);
459  }
460  return $str;
461  }
462  /**
463  * Extract attributes from a string.
464  * @param string $str String with attributes.
465  * @return array Attributes (assoc. array).
466  */
467  public static function attributes($str){
468  $attribs = [];
469  if($str && preg_match_all('/' . self::ATTRIBUTES_PATTERN . '/',$str,$matches,PREG_SET_ORDER)) foreach($matches as $match)
470  $attribs[$match['key']] = array_key_exists('value',$match) ? html_entity_decode(array_pop($match)) : true;
471  return $attribs;
472  }
473 
474 }
static emojify($str)
Replace ASCII emoji&#39;s by their Unicode equivalent.
Definition: Str.php:113
static random($length=32, $chars=null, $time=null)
Generate a random string.
Definition: Str.php:46
static parse($str)
Parse a string into variables.
Definition: Str.php:218
static urlify($str, $replace='-')
Transform a string to a URL-friendly version.
Definition: Str.php:105
static startsWith($haystack, $needle)
Check if a string starts with a specific value.
Definition: Str.php:349
static strip(&$haystack, $needle)
Return part of a string until a needle.
Definition: Str.php:228
static nl2p($str)
Replace all newlines with HTML paragraph tags.
Definition: Str.php:302
String helpers.
Definition: Str.php:8
static nl2pbr($str)
Replace all multi newlines with HTML paragraph tags, and single newlines with line breaks...
Definition: Str.php:310
static limit($str, $length, $words=false, $delimiter='…')
Limit a string to a number of characters.
Definition: Str.php:204
static codeName($index)
Generate a code-name, based on the index.
Definition: Str.php:75
static startWith($haystack, $needle)
Make sure a string starts with a specific value.
Definition: Str.php:358
static part($haystack, $needle, $index=0)
Return part of a string until a needle.
Definition: Str.php:253
static ranges($array, $delimiter=', ', $separator=' - ')
Show ranges from a numerical array.
Definition: Str.php:437
static nullify($str)
Transform an empty string to a null.
Definition: Str.php:88
static endsWith($haystack, $needle)
Check if a string ends with a specific value.
Definition: Str.php:367
static bool($value)
Returns literally &#39;true&#39; or &#39;false&#39;.
Definition: Str.php:33
static format($str, $format, $pad=null, $type=STR_PAD_LEFT, $replace=' *')
Format a string.
Definition: Str.php:167
static normalize($str)
Remove accents from a string.
Definition: Str.php:96
static pop(&$haystack, $needle)
Return part of a string after a needle.
Definition: Str.php:239
static wrap($str, $width)
Wrap a string into multiple lines (better wordwrap()).
Definition: Str.php:284
static endWith($haystack, $needle)
Make sure a string ends with a specific value.
Definition: Str.php:376
static pad($str, $length, $pad='0', $type=STR_PAD_LEFT)
Pad function that defaults to left padding with zeros.
Definition: Str.php:155
Definition: Color.php:3
static operator($ref, $operator,$value, $default=false)
Evaluate an operator between a value and a reference value.
Definition: Str.php:401
static stripQuotes($str, $quotes=["'",'"'])
Remove optinal quotes from a string.
Definition: Str.php:275
static camel($str, $delimiters=' -_')
Converts a delimited string to CamelCase.
Definition: Str.php:184
static snake($str, $delimiter='_')
Converts a CamelCased string to snake_case.
Definition: Str.php:193
static transform($str, $methods, &$count=null)
Transforms a string according to a certain function.
Definition: Str.php:320
static numeric($value)
Numeric detection.
Definition: Str.php:385
static insert($str, $insert, $position, $length=0)
Insert a string at a certain position in another string.
Definition: Str.php:265
static implode($array, $last_delimiter=null, $delimiter=', ')
Convert an array to a list.
Definition: Str.php:425
static attributes($str)
Extract attributes from a string.
Definition: Str.php:467
static unleet($str, $upper=false)
Remove leet-speak (1337 5p33k) from a string.
Definition: Str.php:123
static replaceDate($str, $time=null, $open='[', $close=']')
Replace date tags in a string.
Definition: Str.php:455
static icompare($str1, $str2)
Case insesitive string comparison.
Definition: Str.php:144