PageRenderTime 49ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/library/lib/base.php

https://github.com/plank/Seed-Framework
PHP | 628 lines | 365 code | 77 blank | 186 comment | 68 complexity | 169d40b999048aa11c1d218c2efcf478 MD5 | raw file
Possible License(s): LGPL-3.0
  1. <?php
  2. /**
  3. * base.php, part of the seed framework
  4. *
  5. * A library of procedural functions
  6. *
  7. * @author mateo murphy
  8. * @copyright mateo murphy
  9. * @license The MIT License
  10. * @package library
  11. */
  12. /**
  13. * Load PHP4 or 5 specific functions
  14. */
  15. if (version_compare(phpversion(), '5.0') < 0) {
  16. require_once('base/php4.php');
  17. } else {
  18. require_once('base/php5.php');
  19. }
  20. /**
  21. * Returns the value of var, or the value of default if var isn' set.
  22. * Useful for assigning array elements that are not cartain to exist
  23. *
  24. * @param mixed $var
  25. * @param mixed $default
  26. * @return mixed
  27. */
  28. function assign(& $var, $default = '') {
  29. if (isset($var) && $var) {
  30. return $var;
  31. } else {
  32. return $default;
  33. }
  34. }
  35. /**
  36. * Flatten a multidimensional array into a single array. Does not maintain keys.
  37. *
  38. * @param array $array
  39. * @param bool unique
  40. * @return array
  41. */
  42. function array_flatten($array) {
  43. $return = array();
  44. foreach ($array as $element) {
  45. if (is_array($element)) {
  46. $return = array_merge($return, array_flatten($element));
  47. } else {
  48. $return[] = $element;
  49. }
  50. }
  51. return $return;
  52. }
  53. /**
  54. * Returns all the key value pairs in the first array whose
  55. * keys appear in the second array
  56. *
  57. * @param array $array1
  58. * @param array $array2
  59. * @return array
  60. */
  61. function array_intersect_by_key($array1, $array2) {
  62. $result = array();
  63. foreach($array1 as $key => $value) {
  64. if (key_exists($key, $array2)) {
  65. $result[$key] = $value;
  66. }
  67. }
  68. return $result;
  69. }
  70. /**
  71. * Returns all the key value pairs in the first array whose
  72. * keys don't appear in the second array
  73. *
  74. * @param array $array1
  75. * @param array $array2
  76. * @return array
  77. */
  78. function array_diff_by_key($array1, $array2) {
  79. $result = array();
  80. if (!is_array($array1)) {
  81. trigger_error('Parameter 1 for array_diff_by_key is not an array', E_USER_WARNING);
  82. return false;
  83. }
  84. foreach($array1 as $key => $value) {
  85. if (!key_exists($key, $array2)) {
  86. $result[$key] = $value;
  87. }
  88. }
  89. return $result;
  90. }
  91. /**
  92. * Works like array combine, but works when the array are of different sizes. If there are more keys than values,
  93. * values will be set to null; if there are more values, they will be discarded
  94. *
  95. * @param array $keys
  96. * @param array $values
  97. * @return array
  98. */
  99. function array_combine_resized($keys, $values) {
  100. foreach($keys as $key) {
  101. $result[$key] = array_shift($values);
  102. }
  103. return $result;
  104. }
  105. /**
  106. * Trucantes a string to a given length, with an indicator at the end
  107. *
  108. * @param string $string
  109. * @param int $length
  110. * @param string $indicator
  111. * @return string
  112. */
  113. function truncate($string, $length, $indicator = '...') {
  114. if (strlen($string) < $length) return $string;
  115. return substr($string, 0, $length).$indicator;
  116. }
  117. /**
  118. * Returns the current time with microseconds as a float
  119. *
  120. * @return float
  121. */
  122. function micro_time() {
  123. return array_sum(explode(' ', microtime()));
  124. }
  125. /**
  126. * Evaluates a file and returns the result as a string. Note that variables in the calling function's scope
  127. * won't be available in the included file.
  128. *
  129. * @param string $filename
  130. * @return string
  131. */
  132. function include_into_string($filename) {
  133. if (!file_exists($filename)) {
  134. trigger_error("Couldn't include '$filename', file not found");
  135. return false;
  136. }
  137. ob_start();
  138. require($filename);
  139. $result = ob_get_contents();
  140. ob_end_clean();
  141. return $result;
  142. }
  143. /**
  144. * Checks if a given email address is valid as per RFC822
  145. *
  146. * @copyright 2005 Cal Henderson <cal@iamcal.com>
  147. * @see http://iamcal.com/publish/articles/php/parsing_email/
  148. */
  149. function is_valid_email_address($email) {
  150. $qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
  151. $dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
  152. $atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c'.
  153. '\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
  154. $quoted_pair = '\\x5c[\\x00-\\x7f]';
  155. $domain_literal = "\\x5b($dtext|$quoted_pair)*\\x5d";
  156. $quoted_string = "\\x22($qtext|$quoted_pair)*\\x22";
  157. $domain_ref = $atom;
  158. $sub_domain = "($domain_ref|$domain_literal)";
  159. $word = "($atom|$quoted_string)";
  160. $domain = "$sub_domain(\\x2e$sub_domain)*";
  161. $local_part = "$word(\\x2e$word)*";
  162. $addr_spec = "$local_part\\x40$domain";
  163. return preg_match("!^$addr_spec$!", $email) ? true : false;
  164. }
  165. /**
  166. * Checks if a given url is valid
  167. * This check is not nearly as rigorous as the email one, this should be fixed in the future
  168. *
  169. * @param string $url The url to check
  170. * @return bool
  171. */
  172. function is_valid_url($url) {
  173. $regex = '/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/';
  174. return preg_match($regex, $url) ? true : false;
  175. }
  176. /**
  177. * Adds a given path to any hrefs containing only anchors
  178. *
  179. * @param string $text
  180. * @param string $document_url
  181. * @return string
  182. */
  183. function absolute_anchors($text, $document_url) {
  184. $pattern = '/(href\s*=\s*)((")#([^"]*)"|(\')#([^\']*)\')/';
  185. return preg_replace($pattern, '\1\3\5'.$document_url.'#\4\6\3\5', $text);
  186. }
  187. /**
  188. * Returns the current date/time as an ISO 8601 formated date
  189. *
  190. * @return string
  191. */
  192. function now() {
  193. return date('Y-m-d H:i:s');
  194. }
  195. /**
  196. * Recursively strips slashes from an array
  197. *
  198. * @param array $array
  199. * @param bool $is_top_level
  200. * @return array
  201. */
  202. function transcribe($array, $is_top_level = true) {
  203. $result = array();
  204. $is_magic = get_magic_quotes_gpc();
  205. foreach ($array as $key => $value) {
  206. $decoded_key = ($is_magic && !$is_top_level) ? stripslashes($key) : $key;
  207. if (is_array($value)) {
  208. $decoded_value = transcribe($value, false);
  209. } else {
  210. $decoded_value = ($is_magic) ? stripslashes($value) : $value;
  211. }
  212. $result[$decoded_key] = $decoded_value;
  213. }
  214. return $result;
  215. }
  216. /**
  217. * Strips slashes from GET, POST and COOKIES when magic_quote enabled
  218. *
  219. * @return bool True if quotes needed to be removes, false if not
  220. */
  221. function fix_magic_quotes() {
  222. global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS;
  223. // clean gpc of slashes
  224. if (!get_magic_quotes_gpc()) {
  225. return false;
  226. }
  227. $_GET = transcribe($_GET);
  228. $_POST = transcribe($_POST);
  229. $_COOKIE = transcribe($_COOKIE);
  230. $_REQUEST = transcribe($_REQUEST);
  231. $HTTP_GET_VARS = $_GET;
  232. $HTTP_POST_VARS = $_GET;
  233. $HTTP_COOKIE_VARS = $_COOKIE;
  234. return true;
  235. }
  236. /**
  237. * Quote aware explode function
  238. *
  239. * @param string $seperator
  240. * @param string $str
  241. * @param string $quote_character
  242. * @param string $escape_character Quote characters preceded by the escape character are ignored. Default value is a backslash
  243. * @param bool $unquote If set to true, quoted chunks are unquoted, and escaped quotes are unescaped
  244. * @return array
  245. */
  246. function explode_quoted($seperator, $str, $quote_character = '"', $escape_character = null, $unquote = true){
  247. if (is_null($escape_character)) {
  248. $escape_character = '\\';
  249. }
  250. if (!$seperator) {
  251. return false;
  252. }
  253. $seperator = preg_quote($seperator, '/');
  254. $quote_character = preg_quote($quote_character, '/');
  255. $escape_character = preg_quote($escape_character, '/');
  256. if ($quote_character == $escape_character) {
  257. $qc = "(?<!".$quote_character.")".$quote_character."(?:".$quote_character.$quote_character.")*(?!".$quote_character.")";
  258. $nqc = "(?:[^".$quote_character."]|(?:".$quote_character.$quote_character.")+)";
  259. } else if ($escape_character) {
  260. $qc = "(?<!".$escape_character.")".$quote_character;
  261. $nqc = "(?:[^".$quote_character."]|(?<=".$escape_character.")".$quote_character.")";
  262. } else {
  263. $qc = $quote_character;
  264. $nqc = "[^".$qc."]";
  265. }
  266. $expr = "/".$seperator."(?=(?:".$nqc."*".$qc.$nqc."*".$qc.")*(?!".$nqc."*".$qc."))/";
  267. $results = preg_split($expr, trim($str));
  268. // unquote values
  269. if ($unquote) {
  270. $results = preg_replace("/^".$quote_character."(.*)".$quote_character."$/","$1", $results);
  271. // unescape quotes
  272. if ($escape_character) {
  273. $results = preg_replace("/".$escape_character.$quote_character."/", $quote_character, $results);
  274. }
  275. }
  276. return $results;
  277. }
  278. /**
  279. * Truncate text string function. Tag aware.
  280. * Compensates for img tag at the beginning of a paragraph.
  281. * XHTML only! so solo tags need closing /> ie: good: <br />, <img src="foo" /> bad: <br>, <img src="foo">
  282. *
  283. * @param string $text Text to process
  284. * @param integer $minimum_length Approx length, in characters, you want text to be
  285. * @param integer $length_offset The variation in how long the text can be. Defaults will make length will be between 200 and 200-20=180 characters and the character where the last tag ends
  286. * @param bool $cut_words
  287. * @param mixed $dots Add the final text to the string - can be an image tag, or text, or ... - any string basically. default to FALSE.
  288. * @return string
  289. * @author http://ca.php.net/manual/en/function.substr.php#59719
  290. * @author mitchell amihod - modifications to make it wrapper tag aware.
  291. *
  292. */
  293. function html_substr($text, $minimum_length = 200, $length_offset = 20, $cut_words = FALSE, $dots = FALSE) {
  294. // Reset tag counter & quote checker
  295. $tag_counter = 0;
  296. $quotes_on = FALSE;
  297. $tag_open = "";
  298. $tag_close = "";
  299. if( substr($text,0,1) == "<" ) {
  300. //so we have a tag, lets find the closing >
  301. $close_index = strpos($text, '>' );
  302. $tag_open = substr($text, 0, $close_index+1);
  303. $text = substr($text, $close_index+1);
  304. //we have tag_open, so check if its an image tag.
  305. if( strstr($tag_open, 'img') ) {
  306. $tag_close = "";
  307. }
  308. else {
  309. $closing_tag_index = strrpos($text, '<');
  310. $tag_close = substr($text, $closing_tag_index);
  311. $text = substr($text, 0, -(strlen($tag_close)) );
  312. }
  313. }
  314. // Check if the text is too long
  315. if (strlen($text) > $minimum_length) {
  316. // Reset the tag_counter and pass through (part of) the entire text
  317. $c = 0;
  318. for ($i = 0; $i < strlen($text); $i++) {
  319. // Load the current character and the next one
  320. // if the string has not arrived at the last character
  321. $current_char = substr($text,$i,1);
  322. if ($i < strlen($text) - 1) {
  323. $next_char = substr($text,$i + 1,1);
  324. }
  325. else {
  326. $next_char = "";
  327. }
  328. // First check if quotes are on
  329. if (!$quotes_on) {
  330. // Check if it's a tag
  331. // On a "<" add 3 if it's an opening tag (like <a href...)
  332. // or add only 1 if it's an ending tag (like </a>)
  333. if ($current_char == '<') {
  334. if ($next_char == '/') {
  335. $tag_counter += 1;
  336. }
  337. else {
  338. $tag_counter += 3;
  339. }
  340. }
  341. // Slash signifies an ending (like </a> or ... />)
  342. // substract 2
  343. if ($current_char == '/' && $tag_counter <> 0) $tag_counter -= 2;
  344. // On a ">" substract 1
  345. if ($current_char == '>') $tag_counter -= 1;
  346. // If quotes are encountered, start ignoring the tags
  347. // (for directory slashes)
  348. if ($current_char == '"') $quotes_on = TRUE;
  349. }
  350. else {
  351. // IF quotes are encountered again, turn it back off
  352. if ($current_char == '"') $quotes_on = FALSE;
  353. }
  354. // Count only the chars outside html tags
  355. if($tag_counter == 2 || $tag_counter == 0){
  356. $c++;
  357. }
  358. // Check if the counter has reached the minimum length yet,
  359. // then wait for the tag_counter to become 0, and chop the string there
  360. if ($c > $minimum_length - $length_offset && $tag_counter == 0 && ($next_char == ' ' || $cut_words == TRUE)) {
  361. $text = substr($text,0,$i + 1);
  362. if($dots){
  363. $text .= $dots;
  364. }
  365. return $tag_open.$text.$tag_close;
  366. }
  367. }
  368. }
  369. return $tag_open.$text.$tag_close;
  370. }
  371. /**
  372. * Formats a date
  373. *
  374. * @param string $format The format of the date, same as date() function
  375. * @param mixed $date Can either be a string representation of a date, or a timestamp; null or false values will make the function return false
  376. * @return string The formated date, or false if the date value was null or false
  377. */
  378. function format_date($format, $date = null) {
  379. if (is_null($date) || !$date || $date == '0000-00-00 00:00:00') {
  380. return false;
  381. }
  382. if (!is_numeric($date)) {
  383. $date = strtotime($date);
  384. }
  385. return date($format, $date);
  386. }
  387. /**
  388. * Erases and turns off all output buffers
  389. *
  390. */
  391. function ob_end_clean_all() {
  392. while(ob_get_level()) {
  393. if (!ob_end_clean()) {
  394. return;
  395. }
  396. }
  397. }
  398. /**
  399. * Formats a plaintext string with html paragraphs and breaks
  400. *
  401. * @param string $string
  402. * @return string
  403. */
  404. function nl2p($string) {
  405. $regex = array("/(\r{2,}|\n{2,}|(\r\n){2,})+/", "/(\r{1}|\n{1}|(\r\n){1})+/");
  406. $replace = array("</p><p>", "<br />");
  407. return "<p>".preg_replace($regex, $replace, $string)."</p>";
  408. }
  409. /**
  410. * Returns an xhtml-ized version of a string if it doesn't contain any p or br tags
  411. *
  412. * @param string $string
  413. * @return string
  414. */
  415. function xhtmlize($string) {
  416. if (preg_match('@<p\s*>|<br\s*/?>@', $string)) {
  417. return $string;
  418. } else {
  419. return nl2p($string);
  420. }
  421. }
  422. /**
  423. * Returns the boolean value of a variable. Any value that evaluates to false,
  424. * as well as the strings 'false' or 'f', will return as false. Everything
  425. * else will return as true.
  426. *
  427. * @param mixed $var
  428. * @return bool
  429. */
  430. function boolval($var) {
  431. if (!$var || strtolower($var) == 'false' || strtolower($var) == 'f') {
  432. return false;
  433. }
  434. return true;
  435. }
  436. /**
  437. * Escapes any html entity found that isn't a valid xml entity.
  438. *
  439. * Particularily useful for embedding escaped html into xml, as required by rss feeds
  440. *
  441. * @param string
  442. * @return string
  443. */
  444. function escape_non_xml_entities($string) {
  445. $string = preg_replace('/&(?!(quot|amp|apos|lt|gt))([A-Za-z0-9]*);/', '&amp;\\2;', $string);
  446. return $string;
  447. }
  448. /**
  449. * Returns a time stamp for a RFC3339 formated date string
  450. *
  451. * @param string $string The date string
  452. * @return int
  453. */
  454. function parse_RFC3339_date($string) {
  455. if (preg_match('/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z/', $string, $matches)) {
  456. return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
  457. } else if (preg_match('/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})-(\d{2}:\d{2})/', $string, $matches)) {
  458. return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
  459. } else {
  460. return false;
  461. }
  462. }
  463. /**
  464. * Generates a random password
  465. *
  466. * @param int $length
  467. * @param bool $use_numbers
  468. * @param bool $use_lower_case
  469. * @param bool $use_upper_case
  470. * @param bool $use_punctuation
  471. * @return string
  472. */
  473. function generate_password($length = 8, $use_numbers = true, $use_lower_case = true, $use_upper_case = true, $use_punctuation = false) {
  474. $choices = array();
  475. if ($use_numbers) $choices = array_merge($choices, range(0,9));
  476. if ($use_lower_case) $choices = array_merge($choices, range('a','z'));
  477. if ($use_upper_case) $choices = array_merge($choices, range('A','Z'));
  478. if ($use_punctuation) $choices = array_merge($choices, array('!', '@', '#', '$', '%', '^', '&', '*', '-', '_', '+', '='));
  479. if (!count($choices)) return false;
  480. $result = '';
  481. for ($x = 0; $x < $length; $x ++) {
  482. $result .= $choices[mt_rand(0, count($choices) - 1)];
  483. }
  484. return $result;
  485. }
  486. /**
  487. * Generates a random UUID
  488. *
  489. * @return string
  490. */
  491. function uuid()
  492. {
  493. return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
  494. mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
  495. mt_rand( 0, 0x0fff ) | 0x4000,
  496. mt_rand( 0, 0x3fff ) | 0x8000,
  497. mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
  498. );
  499. }
  500. /**
  501. * Works like strpos, but matches a regex
  502. *
  503. * @param string $pattern
  504. * @param string $subject
  505. * @param int $offset
  506. * @return int Returns the position of the match, or false if no match was found
  507. */
  508. function preg_pos($pattern, $subject, $offset) {
  509. if (!preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE, $offset)) return false;
  510. return $matches[0][1];
  511. }
  512. ?>