1: <?php
2: /**
3: * Basic CakePHP functionality.
4: *
5: * Core functions for including other source files, loading models and so forth.
6: *
7: * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
8: * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
9: *
10: * Licensed under The MIT License
11: * For full copyright and license information, please see the LICENSE.txt
12: * Redistributions of files must retain the above copyright notice.
13: *
14: * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
15: * @link http://cakephp.org CakePHP(tm) Project
16: * @package Cake
17: * @since CakePHP(tm) v 0.2.9
18: * @license http://www.opensource.org/licenses/mit-license.php MIT License
19: */
20:
21: /**
22: * Basic defines for timing functions.
23: */
24: define('SECOND', 1);
25: define('MINUTE', 60);
26: define('HOUR', 3600);
27: define('DAY', 86400);
28: define('WEEK', 604800);
29: define('MONTH', 2592000);
30: define('YEAR', 31536000);
31:
32: if (!function_exists('config')) {
33:
34: /**
35: * Loads configuration files. Receives a set of configuration files
36: * to load.
37: * Example:
38: *
39: * `config('config1', 'config2');`
40: *
41: * @return boolean Success
42: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#config
43: */
44: function config() {
45: $args = func_get_args();
46: $count = count($args);
47: $included = 0;
48: foreach ($args as $arg) {
49: if (file_exists(APP . 'Config' . DS . $arg . '.php')) {
50: include_once APP . 'Config' . DS . $arg . '.php';
51: $included++;
52: }
53: }
54: return $included === $count;
55: }
56:
57: }
58:
59: if (!function_exists('debug')) {
60:
61: /**
62: * Prints out debug information about given variable.
63: *
64: * Only runs if debug level is greater than zero.
65: *
66: * @param mixed $var Variable to show debug information for.
67: * @param boolean $showHtml If set to true, the method prints the debug data in a browser-friendly way.
68: * @param boolean $showFrom If set to true, the method prints from where the function was called.
69: * @return void
70: * @link http://book.cakephp.org/2.0/en/development/debugging.html#basic-debugging
71: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#debug
72: */
73: function debug($var, $showHtml = null, $showFrom = true) {
74: if (Configure::read('debug') > 0) {
75: App::uses('Debugger', 'Utility');
76: $file = '';
77: $line = '';
78: $lineInfo = '';
79: if ($showFrom) {
80: $trace = Debugger::trace(array('start' => 1, 'depth' => 2, 'format' => 'array'));
81: $file = str_replace(array(CAKE_CORE_INCLUDE_PATH, ROOT), '', $trace[0]['file']);
82: $line = $trace[0]['line'];
83: }
84: $html = <<<HTML
85: <div class="cake-debug-output">
86: %s
87: <pre class="cake-debug">
88: %s
89: </pre>
90: </div>
91: HTML;
92: $text = <<<TEXT
93: %s
94: ########## DEBUG ##########
95: %s
96: ###########################
97:
98: TEXT;
99: $template = $html;
100: if (php_sapi_name() === 'cli' || $showHtml === false) {
101: $template = $text;
102: if ($showFrom) {
103: $lineInfo = sprintf('%s (line %s)', $file, $line);
104: }
105: }
106: if ($showHtml === null && $template !== $text) {
107: $showHtml = true;
108: }
109: $var = Debugger::exportVar($var, 25);
110: if ($showHtml) {
111: $template = $html;
112: $var = h($var);
113: if ($showFrom) {
114: $lineInfo = sprintf('<span><strong>%s</strong> (line <strong>%s</strong>)</span>', $file, $line);
115: }
116: }
117: printf($template, $lineInfo, $var);
118: }
119: }
120:
121: }
122:
123: if (!function_exists('sortByKey')) {
124:
125: /**
126: * Sorts given $array by key $sortBy.
127: *
128: * @param array $array Array to sort
129: * @param string $sortBy Sort by this key
130: * @param string $order Sort order asc/desc (ascending or descending).
131: * @param integer $type Type of sorting to perform
132: * @return mixed Sorted array
133: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#sortByKey
134: */
135: function sortByKey(&$array, $sortBy, $order = 'asc', $type = SORT_NUMERIC) {
136: if (!is_array($array)) {
137: return null;
138: }
139:
140: foreach ($array as $key => $val) {
141: $sa[$key] = $val[$sortBy];
142: }
143:
144: if ($order === 'asc') {
145: asort($sa, $type);
146: } else {
147: arsort($sa, $type);
148: }
149:
150: foreach ($sa as $key => $val) {
151: $out[] = $array[$key];
152: }
153: return $out;
154: }
155:
156: }
157:
158: if (!function_exists('h')) {
159:
160: /**
161: * Convenience method for htmlspecialchars.
162: *
163: * @param string|array|object $text Text to wrap through htmlspecialchars. Also works with arrays, and objects.
164: * Arrays will be mapped and have all their elements escaped. Objects will be string cast if they
165: * implement a `__toString` method. Otherwise the class name will be used.
166: * @param boolean $double Encode existing html entities
167: * @param string $charset Character set to use when escaping. Defaults to config value in 'App.encoding' or 'UTF-8'
168: * @return string Wrapped text
169: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#h
170: */
171: function h($text, $double = true, $charset = null) {
172: if (is_array($text)) {
173: $texts = array();
174: foreach ($text as $k => $t) {
175: $texts[$k] = h($t, $double, $charset);
176: }
177: return $texts;
178: } elseif (is_object($text)) {
179: if (method_exists($text, '__toString')) {
180: $text = (string)$text;
181: } else {
182: $text = '(object)' . get_class($text);
183: }
184: } elseif (is_bool($text)) {
185: return $text;
186: }
187:
188: static $defaultCharset = false;
189: if ($defaultCharset === false) {
190: $defaultCharset = Configure::read('App.encoding');
191: if ($defaultCharset === null) {
192: $defaultCharset = 'UTF-8';
193: }
194: }
195: if (is_string($double)) {
196: $charset = $double;
197: }
198: return htmlspecialchars($text, ENT_QUOTES, ($charset) ? $charset : $defaultCharset, $double);
199: }
200:
201: }
202:
203: if (!function_exists('pluginSplit')) {
204:
205: /**
206: * Splits a dot syntax plugin name into its plugin and class name.
207: * If $name does not have a dot, then index 0 will be null.
208: *
209: * Commonly used like `list($plugin, $name) = pluginSplit($name);`
210: *
211: * @param string $name The name you want to plugin split.
212: * @param boolean $dotAppend Set to true if you want the plugin to have a '.' appended to it.
213: * @param string $plugin Optional default plugin to use if no plugin is found. Defaults to null.
214: * @return array Array with 2 indexes. 0 => plugin name, 1 => class name
215: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#pluginSplit
216: */
217: function pluginSplit($name, $dotAppend = false, $plugin = null) {
218: if (strpos($name, '.') !== false) {
219: $parts = explode('.', $name, 2);
220: if ($dotAppend) {
221: $parts[0] .= '.';
222: }
223: return $parts;
224: }
225: return array($plugin, $name);
226: }
227:
228: }
229:
230: if (!function_exists('pr')) {
231:
232: /**
233: * print_r() convenience function
234: *
235: * In terminals this will act the same as using print_r() directly, when not run on cli
236: * print_r() will wrap <PRE> tags around the output of given array. Similar to debug().
237: *
238: * @see debug()
239: * @param mixed $var Variable to print out
240: * @return void
241: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#pr
242: */
243: function pr($var) {
244: if (Configure::read('debug') > 0) {
245: $template = php_sapi_name() !== 'cli' ? '<pre>%s</pre>' : "\n%s\n";
246: printf($template, print_r($var, true));
247: }
248: }
249:
250: }
251:
252: if (!function_exists('am')) {
253:
254: /**
255: * Merge a group of arrays
256: *
257: * @param array First array
258: * @param array Second array
259: * @param array Third array
260: * @param array Etc...
261: * @return array All array parameters merged into one
262: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#am
263: */
264: function am() {
265: $r = array();
266: $args = func_get_args();
267: foreach ($args as $a) {
268: if (!is_array($a)) {
269: $a = array($a);
270: }
271: $r = array_merge($r, $a);
272: }
273: return $r;
274: }
275:
276: }
277:
278: if (!function_exists('env')) {
279:
280: /**
281: * Gets an environment variable from available sources, and provides emulation
282: * for unsupported or inconsistent environment variables (i.e. DOCUMENT_ROOT on
283: * IIS, or SCRIPT_NAME in CGI mode). Also exposes some additional custom
284: * environment information.
285: *
286: * @param string $key Environment variable name.
287: * @return string Environment variable setting.
288: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#env
289: */
290: function env($key) {
291: if ($key === 'HTTPS') {
292: if (isset($_SERVER['HTTPS'])) {
293: return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
294: }
295: return (strpos(env('SCRIPT_URI'), 'https://') === 0);
296: }
297:
298: if ($key === 'SCRIPT_NAME') {
299: if (env('CGI_MODE') && isset($_ENV['SCRIPT_URL'])) {
300: $key = 'SCRIPT_URL';
301: }
302: }
303:
304: $val = null;
305: if (isset($_SERVER[$key])) {
306: $val = $_SERVER[$key];
307: } elseif (isset($_ENV[$key])) {
308: $val = $_ENV[$key];
309: } elseif (getenv($key) !== false) {
310: $val = getenv($key);
311: }
312:
313: if ($key === 'REMOTE_ADDR' && $val === env('SERVER_ADDR')) {
314: $addr = env('HTTP_PC_REMOTE_ADDR');
315: if ($addr !== null) {
316: $val = $addr;
317: }
318: }
319:
320: if ($val !== null) {
321: return $val;
322: }
323:
324: switch ($key) {
325: case 'DOCUMENT_ROOT':
326: $name = env('SCRIPT_NAME');
327: $filename = env('SCRIPT_FILENAME');
328: $offset = 0;
329: if (!strpos($name, '.php')) {
330: $offset = 4;
331: }
332: return substr($filename, 0, -(strlen($name) + $offset));
333: case 'PHP_SELF':
334: return str_replace(env('DOCUMENT_ROOT'), '', env('SCRIPT_FILENAME'));
335: case 'CGI_MODE':
336: return (PHP_SAPI === 'cgi');
337: case 'HTTP_BASE':
338: $host = env('HTTP_HOST');
339: $parts = explode('.', $host);
340: $count = count($parts);
341:
342: if ($count === 1) {
343: return '.' . $host;
344: } elseif ($count === 2) {
345: return '.' . $host;
346: } elseif ($count === 3) {
347: $gTLD = array(
348: 'aero',
349: 'asia',
350: 'biz',
351: 'cat',
352: 'com',
353: 'coop',
354: 'edu',
355: 'gov',
356: 'info',
357: 'int',
358: 'jobs',
359: 'mil',
360: 'mobi',
361: 'museum',
362: 'name',
363: 'net',
364: 'org',
365: 'pro',
366: 'tel',
367: 'travel',
368: 'xxx'
369: );
370: if (in_array($parts[1], $gTLD)) {
371: return '.' . $host;
372: }
373: }
374: array_shift($parts);
375: return '.' . implode('.', $parts);
376: }
377: return null;
378: }
379:
380: }
381:
382: if (!function_exists('cache')) {
383:
384: /**
385: * Reads/writes temporary data to cache files or session.
386: *
387: * @param string $path File path within /tmp to save the file.
388: * @param mixed $data The data to save to the temporary file.
389: * @param mixed $expires A valid strtotime string when the data expires.
390: * @param string $target The target of the cached data; either 'cache' or 'public'.
391: * @return mixed The contents of the temporary file.
392: * @deprecated Will be removed in 3.0. Please use Cache::write() instead.
393: */
394: function cache($path, $data = null, $expires = '+1 day', $target = 'cache') {
395: if (Configure::read('Cache.disable')) {
396: return null;
397: }
398: $now = time();
399:
400: if (!is_numeric($expires)) {
401: $expires = strtotime($expires, $now);
402: }
403:
404: switch (strtolower($target)) {
405: case 'cache':
406: $filename = CACHE . $path;
407: break;
408: case 'public':
409: $filename = WWW_ROOT . $path;
410: break;
411: case 'tmp':
412: $filename = TMP . $path;
413: break;
414: }
415: $timediff = $expires - $now;
416: $filetime = false;
417:
418: if (file_exists($filename)) {
419: //@codingStandardsIgnoreStart
420: $filetime = @filemtime($filename);
421: //@codingStandardsIgnoreEnd
422: }
423:
424: if ($data === null) {
425: if (file_exists($filename) && $filetime !== false) {
426: if ($filetime + $timediff < $now) {
427: //@codingStandardsIgnoreStart
428: @unlink($filename);
429: //@codingStandardsIgnoreEnd
430: } else {
431: //@codingStandardsIgnoreStart
432: $data = @file_get_contents($filename);
433: //@codingStandardsIgnoreEnd
434: }
435: }
436: } elseif (is_writable(dirname($filename))) {
437: //@codingStandardsIgnoreStart
438: @file_put_contents($filename, $data, LOCK_EX);
439: //@codingStandardsIgnoreEnd
440: }
441: return $data;
442: }
443:
444: }
445:
446: if (!function_exists('clearCache')) {
447:
448: /**
449: * Used to delete files in the cache directories, or clear contents of cache directories
450: *
451: * @param string|array $params As String name to be searched for deletion, if name is a directory all files in
452: * directory will be deleted. If array, names to be searched for deletion. If clearCache() without params,
453: * all files in app/tmp/cache/views will be deleted
454: * @param string $type Directory in tmp/cache defaults to view directory
455: * @param string $ext The file extension you are deleting
456: * @return true if files found and deleted false otherwise
457: */
458: function clearCache($params = null, $type = 'views', $ext = '.php') {
459: if (is_string($params) || $params === null) {
460: $params = preg_replace('/\/\//', '/', $params);
461: $cache = CACHE . $type . DS . $params;
462:
463: if (is_file($cache . $ext)) {
464: //@codingStandardsIgnoreStart
465: @unlink($cache . $ext);
466: //@codingStandardsIgnoreEnd
467: return true;
468: } elseif (is_dir($cache)) {
469: $files = glob($cache . '*');
470:
471: if ($files === false) {
472: return false;
473: }
474:
475: foreach ($files as $file) {
476: if (is_file($file) && strrpos($file, DS . 'empty') !== strlen($file) - 6) {
477: //@codingStandardsIgnoreStart
478: @unlink($file);
479: //@codingStandardsIgnoreEnd
480: }
481: }
482: return true;
483: }
484: $cache = array(
485: CACHE . $type . DS . '*' . $params . $ext,
486: CACHE . $type . DS . '*' . $params . '_*' . $ext
487: );
488: $files = array();
489: while ($search = array_shift($cache)) {
490: $results = glob($search);
491: if ($results !== false) {
492: $files = array_merge($files, $results);
493: }
494: }
495: if (empty($files)) {
496: return false;
497: }
498: foreach ($files as $file) {
499: if (is_file($file) && strrpos($file, DS . 'empty') !== strlen($file) - 6) {
500: //@codingStandardsIgnoreStart
501: @unlink($file);
502: //@codingStandardsIgnoreEnd
503: }
504: }
505: return true;
506:
507: } elseif (is_array($params)) {
508: foreach ($params as $file) {
509: clearCache($file, $type, $ext);
510: }
511: return true;
512: }
513: return false;
514: }
515:
516: }
517:
518: if (!function_exists('stripslashes_deep')) {
519:
520: /**
521: * Recursively strips slashes from all values in an array
522: *
523: * @param array $values Array of values to strip slashes
524: * @return mixed What is returned from calling stripslashes
525: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#stripslashes_deep
526: */
527: function stripslashes_deep($values) {
528: if (is_array($values)) {
529: foreach ($values as $key => $value) {
530: $values[$key] = stripslashes_deep($value);
531: }
532: } else {
533: $values = stripslashes($values);
534: }
535: return $values;
536: }
537:
538: }
539:
540: if (!function_exists('__')) {
541:
542: /**
543: * Returns a translated string if one is found; Otherwise, the submitted message.
544: *
545: * @param string $singular Text to translate
546: * @param mixed $args Array with arguments or multiple arguments in function
547: * @return mixed translated string
548: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#__
549: */
550: function __($singular, $args = null) {
551: if (!$singular) {
552: return;
553: }
554:
555: App::uses('I18n', 'I18n');
556: $translated = I18n::translate($singular);
557: if ($args === null) {
558: return $translated;
559: } elseif (!is_array($args)) {
560: $args = array_slice(func_get_args(), 1);
561: }
562: return vsprintf($translated, $args);
563: }
564:
565: }
566:
567: if (!function_exists('__n')) {
568:
569: /**
570: * Returns correct plural form of message identified by $singular and $plural for count $count.
571: * Some languages have more than one form for plural messages dependent on the count.
572: *
573: * @param string $singular Singular text to translate
574: * @param string $plural Plural text
575: * @param integer $count Count
576: * @param mixed $args Array with arguments or multiple arguments in function
577: * @return mixed plural form of translated string
578: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#__n
579: */
580: function __n($singular, $plural, $count, $args = null) {
581: if (!$singular) {
582: return;
583: }
584:
585: App::uses('I18n', 'I18n');
586: $translated = I18n::translate($singular, $plural, null, 6, $count);
587: if ($args === null) {
588: return $translated;
589: } elseif (!is_array($args)) {
590: $args = array_slice(func_get_args(), 3);
591: }
592: return vsprintf($translated, $args);
593: }
594:
595: }
596:
597: if (!function_exists('__d')) {
598:
599: /**
600: * Allows you to override the current domain for a single message lookup.
601: *
602: * @param string $domain Domain
603: * @param string $msg String to translate
604: * @param mixed $args Array with arguments or multiple arguments in function
605: * @return translated string
606: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#__d
607: */
608: function __d($domain, $msg, $args = null) {
609: if (!$msg) {
610: return;
611: }
612: App::uses('I18n', 'I18n');
613: $translated = I18n::translate($msg, null, $domain);
614: if ($args === null) {
615: return $translated;
616: } elseif (!is_array($args)) {
617: $args = array_slice(func_get_args(), 2);
618: }
619: return vsprintf($translated, $args);
620: }
621:
622: }
623:
624: if (!function_exists('__dn')) {
625:
626: /**
627: * Allows you to override the current domain for a single plural message lookup.
628: * Returns correct plural form of message identified by $singular and $plural for count $count
629: * from domain $domain.
630: *
631: * @param string $domain Domain
632: * @param string $singular Singular string to translate
633: * @param string $plural Plural
634: * @param integer $count Count
635: * @param mixed $args Array with arguments or multiple arguments in function
636: * @return plural form of translated string
637: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#__dn
638: */
639: function __dn($domain, $singular, $plural, $count, $args = null) {
640: if (!$singular) {
641: return;
642: }
643: App::uses('I18n', 'I18n');
644: $translated = I18n::translate($singular, $plural, $domain, 6, $count);
645: if ($args === null) {
646: return $translated;
647: } elseif (!is_array($args)) {
648: $args = array_slice(func_get_args(), 4);
649: }
650: return vsprintf($translated, $args);
651: }
652:
653: }
654:
655: if (!function_exists('__dc')) {
656:
657: /**
658: * Allows you to override the current domain for a single message lookup.
659: * It also allows you to specify a category.
660: *
661: * The category argument allows a specific category of the locale settings to be used for fetching a message.
662: * Valid categories are: LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES and LC_ALL.
663: *
664: * Note that the category must be specified with a numeric value, instead of the constant name. The values are:
665: *
666: * - LC_ALL 0
667: * - LC_COLLATE 1
668: * - LC_CTYPE 2
669: * - LC_MONETARY 3
670: * - LC_NUMERIC 4
671: * - LC_TIME 5
672: * - LC_MESSAGES 6
673: *
674: * @param string $domain Domain
675: * @param string $msg Message to translate
676: * @param integer $category Category
677: * @param mixed $args Array with arguments or multiple arguments in function
678: * @return translated string
679: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#__dc
680: */
681: function __dc($domain, $msg, $category, $args = null) {
682: if (!$msg) {
683: return;
684: }
685: App::uses('I18n', 'I18n');
686: $translated = I18n::translate($msg, null, $domain, $category);
687: if ($args === null) {
688: return $translated;
689: } elseif (!is_array($args)) {
690: $args = array_slice(func_get_args(), 3);
691: }
692: return vsprintf($translated, $args);
693: }
694:
695: }
696:
697: if (!function_exists('__dcn')) {
698:
699: /**
700: * Allows you to override the current domain for a single plural message lookup.
701: * It also allows you to specify a category.
702: * Returns correct plural form of message identified by $singular and $plural for count $count
703: * from domain $domain.
704: *
705: * The category argument allows a specific category of the locale settings to be used for fetching a message.
706: * Valid categories are: LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES and LC_ALL.
707: *
708: * Note that the category must be specified with a numeric value, instead of the constant name. The values are:
709: *
710: * - LC_ALL 0
711: * - LC_COLLATE 1
712: * - LC_CTYPE 2
713: * - LC_MONETARY 3
714: * - LC_NUMERIC 4
715: * - LC_TIME 5
716: * - LC_MESSAGES 6
717: *
718: * @param string $domain Domain
719: * @param string $singular Singular string to translate
720: * @param string $plural Plural
721: * @param integer $count Count
722: * @param integer $category Category
723: * @param mixed $args Array with arguments or multiple arguments in function
724: * @return plural form of translated string
725: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#__dcn
726: */
727: function __dcn($domain, $singular, $plural, $count, $category, $args = null) {
728: if (!$singular) {
729: return;
730: }
731: App::uses('I18n', 'I18n');
732: $translated = I18n::translate($singular, $plural, $domain, $category, $count);
733: if ($args === null) {
734: return $translated;
735: } elseif (!is_array($args)) {
736: $args = array_slice(func_get_args(), 5);
737: }
738: return vsprintf($translated, $args);
739: }
740:
741: }
742:
743: if (!function_exists('__c')) {
744:
745: /**
746: * The category argument allows a specific category of the locale settings to be used for fetching a message.
747: * Valid categories are: LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES and LC_ALL.
748: *
749: * Note that the category must be specified with a numeric value, instead of the constant name. The values are:
750: *
751: * - LC_ALL 0
752: * - LC_COLLATE 1
753: * - LC_CTYPE 2
754: * - LC_MONETARY 3
755: * - LC_NUMERIC 4
756: * - LC_TIME 5
757: * - LC_MESSAGES 6
758: *
759: * @param string $msg String to translate
760: * @param integer $category Category
761: * @param mixed $args Array with arguments or multiple arguments in function
762: * @return translated string
763: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#__c
764: */
765: function __c($msg, $category, $args = null) {
766: if (!$msg) {
767: return;
768: }
769: App::uses('I18n', 'I18n');
770: $translated = I18n::translate($msg, null, null, $category);
771: if ($args === null) {
772: return $translated;
773: } elseif (!is_array($args)) {
774: $args = array_slice(func_get_args(), 2);
775: }
776: return vsprintf($translated, $args);
777: }
778:
779: }
780:
781: if (!function_exists('LogError')) {
782:
783: /**
784: * Shortcut to Log::write.
785: *
786: * @param string $message Message to write to log
787: * @return void
788: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#LogError
789: */
790: function LogError($message) {
791: App::uses('CakeLog', 'Log');
792: $bad = array("\n", "\r", "\t");
793: $good = ' ';
794: CakeLog::write('error', str_replace($bad, $good, $message));
795: }
796:
797: }
798:
799: if (!function_exists('fileExistsInPath')) {
800:
801: /**
802: * Searches include path for files.
803: *
804: * @param string $file File to look for
805: * @return Full path to file if exists, otherwise false
806: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#fileExistsInPath
807: */
808: function fileExistsInPath($file) {
809: $paths = explode(PATH_SEPARATOR, ini_get('include_path'));
810: foreach ($paths as $path) {
811: $fullPath = $path . DS . $file;
812:
813: if (file_exists($fullPath)) {
814: return $fullPath;
815: } elseif (file_exists($file)) {
816: return $file;
817: }
818: }
819: return false;
820: }
821:
822: }
823:
824: if (!function_exists('convertSlash')) {
825:
826: /**
827: * Convert forward slashes to underscores and removes first and last underscores in a string
828: *
829: * @param string String to convert
830: * @return string with underscore remove from start and end of string
831: * @link http://book.cakephp.org/2.0/en/core-libraries/global-constants-and-functions.html#convertSlash
832: */
833: function convertSlash($string) {
834: $string = trim($string, '/');
835: $string = preg_replace('/\/\//', '/', $string);
836: $string = str_replace('/', '_', $string);
837: return $string;
838: }
839:
840: }
841: