Common.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. <?php
  2. /**
  3. * Core Bootstrap
  4. *
  5. * This file contains all common system functions and View and Controller classes.
  6. *
  7. * @package MicroMVC
  8. * @author David Pennington
  9. * @copyright (c) 2011 MicroMVC Framework
  10. * @license http://micromvc.com/license
  11. ********************************** 80 Columns *********************************
  12. */
  13. /**
  14. * Attach (or remove) multiple callbacks to an event and trigger those callbacks when that event is called.
  15. *
  16. * @param string $event name
  17. * @param mixed $value the optional value to pass to each callback
  18. * @param mixed $callback the method or function to call - FALSE to remove all callbacks for event
  19. */
  20. function event($event, $value = NULL, $callback = NULL)
  21. {
  22. static $events;
  23. // Adding or removing a callback?
  24. if($callback !== NULL)
  25. {
  26. if($callback)
  27. {
  28. $events[$event][] = $callback;
  29. }
  30. else
  31. {
  32. unset($events[$event]);
  33. }
  34. }
  35. elseif(isset($events[$event])) // Fire a callback
  36. {
  37. foreach($events[$event] as $function)
  38. {
  39. $value = call_user_func($function, $value);
  40. }
  41. return $value;
  42. }
  43. }
  44. /**
  45. * Fetch a config value from a module configuration file
  46. *
  47. * @param string $file name of the config
  48. * @param boolean $clear to clear the config object
  49. * @return object
  50. */
  51. function config($file = 'Config', $clear = FALSE)
  52. {
  53. static $configs = array();
  54. if($clear)
  55. {
  56. unset($configs[$file]);
  57. return;
  58. }
  59. if(empty($configs[$file]))
  60. {
  61. //$configs[$file] = new \Micro\Config($file);
  62. require(SP . 'Config/' . $file . EXT);
  63. $configs[$file] = (object) $config;
  64. //print dump($configs);
  65. }
  66. return $configs[$file];
  67. }
  68. /**
  69. * Return an HTML safe dump of the given variable(s) surrounded by "pre" tags.
  70. * You can pass any number of variables (of any type) to this function.
  71. *
  72. * @param mixed
  73. * @return string
  74. */
  75. function dump()
  76. {
  77. $string = '';
  78. foreach(func_get_args() as $value)
  79. {
  80. $string .= '<pre>' . h($value === NULL ? 'NULL' : (is_scalar($value) ? $value : print_r($value, TRUE))) . "</pre>\n";
  81. }
  82. return $string;
  83. }
  84. /**
  85. * Safely fetch a $_POST value, defaulting to the value provided if the key is
  86. * not found.
  87. *
  88. * @param string $key name
  89. * @param mixed $default value if key is not found
  90. * @param boolean $string TRUE to require string type
  91. * @return mixed
  92. */
  93. function post($key, $default = NULL, $string = FALSE)
  94. {
  95. if(isset($_POST[$key]))
  96. {
  97. return $string ? (string)$_POST[$key] : $_POST[$key];
  98. }
  99. return $default;
  100. }
  101. /**
  102. * Safely fetch a $_GET value, defaulting to the value provided if the key is
  103. * not found.
  104. *
  105. * @param string $key name
  106. * @param mixed $default value if key is not found
  107. * @param boolean $string TRUE to require string type
  108. * @return mixed
  109. */
  110. function get($key, $default = NULL, $string = FALSE)
  111. {
  112. if(isset($_GET[$key]))
  113. {
  114. return $string ? (string)$_GET[$key] : $_GET[$key];
  115. }
  116. return $default;
  117. }
  118. /**
  119. * Safely fetch a $_SESSION value, defaulting to the value provided if the key is
  120. * not found.
  121. *
  122. * @param string $k the post key
  123. * @param mixed $d the default value if key is not found
  124. * @return mixed
  125. */
  126. function session($k, $d = NULL)
  127. {
  128. return isset($_SESSION[$k]) ? $_SESSION[$k] : $d;
  129. }
  130. /**
  131. * Create a random 32 character MD5 token
  132. *
  133. * @return string
  134. */
  135. function token()
  136. {
  137. return md5(str_shuffle(chr(mt_rand(32, 126)) . uniqid() . microtime(TRUE)));
  138. }
  139. /**
  140. * Write to the application log file using error_log
  141. *
  142. * @param string $message to save
  143. * @return bool
  144. */
  145. function log_message($message)
  146. {
  147. //$path = SP . 'Storage/Log/' . date('Y-m-d') . '.log';
  148. $path = 'stderr';
  149. // Append date and IP to log message
  150. return error_log(date('H:i:s ') . getenv('REMOTE_ADDR') . " $message\n", 3, $path);
  151. }
  152. /**
  153. * Send a HTTP header redirect using "location" or "refresh".
  154. *
  155. * @param string $url the URL string
  156. * @param int $c the HTTP status code
  157. * @param string $method either location or redirect
  158. */
  159. function redirect($url = NULL, $code = 302, $method = 'location')
  160. {
  161. if(strpos($url, '://') === FALSE)
  162. {
  163. $url = site_url($url);
  164. }
  165. //print dump($url);
  166. header($method == 'refresh' ? "Refresh:0;url = $url" : "Location: $url", TRUE, $code);
  167. }
  168. /*
  169. * Return the full URL to a path on this site or another.
  170. *
  171. * @param string $uri may contain another sites TLD
  172. * @return string
  173. *
  174. function site_url($uri = NULL)
  175. {
  176. return (strpos($uri, '://') === FALSE ? \Micro\URL::get() : '') . ltrim($uri, '/');
  177. }
  178. */
  179. /**
  180. * Return the full URL to a location on this site
  181. *
  182. * @param string $path to use or FALSE for current path
  183. * @param array $params to append to URL
  184. * @return string
  185. */
  186. function site_url($path = NULL, array $params = NULL)
  187. {
  188. // In PHP 5.4, http_build_query will support RFC 3986
  189. return DOMAIN . ($path ? '/'. trim($path, '/') : PATH)
  190. . ($params ? '?'. str_replace('+', '%20', http_build_query($params, TRUE, '&')) : '');
  191. }
  192. /**
  193. * Return the current URL with path and query params
  194. *
  195. * @return string
  196. *
  197. function current_url()
  198. {
  199. return DOMAIN . getenv('REQUEST_URI');
  200. }
  201. */
  202. /**
  203. * Convert a string from one encoding to another encoding
  204. * and remove invalid bytes sequences.
  205. *
  206. * @param string $string to convert
  207. * @param string $to encoding you want the string in
  208. * @param string $from encoding that string is in
  209. * @return string
  210. */
  211. function encode($string, $to = 'UTF-8', $from = 'UTF-8')
  212. {
  213. // ASCII is already valid UTF-8
  214. if($to == 'UTF-8' AND is_ascii($string))
  215. {
  216. return $string;
  217. }
  218. // Convert the string
  219. return @iconv($from, $to . '//TRANSLIT//IGNORE', $string);
  220. }
  221. /**
  222. * Tests whether a string contains only 7bit ASCII characters.
  223. *
  224. * @param string $string to check
  225. * @return bool
  226. */
  227. function is_ascii($string)
  228. {
  229. return ! preg_match('/[^\x00-\x7F]/S', $string);
  230. }
  231. /**
  232. * Encode a string so it is safe to pass through the URL
  233. *
  234. * @param string $string to encode
  235. * @return string
  236. */
  237. function base64_url_encode($string = NULL)
  238. {
  239. return strtr(base64_encode($string), '+/=', '-_~');
  240. }
  241. /**
  242. * Decode a string passed through the URL
  243. *
  244. * @param string $string to decode
  245. * @return string
  246. */
  247. function base64_url_decode($string = NULL)
  248. {
  249. return base64_decode(strtr($string, '-_~', '+/='));
  250. }
  251. /**
  252. * Convert special characters to HTML safe entities.
  253. *
  254. * @param string $string to encode
  255. * @return string
  256. */
  257. function h($string)
  258. {
  259. return htmlspecialchars($string, ENT_QUOTES, 'utf-8');
  260. }
  261. /**
  262. * Filter a valid UTF-8 string so that it contains only words, numbers,
  263. * dashes, underscores, periods, and spaces - all of which are safe
  264. * characters to use in file names, URI, XML, JSON, and (X)HTML.
  265. *
  266. * @param string $string to clean
  267. * @param bool $spaces TRUE to allow spaces
  268. * @return string
  269. */
  270. function sanitize($string, $spaces = TRUE)
  271. {
  272. $search = array(
  273. '/[^\w\-\. ]+/u', // Remove non safe characters
  274. '/\s\s+/', // Remove extra whitespace
  275. '/\.\.+/', '/--+/', '/__+/' // Remove duplicate symbols
  276. );
  277. $string = preg_replace($search, array(' ', ' ', '.', '-', '_'), $string);
  278. if( ! $spaces)
  279. {
  280. $string = preg_replace('/--+/', '-', str_replace(' ', '-', $string));
  281. }
  282. return trim($string, '-._ ');
  283. }
  284. /**
  285. * Create a SEO friendly URL string from a valid UTF-8 string.
  286. *
  287. * @param string $string to filter
  288. * @return string
  289. */
  290. function sanitize_url($string)
  291. {
  292. return urlencode(mb_strtolower(sanitize($string, FALSE)));
  293. }
  294. /**
  295. * Filter a valid UTF-8 string to be file name safe.
  296. *
  297. * @param string $string to filter
  298. * @return string
  299. */
  300. function sanitize_filename($string)
  301. {
  302. return sanitize($string, FALSE);
  303. }
  304. /**
  305. * Return a SQLite/MySQL/PostgreSQL datetime string
  306. *
  307. * @param int $timestamp
  308. */
  309. function sql_date($timestamp = NULL)
  310. {
  311. return date('Y-m-d H:i:s', $timestamp ?: time());
  312. }
  313. /**
  314. * Make a request to the given URL using cURL.
  315. *
  316. * @param string $url to request
  317. * @param array $options for cURL object
  318. * @return object
  319. */
  320. function curl_request($url, array $options = NULL)
  321. {
  322. $ch = curl_init($url);
  323. $defaults = array(
  324. CURLOPT_HEADER => 0,
  325. CURLOPT_RETURNTRANSFER => 1,
  326. CURLOPT_TIMEOUT => 5,
  327. );
  328. // Connection options override defaults if given
  329. curl_setopt_array($ch, (array) $options + $defaults);
  330. // Create a response object
  331. $object = new stdClass;
  332. // Get additional request info
  333. $object->response = curl_exec($ch);
  334. $object->error_code = curl_errno($ch);
  335. $object->error = curl_error($ch);
  336. $object->info = curl_getinfo($ch);
  337. curl_close($ch);
  338. return $object;
  339. }
  340. /**
  341. * Create a RecursiveDirectoryIterator object
  342. *
  343. * @param string $dir the directory to load
  344. * @param boolean $recursive to include subfolders
  345. * @return object
  346. */
  347. function directory($dir, $recursive = TRUE)
  348. {
  349. $i = new \RecursiveDirectoryIterator($dir);
  350. if( ! $recursive) return $i;
  351. return new \RecursiveIteratorIterator($i, \RecursiveIteratorIterator::SELF_FIRST);
  352. }
  353. /**
  354. * Make sure that a directory exists and is writable by the current PHP process.
  355. *
  356. * @param string $dir the directory to load
  357. * @param string $chmod value as octal
  358. * @return boolean
  359. */
  360. function directory_is_writable($dir, $chmod = 0755)
  361. {
  362. // If it doesn't exist, and can't be made
  363. if(! is_dir($dir) AND ! mkdir($dir, $chmod, TRUE)) return FALSE;
  364. // If it isn't writable, and can't be made writable
  365. if(! is_writable($dir) AND !chmod($dir, $chmod)) return FALSE;
  366. return TRUE;
  367. }
  368. /**
  369. * Convert any given variable into a SimpleXML object
  370. *
  371. * @param mixed $object variable object to convert
  372. * @param string $root root element name
  373. * @param object $xml xml object
  374. * @param string $unknown element name for numeric keys
  375. * @param string $doctype XML doctype
  376. */
  377. function to_xml($object, $root = 'data', $xml = NULL, $unknown = 'element', $doctype = "<?xml version = '1.0' encoding = 'utf-8'?>")
  378. {
  379. if(is_null($xml))
  380. {
  381. $xml = simplexml_load_string("$doctype<$root/>");
  382. }
  383. foreach((array) $object as $k => $v)
  384. {
  385. if(is_int($k))
  386. {
  387. $k = $unknown;
  388. }
  389. if(is_scalar($v))
  390. {
  391. $xml->addChild($k, h($v));
  392. }
  393. else
  394. {
  395. $v = (array) $v;
  396. $node = array_diff_key($v, array_keys(array_keys($v))) ? $xml->addChild($k) : $xml;
  397. self::from($v, $k, $node);
  398. }
  399. }
  400. return $xml;
  401. }
  402. /**
  403. * Return an IntlDateFormatter object using the current system locale
  404. *
  405. * @param string $locale string
  406. * @param integer $datetype IntlDateFormatter constant
  407. * @param integer $timetype IntlDateFormatter constant
  408. * @param string $timezone Time zone ID, default is system default
  409. * @return IntlDateFormatter
  410. */
  411. function __date($locale = NULL, $datetype = IntlDateFormatter::MEDIUM, $timetype = IntlDateFormatter::SHORT, $timezone = NULL)
  412. {
  413. return new IntlDateFormatter($locale ?: setlocale(LC_ALL, 0), $datetype, $timetype, $timezone);
  414. }
  415. /**
  416. * Format the given string using the current system locale
  417. * Basically, it's sprintf on i18n steroids.
  418. *
  419. * @param string $string to parse
  420. * @param array $params to insert
  421. * @return string
  422. */
  423. function __($string, array $params = NULL)
  424. {
  425. return msgfmt_format_message(setlocale(LC_ALL, 0), $string, $params);
  426. }
  427. /**
  428. * Color output text for the CLI
  429. *
  430. * @param string $text to color
  431. * @param string $color of text
  432. * @param string $background color
  433. */
  434. function colorize($text, $color, $bold = FALSE)
  435. {
  436. // Standard CLI colors
  437. $colors = array_flip(array(30 => 'gray', 'red', 'green', 'yellow', 'blue', 'purple', 'cyan', 'white', 'black'));
  438. // Escape string with color information
  439. return"\033[" . ($bold ? '1' : '0') . ';' . $colors[$color] . "m$text\033[0m";
  440. }
  441. // End