Merge pull request #16750 from eileenmcnaughton/sgroups
[civicrm-core.git] / CRM / Utils / System / Base.php
CommitLineData
6a488035
TO
1<?php
2
3/**
4 * Base class for UF system integrations
5 */
6abstract class CRM_Utils_System_Base {
2b0e7d03 7
4caaa696 8 /**
2b0e7d03
EM
9 * Deprecated property to check if this is a drupal install.
10 *
11 * The correct method is to have functions on the UF classes for all UF specific
4caaa696 12 * functions and leave the codebase oblivious to the type of CMS
7cdf0f5b 13 *
4caaa696 14 * @var bool
6714d8d2 15 * @deprecated
7cdf0f5b 16 * TRUE, if the CMS is Drupal.
4caaa696 17 */
6714d8d2 18 public $is_drupal = FALSE;
4caaa696
EM
19
20 /**
100fef9d 21 * Deprecated property to check if this is a joomla install. The correct method is to have functions on the UF classes for all UF specific
4caaa696 22 * functions and leave the codebase oblivious to the type of CMS
7cdf0f5b 23 *
4caaa696 24 * @var bool
6714d8d2 25 * @deprecated
7cdf0f5b 26 * TRUE, if the CMS is Joomla!.
4caaa696 27 */
6714d8d2 28 public $is_joomla = FALSE;
4caaa696 29
7cdf0f5b
AH
30 /**
31 * deprecated property to check if this is a wordpress install. The correct method is to have functions on the UF classes for all UF specific
32 * functions and leave the codebase oblivious to the type of CMS
33 *
7cdf0f5b 34 * @var bool
6714d8d2 35 * @deprecated
7cdf0f5b
AH
36 * TRUE, if the CMS is WordPress.
37 */
6714d8d2 38 public $is_wordpress = FALSE;
6a488035 39
e0dd98a5
EM
40 /**
41 * Does this CMS / UF support a CMS specific logging mechanism?
e0dd98a5 42 * @var bool
6714d8d2 43 * @todo - we should think about offering up logging mechanisms in a way that is also extensible by extensions
e0dd98a5 44 */
6714d8d2 45 public $supports_UF_Logging = FALSE;
e0dd98a5 46
7cdf0f5b
AH
47 /**
48 * @var bool
49 * TRUE, if the CMS allows CMS forms to be extended by hooks.
6a488035 50 */
6714d8d2 51 public $supports_form_extensions = FALSE;
6a488035 52
d4330c62
TO
53 public function initialize() {
54 if (\CRM_Utils_System::isSSL()) {
55 $this->mapConfigToSSL();
56 }
57 }
58
6714d8d2 59 abstract public function loadBootStrap($params = [], $loadUser = TRUE, $throwError = TRUE, $realPath = NULL);
9ba02e3e 60
17f443df 61 /**
fe482240 62 * Append an additional breadcrumb tag to the existing breadcrumb.
17f443df
CW
63 *
64 * @param array $breadCrumbs
65 */
66 public function appendBreadCrumb($breadCrumbs) {
67 }
68
69 /**
fe482240 70 * Reset an additional breadcrumb tag to the existing breadcrumb.
17f443df
CW
71 */
72 public function resetBreadCrumb() {
73 }
74
75 /**
fe482240 76 * Append a string to the head of the html file.
17f443df
CW
77 *
78 * @param string $head
79 * The new string to be appended.
80 */
81 public function addHTMLHead($head) {
82 }
83
84 /**
fe482240 85 * Rewrite various system urls to https.
17f443df
CW
86 */
87 public function mapConfigToSSL() {
88 // dont need to do anything, let CMS handle their own switch to SSL
89 }
90
91 /**
fe482240 92 * Figure out the post url for QuickForm.
17f443df
CW
93 *
94 * @param string $action
95 * The default url if one is pre-specified.
96 *
97 * @return string
98 * The url to post the form.
99 */
100 public function postURL($action) {
101 $config = CRM_Core_Config::singleton();
102 if (!empty($action)) {
103 return $action;
104 }
105
106 return $this->url(CRM_Utils_Array::value($config->userFrameworkURLVar, $_GET),
107 NULL, TRUE, NULL, FALSE
108 );
109 }
110
111 /**
112 * Generate the url string to a CiviCRM path.
113 *
114 * @param string $path
115 * The path being linked to, such as "civicrm/add".
116 * @param string $query
117 * A query string to append to the link.
118 * @param bool $absolute
119 * Whether to force the output to be an absolute link (beginning with http).
120 * Useful for links that will be displayed outside the site, such as in an RSS feed.
121 * @param string $fragment
122 * A fragment identifier (named anchor) to append to the link.
17f443df
CW
123 * @param bool $frontend
124 * This link should be to the CMS front end (applies to WP & Joomla).
125 * @param bool $forceBackend
126 * This link should be to the CMS back end (applies to WP & Joomla).
127 *
128 * @return string
129 */
130 public function url(
131 $path = NULL,
132 $query = NULL,
133 $absolute = FALSE,
134 $fragment = NULL,
17f443df
CW
135 $frontend = FALSE,
136 $forceBackend = FALSE
137 ) {
138 return NULL;
139 }
140
141 /**
fe482240 142 * Authenticate the user against the CMS db.
17f443df
CW
143 *
144 * @param string $name
145 * The user name.
146 * @param string $password
147 * The password for the above user.
148 * @param bool $loadCMSBootstrap
149 * Load cms bootstrap?.
150 * @param string $realPath
151 * Filename of script
152 *
153 * @return array|bool
154 * [contactID, ufID, unique string] else false if no auth
309310bf 155 * @throws \CRM_Core_Exception.
17f443df
CW
156 */
157 public function authenticate($name, $password, $loadCMSBootstrap = FALSE, $realPath = NULL) {
158 return FALSE;
159 }
160
161 /**
fe482240 162 * Set a message in the CMS to display to a user.
17f443df
CW
163 *
164 * @param string $message
165 * The message to set.
166 */
167 public function setMessage($message) {
168 }
169
170 /**
fe482240 171 * Load user into session.
17f443df 172 *
2b0e7d03 173 * @param obj $user
17f443df
CW
174 *
175 * @return bool
176 */
177 public function loadUser($user) {
178 return TRUE;
179 }
180
181 /**
2b0e7d03 182 * Immediately stop script execution and display a 401 "Access Denied" page.
309310bf 183 * @throws \CRM_Core_Exception
17f443df
CW
184 */
185 public function permissionDenied() {
309310bf 186 throw new CRM_Core_Exception(ts('You do not have permission to access this page.'));
17f443df
CW
187 }
188
189 /**
2b0e7d03 190 * Immediately stop script execution, log out the user and redirect to the home page.
17f443df
CW
191 *
192 * @deprecated
193 * This function should be removed in favor of linking to the CMS's logout page
194 */
195 public function logout() {
196 }
197
198 /**
199 * Clear CMS caches related to the user registration/profile forms.
200 * Used when updating/embedding profiles on CMS user forms.
201 * @see CRM-3600
202 */
203 public function updateCategories() {
204 }
205
206 /**
fe482240 207 * Get the locale set in the CMS.
17f443df
CW
208 *
209 * @return string|null
210 * Locale or null for none
211 */
212 public function getUFLocale() {
213 return NULL;
214 }
215
6a488035 216 /**
2b0e7d03 217 * If we are using a theming system, invoke theme, else just print the content.
6a488035 218 *
77855840
TO
219 * @param string $content
220 * The content that will be themed.
221 * @param bool $print
222 * Are we displaying to the screen or bypassing theming?.
223 * @param bool $maintenance
224 * For maintenance mode.
6a488035 225 *
7cdf0f5b
AH
226 * @throws Exception
227 * @return string|null
228 * NULL, If $print is FALSE, and some other criteria match up.
229 * The themed string, otherwise.
26659f0c
AH
230 *
231 * @todo The return value is inconsistent.
232 * @todo Better to always return, and never print.
6a488035 233 */
00be9182 234 public function theme(&$content, $print = FALSE, $maintenance = FALSE) {
6a488035
TO
235 $ret = FALSE;
236
237 // TODO: Split up; this was copied verbatim from CiviCRM 4.0's multi-UF theming function
238 // but the parts should be copied into cleaner subclass implementations
1e305b0b
DL
239 $config = CRM_Core_Config::singleton();
240 if (
241 $config->userSystem->is_drupal &&
242 function_exists('theme') &&
243 !$print
244 ) {
6a488035
TO
245 if ($maintenance) {
246 drupal_set_breadcrumb('');
247 drupal_maintenance_theme();
10221f8a
TO
248 if ($region = CRM_Core_Region::instance('html-header', FALSE)) {
249 CRM_Utils_System::addHTMLHead($region->render(''));
250 }
be2fb01f 251 print theme('maintenance_page', ['content' => $content]);
6a488035
TO
252 exit();
253 }
2b0e7d03
EM
254 // TODO: Figure out why D7 returns but everyone else prints
255 $ret = TRUE;
6a488035
TO
256 }
257 $out = $content;
258
1e305b0b
DL
259 if (
260 !$print &&
f3a87cf4 261 CRM_Core_Config::singleton()->userFramework == 'WordPress'
6a488035 262 ) {
aecede9a
AH
263 if (!function_exists('is_admin')) {
264 throw new \Exception('Function "is_admin()" is missing, even though WordPress is the user framework.');
265 }
266 if (!defined('ABSPATH')) {
267 throw new \Exception('Constant "ABSPATH" is not defined, even though WordPress is the user framework.');
268 }
6a488035 269 if (is_admin()) {
e7292422 270 require_once ABSPATH . 'wp-admin/admin-header.php';
6a488035
TO
271 }
272 else {
7cdf0f5b 273 // FIXME: we need to figure out to replace civicrm content on the frontend pages
6a488035
TO
274 }
275 }
276
277 if ($ret) {
278 return $out;
279 }
280 else {
281 print $out;
85c5f34c 282 return NULL;
6a488035
TO
283 }
284 }
285
bb3a214a
EM
286 /**
287 * @return string
288 */
00be9182 289 public function getDefaultBlockLocation() {
6a488035
TO
290 return 'left';
291 }
292
8246bca4 293 /**
294 * Get the absolute path to the site's base url.
295 *
296 * @return bool|mixed|string
297 */
d4330c62
TO
298 public function getAbsoluteBaseURL() {
299 if (!defined('CIVICRM_UF_BASEURL')) {
300 return FALSE;
301 }
302
303 $url = CRM_Utils_File::addTrailingSlash(CIVICRM_UF_BASEURL, '/');
304
305 //format url for language negotiation, CRM-7803
306 $url = $this->languageNegotiationURL($url);
307
308 if (CRM_Utils_System::isSSL()) {
309 $url = str_replace('http://', 'https://', $url);
310 }
311
312 return $url;
313 }
314
8246bca4 315 /**
316 * Get the relative path to the sites base url.
317 *
318 * @return bool
319 */
d4330c62
TO
320 public function getRelativeBaseURL() {
321 $absoluteBaseURL = $this->getAbsoluteBaseURL();
322 if ($absoluteBaseURL === FALSE) {
323 return FALSE;
324 }
325 $parts = parse_url($absoluteBaseURL);
326 return $parts['path'];
327 //$this->useFrameworkRelativeBase = empty($base['path']) ? '/' : $base['path'];
328 }
329
bb3a214a 330 /**
fe482240 331 * Get CMS Version.
17f443df 332 *
bb3a214a
EM
333 * @return string
334 */
00be9182 335 public function getVersion() {
6a488035
TO
336 return 'Unknown';
337 }
338
339 /**
340 * Format the url as per language Negotiation.
341 *
342 * @param string $url
77b97be7
EM
343 * @param bool $addLanguagePart
344 * @param bool $removeLanguagePart
345 *
7cdf0f5b
AH
346 * @return string
347 * Formatted url.
6a488035 348 */
d5cc0fc2 349 public function languageNegotiationURL(
6a488035
TO
350 $url,
351 $addLanguagePart = TRUE,
352 $removeLanguagePart = FALSE
353 ) {
354 return $url;
355 }
356
e29aefb4
TO
357 /**
358 * Determine the location of the CMS root.
359 *
7cdf0f5b
AH
360 * @return string|null
361 * Local file system path to CMS root, or NULL if it cannot be determined
6a488035 362 */
00be9182 363 public function cmsRootPath() {
e29aefb4 364 return NULL;
6a488035
TO
365 }
366
17f443df
CW
367 /**
368 * Create a user in the CMS.
369 *
370 * @param array $params
371 * @param string $mail
372 * Email id for cms user.
373 *
374 * @return int|bool
375 * uid if user exists, false otherwise
376 */
377 public function createUser(&$params, $mail) {
378 return FALSE;
379 }
380
381 /**
382 * Update a user's email address in the CMS.
383 *
384 * @param int $ufID
385 * User ID in CMS.
386 * @param string $email
387 * Primary contact email address.
388 */
389 public function updateCMSName($ufID, $email) {
390 }
391
392 /**
393 * Check if user is logged in to the CMS.
394 *
395 * @return bool
396 */
397 public function isUserLoggedIn() {
398 return FALSE;
399 }
400
8caad0ce 401 /**
402 * Check if user registration is permitted.
403 *
404 * @return bool
405 */
406 public function isUserRegistrationPermitted() {
407 return FALSE;
408 }
409
63df6889
HD
410 /**
411 * Check if user can create passwords or is initially assigned a system-generated one.
412 *
413 * @return bool
414 */
1a6630be 415 public function isPasswordUserGenerated() {
63df6889
HD
416 return FALSE;
417 }
418
68e3bc34 419 /**
420 * Is a front end page being accessed.
421 *
422 * Generally this would be a contribution form or other public page as opposed to a backoffice page (like contact edit).
423 *
424 * @todo Drupal uses the is_public setting - clarify & rationalise. See https://github.com/civicrm/civicrm-drupal/pull/546/files
425 *
426 * @return bool
427 */
428 public function isFrontEndPage() {
429 return CRM_Core_Config::singleton()->userFrameworkFrontend;
430 }
431
6a488035
TO
432 /**
433 * Get user login URL for hosting CMS (method declared in each CMS system class)
434 *
77855840
TO
435 * @param string $destination
436 * If present, add destination to querystring (works for Drupal only).
6a488035 437 *
a6c01b45
CW
438 * @return string
439 * loginURL for the current CMS
6a488035 440 */
6714d8d2 441 abstract public function getLoginURL($destination = '');
6a488035 442
17f443df 443 /**
2b0e7d03
EM
444 * Get the login destination string.
445 *
446 * When this is passed in the URL the user will be directed to it after filling in the CMS form.
17f443df
CW
447 *
448 * @param CRM_Core_Form $form
449 * Form object representing the 'current' form - to which the user will be returned.
2b0e7d03 450 *
17f443df
CW
451 * @return string|NULL
452 * destination value for URL
453 */
454 public function getLoginDestination(&$form) {
455 return NULL;
456 }
457
46b6363c 458 /**
fe482240 459 * Determine the native ID of the CMS user.
46b6363c 460 *
100fef9d 461 * @param string $username
f4aaa82a
EM
462 *
463 * @throws CRM_Core_Exception
46b6363c 464 */
00be9182 465 public function getUfId($username) {
46b6363c
TO
466 $className = get_class($this);
467 throw new CRM_Core_Exception("Not implemented: {$className}->getUfId");
468 }
469
bc854509 470 /**
471 * Set the localisation from the user framework.
472 *
473 * @param string $civicrm_language
474 *
475 * @return bool
476 */
a7c57397
TO
477 public function setUFLocale($civicrm_language) {
478 return TRUE;
479 }
480
5d0eb86b 481 /**
fe482240 482 * Set a init session with user object.
5d0eb86b 483 *
7cdf0f5b
AH
484 * @param array $data
485 * Array with user specific data
5d0eb86b 486 */
00be9182 487 public function setUserSession($data) {
5d0eb86b
BS
488 list($userID, $ufID) = $data;
489 $session = CRM_Core_Session::singleton();
490 $session->set('ufID', $ufID);
491 $session->set('userID', $userID);
492 }
d8a4acc0
C
493
494 /**
2b0e7d03 495 * Reset any system caches that may be required for proper CiviCRM integration.
d8a4acc0 496 */
00be9182 497 public function flush() {
d8a4acc0
C
498 // nullop by default
499 }
82d9c21e 500
f091327b 501 /**
2b0e7d03 502 * Flush css/js caches.
f091327b 503 */
00be9182 504 public function clearResourceCache() {
f091327b
CW
505 // nullop by default
506 }
507
17f443df 508 /**
fe482240 509 * Add a script file.
17f443df
CW
510 *
511 * Note: This function is not to be called directly
512 * @see CRM_Core_Region::render()
513 *
2b0e7d03 514 * @param string $url absolute path to file
17f443df
CW
515 * @param string $region
516 * location within the document: 'html-header', 'page-header', 'page-footer'.
517 *
518 * @return bool
519 * TRUE if we support this operation in this CMS, FALSE otherwise
520 */
521 public function addScriptUrl($url, $region) {
522 return FALSE;
523 }
524
525 /**
fe482240 526 * Add an inline script.
17f443df
CW
527 *
528 * Note: This function is not to be called directly
529 * @see CRM_Core_Region::render()
530 *
2b0e7d03 531 * @param string $code javascript code
17f443df
CW
532 * @param string $region
533 * location within the document: 'html-header', 'page-header', 'page-footer'.
534 *
535 * @return bool
536 * TRUE if we support this operation in this CMS, FALSE otherwise
537 */
538 public function addScript($code, $region) {
539 return FALSE;
540 }
541
542 /**
fe482240 543 * Add a css file.
17f443df
CW
544 *
545 * Note: This function is not to be called directly
546 * @see CRM_Core_Region::render()
547 *
2b0e7d03 548 * @param string $url absolute path to file
17f443df
CW
549 * @param string $region
550 * location within the document: 'html-header', 'page-header', 'page-footer'.
551 *
552 * @return bool
553 * TRUE if we support this operation in this CMS, FALSE otherwise
554 */
555 public function addStyleUrl($url, $region) {
556 return FALSE;
557 }
558
559 /**
fe482240 560 * Add an inline style.
17f443df
CW
561 *
562 * Note: This function is not to be called directly
563 * @see CRM_Core_Region::render()
564 *
2b0e7d03 565 * @param string $code css code
17f443df
CW
566 * @param string $region
567 * location within the document: 'html-header', 'page-header', 'page-footer'.
568 *
569 * @return bool
570 * TRUE if we support this operation in this CMS, FALSE otherwise
571 */
572 public function addStyle($code, $region) {
573 return FALSE;
574 }
575
576 /**
fe482240 577 * Sets the title of the page.
17f443df
CW
578 *
579 * @param string $title
580 * Title to set in html header
581 * @param string|null $pageTitle
582 * Title to set in html body (if different)
583 */
584 public function setTitle($title, $pageTitle = NULL) {
585 }
586
c8950569 587 /**
fe482240 588 * Return default Site Settings.
f4aaa82a 589 *
7cdf0f5b 590 * @param string $dir
f4aaa82a 591 *
7cdf0f5b 592 * @return array
d5cc0fc2 593 * - $url, (Joomla - non admin url)
594 * - $siteName,
595 * - $siteRoot
9977c6f5 596 */
00be9182 597 public function getDefaultSiteSettings($dir) {
9977c6f5 598 $config = CRM_Core_Config::singleton();
599 $url = $config->userFrameworkBaseURL;
be2fb01f 600 return [$url, NULL, NULL];
9977c6f5 601 }
c8950569 602
f6f958e4
TO
603 /**
604 * Determine the default location for file storage.
605 *
606 * FIXME:
607 * 1. This was pulled out from a bigger function. It should be split
608 * into even smaller pieces and marked abstract.
609 * 2. This would be easier to compute by a calling a CMS API, but
610 * for whatever reason Civi gets it from config data.
611 *
612 * @return array
613 * - url: string. ex: "http://example.com/sites/foo.com/files/civicrm"
614 * - path: string. ex: "/var/www/sites/foo.com/files/civicrm"
615 */
616 public function getDefaultFileStorage() {
617 global $civicrm_root;
618 $config = CRM_Core_Config::singleton();
619 $baseURL = CRM_Utils_System::languageNegotiationURL($config->userFrameworkBaseURL, FALSE, TRUE);
620
621 $filesURL = NULL;
622 $filesPath = NULL;
623
624 if ($config->userFramework == 'Joomla') {
625 // gross hack
626 // we need to remove the administrator/ from the end
627 $tempURL = str_replace("/administrator/", "/", $baseURL);
628 $filesURL = $tempURL . "media/civicrm/";
629 }
f6f958e4
TO
630 elseif ($config->userFramework == 'UnitTests') {
631 $filesURL = $baseURL . "sites/default/files/civicrm/";
632 }
633 else {
634 throw new CRM_Core_Exception("Failed to locate default file storage ($config->userFramework)");
635 }
636
be2fb01f 637 return [
f6f958e4
TO
638 'url' => $filesURL,
639 'path' => CRM_Utils_File::baseFilePath(),
be2fb01f 640 ];
f6f958e4
TO
641 }
642
643 /**
644 * Determine the location of the CiviCRM source tree.
645 *
646 * FIXME:
647 * 1. This was pulled out from a bigger function. It should be split
648 * into even smaller pieces and marked abstract.
649 * 2. This would be easier to compute by a calling a CMS API, but
650 * for whatever reason we take the hard way.
651 *
652 * @return array
653 * - url: string. ex: "http://example.com/sites/all/modules/civicrm"
654 * - path: string. ex: "/var/www/sites/all/modules/civicrm"
655 */
656 public function getCiviSourceStorage() {
657 global $civicrm_root;
658 $config = CRM_Core_Config::singleton();
659
660 // Don't use $config->userFrameworkBaseURL; it has garbage on it.
661 // More generally, w shouldn't be using $config here.
662 if (!defined('CIVICRM_UF_BASEURL')) {
663 throw new RuntimeException('Undefined constant: CIVICRM_UF_BASEURL');
664 }
665 $baseURL = CRM_Utils_File::addTrailingSlash(CIVICRM_UF_BASEURL, '/');
666 if (CRM_Utils_System::isSSL()) {
667 $baseURL = str_replace('http://', 'https://', $baseURL);
668 }
669
670 if ($config->userFramework == 'Joomla') {
671 $userFrameworkResourceURL = $baseURL . "components/com_civicrm/civicrm/";
672 }
673 elseif ($config->userFramework == 'WordPress') {
750752f2 674 $userFrameworkResourceURL = CIVICRM_PLUGIN_URL . "civicrm/";
f6f958e4 675 }
3403e54b
TO
676 elseif ($this->is_drupal) {
677 // Drupal setting
678 // check and see if we are installed in sites/all (for D5 and above)
679 // we dont use checkURL since drupal generates an error page and throws
680 // the system for a loop on lobo's macosx box
681 // or in modules
682 $cmsPath = $config->userSystem->cmsRootPath();
683 $userFrameworkResourceURL = $baseURL . str_replace("$cmsPath/", '',
684 str_replace('\\', '/', $civicrm_root)
685 );
686
687 $siteName = $config->userSystem->parseDrupalSiteNameFromRoot($civicrm_root);
688 if ($siteName) {
689 $civicrmDirName = trim(basename($civicrm_root));
690 $userFrameworkResourceURL = $baseURL . "sites/$siteName/modules/$civicrmDirName/";
691 }
692 }
f6f958e4
TO
693 else {
694 $userFrameworkResourceURL = NULL;
695 }
696
be2fb01f 697 return [
6ee26d90 698 'url' => CRM_Utils_File::addTrailingSlash($userFrameworkResourceURL, '/'),
f6f958e4 699 'path' => CRM_Utils_File::addTrailingSlash($civicrm_root),
be2fb01f 700 ];
f6f958e4
TO
701 }
702
82d9c21e 703 /**
2b0e7d03
EM
704 * Perform any post login activities required by the CMS.
705 *
53980972 706 * e.g. for drupal: records a watchdog message about the new session, saves the login timestamp,
707 * calls hook_user op 'login' and generates a new session.
e43cc689 708 *
7cdf0f5b 709 * @param array $params
95d68223
TO
710 *
711 * FIXME: Document values accepted/required by $params
c8950569 712 */
be2fb01f 713 public function userLoginFinalize($params = []) {
82d9c21e 714 }
5a604d61
E
715
716 /**
fe482240 717 * Set timezone in mysql so that timestamp fields show the correct time.
5a604d61 718 */
9b873358 719 public function setMySQLTimeZone() {
5a604d61 720 $timeZoneOffset = $this->getTimeZoneOffset();
9b873358 721 if ($timeZoneOffset) {
5a604d61
E
722 $sql = "SET time_zone = '$timeZoneOffset'";
723 CRM_Core_DAO::executequery($sql);
724 }
725 }
726
727 /**
fe482240 728 * Get timezone from CMS.
7cdf0f5b
AH
729 *
730 * @return string|false|null
6491539b 731 */
9b873358 732 public function getTimeZoneOffset() {
6491539b 733 $timezone = $this->getTimeZoneString();
8b647c3a 734 if ($timezone) {
2451c06a 735 if ($timezone == 'UTC' || $timezone == 'Etc/UTC') {
030113f0 736 // CRM-17072 Let's short-circuit all the zero handling & return it here!
737 return '+00:00';
738 }
6491539b
DL
739 $tzObj = new DateTimeZone($timezone);
740 $dateTime = new DateTime("now", $tzObj);
741 $tz = $tzObj->getOffset($dateTime);
742
f2173d64 743 if ($tz === 0) {
278460dd
AS
744 // CRM-21422
745 return '+00:00';
746 }
747
8b647c3a
AH
748 if (empty($tz)) {
749 return FALSE;
6491539b
DL
750 }
751
e7292422 752 $timeZoneOffset = sprintf("%02d:%02d", $tz / 3600, abs(($tz / 60) % 60));
6491539b 753
8b647c3a 754 if ($timeZoneOffset > 0) {
6491539b
DL
755 $timeZoneOffset = '+' . $timeZoneOffset;
756 }
757 return $timeZoneOffset;
758 }
85c5f34c 759 return NULL;
6491539b
DL
760 }
761
762 /**
fe482240 763 * Get timezone as a string.
7cdf0f5b 764 * @return string
17f443df 765 * Timezone string e.g. 'America/Los_Angeles'
6491539b 766 */
00be9182 767 public function getTimeZoneString() {
48ec57ab 768 return date_default_timezone_get();
5a604d61 769 }
2b617cb0
EM
770
771 /**
2b0e7d03
EM
772 * Get Unique Identifier from UserFramework system (CMS).
773 *
77855840
TO
774 * @param object $user
775 * Object as described by the User Framework.
2b0e7d03 776 *
72b3a70c 777 * @return mixed
2b0e7d03 778 * Unique identifier from the user Framework system
2b617cb0 779 */
e7292422 780 public function getUniqueIdentifierFromUserObject($user) {
17f443df 781 return NULL;
e7292422 782 }
2b617cb0 783
32998c82 784 /**
2b0e7d03
EM
785 * Get User ID from UserFramework system (CMS).
786 *
77855840 787 * @param object $user
2b0e7d03 788 *
77855840 789 * Object as described by the User Framework.
17f443df 790 * @return null|int
32998c82 791 */
e7292422 792 public function getUserIDFromUserObject($user) {
17f443df 793 return NULL;
e7292422 794 }
32998c82 795
2b0e7d03
EM
796 /**
797 * Get an array of user details for a contact, containing at minimum the user ID & name.
798 *
799 * @param int $contactID
800 *
801 * @return array
802 * CMS user details including
803 * - id
804 * - name (ie the system user name.
805 */
806 public function getUser($contactID) {
be2fb01f 807 $ufMatch = civicrm_api3('UFMatch', 'getsingle', [
2b0e7d03
EM
808 'contact_id' => $contactID,
809 'domain_id' => CRM_Core_Config::domainID(),
be2fb01f
CW
810 ]);
811 return [
2b0e7d03
EM
812 'id' => $ufMatch['uf_id'],
813 'name' => $ufMatch['uf_name'],
be2fb01f 814 ];
2b0e7d03
EM
815 }
816
32998c82
EM
817 /**
818 * Get currently logged in user uf id.
819 *
17f443df
CW
820 * @return int|null
821 * logged in user uf id.
32998c82 822 */
e7292422 823 public function getLoggedInUfID() {
17f443df 824 return NULL;
e7292422 825 }
32998c82 826
2b617cb0
EM
827 /**
828 * Get currently logged in user unique identifier - this tends to be the email address or user name.
829 *
17f443df 830 * @return string|null
a6c01b45 831 * logged in user unique identifier
2b617cb0 832 */
e7292422 833 public function getLoggedInUniqueIdentifier() {
17f443df 834 return NULL;
e7292422 835 }
2b617cb0 836
32998c82 837 /**
2b0e7d03
EM
838 * Return a UFID (user account ID from the UserFramework / CMS system.
839 *
840 * ID is based on the user object passed, defaulting to the logged in user if not passed.
841 *
842 * Note that ambiguous situation occurs in CRM_Core_BAO_UFMatch::synchronize - a cleaner approach would
843 * seem to be resolving the user id before calling the function.
32998c82
EM
844 *
845 * Note there is already a function getUFId which takes $username as a param - we could add $user
2b0e7d03
EM
846 * as a second param to it but it seems messy - just overloading it because the name is taken.
847 *
2b617cb0 848 * @param object $user
2b0e7d03 849 *
a6c01b45 850 * @return int
2b0e7d03 851 * User ID of UF System
32998c82 852 */
00be9182 853 public function getBestUFID($user = NULL) {
22e263ad 854 if ($user) {
32998c82
EM
855 return $this->getUserIDFromUserObject($user);
856 }
857 return $this->getLoggedInUfID();
858 }
2b617cb0
EM
859
860 /**
2b0e7d03
EM
861 * Return a unique identifier (usually an email address or username) from the UserFramework / CMS system.
862 *
863 * This is based on the user object passed, defaulting to the logged in user if not passed.
864 *
865 * Note that ambiguous situation occurs in CRM_Core_BAO_UFMatch::synchronize - a cleaner approach would seem to be
866 * resolving the unique identifier before calling the function.
2b617cb0
EM
867 *
868 * @param object $user
2b0e7d03 869 *
a6c01b45
CW
870 * @return string
871 * unique identifier from the UF System
2b617cb0 872 */
00be9182 873 public function getBestUFUniqueIdentifier($user = NULL) {
22e263ad 874 if ($user) {
2b617cb0
EM
875 return $this->getUniqueIdentifierFromUserObject($user);
876 }
877 return $this->getLoggedInUniqueIdentifier();
878 }
59f97da6 879
66e42142
CW
880 /**
881 * List modules installed in the CMS, including enabled and disabled ones.
882 *
883 * @return array
884 * [CRM_Core_Module]
885 */
886 public function getModules() {
be2fb01f 887 return [];
66e42142
CW
888 }
889
59f97da6 890 /**
fe482240 891 * Get Url to view user record.
2b0e7d03 892 *
77855840
TO
893 * @param int $contactID
894 * Contact ID.
59f97da6 895 *
17f443df 896 * @return string|null
59f97da6 897 */
00be9182 898 public function getUserRecordUrl($contactID) {
59f97da6
EM
899 return NULL;
900 }
353ffa53 901
59f97da6 902 /**
fe482240 903 * Is the current user permitted to add a user.
2b0e7d03 904 *
59f97da6
EM
905 * @return bool
906 */
00be9182 907 public function checkPermissionAddUser() {
59f97da6
EM
908 return FALSE;
909 }
f85b1d20
EM
910
911 /**
fe482240 912 * Output code from error function.
2b0e7d03 913 *
f85b1d20
EM
914 * @param string $content
915 */
00be9182 916 public function outputError($content) {
f85b1d20
EM
917 echo CRM_Utils_System::theme($content);
918 }
e0dd98a5
EM
919
920 /**
fe482240 921 * Log error to CMS.
17f443df 922 *
ad37ac8e 923 * @param string $message
e0dd98a5 924 */
00be9182 925 public function logger($message) {
e0dd98a5 926 }
f9f361d0
CW
927
928 /**
fe482240 929 * Append to coreResourcesList.
17f443df 930 *
303017a1 931 * @param \Civi\Core\Event\GenericHookEvent $e
f9f361d0 932 */
303017a1 933 public function appendCoreResources(\Civi\Core\Event\GenericHookEvent $e) {
e7292422 934 }
96025800 935
62c20d1e
CW
936 /**
937 * Modify dynamic assets.
938 *
939 * @param \Civi\Core\Event\GenericHookEvent $e
940 */
941 public function alterAssetUrl(\Civi\Core\Event\GenericHookEvent $e) {
942 }
943
d42a224c
CW
944 /**
945 * @param string $name
946 * @param string $value
947 */
948 public function setHttpHeader($name, $value) {
949 header("$name: $value");
950 }
951
03d5592a
CW
952 /**
953 * Create CRM contacts for all existing CMS users
954 *
955 * @return array
956 * @throws \Exception
957 */
958 public function synchronizeUsers() {
959 throw new Exception('CMS user creation not supported for this framework');
be2fb01f 960 return [];
03d5592a
CW
961 }
962
79dd7fe9 963 /**
46dddc5c
SL
964 * Send an HTTP Response base on PSR HTTP RespnseInterface response.
965 *
966 * @param \Psr\Http\Message\ResponseInterface $response
79dd7fe9 967 */
46dddc5c 968 public function sendResponse(\Psr\Http\Message\ResponseInterface $response) {
fcfcd0f7 969 http_response_code($response->getStatusCode());
90f6c8df
SL
970 foreach ($response->getHeaders() as $name => $values) {
971 CRM_Utils_System::setHttpHeader($name, implode(', ', (array) $values));
79dd7fe9 972 }
46dddc5c
SL
973 echo $response->getBody();
974 CRM_Utils_System::civiExit();
79dd7fe9
SL
975 }
976
671f655b 977 /**
978 * Start a new session.
979 */
980 public function sessionStart() {
981 session_start();
982 }
983
08d5b4df
JP
984 /**
985 * Get role names
986 *
987 * @return array|null
988 */
989 public function getRoleNames() {
990 return NULL;
991 }
992
6a488035 993}