PageRenderTime 51ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/base.php

http://github.com/fuel/core
PHP | 540 lines | 455 code | 32 blank | 53 comment | 28 complexity | 7406d47a8d563fe85e0fce237b21790c MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Fuel is a fast, lightweight, community driven PHP 5.4+ framework.
  4. *
  5. * @package Fuel
  6. * @version 1.9-dev
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2019 Fuel Development Team
  10. * @link https://fuelphp.com
  11. */
  12. // load PHP 5.6+ specific code
  13. if (PHP_VERSION_ID >= 50600)
  14. {
  15. include "base56.php";
  16. }
  17. /**
  18. * Check if we're running on a Windows platform
  19. */
  20. if ( ! function_exists('is_windows'))
  21. {
  22. function is_windows()
  23. {
  24. return DIRECTORY_SEPARATOR === '\\';
  25. }
  26. }
  27. /**
  28. * Loads in a core class and optionally an app class override if it exists.
  29. *
  30. * @param string $path
  31. * @param string $folder
  32. * @return bool
  33. */
  34. if ( ! function_exists('import'))
  35. {
  36. function import($path, $folder = 'classes')
  37. {
  38. // unify the path
  39. $path = str_replace('/', DIRECTORY_SEPARATOR, $path);
  40. foreach (array('.php', '.phar', '') as $ext)
  41. {
  42. foreach (array(COREPATH, APPPATH) as $loc)
  43. {
  44. // check if the file exist
  45. if (is_file($file = $loc.$folder.DIRECTORY_SEPARATOR.$path.$ext))
  46. {
  47. require_once $file;
  48. return true;
  49. }
  50. }
  51. }
  52. return false;
  53. }
  54. }
  55. /**
  56. * Shortcut for writing to the Log
  57. *
  58. * @param int|string the error level
  59. * @param string the error message
  60. * @param string|array message context information
  61. * @return bool
  62. */
  63. if ( ! function_exists('logger'))
  64. {
  65. function logger($level, $msg, $context = null)
  66. {
  67. return \Log::write($level, $msg, $context);
  68. }
  69. }
  70. /**
  71. * Takes an array of attributes and turns it into a string for an html tag
  72. *
  73. * @param array $attr
  74. * @return string
  75. */
  76. if ( ! function_exists('array_to_attr'))
  77. {
  78. function array_to_attr($attr)
  79. {
  80. $attr_str = '';
  81. foreach ((array) $attr as $property => $value)
  82. {
  83. // Ignore null/false
  84. if ($value === null or $value === false)
  85. {
  86. continue;
  87. }
  88. // If the key is numeric then it must be something like selected="selected"
  89. if (is_numeric($property))
  90. {
  91. $property = $value;
  92. }
  93. $attr_str .= $property.'="'.str_replace('"', '&quot;', $value).'" ';
  94. }
  95. // We strip off the last space for return
  96. return trim($attr_str);
  97. }
  98. }
  99. /**
  100. * Create a XHTML tag
  101. *
  102. * @param string The tag name
  103. * @param array|string The tag attributes
  104. * @param string|bool The content to place in the tag, or false for no closing tag
  105. * @return string
  106. */
  107. if ( ! function_exists('html_tag'))
  108. {
  109. function html_tag($tag, $attr = array(), $content = false)
  110. {
  111. // list of void elements (tags that can not have content)
  112. static $void_elements = array(
  113. // html4
  114. "area","base","br","col","hr","img","input","link","meta","param",
  115. // html5
  116. "command","embed","keygen","source","track","wbr",
  117. // html5.1
  118. "menuitem",
  119. );
  120. // construct the HTML
  121. $html = '<'.$tag;
  122. $html .= ( ! empty($attr)) ? ' '.(is_array($attr) ? array_to_attr($attr) : $attr) : '';
  123. // a void element?
  124. if (in_array(strtolower($tag), $void_elements))
  125. {
  126. // these can not have content
  127. $html .= ' />';
  128. }
  129. else
  130. {
  131. // add the content and close the tag
  132. $html .= '>'.$content.'</'.$tag.'>';
  133. }
  134. return $html;
  135. }
  136. }
  137. /**
  138. * A case-insensitive version of in_array.
  139. *
  140. * @param mixed $needle
  141. * @param array $haystack
  142. * @return bool
  143. */
  144. if ( ! function_exists('in_arrayi'))
  145. {
  146. function in_arrayi($needle, $haystack)
  147. {
  148. return in_array(strtolower($needle), array_map('strtolower', $haystack));
  149. }
  150. }
  151. /**
  152. * Gets all the public vars for an object. Use this if you need to get all the
  153. * public vars of $this inside an object.
  154. *
  155. * @return array
  156. */
  157. if ( ! function_exists('get_object_public_vars'))
  158. {
  159. function get_object_public_vars($obj)
  160. {
  161. return get_object_vars($obj);
  162. }
  163. }
  164. /**
  165. * Renders a view and returns the output.
  166. *
  167. * @param string The view name/path
  168. * @param array The data for the view
  169. * @param bool Auto filter override
  170. * @return string
  171. */
  172. if ( ! function_exists('render'))
  173. {
  174. function render($view, $data = null, $auto_filter = null)
  175. {
  176. return \View::forge($view, $data, $auto_filter)->render();
  177. }
  178. }
  179. /**
  180. * A wrapper function for Lang::get()
  181. *
  182. * @param mixed The string to translate
  183. * @param array The parameters
  184. * @return string
  185. */
  186. if ( ! function_exists('__'))
  187. {
  188. function __($string, $params = array(), $default = null, $language = null)
  189. {
  190. return \Lang::get($string, $params, $default, $language);
  191. }
  192. }
  193. /**
  194. * Encodes the given string. This is just a wrapper function for Security::htmlentities()
  195. *
  196. * @param mixed The string to encode
  197. * @return string
  198. */
  199. if ( ! function_exists('e'))
  200. {
  201. function e($string)
  202. {
  203. return \Security::htmlentities($string);
  204. }
  205. }
  206. /**
  207. * Takes a classname and returns the actual classname for an alias or just the classname
  208. * if it's a normal class.
  209. *
  210. * @param string classname to check
  211. * @return string real classname
  212. */
  213. if ( ! function_exists('get_real_class'))
  214. {
  215. function get_real_class($class)
  216. {
  217. static $classes = array();
  218. if ( ! array_key_exists($class, $classes))
  219. {
  220. $reflect = new ReflectionClass($class);
  221. $classes[$class] = $reflect->getName();
  222. }
  223. return $classes[$class];
  224. }
  225. }
  226. /**
  227. * Takes an associative array in the layout of parse_url, and constructs a URL from it
  228. *
  229. * see http://www.php.net/manual/en/function.http-build-url.php#96335
  230. *
  231. * @param mixed (Part(s) of) an URL in form of a string or associative array like parse_url() returns
  232. * @param mixed Same as the first argument
  233. * @param int A bitmask of binary or'ed HTTP_URL constants (Optional)HTTP_URL_REPLACE is the default
  234. * @param array If set, it will be filled with the parts of the composed url like parse_url() would return
  235. *
  236. * @return string constructed URL
  237. */
  238. if (!function_exists('http_build_url'))
  239. {
  240. define('HTTP_URL_REPLACE', 1); // Replace every part of the first URL when there's one of the second URL
  241. define('HTTP_URL_JOIN_PATH', 2); // Join relative paths
  242. define('HTTP_URL_JOIN_QUERY', 4); // Join query strings
  243. define('HTTP_URL_STRIP_USER', 8); // Strip any user authentication information
  244. define('HTTP_URL_STRIP_PASS', 16); // Strip any password authentication information
  245. define('HTTP_URL_STRIP_AUTH', 32); // Strip any authentication information
  246. define('HTTP_URL_STRIP_PORT', 64); // Strip explicit port numbers
  247. define('HTTP_URL_STRIP_PATH', 128); // Strip complete path
  248. define('HTTP_URL_STRIP_QUERY', 256); // Strip query string
  249. define('HTTP_URL_STRIP_FRAGMENT', 512); // Strip any fragments (#identifier)
  250. define('HTTP_URL_STRIP_ALL', 1024); // Strip anything but scheme and host
  251. function http_build_url($url, $parts = array(), $flags = HTTP_URL_REPLACE, &$new_url = false)
  252. {
  253. $keys = array('user','pass','port','path','query','fragment');
  254. // HTTP_URL_STRIP_ALL becomes all the HTTP_URL_STRIP_Xs
  255. if ($flags & HTTP_URL_STRIP_ALL)
  256. {
  257. $flags |= HTTP_URL_STRIP_USER;
  258. $flags |= HTTP_URL_STRIP_PASS;
  259. $flags |= HTTP_URL_STRIP_PORT;
  260. $flags |= HTTP_URL_STRIP_PATH;
  261. $flags |= HTTP_URL_STRIP_QUERY;
  262. $flags |= HTTP_URL_STRIP_FRAGMENT;
  263. }
  264. // HTTP_URL_STRIP_AUTH becomes HTTP_URL_STRIP_USER and HTTP_URL_STRIP_PASS
  265. elseif ($flags & HTTP_URL_STRIP_AUTH)
  266. {
  267. $flags |= HTTP_URL_STRIP_USER;
  268. $flags |= HTTP_URL_STRIP_PASS;
  269. }
  270. // parse the original URL
  271. $parse_url = is_array($url) ? $url : parse_url($url);
  272. // make sure we always have a scheme, host and path
  273. empty($parse_url['scheme']) and $parse_url['scheme'] = 'http';
  274. empty($parse_url['host']) and $parse_url['host'] = \Input::server('http_host');
  275. isset($parse_url['path']) or $parse_url['path'] = '';
  276. // make the path absolute if needed
  277. if ( ! empty($parse_url['path']) and substr($parse_url['path'], 0, 1) != '/')
  278. {
  279. $parse_url['path'] = '/'.$parse_url['path'];
  280. }
  281. // scheme and host are always replaced
  282. isset($parts['scheme']) and $parse_url['scheme'] = $parts['scheme'];
  283. isset($parts['host']) and $parse_url['host'] = $parts['host'];
  284. // replace the original URL with it's new parts (if applicable)
  285. if ($flags & HTTP_URL_REPLACE)
  286. {
  287. foreach ($keys as $key)
  288. {
  289. if (isset($parts[$key]))
  290. $parse_url[$key] = $parts[$key];
  291. }
  292. }
  293. else
  294. {
  295. // join the original URL path with the new path
  296. if (isset($parts['path']) && ($flags & HTTP_URL_JOIN_PATH))
  297. {
  298. if (isset($parse_url['path']))
  299. $parse_url['path'] = rtrim(str_replace(basename($parse_url['path']), '', $parse_url['path']), '/') . '/' . ltrim($parts['path'], '/');
  300. else
  301. $parse_url['path'] = $parts['path'];
  302. }
  303. // join the original query string with the new query string
  304. if (isset($parts['query']) && ($flags & HTTP_URL_JOIN_QUERY))
  305. {
  306. if (isset($parse_url['query']))
  307. $parse_url['query'] .= '&' . $parts['query'];
  308. else
  309. $parse_url['query'] = $parts['query'];
  310. }
  311. }
  312. // strips all the applicable sections of the URL
  313. // note: scheme and host are never stripped
  314. foreach ($keys as $key)
  315. {
  316. if ($flags & (int) constant('HTTP_URL_STRIP_' . strtoupper($key)))
  317. unset($parse_url[$key]);
  318. }
  319. $new_url = $parse_url;
  320. return
  321. ((isset($parse_url['scheme'])) ? $parse_url['scheme'] . '://' : '')
  322. .((isset($parse_url['user'])) ? $parse_url['user'] . ((isset($parse_url['pass'])) ? ':' . $parse_url['pass'] : '') .'@' : '')
  323. .((isset($parse_url['host'])) ? $parse_url['host'] : '')
  324. .((isset($parse_url['port'])) ? ':' . $parse_url['port'] : '')
  325. .((isset($parse_url['path'])) ? $parse_url['path'] : '')
  326. .((isset($parse_url['query'])) ? '?' . $parse_url['query'] : '')
  327. .((isset($parse_url['fragment'])) ? '#' . $parse_url['fragment'] : '')
  328. ;
  329. }
  330. }
  331. /**
  332. * Find the common "root" path of two given paths or FQFN's
  333. *
  334. * @param array array with the paths to compare
  335. *
  336. * @return string the determined common path section
  337. */
  338. if ( ! function_exists('get_common_path'))
  339. {
  340. function get_common_path($paths)
  341. {
  342. $lastOffset = 1;
  343. $common = '/';
  344. if ( ! empty($paths[0]))
  345. {
  346. while (($index = strpos($paths[0], '/', $lastOffset)) !== false)
  347. {
  348. $dirLen = $index - $lastOffset + 1; // include /
  349. $dir = substr($paths[0], $lastOffset, $dirLen);
  350. foreach ($paths as $path)
  351. {
  352. if (substr($path, $lastOffset, $dirLen) != $dir)
  353. {
  354. return $common;
  355. }
  356. }
  357. $common .= $dir;
  358. $lastOffset = $index + 1;
  359. }
  360. }
  361. return $common;
  362. }
  363. }
  364. /**
  365. * Faster equivalent of call_user_func_array
  366. */
  367. if ( ! function_exists('call_fuel_func_array'))
  368. {
  369. function call_fuel_func_array($callback, array $args)
  370. {
  371. // deal with "class::method" syntax
  372. if (is_string($callback) and strpos($callback, '::') !== false)
  373. {
  374. $callback = explode('::', $callback);
  375. }
  376. // if an array is passed, extract the object and method to call
  377. if (is_array($callback) and isset($callback[1]) and is_object($callback[0]))
  378. {
  379. // make sure our arguments array is indexed
  380. if ($count = count($args))
  381. {
  382. $args = array_values($args);
  383. }
  384. list($instance, $method) = $callback;
  385. // calling the method directly is faster then call_user_func_array() !
  386. switch ($count)
  387. {
  388. case 0:
  389. return $instance->$method();
  390. case 1:
  391. return $instance->$method($args[0]);
  392. case 2:
  393. return $instance->$method($args[0], $args[1]);
  394. case 3:
  395. return $instance->$method($args[0], $args[1], $args[2]);
  396. case 4:
  397. return $instance->$method($args[0], $args[1], $args[2], $args[3]);
  398. }
  399. }
  400. elseif (is_array($callback) and isset($callback[1]) and is_string($callback[0]))
  401. {
  402. list($class, $method) = $callback;
  403. $class = '\\'.ltrim($class, '\\');
  404. // calling the method directly is faster then call_user_func_array() !
  405. switch (count($args))
  406. {
  407. case 0:
  408. return $class::$method();
  409. case 1:
  410. return $class::$method($args[0]);
  411. case 2:
  412. return $class::$method($args[0], $args[1]);
  413. case 3:
  414. return $class::$method($args[0], $args[1], $args[2]);
  415. case 4:
  416. return $class::$method($args[0], $args[1], $args[2], $args[3]);
  417. }
  418. }
  419. // if it's a string, it's a native function or a static method call
  420. elseif (is_string($callback) or $callback instanceOf \Closure)
  421. {
  422. is_string($callback) and $callback = ltrim($callback, '\\');
  423. // calling the method directly is faster then call_user_func_array() !
  424. switch (count($args))
  425. {
  426. case 0:
  427. return $callback();
  428. case 1:
  429. return $callback($args[0]);
  430. case 2:
  431. return $callback($args[0], $args[1]);
  432. case 3:
  433. return $callback($args[0], $args[1], $args[2]);
  434. case 4:
  435. return $callback($args[0], $args[1], $args[2], $args[3]);
  436. }
  437. }
  438. // fallback, handle the old way
  439. return call_user_func_array($callback, $args);
  440. }
  441. }
  442. /**
  443. * hash_pbkdf2() implementation for PHP < 5.5.0
  444. */
  445. if ( ! function_exists('hash_pbkdf2'))
  446. {
  447. /* PBKDF2 Implementation (described in RFC 2898)
  448. *
  449. * @param string a hash algorithm to use
  450. * @param string p password
  451. * @param string s salt
  452. * @param int c iteration count (use 1000 or higher)
  453. * @param int kl derived key length
  454. * @param bool r when set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits.
  455. *
  456. * @return string derived key
  457. */
  458. function hash_pbkdf2($a, $p, $s, $c, $kl = 0, $r = false)
  459. {
  460. $hl = strlen(hash($a, null, true)); # Hash length
  461. $kb = ceil($kl / $hl); # Key blocks to compute
  462. $dk = ''; # Derived key
  463. # Create key
  464. for ( $block = 1; $block <= $kb; $block ++ )
  465. {
  466. # Initial hash for this block
  467. $ib = $b = hash_hmac($a, $s . pack('N', $block), $p, true);
  468. # Perform block iterations
  469. for ( $i = 1; $i < $c; $i ++ )
  470. {
  471. # XOR each iterate
  472. $ib ^= ($b = hash_hmac($a, $b, $p, true));
  473. }
  474. $dk .= $ib; # Append iterated block
  475. }
  476. # Return derived key of correct length
  477. return substr($r ? $dk : bin2hex($dk), 0, $kl);
  478. }
  479. }