3 * Basic Cake functionality.
5 * Core functions for including other source files, loading models and so forth.
9 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
10 * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
12 * Licensed under The MIT License
13 * Redistributions of files must retain the above copyright notice.
15 * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
16 * @link http://cakephp.org CakePHP(tm) Project
18 * @subpackage cake.cake
19 * @since CakePHP(tm) v 0.2.9
20 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
24 * Basic defines for timing functions.
30 define('WEEK', 604800);
31 define('MONTH', 2592000);
32 define('YEAR', 31536000);
37 if (!function_exists('clone')) {
38 if (version_compare(PHP_VERSION
, '5.0') < 0) {
40 function clone($object)
48 * Loads configuration files. Receives a set of configuration files
52 * `config('config1', 'config2');`
54 * @return boolean Success
55 * @link http://book.cakephp.org/view/1125/config
58 $args = func_get_args();
59 foreach ($args as $arg) {
60 if ($arg === 'database' && file_exists(CONFIGS
. 'database.php')) {
61 include_once(CONFIGS
. $arg . '.php');
62 } elseif (file_exists(CONFIGS
. $arg . '.php')) {
63 include_once(CONFIGS
. $arg . '.php');
65 if (count($args) == 1) {
69 if (count($args) == 1) {
78 * Loads component/components from LIBS. Takes optional number of parameters.
82 * `uses('flay', 'time');`
84 * @param string $name Filename without the .php part
85 * @deprecated Will be removed in 2.0
86 * @link http://book.cakephp.org/view/1140/uses
89 $args = func_get_args();
90 foreach ($args as $file) {
91 require_once(LIBS
. strtolower($file) . '.php');
96 * Prints out debug information about given variable.
98 * Only runs if debug level is greater than zero.
100 * @param boolean $var Variable to show debug information for.
101 * @param boolean $showHtml If set to true, the method prints the debug data in a screen-friendly way.
102 * @param boolean $showFrom If set to true, the method prints from where the function was called.
103 * @link http://book.cakephp.org/view/1190/Basic-Debugging
104 * @link http://book.cakephp.org/view/1128/debug
106 function debug($var = false, $showHtml = false, $showFrom = true) {
107 if (Configure
::read() > 0) {
109 $calledFrom = debug_backtrace();
110 echo '<strong>' . substr(str_replace(ROOT
, '', $calledFrom[0]['file']), 1) . '</strong>';
111 echo ' (line <strong>' . $calledFrom[0]['line'] . '</strong>)';
113 echo "\n<pre class=\"cake-debug\">\n";
115 $var = print_r($var, true);
117 $var = str_replace('<', '<', str_replace('>', '>', $var));
119 echo $var . "\n</pre>\n";
122 if (!function_exists('getMicrotime')) {
125 * Returns microtime for execution time checking
127 * @return float Microtime
129 function getMicrotime() {
130 list($usec, $sec) = explode(' ', microtime());
131 return ((float)$usec +
(float)$sec);
134 if (!function_exists('sortByKey')) {
137 * Sorts given $array by key $sortby.
139 * @param array $array Array to sort
140 * @param string $sortby Sort by this key
141 * @param string $order Sort order asc/desc (ascending or descending).
142 * @param integer $type Type of sorting to perform
143 * @return mixed Sorted array
145 function sortByKey(&$array, $sortby, $order = 'asc', $type = SORT_NUMERIC
) {
146 if (!is_array($array)) {
150 foreach ($array as $key => $val) {
151 $sa[$key] = $val[$sortby];
154 if ($order == 'asc') {
160 foreach ($sa as $key => $val) {
161 $out[] = $array[$key];
166 if (!function_exists('array_combine')) {
169 * Combines given identical arrays by using the first array's values as keys,
170 * and the second one's values as values. (Implemented for backwards compatibility with PHP4)
172 * @param array $a1 Array to use for keys
173 * @param array $a2 Array to use for values
174 * @return mixed Outputs either combined array or false.
175 * @deprecated Will be removed in 2.0
177 function array_combine($a1, $a2) {
178 $a1 = array_values($a1);
179 $a2 = array_values($a2);
191 for ($i = 0; $i < $c1; $i++
) {
192 $output[$a1[$i]] = $a2[$i];
199 * Convenience method for htmlspecialchars.
201 * @param string $text Text to wrap through htmlspecialchars
202 * @param string $charset Character set to use when escaping. Defaults to config value in 'App.encoding' or 'UTF-8'
203 * @return string Wrapped text
204 * @link http://book.cakephp.org/view/1132/h
206 function h($text, $charset = null) {
207 if (is_array($text)) {
208 return array_map('h', $text);
211 static $defaultCharset = false;
212 if ($defaultCharset === false) {
213 $defaultCharset = Configure
::read('App.encoding');
214 if ($defaultCharset === null) {
215 $defaultCharset = 'UTF-8';
219 return htmlspecialchars($text, ENT_QUOTES
, $charset);
221 return htmlspecialchars($text, ENT_QUOTES
, $defaultCharset);
226 * Splits a dot syntax plugin name into its plugin and classname.
227 * If $name does not have a dot, then index 0 will be null.
229 * Commonly used like `list($plugin, $name) = pluginSplit($name);`
231 * @param string $name The name you want to plugin split.
232 * @param boolean $dotAppend Set to true if you want the plugin to have a '.' appended to it.
233 * @param string $plugin Optional default plugin to use if no plugin is found. Defaults to null.
234 * @return array Array with 2 indexes. 0 => plugin name, 1 => classname
236 function pluginSplit($name, $dotAppend = false, $plugin = null) {
237 if (strpos($name, '.') !== false) {
238 $parts = explode('.', $name, 2);
244 return array($plugin, $name);
248 * Returns an array of all the given parameters.
258 * @return array Array of given parameters
259 * @link http://book.cakephp.org/view/1122/a
260 * @deprecated Will be removed in 2.0
263 $args = func_get_args();
268 * Constructs associative array from pairs of arguments.
278 * @return array Associative array
279 * @link http://book.cakephp.org/view/1123/aa
280 * @deprecated Will be removed in 2.0
283 $args = func_get_args();
284 $argc = count($args);
285 for ($i = 0; $i < $argc; $i++
) {
286 if ($i +
1 < $argc) {
287 $a[$args[$i]] = $args[$i +
1];
289 $a[$args[$i]] = null;
297 * Convenience method for echo().
299 * @param string $text String to echo
300 * @link http://book.cakephp.org/view/1129/e
301 * @deprecated Will be removed in 2.0
308 * Convenience method for strtolower().
310 * @param string $str String to lowercase
311 * @return string Lowercased string
312 * @link http://book.cakephp.org/view/1134/low
313 * @deprecated Will be removed in 2.0
316 return strtolower($str);
320 * Convenience method for strtoupper().
322 * @param string $str String to uppercase
323 * @return string Uppercased string
324 * @link http://book.cakephp.org/view/1139/up
325 * @deprecated Will be removed in 2.0
328 return strtoupper($str);
332 * Convenience method for str_replace().
334 * @param string $search String to be replaced
335 * @param string $replace String to insert
336 * @param string $subject String to search
337 * @return string Replaced string
338 * @link http://book.cakephp.org/view/1137/r
339 * @deprecated Will be removed in 2.0
341 function r($search, $replace, $subject) {
342 return str_replace($search, $replace, $subject);
346 * Print_r convenience function, which prints out <PRE> tags around
347 * the output of given array. Similar to debug().
350 * @param array $var Variable to print out
351 * @link http://book.cakephp.org/view/1136/pr
354 if (Configure
::read() > 0) {
362 * Display parameters.
364 * @param mixed $p Parameter as string or array
366 * @deprecated Will be removed in 2.0
368 function params($p) {
369 if (!is_array($p) ||
count($p) == 0) {
372 if (is_array($p[0]) && count($p) == 1) {
379 * Merge a group of arrays
381 * @param array First array
382 * @param array Second array
383 * @param array Third array
384 * @param array Etc...
385 * @return array All array parameters merged into one
386 * @link http://book.cakephp.org/view/1124/am
390 $args = func_get_args();
391 foreach ($args as $a) {
395 $r = array_merge($r, $a);
401 * Gets an environment variable from available sources, and provides emulation
402 * for unsupported or inconsistent environment variables (i.e. DOCUMENT_ROOT on
403 * IIS, or SCRIPT_NAME in CGI mode). Also exposes some additional custom
404 * environment information.
406 * @param string $key Environment variable name.
407 * @return string Environment variable setting.
408 * @link http://book.cakephp.org/view/1130/env
411 if ($key == 'HTTPS') {
412 if (isset($_SERVER['HTTPS'])) {
413 return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
415 return (strpos(env('SCRIPT_URI'), 'https://') === 0);
418 if ($key == 'SCRIPT_NAME') {
419 if (env('CGI_MODE') && isset($_ENV['SCRIPT_URL'])) {
425 if (isset($_SERVER[$key])) {
426 $val = $_SERVER[$key];
427 } elseif (isset($_ENV[$key])) {
429 } elseif (getenv($key) !== false) {
433 if ($key === 'REMOTE_ADDR' && $val === env('SERVER_ADDR')) {
434 $addr = env('HTTP_PC_REMOTE_ADDR');
435 if ($addr !== null) {
445 case 'SCRIPT_FILENAME':
446 if (defined('SERVER_IIS') && SERVER_IIS
=== true) {
447 return str_replace('\\\\', '\\', env('PATH_TRANSLATED'));
450 case 'DOCUMENT_ROOT':
451 $name = env('SCRIPT_NAME');
452 $filename = env('SCRIPT_FILENAME');
454 if (!strpos($name, '.php')) {
457 return substr($filename, 0, strlen($filename) - (strlen($name) +
$offset));
460 return str_replace(env('DOCUMENT_ROOT'), '', env('SCRIPT_FILENAME'));
463 return (PHP_SAPI
=== 'cgi');
466 $host = env('HTTP_HOST');
467 $parts = explode('.', $host);
468 $count = count($parts);
472 } elseif ($count === 2) {
474 } elseif ($count === 3) {
475 $gTLD = array('aero', 'asia', 'biz', 'cat', 'com', 'coop', 'edu', 'gov', 'info', 'int', 'jobs', 'mil', 'mobi', 'museum', 'name', 'net', 'org', 'pro', 'tel', 'travel', 'xxx');
476 if (in_array($parts[1], $gTLD)) {
481 return '.' . implode('.', $parts);
486 if (!function_exists('file_put_contents')) {
489 * Writes data into file.
491 * If file exists, it will be overwritten. If data is an array, it will be implode()ed with an empty string.
493 * @param string $fileName File name.
494 * @param mixed $data String or array.
495 * @return boolean Success
496 * @deprecated Will be removed in 2.0
498 function file_put_contents($fileName, $data) {
499 if (is_array($data)) {
500 $data = implode('', $data);
502 $res = @fopen
($fileName, 'w+b');
505 $write = @fwrite
($res, $data);
506 if ($write === false) {
518 * Reads/writes temporary data to cache files or session.
520 * @param string $path File path within /tmp to save the file.
521 * @param mixed $data The data to save to the temporary file.
522 * @param mixed $expires A valid strtotime string when the data expires.
523 * @param string $target The target of the cached data; either 'cache' or 'public'.
524 * @return mixed The contents of the temporary file.
525 * @deprecated Please use Cache::write() instead
527 function cache($path, $data = null, $expires = '+1 day', $target = 'cache') {
528 if (Configure
::read('Cache.disable')) {
533 if (!is_numeric($expires)) {
534 $expires = strtotime($expires, $now);
537 switch (strtolower($target)) {
539 $filename = CACHE
. $path;
542 $filename = WWW_ROOT
. $path;
545 $filename = TMP
. $path;
548 $timediff = $expires - $now;
551 if (file_exists($filename)) {
552 $filetime = @filemtime
($filename);
555 if ($data === null) {
556 if (file_exists($filename) && $filetime !== false) {
557 if ($filetime +
$timediff < $now) {
560 $data = @file_get_contents
($filename);
563 } elseif (is_writable(dirname($filename))) {
564 @file_put_contents
($filename, $data);
570 * Used to delete files in the cache directories, or clear contents of cache directories
572 * @param mixed $params As String name to be searched for deletion, if name is a directory all files in
573 * directory will be deleted. If array, names to be searched for deletion. If clearCache() without params,
574 * all files in app/tmp/cache/views will be deleted
575 * @param string $type Directory in tmp/cache defaults to view directory
576 * @param string $ext The file extension you are deleting
577 * @return true if files found and deleted false otherwise
579 function clearCache($params = null, $type = 'views', $ext = '.php') {
580 if (is_string($params) ||
$params === null) {
581 $params = preg_replace('/\/\//', '/', $params);
582 $cache = CACHE
. $type . DS
. $params;
584 if (is_file($cache . $ext)) {
585 @unlink
($cache . $ext);
587 } elseif (is_dir($cache)) {
588 $files = glob($cache . '*');
590 if ($files === false) {
594 foreach ($files as $file) {
595 if (is_file($file) && strrpos($file, DS
. 'empty') !== strlen($file) - 6) {
602 CACHE
. $type . DS
. '*' . $params . $ext,
603 CACHE
. $type . DS
. '*' . $params . '_*' . $ext
606 while ($search = array_shift($cache)) {
607 $results = glob($search);
608 if ($results !== false) {
609 $files = array_merge($files, $results);
615 foreach ($files as $file) {
616 if (is_file($file) && strrpos($file, DS
. 'empty') !== strlen($file) - 6) {
622 } elseif (is_array($params)) {
623 foreach ($params as $file) {
624 clearCache($file, $type, $ext);
632 * Recursively strips slashes from all values in an array
634 * @param array $values Array of values to strip slashes
635 * @return mixed What is returned from calling stripslashes
636 * @link http://book.cakephp.org/view/1138/stripslashes_deep
638 function stripslashes_deep($values) {
639 if (is_array($values)) {
640 foreach ($values as $key => $value) {
641 $values[$key] = stripslashes_deep($value);
644 $values = stripslashes($values);
650 * Returns a translated string if one is found; Otherwise, the submitted message.
652 * @param string $singular Text to translate
653 * @param boolean $return Set to true to return translated string, or false to echo
654 * @return mixed translated string if $return is false string will be echoed
655 * @link http://book.cakephp.org/view/1121/__
657 function __($singular, $return = false) {
661 if (!class_exists('I18n')) {
662 App
::import('Core', 'i18n');
665 if ($return === false) {
666 echo I18n
::translate($singular);
668 return I18n
::translate($singular);
673 * Returns correct plural form of message identified by $singular and $plural for count $count.
674 * Some languages have more than one form for plural messages dependent on the count.
676 * @param string $singular Singular text to translate
677 * @param string $plural Plural text
678 * @param integer $count Count
679 * @param boolean $return true to return, false to echo
680 * @return mixed plural form of translated string if $return is false string will be echoed
682 function __n($singular, $plural, $count, $return = false) {
686 if (!class_exists('I18n')) {
687 App
::import('Core', 'i18n');
690 if ($return === false) {
691 echo I18n
::translate($singular, $plural, null, 6, $count);
693 return I18n
::translate($singular, $plural, null, 6, $count);
698 * Allows you to override the current domain for a single message lookup.
700 * @param string $domain Domain
701 * @param string $msg String to translate
702 * @param string $return true to return, false to echo
703 * @return translated string if $return is false string will be echoed
705 function __d($domain, $msg, $return = false) {
709 if (!class_exists('I18n')) {
710 App
::import('Core', 'i18n');
713 if ($return === false) {
714 echo I18n
::translate($msg, null, $domain);
716 return I18n
::translate($msg, null, $domain);
721 * Allows you to override the current domain for a single plural message lookup.
722 * Returns correct plural form of message identified by $singular and $plural for count $count
723 * from domain $domain.
725 * @param string $domain Domain
726 * @param string $singular Singular string to translate
727 * @param string $plural Plural
728 * @param integer $count Count
729 * @param boolean $return true to return, false to echo
730 * @return plural form of translated string if $return is false string will be echoed
732 function __dn($domain, $singular, $plural, $count, $return = false) {
736 if (!class_exists('I18n')) {
737 App
::import('Core', 'i18n');
740 if ($return === false) {
741 echo I18n
::translate($singular, $plural, $domain, 6, $count);
743 return I18n
::translate($singular, $plural, $domain, 6, $count);
748 * Allows you to override the current domain for a single message lookup.
749 * It also allows you to specify a category.
751 * The category argument allows a specific category of the locale settings to be used for fetching a message.
752 * Valid categories are: LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES and LC_ALL.
754 * Note that the category must be specified with a numeric value, instead of the constant name. The values are:
764 * @param string $domain Domain
765 * @param string $msg Message to translate
766 * @param integer $category Category
767 * @param boolean $return true to return, false to echo
768 * @return translated string if $return is false string will be echoed
770 function __dc($domain, $msg, $category, $return = false) {
774 if (!class_exists('I18n')) {
775 App
::import('Core', 'i18n');
778 if ($return === false) {
779 echo I18n
::translate($msg, null, $domain, $category);
781 return I18n
::translate($msg, null, $domain, $category);
786 * Allows you to override the current domain for a single plural message lookup.
787 * It also allows you to specify a category.
788 * Returns correct plural form of message identified by $singular and $plural for count $count
789 * from domain $domain.
791 * The category argument allows a specific category of the locale settings to be used for fetching a message.
792 * Valid categories are: LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES and LC_ALL.
794 * Note that the category must be specified with a numeric value, instead of the constant name. The values are:
804 * @param string $domain Domain
805 * @param string $singular Singular string to translate
806 * @param string $plural Plural
807 * @param integer $count Count
808 * @param integer $category Category
809 * @param boolean $return true to return, false to echo
810 * @return plural form of translated string if $return is false string will be echoed
812 function __dcn($domain, $singular, $plural, $count, $category, $return = false) {
816 if (!class_exists('I18n')) {
817 App
::import('Core', 'i18n');
820 if ($return === false) {
821 echo I18n
::translate($singular, $plural, $domain, $category, $count);
823 return I18n
::translate($singular, $plural, $domain, $category, $count);
828 * The category argument allows a specific category of the locale settings to be used for fetching a message.
829 * Valid categories are: LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES and LC_ALL.
831 * Note that the category must be specified with a numeric value, instead of the constant name. The values are:
841 * @param string $msg String to translate
842 * @param integer $category Category
843 * @param string $return true to return, false to echo
844 * @return translated string if $return is false string will be echoed
846 function __c($msg, $category, $return = false) {
850 if (!class_exists('I18n')) {
851 App
::import('Core', 'i18n');
854 if ($return === false) {
855 echo I18n
::translate($msg, null, null, $category);
857 return I18n
::translate($msg, null, null, $category);
862 * Computes the difference of arrays using keys for comparison.
864 * @param array First array
865 * @param array Second array
866 * @return array Array with different keys
867 * @deprecated Will be removed in 2.0
869 if (!function_exists('array_diff_key')) {
870 function array_diff_key() {
871 $valuesDiff = array();
873 $argc = func_num_args();
878 $args = func_get_args();
879 foreach ($args as $param) {
880 if (!is_array($param)) {
885 foreach ($args[0] as $valueKey => $valueData) {
886 for ($i = 1; $i < $argc; $i++
) {
887 if (array_key_exists($valueKey, $args[$i])) {
891 $valuesDiff[$valueKey] = $valueData;
898 * Computes the intersection of arrays using keys for comparison
900 * @param array First array
901 * @param array Second array
902 * @return array Array with interesected keys
903 * @deprecated Will be removed in 2.0
905 if (!function_exists('array_intersect_key')) {
906 function array_intersect_key($arr1, $arr2) {
908 foreach ($arr1 as $key => $value) {
909 if (array_key_exists($key, $arr2)) {
910 $res[$key] = $arr1[$key];
918 * Shortcut to Log::write.
920 * @param string $message Message to write to log
922 function LogError($message) {
923 if (!class_exists('CakeLog')) {
924 App
::import('Core', 'CakeLog');
926 $bad = array("\n", "\r", "\t");
928 CakeLog
::write('error', str_replace($bad, $good, $message));
932 * Searches include path for files.
934 * @param string $file File to look for
935 * @return Full path to file if exists, otherwise false
936 * @link http://book.cakephp.org/view/1131/fileExistsInPath
938 function fileExistsInPath($file) {
939 $paths = explode(PATH_SEPARATOR
, ini_get('include_path'));
940 foreach ($paths as $path) {
941 $fullPath = $path . DS
. $file;
943 if (file_exists($fullPath)) {
945 } elseif (file_exists($file)) {
953 * Convert forward slashes to underscores and removes first and last underscores in a string
955 * @param string String to convert
956 * @return string with underscore remove from start and end of string
957 * @link http://book.cakephp.org/view/1126/convertSlash
959 function convertSlash($string) {
960 $string = trim($string, '/');
961 $string = preg_replace('/\/\//', '/', $string);
962 $string = str_replace('/', '_', $string);
967 * Implements http_build_query for PHP4.
969 * @param string $data Data to set in query string
970 * @param string $prefix If numeric indices, prepend this to index for elements in base array.
971 * @param string $argSep String used to separate arguments
972 * @param string $baseKey Base key
973 * @return string URL encoded query string
974 * @see http://php.net/http_build_query
975 * @deprecated Will be removed in 2.0
977 if (!function_exists('http_build_query')) {
978 function http_build_query($data, $prefix = null, $argSep = null, $baseKey = null) {
979 if (empty($argSep)) {
980 $argSep = ini_get('arg_separator.output');
982 if (is_object($data)) {
983 $data = get_object_vars($data);
987 foreach ((array)$data as $key => $v) {
988 if (is_numeric($key) && !empty($prefix)) {
989 $key = $prefix . $key;
991 $key = urlencode($key);
993 if (!empty($baseKey)) {
994 $key = $baseKey . '[' . $key . ']';
997 if (is_array($v) ||
is_object($v)) {
998 $out[] = http_build_query($v, $prefix, $argSep, $key);
1000 $out[] = $key . '=' . urlencode($v);
1003 return implode($argSep, $out);
1008 * Wraps ternary operations. If $condition is a non-empty value, $val1 is returned, otherwise $val2.
1009 * Don't use for isset() conditions, or wrap your variable with @ operator:
1012 * `ife(isset($variable), @$variable, 'default');`
1014 * @param mixed $condition Conditional expression
1015 * @param mixed $val1 Value to return in case condition matches
1016 * @param mixed $val2 Value to return if condition doesn't match
1017 * @return mixed $val1 or $val2, depending on whether $condition evaluates to a non-empty expression.
1018 * @link http://book.cakephp.org/view/1133/ife
1019 * @deprecated Will be removed in 2.0
1021 function ife($condition, $val1 = null, $val2 = null) {
1022 if (!empty($condition)) {