CRM_Utils_Hook_Joomla - Fix PHP fatal parse error (missing comma)
[civicrm-core.git] / CRM / Utils / System.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
232624b1 4 | CiviCRM version 4.4 |
6a488035
TO
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2013
32 * $Id$
33 *
34 */
35
36/**
37 * System wide utilities.
38 *
39 */
40class CRM_Utils_System {
41
42 static $_callbacks = NULL;
43
5af8c999
CW
44 /**
45 * @var string Page title
46 */
47 static $title = '';
48
6a488035
TO
49 /**
50 * Compose a new url string from the current url string
51 * Used by all the framework components, specifically,
52 * pager, sort and qfc
53 *
54 * @param string $urlVar the url variable being considered (i.e. crmPageID, crmSortID etc)
3ab88a8c
DL
55 * @param boolean $includeReset - should we include or ignore the reset GET string (if present)
56 * @param boolean $includeForce - should we include or ignore the force GET string (if present)
57 * @param string $path - the path to use for the new url
58 * @param string $absolute - do we need a absolute or relative URL?
6a488035
TO
59 *
60 * @return string the url fragment
61 * @access public
62 */
3ab88a8c 63 static function makeURL($urlVar, $includeReset = FALSE, $includeForce = TRUE, $path = NULL, $absolute = FALSE) {
6a488035
TO
64 if (empty($path)) {
65 $config = CRM_Core_Config::singleton();
66 $path = CRM_Utils_Array::value($config->userFrameworkURLVar, $_GET);
67 if (empty($path)) {
68 return '';
69 }
70 }
71
3ab88a8c
DL
72 return
73 self::url(
74 $path,
75 CRM_Utils_System::getLinksUrl($urlVar, $includeReset, $includeForce),
76 $absolute
77 );
6a488035
TO
78 }
79
80 /**
81 * get the query string and clean it up. Strip some variables that should not
82 * be propagated, specically variable like 'reset'. Also strip any side-affect
83 * actions (i.e. export)
84 *
85 * This function is copied mostly verbatim from Pager.php (_getLinksUrl)
86 *
87 * @param string $urlVar the url variable being considered (i.e. crmPageID, crmSortID etc)
88 * @param boolean $includeReset should we include the reset var (generally this variable should be skipped)
89 *
90 * @return string
91 * @access public
92 */
93 static function getLinksUrl($urlVar, $includeReset = FALSE, $includeForce = TRUE, $skipUFVar = TRUE) {
94 // Sort out query string to prevent messy urls
95 $querystring = array();
96 $qs = array();
97 $arrays = array();
98
99 if (!empty($_SERVER['QUERY_STRING'])) {
100 $qs = explode('&', str_replace('&amp;', '&', $_SERVER['QUERY_STRING']));
101 for ($i = 0, $cnt = count($qs); $i < $cnt; $i++) {
102 // check first if exist a pair
103 if (strstr($qs[$i], '=') !== FALSE) {
104 list($name, $value) = explode('=', $qs[$i]);
105 if ($name != $urlVar) {
106 $name = rawurldecode($name);
107 //check for arrays in parameters: site.php?foo[]=1&foo[]=2&foo[]=3
108 if ((strpos($name, '[') !== FALSE) &&
109 (strpos($name, ']') !== FALSE)
110 ) {
111 $arrays[] = $qs[$i];
112 }
113 else {
114 $qs[$name] = $value;
115 }
116 }
117 }
118 else {
119 $qs[$qs[$i]] = '';
120 }
121 unset($qs[$i]);
122 }
123 }
124
125 if ($includeForce) {
126 $qs['force'] = 1;
127 }
128
129 unset($qs['snippet']);
130 unset($qs['section']);
131
132 if ($skipUFVar) {
133 $config = CRM_Core_Config::singleton();
134 unset($qs[$config->userFrameworkURLVar]);
135 }
136
137 foreach ($qs as $name => $value) {
138 if ($name != 'reset' || $includeReset) {
139 $querystring[] = $name . '=' . $value;
140 }
141 }
142
143 $querystring = array_merge($querystring, array_unique($arrays));
144 $querystring = array_map('htmlentities', $querystring);
145
3ab88a8c
DL
146 $url = implode('&amp;', $querystring);
147 if ($urlVar) {
148 $url .= (!empty($querystring) ? '&amp;' : '') . $urlVar . '=';
149 }
150
151 return $url;
6a488035
TO
152 }
153
154 /**
155 * if we are using a theming system, invoke theme, else just print the
156 * content
157 *
158 * @param string $content the content that will be themed
159 * @param boolean $print are we displaying to the screen or bypassing theming?
160 * @param boolean $maintenance for maintenance mode
161 *
162 * @return void prints content on stdout
163 * @access public
164 * @static
165 */
166 static function theme(
167 &$content,
168 $print = FALSE,
169 $maintenance = FALSE
170 ) {
171 $config = &CRM_Core_Config::singleton();
172 return $config->userSystem->theme($content, $print, $maintenance);
173 }
174
175 /**
176 * Generate a query string if input is an array
177 *
178 * @param mixed $query: array or string
179 * @return str
180 *
181 * @static
182 */
183 static function makeQueryString($query) {
184 if (is_array($query)) {
185 $buf = '';
186 foreach ($query as $key => $value) {
187 $buf .= ($buf ? '&' : '') . urlencode($key) . '=' . urlencode($value);
188 }
189 $query = $buf;
190 }
191 return $query;
192 }
193
194 /**
195 * Generate an internal CiviCRM URL
196 *
197 * @param $path string The path being linked to, such as "civicrm/add"
198 * @param $query mixed A query string to append to the link, or an array of key-value pairs
199 * @param $absolute boolean Whether to force the output to be an absolute link (beginning with http:).
200 * Useful for links that will be displayed outside the site, such as in an
201 * RSS feed.
202 * @param $fragment string A fragment identifier (named anchor) to append to the link.
203 *
204 * @return string an HTML string containing a link to the given path.
205 * @access public
206 * @static
207 */
208 static function url(
209 $path = NULL,
210 $query = NULL,
211 $absolute = FALSE,
212 $fragment = NULL,
213 $htmlize = TRUE,
214 $frontend = FALSE,
215 $forceBackend = FALSE
216 ) {
217 $query = self::makeQueryString($query);
218
219 // we have a valid query and it has not yet been transformed
220 if ($htmlize && !empty($query) && strpos($query, '&amp;') === FALSE) {
221 $query = htmlentities($query);
222 }
223
224 $config = CRM_Core_Config::singleton();
225 return $config->userSystem->url($path, $query, $absolute, $fragment, $htmlize, $frontend, $forceBackend);
226 }
227
553f116a 228 static function href($text, $path = NULL, $query = NULL, $absolute = TRUE,
6a488035
TO
229 $fragment = NULL, $htmlize = TRUE, $frontend = FALSE, $forceBackend = FALSE
230 ) {
231 $url = self::url($path, $query, $absolute, $fragment, $htmlize, $frontend, $forceBackend);
232 return "<a href=\"$url\">$text</a>";
233 }
234
235 static function permissionDenied() {
236 $config = CRM_Core_Config::singleton();
237 return $config->userSystem->permissionDenied();
238 }
239
240 static function logout() {
241 $config = CRM_Core_Config::singleton();
242 return $config->userSystem->logout();
243 }
244
245 // this is a very drupal specific function for now
246 static function updateCategories() {
247 $config = CRM_Core_Config::singleton();
248 if ($config->userSystem->is_drupal) {
249 $config->userSystem->updateCategories();
250 }
251 }
252
253 /**
254 * What menu path are we currently on. Called for the primary tpl
255 *
256 * @return string the current menu path
257 * @access public
258 */
259 static function currentPath() {
260 $config = CRM_Core_Config::singleton();
261 return trim(CRM_Utils_Array::value($config->userFrameworkURLVar, $_GET), '/');
262 }
263
264 /**
265 * this function is called from a template to compose a url
266 *
267 * @param array $params list of parameters
268 *
269 * @return string url
270 * @access public
271 * @static
272 */
273 static function crmURL($params) {
274 $p = CRM_Utils_Array::value('p', $params);
275 if (!isset($p)) {
276 $p = self::currentPath();
277 }
278
496e07aa
DL
279 return self::url(
280 $p,
6a488035
TO
281 CRM_Utils_Array::value('q', $params),
282 CRM_Utils_Array::value('a', $params, FALSE),
283 CRM_Utils_Array::value('f', $params),
284 CRM_Utils_Array::value('h', $params, TRUE),
285 CRM_Utils_Array::value('fe', $params, FALSE),
286 CRM_Utils_Array::value('fb', $params, FALSE)
287 );
288 }
289
290 /**
291 * sets the title of the page
292 *
293 * @param string $title
294 * @param string $pageTitle
295 *
296 * @return void
297 * @access public
298 * @static
299 */
300 static function setTitle($title, $pageTitle = NULL) {
5af8c999 301 self::$title = $title;
6a488035
TO
302 $config = CRM_Core_Config::singleton();
303 return $config->userSystem->setTitle($title, $pageTitle);
304 }
305
306 /**
307 * figures and sets the userContext. Uses the referer if valid
308 * else uses the default
309 *
310 * @param array $names refererer should match any str in this array
311 * @param string $default the default userContext if no match found
312 *
313 * @return void
314 * @access public
315 */
316 static function setUserContext($names, $default = NULL) {
317 $url = $default;
318
319 $session = CRM_Core_Session::singleton();
320 $referer = CRM_Utils_Array::value('HTTP_REFERER', $_SERVER);
321
322 if ($referer && !empty($names)) {
323 foreach ($names as $name) {
324 if (strstr($referer, $name)) {
325 $url = $referer;
326 break;
327 }
328 }
329 }
330
331 if ($url) {
332 $session->pushUserContext($url);
333 }
334 }
335
336 /**
337 * gets a class name for an object
338 *
339 * @param object $object - object whose class name is needed
340 *
341 * @return string $className - class name
342 *
343 * @access public
344 * @static
345 */
346 static function getClassName($object) {
347 return get_class($object);
348 }
349
350 /**
351 * redirect to another url
352 *
353 * @param string $url the url to goto
354 *
355 * @return void
356 * @access public
357 * @static
358 */
359 static function redirect($url = NULL) {
360 if (!$url) {
361 $url = self::url('civicrm/dashboard', 'reset=1');
362 }
363
364 // replace the &amp; characters with &
365 // this is kinda hackish but not sure how to do it right
366 $url = str_replace('&amp;', '&', $url);
367 header('Location: ' . $url);
368 self::civiExit();
369 }
370
371 /**
372 * use a html based file with javascript embedded to redirect to another url
373 * This prevent the too many redirect errors emitted by various browsers
374 *
375 * @param string $url the url to goto
376 *
377 * @return void
378 * @access public
379 * @static
380 */
381 static function jsRedirect(
382 $url = NULL,
383 $title = NULL,
384 $message = NULL
385 ) {
386 if (!$url) {
387 $url = self::url('civicrm/dashboard', 'reset=1');
388 }
389
390 if (!$title) {
391 $title = ts('CiviCRM task in progress');
392 }
393
394 if (!$message) {
395 $message = ts('A long running CiviCRM task is currently in progress. This message will be refreshed till the task is completed');
396 }
397
398 // replace the &amp; characters with &
399 // this is kinda hackish but not sure how to do it right
400 $url = str_replace('&amp;', '&', $url);
401
402 $template = CRM_Core_Smarty::singleton();
403 $template->assign('redirectURL', $url);
404 $template->assign('title', $title);
405 $template->assign('message', $message);
406
407 $html = $template->fetch('CRM/common/redirectJS.tpl');
408
409 echo $html;
410
411 self::civiExit();
412 }
413
414 /**
415 * Append an additional breadcrumb tag to the existing breadcrumb
416 *
417 * @param string $title
418 * @param string $url
419 *
420 * @return void
421 * @access public
422 * @static
423 */
424 static function appendBreadCrumb($breadCrumbs) {
425 $config = CRM_Core_Config::singleton();
426 return $config->userSystem->appendBreadCrumb($breadCrumbs);
427 }
428
429 /**
430 * Reset an additional breadcrumb tag to the existing breadcrumb
431 *
432 * @return void
433 * @access public
434 * @static
435 */
436 static function resetBreadCrumb() {
437 $config = CRM_Core_Config::singleton();
438 return $config->userSystem->resetBreadCrumb();
439 }
440
441 /**
442 * Append a string to the head of the html file
443 *
444 * @param string $head the new string to be appended
445 *
446 * @return void
447 * @access public
448 * @static
449 */
450 static function addHTMLHead($bc) {
451 $config = CRM_Core_Config::singleton();
452 return $config->userSystem->addHTMLHead($bc);
453 }
454
455 /**
456 * figure out the post url for the form
457 *
458 * @param the default action if one is pre-specified
459 *
460 * @return string the url to post the form
461 * @access public
462 * @static
463 */
464 static function postURL($action) {
465 $config = CRM_Core_Config::singleton();
466 return $config->userSystem->postURL($action);
467 }
468
469 /**
470 * rewrite various system urls to https
471 *
472 * @return void
473 * access public
474 * @static
475 */
476 static function mapConfigToSSL() {
477 $config = CRM_Core_Config::singleton();
7113f506 478 $config->userFrameworkResourceURL = str_replace('http://', 'https://', $config->userFrameworkResourceURL);
6a488035 479 $config->resourceBase = $config->userFrameworkResourceURL;
7113f506
ML
480
481 if (! empty($config->extensionsURL)) {
482 $config->extensionsURL = str_replace('http://', 'https://', $config->extensionsURL);
483 }
484
6a488035
TO
485 return $config->userSystem->mapConfigToSSL();
486 }
487
488 /**
489 * Get the base URL from the system
490 *
491 * @param
492 *
493 * @return string
494 * @access public
495 * @static
496 */
497 static function baseURL() {
498 $config = CRM_Core_Config::singleton();
499 return $config->userFrameworkBaseURL;
500 }
501
502 static function authenticateAbort($message, $abort) {
503 if ($abort) {
504 echo $message;
505 self::civiExit(0);
506 }
507 else {
508 return FALSE;
509 }
510 }
511
512 static function authenticateKey($abort = TRUE) {
513 // also make sure the key is sent and is valid
514 $key = trim(CRM_Utils_Array::value('key', $_REQUEST));
515
516 $docAdd = "More info at:" . CRM_Utils_System::docURL2("Managing Scheduled Jobs", TRUE, NULL, NULL, NULL, "wiki");
517
518 if (!$key) {
0af0e4c9
DL
519 return self::authenticateAbort(
520 "ERROR: You need to send a valid key to execute this file. " . $docAdd . "\n",
6a488035
TO
521 $abort
522 );
523 }
524
525 $siteKey = defined('CIVICRM_SITE_KEY') ? CIVICRM_SITE_KEY : NULL;
526
0af0e4c9
DL
527 if (!$siteKey || empty($siteKey)) {
528 return self::authenticateAbort(
529 "ERROR: You need to set a valid site key in civicrm.settings.php. " . $docAdd . "\n",
6a488035
TO
530 $abort
531 );
532 }
533
534 if (strlen($siteKey) < 8) {
0af0e4c9
DL
535 return self::authenticateAbort(
536 "ERROR: Site key needs to be greater than 7 characters in civicrm.settings.php. " . $docAdd . "\n",
6a488035
TO
537 $abort
538 );
539 }
540
541 if ($key !== $siteKey) {
0af0e4c9
DL
542 return self::authenticateAbort(
543 "ERROR: Invalid key value sent. " . $docAdd . "\n",
6a488035
TO
544 $abort
545 );
546 }
547
548 return TRUE;
549 }
550
bec3fc7c 551 static function authenticateScript($abort = TRUE, $name = NULL, $pass = NULL, $storeInSession = TRUE, $loadCMSBootstrap = TRUE, $requireKey = TRUE) {
6a488035
TO
552 // auth to make sure the user has a login/password to do a shell
553 // operation
554 // later on we'll link this to acl's
555 if (!$name) {
556 $name = trim(CRM_Utils_Array::value('name', $_REQUEST));
557 $pass = trim(CRM_Utils_Array::value('pass', $_REQUEST));
558 }
559
560 // its ok to have an empty password
561 if (!$name) {
0af0e4c9
DL
562 return self::authenticateAbort(
563 "ERROR: You need to send a valid user name and password to execute this file\n",
6a488035
TO
564 $abort
565 );
566 }
567
bec3fc7c 568 if ($requireKey && !self::authenticateKey($abort)) {
6a488035
TO
569 return FALSE;
570 }
571
572 $result = CRM_Utils_System::authenticate($name, $pass, $loadCMSBootstrap);
573 if (!$result) {
0af0e4c9
DL
574 return self::authenticateAbort(
575 "ERROR: Invalid username and/or password\n",
6a488035
TO
576 $abort
577 );
578 }
579 elseif ($storeInSession) {
580 // lets store contact id and user id in session
581 list($userID, $ufID, $randomNumber) = $result;
582 if ($userID && $ufID) {
bec3fc7c
BS
583 $config = CRM_Core_Config::singleton();
584 $config->userSystem->setUserSession( array($userID, $ufID) );
6a488035
TO
585 }
586 else {
0af0e4c9
DL
587 return self::authenticateAbort(
588 "ERROR: Unexpected error, could not match userID and contactID",
6a488035
TO
589 $abort
590 );
591 }
592 }
593
594 return $result;
595 }
596
597 /**
598 * Authenticate the user against the uf db
599 *
600 * @param string $name the user name
601 * @param string $password the password for the above user name
602 *
603 * @return mixed false if no auth
604 * array(
605 contactID, ufID, unique string ) if success
606 * @access public
607 * @static
608 */
609 static function authenticate($name, $password, $loadCMSBootstrap = FALSE, $realPath = NULL) {
610 $config = CRM_Core_Config::singleton();
c1e1e8b8
DL
611
612 // before we do any loading, lets start the session and write to it
613 // we typically call authenticate only when we need to bootstrap the CMS directly via Civi
614 // and hence bypass the normal CMS auth and bootstrap process
615 // typically done in cli and cron scripts
616 // CRM-12648
617 $session = CRM_Core_Session::singleton();
618 $session->set( 'civicrmInitSession', TRUE );
619
620 $dbDrupal = DB::connect($config->userFrameworkDSN);
6a488035
TO
621 return $config->userSystem->authenticate($name, $password, $loadCMSBootstrap, $realPath);
622 }
623
624 /**
625 * Set a message in the UF to display to a user
626 *
627 * @param string $name the message to set
628 *
629 * @access public
630 * @static
631 */
632 static function setUFMessage($message) {
633 $config = CRM_Core_Config::singleton();
634 return $config->userSystem->setMessage($message);
635 }
636
637
638
639 static function isNull($value) {
640 // FIXME: remove $value = 'null' string test when we upgrade our DAO code to handle passing null in a better way.
641 if (!isset($value) || $value === NULL || $value === '' || $value === 'null') {
642 return TRUE;
643 }
644 if (is_array($value)) {
645 foreach ($value as $key => $value) {
646 if (!self::isNull($value)) {
647 return FALSE;
648 }
649 }
650 return TRUE;
651 }
652 return FALSE;
653 }
654
655 static function mungeCreditCard($number, $keep = 4) {
656 $number = trim($number);
657 if (empty($number)) {
658 return NULL;
659 }
660 $replace = str_repeat('*', strlen($number) - $keep);
661 return substr_replace($number, $replace, 0, -$keep);
662 }
663
664 /** parse php modules from phpinfo */
fcc5922d 665 public static function parsePHPModules() {
6a488035
TO
666 ob_start();
667 phpinfo(INFO_MODULES);
668 $s = ob_get_contents();
669 ob_end_clean();
670
671 $s = strip_tags($s, '<h2><th><td>');
672 $s = preg_replace('/<th[^>]*>([^<]+)<\/th>/', "<info>\\1</info>", $s);
673 $s = preg_replace('/<td[^>]*>([^<]+)<\/td>/', "<info>\\1</info>", $s);
674 $vTmp = preg_split('/(<h2>[^<]+<\/h2>)/', $s, -1, PREG_SPLIT_DELIM_CAPTURE);
675 $vModules = array();
676 for ($i = 1; $i < count($vTmp); $i++) {
677 if (preg_match('/<h2>([^<]+)<\/h2>/', $vTmp[$i], $vMat)) {
678 $vName = trim($vMat[1]);
679 $vTmp2 = explode("\n", $vTmp[$i + 1]);
680 foreach ($vTmp2 AS $vOne) {
681 $vPat = '<info>([^<]+)<\/info>';
682 $vPat3 = "/$vPat\s*$vPat\s*$vPat/";
683 $vPat2 = "/$vPat\s*$vPat/";
684 // 3cols
685 if (preg_match($vPat3, $vOne, $vMat)) {
686 $vModules[$vName][trim($vMat[1])] = array(trim($vMat[2]), trim($vMat[3]));
687 // 2cols
688 }
689 elseif (preg_match($vPat2, $vOne, $vMat)) {
690 $vModules[$vName][trim($vMat[1])] = trim($vMat[2]);
691 }
692 }
693 }
694 }
695 return $vModules;
696 }
697
698 /** get a module setting */
fcc5922d 699 public static function getModuleSetting($pModuleName, $pSetting) {
6a488035
TO
700 $vModules = self::parsePHPModules();
701 return $vModules[$pModuleName][$pSetting];
702 }
703
704 static function memory($title = NULL) {
705 static $pid = NULL;
706 if (!$pid) {
707 $pid = posix_getpid();
708 }
709
710 $memory = str_replace("\n", '', shell_exec("ps -p" . $pid . " -o rss="));
711 $memory .= ", " . time();
712 if ($title) {
713 CRM_Core_Error::debug_var($title, $memory);
714 }
715 return $memory;
716 }
717
718 static function download($name, $mimeType, &$buffer,
719 $ext = NULL,
720 $output = TRUE
721 ) {
722 $now = gmdate('D, d M Y H:i:s') . ' GMT';
723
724 header('Content-Type: ' . $mimeType);
725 header('Expires: ' . $now);
726
727 // lem9 & loic1: IE need specific headers
728 $isIE = strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE');
729 if ($ext) {
730 $fileString = "filename=\"{$name}.{$ext}\"";
731 }
732 else {
733 $fileString = "filename=\"{$name}\"";
734 }
735 if ($isIE) {
736 header("Content-Disposition: inline; $fileString");
737 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
738 header('Pragma: public');
739 }
740 else {
741 header("Content-Disposition: attachment; $fileString");
742 header('Pragma: no-cache');
743 }
744
745 if ($output) {
746 print $buffer;
747 self::civiExit();
748 }
749 }
750
751 static function xMemory($title = NULL, $log = FALSE) {
752 $mem = (float ) xdebug_memory_usage() / (float )(1024);
753 $mem = number_format($mem, 5) . ", " . time();
754 if ($log) {
755 echo "<p>$title: $mem<p>";
756 flush();
757 CRM_Core_Error::debug_var($title, $mem);
758 }
759 else {
760 echo "<p>$title: $mem<p>";
761 flush();
762 }
763 }
764
765 static function fixURL($url) {
766 $components = parse_url($url);
767
768 if (!$components) {
769 return NULL;
770 }
771
772 // at some point we'll add code here to make sure the url is not
773 // something that will mess up up, so we need to clean it up here
774 return $url;
775 }
776
777 /**
778 * make sure the callback is valid in the current context
779 *
780 * @param string $callback the name of the function
781 *
782 * @return boolean
783 * @static
784 */
785 static function validCallback($callback) {
786 if (self::$_callbacks === NULL) {
787 self::$_callbacks = array();
788 }
789
790 if (!array_key_exists($callback, self::$_callbacks)) {
791 if (strpos($callback, '::') !== FALSE) {
792 list($className, $methodName) = explode('::', $callback);
793 $fileName = str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
794 // ignore errors if any
795 @include_once ($fileName);
796 if (!class_exists($className)) {
797 self::$_callbacks[$callback] = FALSE;
798 }
799 else {
800 // instantiate the class
801 $object = new $className();
802 if (!method_exists($object, $methodName)) {
803 self::$_callbacks[$callback] = FALSE;
804 }
805 else {
806 self::$_callbacks[$callback] = TRUE;
807 }
808 }
809 }
810 else {
811 self::$_callbacks[$callback] = function_exists($callback);
812 }
813 }
814 return self::$_callbacks[$callback];
815 }
816
817 /**
818 * This serves as a wrapper to the php explode function
819 * we expect exactly $limit arguments in return, and if we dont
820 * get them, we pad it with null
821 */
822 static function explode($separator, $string, $limit) {
823 $result = explode($separator, $string, $limit);
824 for ($i = count($result); $i < $limit; $i++) {
825 $result[$i] = NULL;
826 }
827 return $result;
828 }
829
830 static function checkURL($url, $addCookie = FALSE) {
831 // make a GET request to $url
832 $ch = curl_init($url);
833 if ($addCookie) {
834 curl_setopt($ch, CURLOPT_COOKIE, http_build_query($_COOKIE));
835 }
836 // it's quite alright to use a self-signed cert
837 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
838
839 // lets capture the return stuff rather than echo
840 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );
841
842 return curl_exec($ch);
843 }
844
845 static function checkPHPVersion($ver = 5, $abort = TRUE) {
846 $phpVersion = substr(PHP_VERSION, 0, 1);
847 if ($phpVersion >= $ver) {
848 return TRUE;
849 }
850
851 if ($abort) {
852 CRM_Core_Error::fatal(ts('This feature requires PHP Version %1 or greater',
853 array(1 => $ver)
854 ));
855 }
856 return FALSE;
857 }
858
859 static function formatWikiURL($string, $encode = FALSE) {
860 $items = explode(' ', trim($string), 2);
861 if (count($items) == 2) {
862 $title = $items[1];
863 }
864 else {
865 $title = $items[0];
866 }
867
868 // fix for CRM-4044
869 $url = $encode ? self::urlEncode($items[0]) : $items[0];
870 return "<a href=\"$url\">$title</a>";
871 }
872
873 static function urlEncode($url) {
874 $items = parse_url($url);
875 if ($items === FALSE) {
876 return NULL;
877 }
878
879 if (!CRM_Utils_Array::value('query', $items)) {
880 return $url;
881 }
882
883 $items['query'] = urlencode($items['query']);
884
885 $url = $items['scheme'] . '://';
886 if (CRM_Utils_Array::value('user', $items)) {
887 $url .= "{$items['user']}:{$items['pass']}@";
888 }
889
890 $url .= $items['host'];
891 if (CRM_Utils_Array::value('port', $items)) {
892 $url .= ":{$items['port']}";
893 }
894
895 $url .= "{$items['path']}?{$items['query']}";
896 if (CRM_Utils_Array::value('fragment', $items)) {
897 $url .= "#{$items['fragment']}";
898 }
899
900 return $url;
901 }
902
903 /**
904 * Function to return the latest civicrm version.
905 *
906 * @return string civicrm version
907 * @access public
908 */
909 static function version() {
910 static $version;
911
912 if (!$version) {
913 $verFile = implode(DIRECTORY_SEPARATOR,
914 array(dirname(__FILE__), '..', '..', 'civicrm-version.php')
915 );
916 if (file_exists($verFile)) {
917 require_once ($verFile);
918 if (function_exists('civicrmVersion')) {
919 $info = civicrmVersion();
920 $version = $info['version'];
921 }
922 }
923 else {
924 // svn installs don't have version.txt by default. In that case version.xml should help -
925 $verFile = implode(DIRECTORY_SEPARATOR,
926 array(dirname(__FILE__), '..', '..', 'xml', 'version.xml')
927 );
928 if (file_exists($verFile)) {
929 $str = file_get_contents($verFile);
930 $xmlObj = simplexml_load_string($str);
931 $version = (string) $xmlObj->version_no;
932 }
933 }
934
935 // pattern check
936 if (!CRM_Utils_System::isVersionFormatValid($version)) {
937 CRM_Core_Error::fatal('Unknown codebase version.');
938 }
939 }
940
941 return $version;
942 }
943
944 static function isVersionFormatValid($version) {
945 return preg_match("/^(\d{1,2}\.){2,3}(\d{1,2}|(alpha|beta)\d{1,2})(\.upgrade)?$/", $version);
946 }
947
948 static function getAllHeaders() {
949 if (function_exists('getallheaders')) {
950 return getallheaders();
951 }
952
953 // emulate get all headers
954 // http://www.php.net/manual/en/function.getallheaders.php#66335
955 $headers = array();
956 foreach ($_SERVER as $name => $value) {
957 if (substr($name, 0, 5) == 'HTTP_') {
958 $headers[str_replace(' ',
959 '-',
960 ucwords(strtolower(str_replace('_',
961 ' ',
962 substr($name, 5)
963 )
964 ))
965 )] = $value;
966 }
967 }
968 return $headers;
969 }
970
971 static function getRequestHeaders() {
972 if (function_exists('apache_request_headers')) {
973 return apache_request_headers();
974 }
975 else {
976 return $_SERVER;
977 }
978 }
979
980 /**
981 * Check and determine is this is an SSL request
982 * Note that we inline this function in install/civicrm.php, so if
983 * you change this function, please go and change the code in the install script
984 */
985 static function isSSL( ) {
986 return
987 (isset($_SERVER['HTTPS']) &&
988 !empty($_SERVER['HTTPS']) &&
989 strtolower($_SERVER['HTTPS']) != 'off') ? true : false;
990 }
991
992 static function redirectToSSL($abort = FALSE) {
993 $config = CRM_Core_Config::singleton();
994 $req_headers = self::getRequestHeaders();
995 if (CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'enableSSL') &&
996 !self::isSSL() &&
997 strtolower(CRM_Utils_Array::value('X_FORWARDED_PROTO', $req_headers)) != 'https'
998 ) {
999 // ensure that SSL is enabled on a civicrm url (for cookie reasons etc)
1000 $url = "https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
1001 if (!self::checkURL($url, TRUE)) {
1002 if ($abort) {
1003 CRM_Core_Error::fatal('HTTPS is not set up on this machine');
1004 }
1005 else {
1006 CRM_Core_Session::setStatus(ts('HTTPS is not set up on this machine'), ts('Warning'), 'alert');
1007 // admin should be the only one following this
1008 // since we dont want the user stuck in a bad place
1009 return;
1010 }
1011 }
1012 CRM_Utils_System::redirect($url);
1013 }
1014 }
1015
1016 /*
5df36634
PJ
1017 * Get logged in user's IP address.
1018 *
1019 * Get IP address from HTTP Header. If the CMS is Drupal then use the Drupal function
1020 * as this also handles reverse proxies (based on proper configuration in settings.php)
1021 *
1022 * @return string ip address of logged in user
1023 */
1024 static function ipAddress($strictIPV4 = TRUE) {
6a488035
TO
1025 $address = CRM_Utils_Array::value('REMOTE_ADDR', $_SERVER);
1026
1027 $config = CRM_Core_Config::singleton();
1028 if ($config->userSystem->is_drupal) {
1029 //drupal function handles the server being behind a proxy securely
5df36634 1030 $address = ip_address();
6a488035
TO
1031 }
1032
1033 // hack for safari
1034 if ($address == '::1') {
1035 $address = '127.0.0.1';
1036 }
1037
5df36634
PJ
1038 // when we need to have strictly IPV4 ip address
1039 // convert ipV6 to ipV4
1040 if ($strictIPV4) {
1041 // this converts 'IPV4 mapped IPV6 address' to IPV4
1042 if (filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) && strstr($address, '::ffff:')) {
1043 $address = ltrim($address, '::ffff:');
1044 }
1045 }
1046
6a488035
TO
1047 return $address;
1048 }
1049
1050 /**
1051 * Returns you the referring / previous page url
1052 *
1053 * @return string the previous page url
1054 * @access public
1055 */
1056 static function refererPath() {
1057 return CRM_Utils_Array::value('HTTP_REFERER', $_SERVER);
1058 }
1059
1060 /**
1061 * Returns default documentation URL base
1062 *
1063 * @return string documentation url
1064 * @access public
1065 */
1066 static function getDocBaseURL() {
1067 // FIXME: move this to configuration at some stage
1068 return 'http://book.civicrm.org/';
1069 }
1070
1071 /**
1072 * Returns wiki (alternate) documentation URL base
1073 *
1074 * @return string documentation url
1075 * @access public
1076 */
1077 static function getWikiBaseURL() {
1078 // FIXME: move this to configuration at some stage
1079 return 'http://wiki.civicrm.org/confluence/display/CRMDOC/';
1080 }
1081
1082 /**
1083 * Returns URL or link to documentation page, based on provided parameters.
1084 * For use in PHP code.
1085 * WARNING: Always returns URL, if ts function is not defined ($URLonly has no effect).
1086 *
1087 * @param string $page Title of documentation wiki page
1088 * @param boolean $URLonly Whether function should return URL only or whole link (default)
1089 * @param string $text Text of HTML link (no effect if $URLonly = false)
1090 * @param string $title Tooltip text for HTML link (no effect if $URLonly = false)
1091 * @param string $style Style attribute value for HTML link (no effect if $URLonly = false)
1092 *
1093 * @return string URL or link to documentation page, based on provided parameters
1094 * @access public
1095 */
1096 static function docURL2($page, $URLonly = FALSE, $text = NULL, $title = NULL, $style = NULL, $resource = NULL) {
1097 // if ts function doesn't exist, it means that CiviCRM hasn't been fully initialised yet -
1098 // return just the URL, no matter what other parameters are defined
1099 if (!function_exists('ts')) {
1100 if ($resource == 'wiki') {
1101 $docBaseURL = self::getWikiBaseURL();
1102 } else {
1103 $docBaseURL = self::getDocBaseURL();
1104 }
1105 return $docBaseURL . str_replace(' ', '+', $page);
1106 }
1107 else {
1108 $params = array(
1109 'page' => $page,
1110 'URLonly' => $URLonly,
1111 'text' => $text,
1112 'title' => $title,
1113 'style' => $style,
1114 'resource' => $resource,
1115 );
1116 return self::docURL($params);
1117 }
1118 }
1119
1120 /**
1121 * Returns URL or link to documentation page, based on provided parameters.
1122 * For use in templates code.
1123 *
1124 * @param array $params An array of parameters (see CRM_Utils_System::docURL2 method for names)
1125 *
1126 * @return string URL or link to documentation page, based on provided parameters
1127 * @access public
1128 */
1129 static function docURL($params) {
1130
1131 if (!isset($params['page'])) {
1132 return;
1133 }
1134
1135 if (CRM_Utils_Array::value('resource', $params) == 'wiki') {
1136 $docBaseURL = self::getWikiBaseURL();
1137 } else {
1138 $docBaseURL = self::getDocBaseURL();
1139 }
1140
1141 if (!isset($params['title']) or $params['title'] === NULL) {
1142 $params['title'] = ts('Opens documentation in a new window.');
1143 }
1144
1145 if (!isset($params['text']) or $params['text'] === NULL) {
1146 $params['text'] = ts('(learn more...)');
1147 }
1148
1149 if (!isset($params['style']) || $params['style'] === NULL) {
1150 $style = '';
1151 }
1152 else {
1153 $style = "style=\"{$params['style']}\"";
1154 }
1155
1156 $link = $docBaseURL . str_replace(' ', '+', $params['page']);
1157
1158 if (isset($params['URLonly']) && $params['URLonly'] == TRUE) {
1159 return $link;
1160 }
1161 else {
1162 return "<a href=\"{$link}\" $style target=\"_blank\" title=\"{$params['title']}\">{$params['text']}</a>";
1163 }
1164 }
1165
1166 /**
1167 * Get the locale set in the hosting CMS
1168 *
1169 * @return string the used locale or null for none
1170 */
1171 static function getUFLocale() {
1172 $config = CRM_Core_Config::singleton();
1173 return $config->userSystem->getUFLocale();
1174 }
1175
1176 /**
1177 * Execute external or internal urls and return server response
1178 *
1179 * @param string $url request url
1180 * @param boolean $addCookie should be true to access internal urls
1181 *
1182 * @return string $response response from url
1183 * @static
1184 */
1185 static function getServerResponse($url, $addCookie = TRUE) {
1186 CRM_Core_Error::ignoreException();
1187 require_once 'HTTP/Request.php';
1188 $request = new HTTP_Request($url);
1189
1190 if ($addCookie) {
1191 foreach ($_COOKIE as $name => $value) {
1192 $request->addCookie($name, $value);
1193 }
1194 }
1195
1196 if (isset($_SERVER['AUTH_TYPE'])) {
1197 $request->setBasicAuth($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
1198 }
1199
1200 $config = CRM_Core_Config::singleton();
1201 if ($config->userFramework == 'WordPress') {
1202 session_write_close();
1203 }
1204
1205 $request->sendRequest();
1206 $response = $request->getResponseBody();
1207
1208 CRM_Core_Error::setCallback();
1209 return $response;
1210 }
1211
1212 static function isDBVersionValid(&$errorMessage) {
1213 $dbVersion = CRM_Core_BAO_Domain::version();
1214
1215 if (!$dbVersion) {
1216 // if db.ver missing
1217 $errorMessage = ts('Version information found to be missing in database. You will need to determine the correct version corresponding to your current database state.');
1218 return FALSE;
1219 }
1220 elseif (!CRM_Utils_System::isVersionFormatValid($dbVersion)) {
1221 $errorMessage = ts('Database is marked with invalid version format. You may want to investigate this before you proceed further.');
1222 return FALSE;
1223 }
1224 elseif (stripos($dbVersion, 'upgrade')) {
1225 // if db.ver indicates a partially upgraded db
1226 $upgradeUrl = CRM_Utils_System::url("civicrm/upgrade", "reset=1");
1227 $errorMessage = ts('Database check failed - the database looks to have been partially upgraded. You may want to reload the database with the backup and try the <a href=\'%1\'>upgrade process</a> again.', array(1 => $upgradeUrl));
1228 return FALSE;
1229 }
1230 else {
1231 $codeVersion = CRM_Utils_System::version();
1232
1233 // if db.ver < code.ver, time to upgrade
1234 if (version_compare($dbVersion, $codeVersion) < 0) {
1235 $upgradeUrl = CRM_Utils_System::url("civicrm/upgrade", "reset=1");
1236 $errorMessage = ts('New codebase version detected. You might want to visit <a href=\'%1\'>upgrade screen</a> to upgrade the database.', array(1 => $upgradeUrl));
1237 return FALSE;
1238 }
1239
1240 // if db.ver > code.ver, sth really wrong
1241 if (version_compare($dbVersion, $codeVersion) > 0) {
42daf119 1242 $errorMessage = '<p>' . ts('Your database is marked with an unexpected version number: %1. The v%2 codebase may not be compatible with your database state. You will need to determine the correct version corresponding to your current database state. You may want to revert to the codebase you were using until you resolve this problem.',
6a488035 1243 array(1 => $dbVersion, 2 => $codeVersion)
42daf119
CW
1244 ) . '</p>';
1245 $errorMessage .= "<p>" . ts('OR if this is a manual install from git, you might want to fix civicrm-version.php file.') . "</p>";
6a488035
TO
1246 return FALSE;
1247 }
1248 }
1249 // FIXME: there should be another check to make sure version is in valid format - X.Y.alpha_num
1250
1251 return TRUE;
1252 }
1253
1254 static function civiExit($status = 0) {
1255 // move things to CiviCRM cache as needed
1256 CRM_Core_Session::storeSessionObjects();
1257
1258 exit($status);
1259 }
1260
1261 /**
1262 * Reset the various system caches and some important
1263 * static variables
1264 */
1265 static function flushCache( ) {
1266 // flush out all cache entries so we can reload new data
1267 // a bit aggressive, but livable for now
1268 $cache = CRM_Utils_Cache::singleton();
1269 $cache->flush();
1270
1271 // also reset the various static memory caches
1272
1273 // reset the memory or array cache
1274 CRM_Core_BAO_Cache::deleteGroup('contact fields', NULL, FALSE);
1275
1276 // reset ACL cache
1277 CRM_ACL_BAO_Cache::resetCache();
1278
1279 // reset various static arrays used here
1280 CRM_Contact_BAO_Contact::$_importableFields =
1281 CRM_Contact_BAO_Contact::$_exportableFields =
1282 CRM_Contribute_BAO_Contribution::$_importableFields =
1283 CRM_Contribute_BAO_Contribution::$_exportableFields =
1284 CRM_Pledge_BAO_Pledge::$_exportableFields =
1285 CRM_Contribute_BAO_Query::$_contributionFields =
1286 CRM_Core_BAO_CustomField::$_importFields =
ef569d27 1287 CRM_Core_BAO_Cache::$_cache =
6a488035
TO
1288 CRM_Core_DAO::$_dbColumnValueCache = NULL;
1289
1290 CRM_Core_OptionGroup::flushAll();
1291 CRM_Utils_PseudoConstant::flushAll();
1292 }
1293
1294 /**
1295 * load cms bootstrap
1296 *
1297 * @param $params array with uid name and pass
1298 * @param $loadUser boolean load user or not
1299 */
1300 static function loadBootStrap($params = array(
1301 ), $loadUser = TRUE, $throwError = TRUE, $realPath = NULL) {
1302 if (!is_array($params)) {
1303 $params = array();
1304 }
1305 $config = CRM_Core_Config::singleton();
1306 return $config->userSystem->loadBootStrap($params, $loadUser, $throwError, $realPath);
1307 }
1308
1309 /**
1310 * check is user logged in.
1311 *
1312 * @return boolean.
1313 */
1314 public static function isUserLoggedIn() {
1315 $config = CRM_Core_Config::singleton();
1316 return $config->userSystem->isUserLoggedIn();
1317 }
1318
1319 /**
1320 * Get current logged in user id.
1321 *
1322 * @return int ufId, currently logged in user uf id.
1323 */
1324 public static function getLoggedInUfID() {
1325 $config = CRM_Core_Config::singleton();
1326 return $config->userSystem->getLoggedInUfID();
1327 }
1328
1329 static function baseCMSURL() {
1330 static $_baseURL = NULL;
1331 if (!$_baseURL) {
1332 $config = CRM_Core_Config::singleton();
1333 $_baseURL = $userFrameworkBaseURL = $config->userFrameworkBaseURL;
1334
1335 if ($config->userFramework == 'Joomla') {
1336 // gross hack
1337 // we need to remove the administrator/ from the end
1338 $_baseURL = str_replace("/administrator/", "/", $userFrameworkBaseURL);
1339 }
1340 else {
1341 // Drupal setting
1342 global $civicrm_root;
1343 if (strpos($civicrm_root,
1344 DIRECTORY_SEPARATOR . 'sites' .
1345 DIRECTORY_SEPARATOR . 'all' .
1346 DIRECTORY_SEPARATOR . 'modules'
1347 ) === FALSE) {
1348 $startPos = strpos($civicrm_root,
1349 DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR
1350 );
1351 $endPos = strpos($civicrm_root,
1352 DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR
1353 );
1354 if ($startPos && $endPos) {
1355 // if component is in sites/SITENAME/modules
1356 $siteName = substr($civicrm_root,
1357 $startPos + 7,
1358 $endPos - $startPos - 7
1359 );
1360
1361 $_baseURL = $userFrameworkBaseURL . "sites/$siteName/";
1362 }
1363 }
1364 }
1365 }
1366 return $_baseURL;
1367 }
1368
1369 static function relativeURL($url) {
1370 // check if url is relative, if so return immediately
1371 if (substr($url, 0, 4) != 'http') {
1372 return $url;
1373 }
1374
1375 // make everything relative from the baseFilePath
1376 $baseURL = self::baseCMSURL();
1377
1378 // check if baseURL is a substr of $url, if so
1379 // return rest of string
1380 if (substr($url, 0, strlen($baseURL)) == $baseURL) {
1381 return substr($url, strlen($baseURL));
1382 }
1383
1384 // return the original value
1385 return $url;
1386 }
1387
1388 static function absoluteURL($url, $removeLanguagePart = FALSE) {
1389 // check if url is already absolute, if so return immediately
1390 if (substr($url, 0, 4) == 'http') {
1391 return $url;
1392 }
1393
1394 // make everything absolute from the baseFileURL
1395 $baseURL = self::baseCMSURL();
1396
1397 //CRM-7622: drop the language from the URL if requested (and it’s there)
1398 $config = CRM_Core_Config::singleton();
1399 if ($removeLanguagePart) {
1400 $baseURL = self::languageNegotiationURL($baseURL, FALSE, TRUE);
1401 }
1402
1403 return $baseURL . $url;
1404 }
1405
1406 /**
1407 * Function to clean url, replaces first '&' with '?'
1408 *
1409 * @param string $url
1410 *
1411 * @return string $url, clean url
1412 * @static
1413 */
1414 static function cleanUrl($url) {
1415 if (!$url) {
1416 return NULL;
1417 }
1418
1419 if ($pos = strpos($url, '&')) {
1420 $url = substr_replace($url, '?', $pos, 1);
1421 }
1422
1423 return $url;
1424 }
1425
1426 /**
1427 * Format the url as per language Negotiation.
1428 *
1429 * @param string $url
1430 *
1431 * @return string $url, formatted url.
1432 * @static
1433 */
1434 static function languageNegotiationURL($url,
1435 $addLanguagePart = TRUE,
1436 $removeLanguagePart = FALSE
1437 ) {
1438 $config = &CRM_Core_Config::singleton();
1439 return $config->userSystem->languageNegotiationURL($url, $addLanguagePart, $removeLanguagePart);
1440 }
1441
1442 /**
1443 * Append the contents of an 'extra' smarty template file if it is present in
1444 * the custom template directory. This does not work if there are
1445 * multiple custom template directories
1446 *
1447 * @param string $fileName - the name of the tpl file that we are processing
1448 * @param string $content (by reference) - the current content string
1449 * @param string $overideFileName - an optional parameter which is sent by contribution/event reg/profile pages
1450 * which uses a id specific extra file name if present
1451 *
1452 * @return void - the content string is modified if needed
1453 * @static
1454 */
1455 static function appendTPLFile($fileName,
1456 &$content,
1457 $overideFileName = NULL
1458 ) {
1459 $template = CRM_Core_Smarty::singleton();
1460 if ($overideFileName) {
1461 $additionalTPLFile = $overideFileName;
1462 }
1463 else {
1464 $additionalTPLFile = str_replace('.tpl', '.extra.tpl', $fileName);
1465 }
1466
1467 if ($template->template_exists($additionalTPLFile)) {
1468 $content .= $template->fetch($additionalTPLFile);
1469 }
1470 }
1471
1472 /**
1473 * Get a list of all files that are found within the directories
1474 * that are the result of appending the provided relative path to
1475 * each component of the PHP include path.
1476 *
1477 * @author Ken Zalewski
1478 *
1479 * @param string $relpath a relative path, typically pointing to
1480 * a directory with multiple class files
1481 *
1482 * @return array An array of files that exist in one or more of the
1483 * directories that are referenced by the relative path
1484 * when appended to each element of the PHP include path
1485 * @access public
1486 */
1487 static function listIncludeFiles($relpath) {
1488 $file_list = array();
1489 $inc_dirs = explode(PATH_SEPARATOR, get_include_path());
1490 foreach ($inc_dirs as $inc_dir) {
1491 $target_dir = $inc_dir . DIRECTORY_SEPARATOR . $relpath;
1492 if (is_dir($target_dir)) {
1493 $cur_list = scandir($target_dir);
1494 foreach ($cur_list as $fname) {
1495 if ($fname != '.' && $fname != '..') {
1496 $file_list[$fname] = $fname;
1497 }
1498 }
1499 }
1500 }
1501 return $file_list;
1502 }
1503 // listIncludeFiles()
1504
1505 /**
1506 * Get a list of all "plugins" (PHP classes that implement a piece of
1507 * functionality using a well-defined interface) that are found in a
1508 * particular CiviCRM directory (both custom and core are searched).
1509 *
1510 * @author Ken Zalewski
1511 *
1512 * @param string $relpath a relative path referencing a directory that
1513 * contains one or more plugins
1514 * @param string $fext only files with this extension will be considered
1515 * to be plugins
1516 * @param array $skipList list of files to skip
1517 *
1518 * @return array List of plugins, where the plugin name is both the
1519 * key and the value of each element.
1520 * @access public
1521 */
1522 static function getPluginList($relpath, $fext = '.php', $skipList = array(
1523 )) {
1524 $fext_len = strlen($fext);
1525 $plugins = array();
1526 $inc_files = CRM_Utils_System::listIncludeFiles($relpath);
1527 foreach ($inc_files as $inc_file) {
1528 if (substr($inc_file, 0 - $fext_len) == $fext) {
1529 $plugin_name = substr($inc_file, 0, 0 - $fext_len);
1530 if (!in_array($plugin_name, $skipList)) {
1531 $plugins[$plugin_name] = $plugin_name;
1532 }
1533 }
1534 }
1535 return $plugins;
1536 }
1537 // getPluginList()
1538
1539 /**
1540 *
1541 * @param string $fileName - the name of the tpl file that we are processing
1542 * @param string $content (by reference) - the current content string
1543 *
1544 * @return void - the content string is modified if needed
1545 * @static
1546 */
1547 static function executeScheduledJobs() {
1548 $facility = new CRM_Core_JobManager();
1549 $facility->execute(FALSE);
1550
1551 $redirectUrl = self::url('civicrm/admin/job', 'reset=1');
1552
1553 CRM_Core_Session::setStatus(
1554 ts('Scheduled jobs have been executed according to individual timing settings. Please check log for messages.'),
1555 ts('Complete'), 'success');
1556
1557 CRM_Utils_System::redirect($redirectUrl);
1558 }
1559
efceedd4 1560 /**
c4e76569 1561 * Evaluate any tokens in a URL
efceedd4
TO
1562 *
1563 * @param string|FALSE $url
1564 * @return string|FALSE
1565 */
1566 public static function evalUrl($url) {
efceedd4
TO
1567 if ($url === FALSE) {
1568 return FALSE;
1569 }
1570 else {
1571 $config = CRM_Core_Config::singleton();
1572 $vars = array(
1573 '{ver}' => CRM_Utils_System::version(),
1574 '{uf}' => $config->userFramework,
1575 '{php}' => phpversion(),
c4e76569
TO
1576 '{sid}' => md5('sid_' . (defined('CIVICRM_SITE_KEY') ? CIVICRM_SITE_KEY : '') . '_' . $config->userFrameworkBaseURL),
1577 '{baseUrl}' => $config->userFrameworkBaseURL,
1578 '{lang}' => $config->lcMessages,
1579 '{co}' => $config->defaultContactCountry,
efceedd4 1580 );
c4e76569
TO
1581 foreach (array_keys($vars) as $k) {
1582 $vars[$k] = urlencode($vars[$k]);
1583 }
efceedd4
TO
1584 return strtr($url, $vars);
1585 }
1586 }
1587
1588
6a488035
TO
1589 /**
1590 * Determine whether this is a developmental system.
1591 *
1592 * @return bool
1593 */
1594 static function isDevelopment() {
1595 static $cache = NULL;
1596 if ($cache === NULL) {
1597 global $civicrm_root;
1598 $cache = file_exists("{$civicrm_root}/.svn") || file_exists("{$civicrm_root}/.git");
1599 }
1600 return $cache;
1601 }
1602}
1603