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