PageRenderTime 57ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/util.php

https://github.com/adoweb/utilphp
PHP | 2002 lines | 1126 code | 199 blank | 677 comment | 292 complexity | 267c66e560caab64148ae1e624dd4f7c MD5 | raw file
Possible License(s): GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * util.php
  4. *
  5. * util.php is a library of helper functions for common tasks such as
  6. * formatting bytes as a string or displaying a date in terms of how long ago
  7. * it was in human readable terms (E.g. 4 minutes ago). The library is entirely
  8. * contained within a single file and hosts no dependencies. The library is
  9. * designed to avoid any possible conflicts.
  10. *
  11. * @author Brandon Wamboldt
  12. * @link http://github.com/brandonwamboldt/utilphp/ Official Documentation
  13. * @version 1.0.004
  14. */
  15. if ( ! class_exists( 'util' ) ) {
  16. class util
  17. {
  18. /**
  19. * A constant representing the number of seconds in a minute, for
  20. * making code more verbose
  21. *
  22. * @since 1.0.000
  23. * @var int
  24. */
  25. const SECONDS_IN_A_MINUTE = 60;
  26. /**
  27. * A constant representing the number of seconds in an hour, for making
  28. * code more verbose
  29. *
  30. * @since 1.0.000
  31. * @var int
  32. */
  33. const SECONDS_IN_A_HOUR = 3600;
  34. const SECONDS_IN_AN_HOUR = 3600;
  35. /**
  36. * A constant representing the number of seconds in a day, for making
  37. * code more verbose
  38. *
  39. * @since 1.0.000
  40. * @var int
  41. */
  42. const SECONDS_IN_A_DAY = 86400;
  43. /**
  44. * A constant representing the number of seconds in a week, for making
  45. * code more verbose
  46. *
  47. * @since 1.0.000
  48. * @var int
  49. */
  50. const SECONDS_IN_A_WEEK = 604800;
  51. /**
  52. * A constant representing the number of seconds in a month (30 days),
  53. * for making code more verbose
  54. *
  55. * @since 1.0.000
  56. * @var int
  57. */
  58. const SECONDS_IN_A_MONTH = 2592000;
  59. /**
  60. * A constant representing the number of seconds in a year (365 days),
  61. * for making code more verbose
  62. *
  63. * @since 1.0.000
  64. * @var int
  65. */
  66. const SECONDS_IN_A_YEAR = 31536000;
  67. /**
  68. * A collapse icon, using in the dump_var function to allow collapsing
  69. * an array or object
  70. *
  71. * @access public
  72. * @since 1.0.000
  73. * @static
  74. * @var string
  75. */
  76. public static $icon_collapse = 'iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAMAAADXT/YiAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3MjlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFNzFDNDQyNEMyQzkxMUUxOTU4MEM4M0UxRDA0MUVGNSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFNzFDNDQyM0MyQzkxMUUxOTU4MEM4M0UxRDA0MUVGNSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NDlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3MjlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuF4AWkAAAA2UExURU9t2DBStczM/1h16DNmzHiW7iNFrypMvrnD52yJ4ezs7Onp6ejo6P///+Tk5GSG7D9h5SRGq0Q2K74AAAA/SURBVHjaLMhZDsAgDANRY3ZISnP/y1ZWeV+jAeuRSky6cKL4ryDdSggP8UC7r6GvR1YHxjazPQDmVzI/AQYAnFQDdVSJ80EAAAAASUVORK5CYII=';
  77. /**
  78. * A collapse icon, using in the dump_var function to allow collapsing
  79. * an array or object
  80. *
  81. * @access public
  82. * @since 1.0.000
  83. * @static
  84. * @var string
  85. */
  86. public static $icon_expand = 'iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAMAAADXT/YiAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3MTlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFQzZERTJDNEMyQzkxMUUxODRCQzgyRUNDMzZEQkZFQiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFQzZERTJDM0MyQzkxMUUxODRCQzgyRUNDMzZEQkZFQiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3MzlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3MTlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkmDvWIAAABIUExURU9t2MzM/3iW7ubm59/f5urq85mZzOvr6////9ra38zMzObm5rfB8FZz5myJ4SNFrypMvjBStTNmzOvr+mSG7OXl8T9h5SRGq/OfqCEAAABKSURBVHjaFMlbEoAwCEPRULXF2jdW9r9T4czcyUdA4XWB0IgdNSybxU9amMzHzDlPKKu7Fd1e6+wY195jW0ARYZECxPq5Gn8BBgCr0gQmxpjKAwAAAABJRU5ErkJggg==';
  87. /**
  88. * Access an array index, retrieving the value stored there if it
  89. * exists or a default if it does not. This function allows you to
  90. * concisely access an index which may or may not exist without
  91. * raising a warning
  92. *
  93. * @param array $var Array to access
  94. * @param string $field Index to access in the array
  95. * @param mixed $default Default value to return if the key is not
  96. * present in the array
  97. * @return mixed
  98. *
  99. * @access public
  100. * @since 1.0.000
  101. * @static
  102. */
  103. public static function array_get( & $var, $default = NULL )
  104. {
  105. if ( isset( $var ) ) {
  106. return $var;
  107. } else {
  108. return $default;
  109. }
  110. }
  111. /**
  112. * Display a variable's contents using nice HTML formatting and will
  113. * properly display the value of booleans as true or false
  114. *
  115. * @param mixed $var The variable to dump
  116. * @return string
  117. *
  118. * @see var_dump_plain()
  119. *
  120. * @access public
  121. * @since 1.0.000
  122. * @static
  123. */
  124. public static function var_dump( $var, $return = FALSE )
  125. {
  126. $html = '<pre style="margin-bottom: 18px;' .
  127. 'background: #f7f7f9;' .
  128. 'border: 1px solid #e1e1e8;' .
  129. 'padding: 8px;' .
  130. 'border-radius: 4px;' .
  131. '-moz-border-radius: 4px;' .
  132. '-webkit-border radius: 4px;' .
  133. 'display: block;' .
  134. 'font-size: 12.05px;' .
  135. 'white-space: pre-wrap;' .
  136. 'word-wrap: break-word;' .
  137. 'color: #333;' .
  138. 'font-family: Menlo,Monaco,Consolas,\'Courier New\',monospace;">';
  139. $html .= self::var_dump_plain( $var );
  140. $html .= '</pre>';
  141. if ( ! $return ) {
  142. echo $html;
  143. } else {
  144. return $html;
  145. }
  146. }
  147. /**
  148. * Display a variable's contents using nice HTML formatting (Without
  149. * the <pre> tag) and will properly display the values of variables
  150. * like booleans and resources. Supports collapsable arrays and objects
  151. * as well.
  152. *
  153. * @param mixed $var The variable to dump
  154. * @return string
  155. *
  156. * @access public
  157. * @since 1.0.000
  158. * @static
  159. */
  160. public static function var_dump_plain( $var )
  161. {
  162. $html = '';
  163. if ( is_bool( $var ) ) {
  164. $html .= '<span style="color:#588bff;">bool</span><span style="color:#999;">(</span><strong>' . ( ( $var ) ? 'true' : 'false' ) . '</strong><span style="color:#999;">)</span>';
  165. } else if ( is_int( $var ) ) {
  166. $html .= '<span style="color:#588bff;">int</span><span style="color:#999;">(</span><strong>' . $var . '</strong><span style="color:#999;">)</span>';
  167. } else if ( is_float( $var ) ) {
  168. $html .= '<span style="color:#588bff;">float</span><span style="color:#999;">(</span><strong>' . $var . '</strong><span style="color:#999;">)</span>';
  169. } else if ( is_string( $var ) ) {
  170. $html .= '<span style="color:#588bff;">string</span><span style="color:#999;">(</span>' . strlen( $var ) . '<span style="color:#999;">)</span> <strong>"' . self::htmlentities( $var ) . '"</strong>';
  171. } else if ( is_null( $var ) ) {
  172. $html .= '<strong>NULL</strong>';
  173. } else if ( is_resource( $var ) ) {
  174. $html .= '<span style="color:#588bff;">resource</span>("' . get_resource_type( $var ) . '") <strong>"' . $var . '"</strong>';
  175. } else if ( is_array( $var ) ) {
  176. $uuid = 'include-php-' . uniqid();
  177. $html .= '<span style="color:#588bff;">array</span>(' . count( $var ) . ')';
  178. if ( ! empty( $var ) ) {
  179. $html .= ' <img id="' . $uuid . '" data-expand="data:image/png;base64,' . self::$icon_expand . '" style="position:relative;left:-5px;top:-1px;cursor:pointer;" src="data:image/png;base64,' . self::$icon_collapse . '" /><br /><span id="' . $uuid . '-collapsable">[<br />';
  180. $indent = 4;
  181. $longest_key = 0;
  182. foreach( $var as $key => $value ) {
  183. if ( is_string( $key ) ) {
  184. $longest_key = max( $longest_key, strlen( $key ) + 2 );
  185. } else {
  186. $longest_key = max( $longest_key, strlen( $key ) );
  187. }
  188. }
  189. foreach ( $var as $key => $value ) {
  190. if ( is_numeric( $key ) ) {
  191. $html .= str_repeat( ' ', $indent ) . str_pad( $key, $longest_key, ' ');
  192. } else {
  193. $html .= str_repeat( ' ', $indent ) . str_pad( '"' . self::htmlentities( $key ) . '"', $longest_key, ' ' );
  194. }
  195. $html .= ' => ';
  196. $value = explode( '<br />', self::var_dump_plain( $value ) );
  197. foreach ( $value as $line => $val ) {
  198. if ( $line != 0 ) {
  199. $value[$line] = str_repeat( ' ', $indent * 2 ) . $val;
  200. }
  201. }
  202. $html .= implode( '<br />', $value ) . '<br />';
  203. }
  204. $html .= ']</span>';
  205. $html .= preg_replace( '/ +/', ' ', '<script type="text/javascript">(function() {
  206. var img = document.getElementById("' . $uuid . '");
  207. img.onclick = function() {
  208. if ( document.getElementById("' . $uuid . '-collapsable").style.display == "none" ) {
  209. document.getElementById("' . $uuid . '-collapsable").style.display = "inline";
  210. img.src = img.getAttribute("data-collapse");
  211. var previousSibling = document.getElementById("' . $uuid . '-collapsable").previousSibling;
  212. while ( previousSibling != null && ( previousSibling.nodeType != 1 || previousSibling.tagName.toLowerCase() != "br" ) ) {
  213. previousSibling = previousSibling.previousSibling;
  214. }
  215. if ( previousSibling != null && previousSibling.tagName.toLowerCase() == "br" ) {
  216. previousSibling.style.display = "inline";
  217. }
  218. } else {
  219. document.getElementById("' . $uuid . '-collapsable").style.display = "none";
  220. img.setAttribute( "data-collapse", img.getAttribute("src") );
  221. img.src = img.getAttribute("data-expand");
  222. var previousSibling = document.getElementById("' . $uuid . '-collapsable").previousSibling;
  223. while ( previousSibling != null && ( previousSibling.nodeType != 1 || previousSibling.tagName.toLowerCase() != "br" ) ) {
  224. previousSibling = previousSibling.previousSibling;
  225. }
  226. if ( previousSibling != null && previousSibling.tagName.toLowerCase() == "br" ) {
  227. previousSibling.style.display = "none";
  228. }
  229. }
  230. };
  231. })();
  232. </script>' );
  233. }
  234. } else if ( is_object( $var ) ) {
  235. $uuid = 'include-php-' . uniqid();
  236. $html .= '<span style="color:#588bff;">object</span>(' . get_class( $var ) . ') <img id="' . $uuid . '" data-expand="data:image/png;base64,' . self::$icon_expand . '" style="position:relative;left:-5px;top:-1px;cursor:pointer;" src="data:image/png;base64,' . self::$icon_collapse . '" /><br /><span id="' . $uuid . '-collapsable">[<br />';
  237. $original = $var;
  238. $var = (array) $var;
  239. $indent = 4;
  240. $longest_key = 0;
  241. foreach( $var as $key => $value ) {
  242. if ( substr( $key, 0, 2 ) == "\0*" ) {
  243. unset( $var[$key] );
  244. $key = 'protected:' . substr( $key, 2 );
  245. $var[$key] = $value;
  246. } else if ( substr( $key, 0, 1 ) == "\0" ) {
  247. unset( $var[$key] );
  248. $key = 'private:' . substr( $key, 1, strpos( substr( $key, 1 ), "\0" ) ) . ':' . substr( $key, strpos( substr( $key, 1 ), "\0" ) + 1 );
  249. $var[$key] = $value;
  250. }
  251. if ( is_string( $key ) ) {
  252. $longest_key = max( $longest_key, strlen( $key ) + 2 );
  253. } else {
  254. $longest_key = max( $longest_key, strlen( $key ) );
  255. }
  256. }
  257. foreach ( $var as $key => $value ) {
  258. if ( is_numeric( $key ) ) {
  259. $html .= str_repeat( ' ', $indent ) . str_pad( $key, $longest_key, ' ');
  260. } else {
  261. $html .= str_repeat( ' ', $indent ) . str_pad( '"' . self::htmlentities( $key ) . '"', $longest_key, ' ' );
  262. }
  263. $html .= ' => ';
  264. $value = explode( '<br />', self::var_dump_plain( $value ) );
  265. foreach ( $value as $line => $val ) {
  266. if ( $line != 0 ) {
  267. $value[$line] = str_repeat( ' ', $indent * 2 ) . $val;
  268. }
  269. }
  270. $html .= implode( '<br />', $value ) . '<br />';
  271. }
  272. $html .= ']</span>';
  273. $html .= preg_replace( '/ +/', ' ', '<script type="text/javascript">(function() {
  274. var img = document.getElementById("' . $uuid . '");
  275. img.onclick = function() {
  276. if ( document.getElementById("' . $uuid . '-collapsable").style.display == "none" ) {
  277. document.getElementById("' . $uuid . '-collapsable").style.display = "inline";
  278. img.src = img.getAttribute("data-collapse");
  279. var previousSibling = document.getElementById("' . $uuid . '-collapsable").previousSibling;
  280. while ( previousSibling != null && ( previousSibling.nodeType != 1 || previousSibling.tagName.toLowerCase() != "br" ) ) {
  281. previousSibling = previousSibling.previousSibling;
  282. }
  283. if ( previousSibling != null && previousSibling.tagName.toLowerCase() == "br" ) {
  284. previousSibling.style.display = "inline";
  285. }
  286. } else {
  287. document.getElementById("' . $uuid . '-collapsable").style.display = "none";
  288. img.setAttribute( "data-collapse", img.getAttribute("src") );
  289. img.src = img.getAttribute("data-expand");
  290. var previousSibling = document.getElementById("' . $uuid . '-collapsable").previousSibling;
  291. while ( previousSibling != null && ( previousSibling.nodeType != 1 || previousSibling.tagName.toLowerCase() != "br" ) ) {
  292. previousSibling = previousSibling.previousSibling;
  293. }
  294. if ( previousSibling != null && previousSibling.tagName.toLowerCase() == "br" ) {
  295. previousSibling.style.display = "none";
  296. }
  297. }
  298. };
  299. })();
  300. </script>' );
  301. }
  302. return $html;
  303. }
  304. /**
  305. * Converts any accent characters to their equivalent normal characters
  306. * and converts any other non-alphanumeric characters to dashes, then
  307. * converts any sequence of two or more dashes to a single dash. This
  308. * function generates slugs safe for use as URLs, and if you pass TRUE
  309. * as the second parameter, it will create strings safe for use as CSS
  310. * classes or IDs
  311. *
  312. * @param string $string A string to convert to a slug
  313. * @param bool $css_mode Whether or not to generate strings safe
  314. * for CSS classes/IDs (Default to false)
  315. * @return string
  316. *
  317. * @access public
  318. * @since 1.0.000
  319. * @static
  320. */
  321. public static function slugify( $string, $css_mode = FALSE )
  322. {
  323. $slug = preg_replace( '/([^a-z0-9]+)/', '-', strtolower( self::remove_accents( $string ) ) );
  324. if ( $css_mode ) {
  325. $digits = array( 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine' );
  326. if ( is_numeric( substr( $slug, 0, 1 ) ) ) {
  327. $slug = $digits[substr( $slug, 0, 1 )] . substr( $slug, 1 );
  328. }
  329. }
  330. return $slug;
  331. }
  332. /**
  333. * Checks to see if a string is utf8 encoded.
  334. *
  335. * NOTE: This function checks for 5-Byte sequences, UTF8
  336. * has Bytes Sequences with a maximum length of 4.
  337. *
  338. * @param string $string The string to be checked
  339. * @return bool
  340. *
  341. * @link https://github.com/facebook/libphutil/blob/master/src/utils/utf8.php
  342. *
  343. * @access public
  344. * @author bmorel@ssi.fr
  345. * @since 1.0.000
  346. * @static
  347. */
  348. public static function seems_utf8( $string )
  349. {
  350. if ( function_exists( 'mb_check_encoding' ) ) {
  351. // If mbstring is available, this is significantly faster than
  352. // using PHP regexps.
  353. return mb_check_encoding( $string, 'UTF-8' );
  354. }
  355. $regex = '/(
  356. | [\xF8-\xFF] # Invalid UTF-8 Bytes
  357. | [\xC0-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
  358. | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
  359. | [\xF0-\xF7](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
  360. | (?<=[\x0-\x7F\xF8-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
  361. | (?<![\xC0-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF7]|[\xF0-\xF7][\x80-\xBF]|[\xF0-\xF7][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence
  362. | (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence
  363. | (?<=[\xF0-\xF7])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence
  364. | (?<=[\xF0-\xF7][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2)
  365. )/x';
  366. return ! preg_match( $regex, $string );
  367. }
  368. /**
  369. * Nice formatting for computer sizes (Bytes)
  370. *
  371. * @param int $bytes The number in bytes to format
  372. * @param int $decimals The number of decimal points to include
  373. * @return string
  374. *
  375. * @access public
  376. * @since 1.0.000
  377. * @static
  378. */
  379. public static function size_format( $bytes, $decimals = 0 )
  380. {
  381. $bytes = floatval( $bytes );
  382. if ( $bytes < 1024 ) {
  383. return $bytes . ' B';
  384. } else if ( $bytes < pow( 1024, 2 ) ) {
  385. return number_format( $bytes / 1024, $decimals, '.', '' ) . ' KiB';
  386. } else if ( $bytes < pow( 1024, 3 ) ) {
  387. return number_format( $bytes / pow( 1024, 2 ), $decimals, '.', '' ) . ' MiB';
  388. } else if ( $bytes < pow( 1024, 4 ) ) {
  389. return number_format( $bytes / pow( 1024, 3 ), $decimals, '.', '' ) . ' GiB';
  390. } else if ( $bytes < pow( 1024, 5 ) ) {
  391. return number_format( $bytes / pow( 1024, 4 ), $decimals, '.', '' ) . ' TiB';
  392. } else if ( $bytes < pow( 1024, 6 ) ) {
  393. return number_format( $bytes / pow( 1024, 5 ), $decimals, '.', '' ) . ' PiB';
  394. } else {
  395. return number_format( $bytes / pow( 1024, 5 ), $decimals, '.', '' ) . ' PiB';
  396. }
  397. }
  398. /**
  399. * Serialize data, if needed.
  400. *
  401. * @param mixed $data Data that might need to be serialized
  402. * @return mixed
  403. *
  404. * @link http://codex.wordpress.org/Function_Reference/maybe_serialize
  405. *
  406. * @access public
  407. * @since 1.0.000
  408. * @static
  409. */
  410. public static function maybe_serialize( $data )
  411. {
  412. if ( is_array( $data ) || is_object( $data ) ) {
  413. return serialize( $data );
  414. }
  415. return $data;
  416. }
  417. /**
  418. * Unserialize value only if it is serialized
  419. *
  420. * @param string $data A variable that may or may not be serialized
  421. * @return mixed
  422. *
  423. * @link http://codex.wordpress.org/Function_Reference/maybe_unserialize
  424. *
  425. * @access public
  426. * @since 1.0.000
  427. * @static
  428. */
  429. public static function maybe_unserialize( $data )
  430. {
  431. // Don't attempt to unserialize data that isn't serialized
  432. if ( self::is_serialized( $data ) ) {
  433. return @unserialize( $data );
  434. }
  435. return $data;
  436. }
  437. /**
  438. * Check value to find if it was serialized.
  439. *
  440. * If $data is not an string, then returned value will always be false.
  441. * Serialized data is always a string.
  442. *
  443. * @param mixed $data Value to check to see if was serialized
  444. * @return bool
  445. *
  446. * @link http://codex.wordpress.org/Function_Reference/is_serialized
  447. *
  448. * @access public
  449. * @since 1.0.000
  450. * @static
  451. */
  452. public static function is_serialized( $data )
  453. {
  454. // If it isn't a string, it isn't serialized
  455. if ( ! is_string( $data ) ) {
  456. return FALSE;
  457. }
  458. $data = trim( $data );
  459. if ( 'N;' == $data ) {
  460. return TRUE;
  461. }
  462. $length = strlen( $data );
  463. if ( $length < 4 ) {
  464. return FALSE;
  465. }
  466. if ( ':' !== $data[1] ) {
  467. return FALSE;
  468. }
  469. $lastc = $data[$length - 1];
  470. if ( ';' !== $lastc && '}' !== $lastc ) {
  471. return FALSE;
  472. }
  473. $token = $data[0];
  474. switch ( $token ) {
  475. case 's' :
  476. if ( '"' !== $data[$length-2] ) {
  477. return FALSE;
  478. }
  479. case 'a' :
  480. case 'O' :
  481. return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
  482. case 'b' :
  483. case 'i' :
  484. case 'd' :
  485. return (bool) preg_match( "/^{$token}:[0-9.E-]+;\$/", $data );
  486. }
  487. return FALSE;
  488. }
  489. /**
  490. * Checks to see if the page is being server over SSL or not
  491. *
  492. * @return bool
  493. *
  494. * @access public
  495. * @since 1.0.000
  496. * @static
  497. */
  498. public static function is_https()
  499. {
  500. if ( isset( $_SERVER['HTTPS'] ) && ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] != 'off' ) {
  501. return TRUE;
  502. } else {
  503. return FALSE;
  504. }
  505. }
  506. /**
  507. * Retrieve a modified URL query string.
  508. *
  509. * You can rebuild the URL and append a new query variable to the URL
  510. * query by using this function. You can also retrieve the full URL
  511. * with query data.
  512. *
  513. * Adding a single key & value or an associative array. Setting a key
  514. * value to an empty string removes the key. Omitting oldquery_or_uri
  515. * uses the $_SERVER value. Additional values provided are expected
  516. * to be encoded appropriately with urlencode() or rawurlencode().
  517. *
  518. * @param mixed $newkey Either newkey or an associative
  519. * array
  520. * @param mixed $newvalue Either newvalue or oldquery or uri
  521. * @param mixed $oldquery_or_uri Optionally the old query or uri
  522. * @return string
  523. *
  524. * @link http://codex.wordpress.org/Function_Reference/add_query_arg
  525. *
  526. * @access public
  527. * @since 1.0.000
  528. * @static
  529. */
  530. public static function add_query_arg()
  531. {
  532. $ret = '';
  533. // Was an associative array of key => value pairs passed?
  534. if ( is_array( func_get_arg( 0 ) ) ) {
  535. // Was the URL passed as an argument?
  536. if ( func_num_args() == 2 && func_get_arg( 1 ) ) {
  537. $uri = func_get_arg( 1 );
  538. } else if ( func_num_args() == 3 && func_get_arg( 2 ) ) {
  539. $uri = func_get_arg( 2 );
  540. } else {
  541. $uri = $_SERVER['REQUEST_URI'];
  542. }
  543. } else {
  544. // Was the URL passed as an argument?
  545. if ( func_num_args() == 3 && func_get_arg( 2 ) ) {
  546. $uri = func_get_arg( 2 );
  547. } else {
  548. $uri = $_SERVER['REQUEST_URI'];
  549. }
  550. }
  551. // Does the URI contain a fragment section (The part after the #)
  552. if ( $frag = strstr( $uri, '#' ) ) {
  553. $uri = substr( $uri, 0, -strlen( $frag ) );
  554. } else {
  555. $frag = '';
  556. }
  557. // Get the URI protocol if possible
  558. if ( preg_match( '|^https?://|i', $uri, $matches ) ) {
  559. $protocol = $matches[0];
  560. $uri = substr( $uri, strlen( $protocol ) );
  561. } else {
  562. $protocol = '';
  563. }
  564. // Does the URI contain a query string?
  565. if ( strpos( $uri, '?' ) !== FALSE ) {
  566. $parts = explode( '?', $uri, 2 );
  567. if ( 1 == count( $parts ) ) {
  568. $base = '?';
  569. $query = $parts[0];
  570. } else {
  571. $base = $parts[0] . '?';
  572. $query = $parts[1];
  573. }
  574. } else if ( ! empty( $protocol ) || strpos( $uri, '=' ) === FALSE ) {
  575. $base = $uri . '?';
  576. $query = '';
  577. } else {
  578. $base = '';
  579. $query = $uri;
  580. }
  581. // Parse the query string into an array
  582. parse_str( $query, $qs );
  583. // This re-URL-encodes things that were already in the query string
  584. $qs = self::array_map_deep( $qs, 'urlencode' );
  585. if ( is_array( func_get_arg( 0 ) ) ) {
  586. $kayvees = func_get_arg( 0 );
  587. $qs = array_merge( $qs, $kayvees );
  588. } else {
  589. $qs[func_get_arg( 0 )] = func_get_arg( 1 );
  590. }
  591. foreach ( (array) $qs as $k => $v ) {
  592. if ( $v === false )
  593. unset( $qs[$k] );
  594. }
  595. $ret = http_build_query( $qs );
  596. $ret = trim( $ret, '?' );
  597. $ret = preg_replace( '#=(&|$)#', '$1', $ret );
  598. $ret = $protocol . $base . $ret . $frag;
  599. $ret = rtrim( $ret, '?' );
  600. return $ret;
  601. }
  602. /**
  603. * Removes an item or list from the query string.
  604. *
  605. * @param string|array $keys Query key or keys to remove.
  606. * @param bool $uri When false uses the $_SERVER value
  607. * @return string
  608. *
  609. * @link http://codex.wordpress.org/Function_Reference/remove_query_arg
  610. *
  611. * @access public
  612. * @since 1.0.000
  613. * @static
  614. */
  615. public static function remove_query_arg( $keys, $uri = FALSE )
  616. {
  617. if ( is_array( $keys ) ) {
  618. foreach ( $keys as $key ) {
  619. $uri = self::add_query_arg( $key, FALSE, $uri );
  620. }
  621. return $uri;
  622. }
  623. return self::add_query_arg( $keys, FALSE, $uri );
  624. }
  625. /**
  626. * Converts many english words that equate to true or false to boolean
  627. *
  628. * Supports 'y', 'n', 'yes', 'no' and a few other variations
  629. *
  630. * @param string $string The string to convert to boolean
  631. * @param bool $default The value to return if we can't match any
  632. * yes/no words
  633. * @return bool
  634. *
  635. * @access public
  636. * @since 1.0.000
  637. * @static
  638. */
  639. public static function str_to_bool( $string, $default = FALSE )
  640. {
  641. $yes_words = 'affirmative|all right|aye|indubitably|most assuredly|ok|of course|okay|sure thing|y|yes+|yea|yep|sure|yeah|true|t|on|1';
  642. $no_words = 'no*|no way|nope|nah|na|never|absolutely not|by no means|negative|never ever|false|f|off|0';
  643. if ( preg_match( '/^(' . $yes_words . ')$/i', $string ) ) {
  644. return TRUE;
  645. } else if ( preg_match( '/^(' . $no_words . ')$/i', $string ) ) {
  646. return FALSE;
  647. } else {
  648. return $default;
  649. }
  650. }
  651. /**
  652. * Convert entities, while preserving already-encoded entities
  653. *
  654. * @param string $string The text to be converted
  655. * @return string
  656. *
  657. * @link http://ca2.php.net/manual/en/function.htmlentities.php#90111
  658. *
  659. * @access public
  660. * @since 1.0.000
  661. * @static
  662. */
  663. public static function htmlentities( $string, $preserve_encoded_entities = FALSE )
  664. {
  665. if ( $preserve_encoded_entities ) {
  666. $translation_table = get_html_translation_table( HTML_ENTITIES, ENT_QUOTES, mb_internal_encoding() );
  667. $translation_table[chr(38)] = '&';
  668. return preg_replace( '/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/', '&amp;', strtr( $string, $translation_table ) );
  669. } else {
  670. return htmlentities( $string, ENT_QUOTES, mb_internal_encoding() );
  671. }
  672. }
  673. /**
  674. * Convert >, <, ', " and & to html entities, but preserves entities
  675. * that are already encoded
  676. *
  677. * @param string $string The text to be converted
  678. * @return string
  679. *
  680. * @link http://ca2.php.net/manual/en/function.htmlentities.php#90111
  681. *
  682. * @access public
  683. * @since 1.0.000
  684. * @static
  685. */
  686. public static function htmlspecialchars( $string, $preserve_encoded_entities = FALSE )
  687. {
  688. if ( $preserve_encoded_entities ) {
  689. $translation_table = get_html_translation_table( HTML_SPECIALCHARS, ENT_QUOTES, mb_internal_encoding() );
  690. $translation_table[chr( 38 )] = '&';
  691. return preg_replace( '/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/', '&amp;', strtr( $string, $translation_table ) );
  692. } else {
  693. return htmlentities( $string, ENT_QUOTES, mb_internal_encoding() );
  694. }
  695. }
  696. /**
  697. * Converts all accent characters to ASCII characters
  698. *
  699. * If there are no accent characters, then the string given is just
  700. * returned
  701. *
  702. * @param string $string Text that might have accent characters
  703. * @return string Filtered string with replaced "nice" characters
  704. *
  705. * @link http://codex.wordpress.org/Function_Reference/remove_accents
  706. *
  707. * @access public
  708. * @since 1.0.000
  709. * @static
  710. */
  711. public static function remove_accents( $string )
  712. {
  713. if ( ! preg_match( '/[\x80-\xff]/', $string ) ) {
  714. return $string;
  715. }
  716. if ( self::seems_utf8( $string ) ) {
  717. $chars = array(
  718. // Decompositions for Latin-1 Supplement
  719. chr(194).chr(170) => 'a', chr(194).chr(186) => 'o',
  720. chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
  721. chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
  722. chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
  723. chr(195).chr(134) => 'AE',chr(195).chr(135) => 'C',
  724. chr(195).chr(136) => 'E', chr(195).chr(137) => 'E',
  725. chr(195).chr(138) => 'E', chr(195).chr(139) => 'E',
  726. chr(195).chr(140) => 'I', chr(195).chr(141) => 'I',
  727. chr(195).chr(142) => 'I', chr(195).chr(143) => 'I',
  728. chr(195).chr(144) => 'D', chr(195).chr(145) => 'N',
  729. chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
  730. chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
  731. chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
  732. chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
  733. chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
  734. chr(195).chr(158) => 'TH',chr(195).chr(159) => 's',
  735. chr(195).chr(160) => 'a', chr(195).chr(161) => 'a',
  736. chr(195).chr(162) => 'a', chr(195).chr(163) => 'a',
  737. chr(195).chr(164) => 'a', chr(195).chr(165) => 'a',
  738. chr(195).chr(166) => 'ae',chr(195).chr(167) => 'c',
  739. chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
  740. chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
  741. chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
  742. chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
  743. chr(195).chr(176) => 'd', chr(195).chr(177) => 'n',
  744. chr(195).chr(178) => 'o', chr(195).chr(179) => 'o',
  745. chr(195).chr(180) => 'o', chr(195).chr(181) => 'o',
  746. chr(195).chr(182) => 'o', chr(195).chr(184) => 'o',
  747. chr(195).chr(185) => 'u', chr(195).chr(186) => 'u',
  748. chr(195).chr(187) => 'u', chr(195).chr(188) => 'u',
  749. chr(195).chr(189) => 'y', chr(195).chr(190) => 'th',
  750. chr(195).chr(191) => 'y', chr(195).chr(152) => 'O',
  751. // Decompositions for Latin Extended-A
  752. chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
  753. chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
  754. chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
  755. chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
  756. chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
  757. chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
  758. chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
  759. chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
  760. chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
  761. chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
  762. chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
  763. chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
  764. chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
  765. chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
  766. chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
  767. chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
  768. chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
  769. chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
  770. chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
  771. chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
  772. chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
  773. chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
  774. chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
  775. chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
  776. chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
  777. chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
  778. chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
  779. chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
  780. chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
  781. chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
  782. chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
  783. chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
  784. chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
  785. chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
  786. chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
  787. chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
  788. chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
  789. chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
  790. chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
  791. chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
  792. chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
  793. chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
  794. chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
  795. chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
  796. chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
  797. chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
  798. chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
  799. chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
  800. chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
  801. chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
  802. chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
  803. chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
  804. chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
  805. chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
  806. chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
  807. chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
  808. chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
  809. chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
  810. chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
  811. chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
  812. chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
  813. chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
  814. chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
  815. chr(197).chr(190) => 'z', chr(197).chr(191) => 's',
  816. // Decompositions for Latin Extended-B
  817. chr(200).chr(152) => 'S', chr(200).chr(153) => 's',
  818. chr(200).chr(154) => 'T', chr(200).chr(155) => 't',
  819. // Euro Sign
  820. chr(226).chr(130).chr(172) => 'E',
  821. // GBP (Pound) Sign
  822. chr(194).chr(163) => ''
  823. );
  824. $string = strtr( $string, $chars );
  825. } else {
  826. // Assume ISO-8859-1 if not UTF-8
  827. $chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158)
  828. .chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194)
  829. .chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202)
  830. .chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210)
  831. .chr(211).chr(212).chr(213).chr(214).chr(216).chr(217).chr(218)
  832. .chr(219).chr(220).chr(221).chr(224).chr(225).chr(226).chr(227)
  833. .chr(228).chr(229).chr(231).chr(232).chr(233).chr(234).chr(235)
  834. .chr(236).chr(237).chr(238).chr(239).chr(241).chr(242).chr(243)
  835. .chr(244).chr(245).chr(246).chr(248).chr(249).chr(250).chr(251)
  836. .chr(252).chr(253).chr(255);
  837. $chars['out'] = 'EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy';
  838. $string = strtr( $string, $chars['in'], $chars['out'] );
  839. $double_chars['in'] = array( chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254) );
  840. $double_chars['out'] = array( 'OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th' );
  841. $string = str_replace( $double_chars['in'], $double_chars['out'], $string );
  842. }
  843. return $string;
  844. }
  845. /**
  846. * Pads a given string with zeroes on the left
  847. *
  848. * @param int $number The number to pad
  849. * @param int $length The total length of the desired string
  850. * @return string
  851. *
  852. * @access public
  853. * @since 1.0.000
  854. * @static
  855. */
  856. public static function zero_pad( $number, $length )
  857. {
  858. return str_pad( $number, $length, '0', STR_PAD_LEFT );
  859. }
  860. /**
  861. * Converts a unix timestamp to a relative time string, such as "3 days
  862. * ago" or "2 weeks ago"
  863. *
  864. * @param int $from The date to use as a starting point
  865. * @param int $to The date to compare to. Defaults to the
  866. * current time
  867. * @param string $suffix The string to add to the end, defaults to
  868. * " ago"
  869. * @return string
  870. *
  871. * @access public
  872. * @since 1.0.000
  873. * @static
  874. */
  875. public static function human_time_diff( $from, $to = '', $as_text = FALSE, $suffix = ' ago' )
  876. {
  877. if ( $to == '' ) {
  878. $to = time();
  879. }
  880. $from = new DateTime( date( 'Y-m-d H:i:s', $from ) );
  881. $to = new DateTime( date( 'Y-m-d H:i:s', $to ) );
  882. $diff = $from->diff( $to );
  883. if ( $diff->y > 1 ) {
  884. $text = $diff->y . ' years';
  885. } else if ( $diff->y == 1 ) {
  886. $text = '1 year';
  887. } else if ( $diff->m > 1 ) {
  888. $text = $diff->m . ' months';
  889. } else if ( $diff->m == 1 ) {
  890. $text = '1 month';
  891. } else if ( $diff->d > 7 ) {
  892. $text = ceil( $diff->d / 7 ) . ' weeks';
  893. } else if ( $diff->d == 7 ) {
  894. $text = '1 week';
  895. } else if ( $diff->d > 1 ) {
  896. $text = $diff->d . ' days';
  897. } else if ( $diff->d == 1 ) {
  898. $text = '1 day';
  899. } else if ( $diff->h > 1 ) {
  900. $text = $diff->h . ' hours';
  901. } else if ( $diff->h == 1 ) {
  902. $text = ' 1 hour';
  903. } else if ( $diff->i > 1 ) {
  904. $text = $diff->i . ' minutes';
  905. } else if ( $diff->i == 1 ) {
  906. $text = '1 minute';
  907. } else if ( $diff->s > 1 ) {
  908. $text = $diff->s . ' seconds';
  909. } else {
  910. $text = '1 second';
  911. }
  912. if ( $as_text ) {
  913. $text = explode( ' ', $text, 2 );
  914. $text = self::number_to_word( $text[0] ) . ' ' . $text[1];
  915. }
  916. return trim( $text ) . $suffix;
  917. }
  918. /**
  919. * Converts a number into the text equivalent. For example, 456 becomes
  920. * four hundred and fifty-six
  921. *
  922. * @param int|float $number The number to convert into text
  923. * @return string
  924. *
  925. * @link http://bloople.net/num2text
  926. *
  927. * @access public
  928. * @author Brenton Fletcher
  929. * @since 1.0.000
  930. * @static
  931. */
  932. public static function number_to_word( $number )
  933. {
  934. $number = (string) $number;
  935. if ( strpos( $number, '.' ) !== FALSE ) {
  936. list( $number, $decimal ) = explode( '.', $number );
  937. } else {
  938. $number = $number;
  939. $decimal = FALSE;
  940. }
  941. $output = '';
  942. if ( $number[0] == '-' ) {
  943. $output = 'negative ';
  944. $number = ltrim( $number, '-' );
  945. } else if ( $number[0] == '+' ) {
  946. $output = 'positive ';
  947. $number = ltrim( $number, '+' );
  948. }
  949. if ( $number[0] == '0' ) {
  950. $output .= 'zero';
  951. } else {
  952. $number = str_pad( $number, 36, '0', STR_PAD_LEFT );
  953. $group = rtrim( chunk_split( $number, 3, ' ' ), ' ' );
  954. $groups = explode( ' ', $group );
  955. $groups2 = array();
  956. foreach ( $groups as $group ) {
  957. $groups2[] = self::_number_to_word_three_digits( $group[0], $group[1], $group[2] );
  958. }
  959. for ( $z = 0; $z < count( $groups2 ); $z++ ) {
  960. if ( $groups2[$z] != '' ) {
  961. $output .= $groups2[$z] . self::_number_to_word_convert_group( 11 - $z );
  962. $output .= ( $z < 11 && ! array_search( '', array_slice( $groups2, $z + 1, -1 ) ) && $groups2[11] != '' && $groups[11][0] == '0' ? ' and ' : ', ' );
  963. }
  964. }
  965. $output = rtrim( $output, ', ' );
  966. }
  967. if ( $decimal > 0 ) {
  968. $output .= ' point';
  969. for ( $i = 0; $i < strlen( $decimal ); $i++ ) {
  970. $output .= ' ' . self::_number_to_word_convert_digit( $decimal[$i] );
  971. }
  972. }
  973. return $output;
  974. }
  975. protected static function _number_to_word_convert_group( $index )
  976. {
  977. switch( $index ) {
  978. case 11:
  979. return ' decillion';
  980. case 10:
  981. return ' nonillion';
  982. case 9:
  983. return ' octillion';
  984. case 8:
  985. return ' septillion';
  986. case 7:
  987. return ' sextillion';
  988. case 6:
  989. return ' quintrillion';
  990. case 5:
  991. return ' quadrillion';
  992. case 4:
  993. return ' trillion';
  994. case 3:
  995. return ' billion';
  996. case 2:
  997. return ' million';
  998. case 1:
  999. return ' thousand';
  1000. case 0:
  1001. return '';
  1002. }
  1003. }
  1004. protected static function _number_to_word_three_digits( $digit1, $digit2, $digit3 )
  1005. {
  1006. $output = '';
  1007. if ( $digit1 == '0' && $digit2 == '0' && $digit3 == '0') {
  1008. return '';
  1009. }
  1010. if ( $digit1 != '0' ) {
  1011. $output .= self::_number_to_word_convert_digit( $digit1 ) . ' hundred';
  1012. if ( $digit2 != '0' || $digit3 != '0' ) {
  1013. $output .= ' and ';
  1014. }
  1015. }
  1016. if ( $digit2 != '0') {
  1017. $output .= se

Large files files are truncated, but you can click here to view the full file