Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
bc77d7c0 | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
6a488035 | 5 | | | |
bc77d7c0 TO |
6 | | This work is published under the GNU AGPLv3 license with some | |
7 | | permitted exceptions and without any warranty. For full license | | |
8 | | and copyright information, see https://civicrm.org/licensing | | |
6a488035 | 9 | +--------------------------------------------------------------------+ |
d25dd0ee | 10 | */ |
6a488035 TO |
11 | |
12 | /** | |
13 | * | |
14 | * @package CRM | |
ca5cec67 | 15 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
6a488035 TO |
16 | */ |
17 | ||
18 | /** | |
b8c71ffa | 19 | * Joomla specific stuff goes here. |
6a488035 TO |
20 | */ |
21 | class CRM_Utils_System_Joomla extends CRM_Utils_System_Base { | |
6714d8d2 | 22 | |
bb3a214a | 23 | /** |
b8c71ffa | 24 | * Class constructor. |
bb3a214a | 25 | */ |
00be9182 | 26 | public function __construct() { |
4caaa696 EM |
27 | /** |
28 | * deprecated property to check if this is a drupal install. The correct method is to have functions on the UF classes for all UF specific | |
29 | * functions and leave the codebase oblivious to the type of CMS | |
30 | * @deprecated | |
31 | * @var bool | |
32 | */ | |
6a488035 TO |
33 | $this->is_drupal = FALSE; |
34 | } | |
35 | ||
36 | /** | |
17f443df | 37 | * @inheritDoc |
6a488035 | 38 | */ |
00be9182 | 39 | public function createUser(&$params, $mail) { |
6a488035 TO |
40 | $baseDir = JPATH_SITE; |
41 | require_once $baseDir . '/components/com_users/models/registration.php'; | |
42 | ||
43 | $userParams = JComponentHelper::getParams('com_users'); | |
353ffa53 TO |
44 | $model = new UsersModelRegistration(); |
45 | $ufID = NULL; | |
6a488035 TO |
46 | |
47 | // get the default usertype | |
48 | $userType = $userParams->get('new_usertype'); | |
49 | if (!$userType) { | |
50 | $userType = 2; | |
51 | } | |
52 | ||
53 | if (isset($params['name'])) { | |
54 | $fullname = trim($params['name']); | |
55 | } | |
56 | elseif (isset($params['contactID'])) { | |
57 | $fullname = trim(CRM_Contact_BAO_Contact::displayName($params['contactID'])); | |
58 | } | |
59 | else { | |
60 | $fullname = trim($params['cms_name']); | |
61 | } | |
62 | ||
63 | // Prepare the values for a new Joomla user. | |
be2fb01f | 64 | $values = []; |
353ffa53 TO |
65 | $values['name'] = $fullname; |
66 | $values['username'] = trim($params['cms_name']); | |
6a488035 | 67 | $values['password1'] = $values['password2'] = $params['cms_pass']; |
353ffa53 | 68 | $values['email1'] = $values['email2'] = trim($params[$mail]); |
6a488035 TO |
69 | |
70 | $lang = JFactory::getLanguage(); | |
71 | $lang->load('com_users', $baseDir); | |
72 | ||
73 | $register = $model->register($values); | |
74 | ||
75 | $ufID = JUserHelper::getUserId($values['username']); | |
76 | return $ufID; | |
77 | } | |
78 | ||
f4aaa82a | 79 | /** |
17f443df | 80 | * @inheritDoc |
6a488035 | 81 | */ |
00be9182 | 82 | public function updateCMSName($ufID, $ufName) { |
6a488035 TO |
83 | $ufID = CRM_Utils_Type::escape($ufID, 'Integer'); |
84 | $ufName = CRM_Utils_Type::escape($ufName, 'String'); | |
85 | ||
be2fb01f | 86 | $values = []; |
e851ce06 | 87 | $user = JUser::getInstance($ufID); |
6a488035 TO |
88 | |
89 | $values['email'] = $ufName; | |
90 | $user->bind($values); | |
91 | ||
92 | $user->save(); | |
93 | } | |
94 | ||
95 | /** | |
94f9f81a | 96 | * Check if username and email exists in the Joomla db. |
6a488035 | 97 | * |
77855840 TO |
98 | * @param array $params |
99 | * Array of name and mail values. | |
100 | * @param array $errors | |
101 | * Array of errors. | |
102 | * @param string $emailName | |
103 | * Field label for the 'email'. | |
6a488035 | 104 | */ |
00be9182 | 105 | public function checkUserNameEmailExists(&$params, &$errors, $emailName = 'email') { |
6a488035 TO |
106 | $config = CRM_Core_Config::singleton(); |
107 | ||
185ef241 TO |
108 | $name = CRM_Utils_Array::value('name', $params); |
109 | $email = CRM_Utils_Array::value('mail', $params); | |
6a488035 TO |
110 | //don't allow the special characters and min. username length is two |
111 | //regex \\ to match a single backslash would become '/\\\\/' | |
112 | $isNotValid = (bool) preg_match('/[\<|\>|\"|\'|\%|\;|\(|\)|\&|\\\\|\/]/im', $name); | |
113 | if ($isNotValid || strlen($name) < 2) { | |
114 | $errors['cms_name'] = ts('Your username contains invalid characters or is too short'); | |
115 | } | |
116 | ||
6a488035 TO |
117 | $JUserTable = &JTable::getInstance('User', 'JTable'); |
118 | ||
119 | $db = $JUserTable->getDbo(); | |
120 | $query = $db->getQuery(TRUE); | |
121 | $query->select('username, email'); | |
122 | $query->from($JUserTable->getTableName()); | |
b27d1855 | 123 | |
124 | // LOWER in query below roughly translates to 'hurt my database without deriving any benefit' See CRM-19811. | |
185ef241 | 125 | $query->where('(LOWER(username) = LOWER(' . $db->quote($name) . ')) OR (LOWER(email) = LOWER(' . $db->quote($email) . '))'); |
6a488035 TO |
126 | $db->setQuery($query, 0, 10); |
127 | $users = $db->loadAssocList(); | |
128 | ||
be2fb01f | 129 | $row = []; |
6a488035 TO |
130 | if (count($users)) { |
131 | $row = $users[0]; | |
132 | } | |
133 | ||
134 | if (!empty($row)) { | |
9c1bc317 CW |
135 | $dbName = $row['username'] ?? NULL; |
136 | $dbEmail = $row['email'] ?? NULL; | |
6a488035 TO |
137 | if (strtolower($dbName) == strtolower($name)) { |
138 | $errors['cms_name'] = ts('The username %1 is already taken. Please select another username.', | |
be2fb01f | 139 | [1 => $name] |
6a488035 TO |
140 | ); |
141 | } | |
142 | if (strtolower($dbEmail) == strtolower($email)) { | |
143 | $resetUrl = str_replace('administrator/', '', $config->userFrameworkBaseURL) . 'index.php?option=com_users&view=reset'; | |
89374eb2 | 144 | $errors[$emailName] = ts('The email address %1 already has an account associated with it. <a href="%2">Have you forgotten your password?</a>', |
be2fb01f | 145 | [1 => $email, 2 => $resetUrl] |
6a488035 TO |
146 | ); |
147 | } | |
148 | } | |
149 | } | |
150 | ||
151 | /** | |
17f443df | 152 | * @inheritDoc |
6a488035 | 153 | */ |
00be9182 | 154 | public function setTitle($title, $pageTitle = NULL) { |
6a488035 TO |
155 | if (!$pageTitle) { |
156 | $pageTitle = $title; | |
157 | } | |
158 | ||
159 | $template = CRM_Core_Smarty::singleton(); | |
160 | $template->assign('pageTitle', $pageTitle); | |
161 | ||
162 | $document = JFactory::getDocument(); | |
163 | $document->setTitle($title); | |
6a488035 TO |
164 | } |
165 | ||
166 | /** | |
17f443df | 167 | * @inheritDoc |
6a488035 | 168 | */ |
00be9182 | 169 | public function appendBreadCrumb($breadCrumbs) { |
6a488035 TO |
170 | $template = CRM_Core_Smarty::singleton(); |
171 | $bc = $template->get_template_vars('breadcrumb'); | |
172 | ||
173 | if (is_array($breadCrumbs)) { | |
174 | foreach ($breadCrumbs as $crumbs) { | |
175 | if (stripos($crumbs['url'], 'id%%')) { | |
be2fb01f | 176 | $args = ['cid', 'mid']; |
6a488035 TO |
177 | foreach ($args as $a) { |
178 | $val = CRM_Utils_Request::retrieve($a, 'Positive', CRM_Core_DAO::$_nullObject, | |
179 | FALSE, NULL, $_GET | |
180 | ); | |
181 | if ($val) { | |
182 | $crumbs['url'] = str_ireplace("%%{$a}%%", $val, $crumbs['url']); | |
183 | } | |
184 | } | |
185 | } | |
186 | $bc[] = $crumbs; | |
187 | } | |
188 | } | |
189 | $template->assign_by_ref('breadcrumb', $bc); | |
6a488035 TO |
190 | } |
191 | ||
192 | /** | |
17f443df | 193 | * @inheritDoc |
6a488035 | 194 | */ |
00be9182 | 195 | public function resetBreadCrumb() { |
6a488035 TO |
196 | } |
197 | ||
198 | /** | |
17f443df | 199 | * @inheritDoc |
6a488035 | 200 | */ |
17f443df | 201 | public function addHTMLHead($string = NULL) { |
6a488035 TO |
202 | if ($string) { |
203 | $document = JFactory::getDocument(); | |
204 | $document->addCustomTag($string); | |
205 | } | |
206 | } | |
207 | ||
208 | /** | |
17f443df | 209 | * @inheritDoc |
6a488035 TO |
210 | */ |
211 | public function addStyleUrl($url, $region) { | |
212 | if ($region == 'html-header') { | |
213 | $document = JFactory::getDocument(); | |
214 | $document->addStyleSheet($url); | |
215 | return TRUE; | |
216 | } | |
217 | return FALSE; | |
218 | } | |
219 | ||
220 | /** | |
17f443df | 221 | * @inheritDoc |
6a488035 TO |
222 | */ |
223 | public function addStyle($code, $region) { | |
224 | if ($region == 'html-header') { | |
225 | $document = JFactory::getDocument(); | |
226 | $document->addStyleDeclaration($code); | |
227 | return TRUE; | |
228 | } | |
229 | return FALSE; | |
230 | } | |
231 | ||
232 | /** | |
17f443df | 233 | * @inheritDoc |
6a488035 | 234 | */ |
e7483cbe | 235 | public function url( |
17f443df CW |
236 | $path = NULL, |
237 | $query = NULL, | |
238 | $absolute = FALSE, | |
239 | $fragment = NULL, | |
17f443df | 240 | $frontend = FALSE, |
8de2a34e SL |
241 | $forceBackend = FALSE, |
242 | $htmlize = TRUE | |
6a488035 | 243 | ) { |
353ffa53 | 244 | $config = CRM_Core_Config::singleton(); |
c80e2dbf | 245 | $separator = '&'; |
353ffa53 TO |
246 | $Itemid = ''; |
247 | $script = ''; | |
248 | $path = CRM_Utils_String::stripPathChars($path); | |
6a488035 TO |
249 | |
250 | if ($config->userFrameworkFrontend) { | |
251 | $script = 'index.php'; | |
92b78d1d AT |
252 | |
253 | // Get Itemid using JInput::get() | |
254 | $input = Joomla\CMS\Factory::getApplication()->input; | |
255 | $itemIdNum = $input->get("Itemid"); | |
256 | if ($itemIdNum && (strpos($path, 'civicrm/payment/ipn') === FALSE)) { | |
257 | $Itemid = "{$separator}Itemid=" . $itemIdNum; | |
6a488035 TO |
258 | } |
259 | } | |
260 | ||
261 | if (isset($fragment)) { | |
262 | $fragment = '#' . $fragment; | |
263 | } | |
264 | ||
6a488035 TO |
265 | $base = $absolute ? $config->userFrameworkBaseURL : $config->useFrameworkRelativeBase; |
266 | ||
267 | if (!empty($query)) { | |
268 | $url = "{$base}{$script}?option=com_civicrm{$separator}task={$path}{$Itemid}{$separator}{$query}{$fragment}"; | |
269 | } | |
270 | else { | |
271 | $url = "{$base}{$script}?option=com_civicrm{$separator}task={$path}{$Itemid}{$fragment}"; | |
272 | } | |
273 | ||
274 | // gross hack for joomla, we are in the backend and want to send a frontend url | |
275 | if ($frontend && $config->userFramework == 'Joomla') { | |
276 | // handle both joomla v1.5 and v1.6, CRM-7939 | |
277 | $url = str_replace('/administrator/index2.php', '/index.php', $url); | |
278 | $url = str_replace('/administrator/index.php', '/index.php', $url); | |
279 | ||
280 | // CRM-8215 | |
281 | $url = str_replace('/administrator/', '/index.php', $url); | |
282 | } | |
283 | elseif ($forceBackend) { | |
284 | if (defined('JVERSION')) { | |
285 | $joomlaVersion = JVERSION; | |
0db6c3e1 TO |
286 | } |
287 | else { | |
e7483cbe | 288 | $jversion = new JVersion(); |
6a488035 TO |
289 | $joomlaVersion = $jversion->getShortVersion(); |
290 | } | |
291 | ||
292 | if (version_compare($joomlaVersion, '1.6') >= 0) { | |
293 | $url = str_replace('/index.php', '/administrator/index.php', $url); | |
294 | } | |
295 | } | |
296 | return $url; | |
297 | } | |
298 | ||
6a488035 | 299 | /** |
fe482240 | 300 | * Set the email address of the user. |
6a488035 | 301 | * |
77855840 TO |
302 | * @param object $user |
303 | * Handle to the user object. | |
6a488035 | 304 | */ |
00be9182 | 305 | public function setEmail(&$user) { |
6a488035 | 306 | global $database; |
94f9f81a EW |
307 | $query = $db->getQuery(TRUE); |
308 | $query->select($db->quoteName('email')) | |
6714d8d2 SL |
309 | ->from($db->quoteName('#__users')) |
310 | ->where($db->quoteName('id') . ' = ' . $user->id); | |
6a488035 TO |
311 | $database->setQuery($query); |
312 | $user->email = $database->loadResult(); | |
313 | } | |
314 | ||
315 | /** | |
17f443df | 316 | * @inheritDoc |
6a488035 | 317 | */ |
17f443df | 318 | public function authenticate($name, $password, $loadCMSBootstrap = FALSE, $realPath = NULL) { |
6a488035 TO |
319 | require_once 'DB.php'; |
320 | ||
321 | $config = CRM_Core_Config::singleton(); | |
ebc28bab | 322 | $user = NULL; |
6a488035 TO |
323 | |
324 | if ($loadCMSBootstrap) { | |
be2fb01f | 325 | $bootStrapParams = []; |
6a488035 | 326 | if ($name && $password) { |
be2fb01f | 327 | $bootStrapParams = [ |
6a488035 TO |
328 | 'name' => $name, |
329 | 'pass' => $password, | |
be2fb01f | 330 | ]; |
6a488035 | 331 | } |
bec3fc7c | 332 | CRM_Utils_System::loadBootStrap($bootStrapParams, TRUE, TRUE, FALSE); |
6a488035 TO |
333 | } |
334 | ||
335 | jimport('joomla.application.component.helper'); | |
336 | jimport('joomla.database.table'); | |
c1f3c6da BS |
337 | jimport('joomla.user.helper'); |
338 | ||
339 | $JUserTable = JTable::getInstance('User', 'JTable'); | |
340 | ||
341 | $db = $JUserTable->getDbo(); | |
342 | $query = $db->getQuery(TRUE); | |
343 | $query->select('id, name, username, email, password'); | |
344 | $query->from($JUserTable->getTableName()); | |
4cb3f512 | 345 | $query->where('(LOWER(username) = LOWER(' . $db->quote($name) . ')) AND (block = 0)'); |
c1f3c6da BS |
346 | $db->setQuery($query, 0, 0); |
347 | $users = $db->loadObjectList(); | |
348 | ||
be2fb01f | 349 | $row = []; |
c1f3c6da BS |
350 | if (count($users)) { |
351 | $row = $users[0]; | |
352 | } | |
6a488035 | 353 | |
e1d37cef MW |
354 | $joomlaBase = self::getBasePath(); |
355 | self::getJVersion($joomlaBase); | |
6a488035 | 356 | |
c1f3c6da BS |
357 | if (!empty($row)) { |
358 | $dbPassword = $row->password; | |
359 | $dbId = $row->id; | |
360 | $dbEmail = $row->email; | |
6a488035 | 361 | |
481a74f4 TO |
362 | if (version_compare(JVERSION, '2.5.18', 'lt') || |
363 | (version_compare(JVERSION, '3.0', 'ge') && version_compare(JVERSION, '3.2.1', 'lt')) | |
c1f3c6da | 364 | ) { |
ebc28bab | 365 | // now check password |
009eff21 EW |
366 | list($hash, $salt) = explode(':', $dbPassword); |
367 | $cryptpass = md5($password . $salt); | |
368 | if ($hash != $cryptpass) { | |
01c77fa9 EW |
369 | return FALSE; |
370 | } | |
6a488035 | 371 | } |
c1f3c6da | 372 | else { |
4f99ca55 TO |
373 | if (!JUserHelper::verifyPassword($password, $dbPassword, $dbId)) { |
374 | return FALSE; | |
e7292422 | 375 | } |
9d735153 | 376 | |
3a8c9bb6 MW |
377 | if (version_compare(JVERSION, '3.8.0', 'ge')) { |
378 | jimport('joomla.application.helper'); | |
379 | jimport('joomla.application.cms'); | |
380 | jimport('joomla.application.administrator'); | |
381 | } | |
9d735153 | 382 | //include additional files required by Joomla 3.2.1+ |
3a8c9bb6 | 383 | elseif (version_compare(JVERSION, '3.2.1', 'ge')) { |
90eac10a BS |
384 | require_once $joomlaBase . '/libraries/cms/application/helper.php'; |
385 | require_once $joomlaBase . '/libraries/cms/application/cms.php'; | |
386 | require_once $joomlaBase . '/libraries/cms/application/administrator.php'; | |
9d735153 | 387 | } |
6a488035 TO |
388 | } |
389 | ||
c1f3c6da | 390 | CRM_Core_BAO_UFMatch::synchronizeUFMatch($row, $dbId, $dbEmail, 'Joomla'); |
6a488035 TO |
391 | $contactID = CRM_Core_BAO_UFMatch::getContactId($dbId); |
392 | if (!$contactID) { | |
393 | return FALSE; | |
394 | } | |
be2fb01f | 395 | return [$contactID, $dbId, mt_rand()]; |
6a488035 | 396 | } |
c1f3c6da | 397 | |
6a488035 TO |
398 | return FALSE; |
399 | } | |
400 | ||
bec3fc7c | 401 | /** |
fe482240 | 402 | * Set a init session with user object. |
bec3fc7c | 403 | * |
77855840 TO |
404 | * @param array $data |
405 | * Array with user specific data. | |
bec3fc7c | 406 | */ |
00be9182 | 407 | public function setUserSession($data) { |
bec3fc7c | 408 | list($userID, $ufID) = $data; |
481a74f4 | 409 | $user = new JUser($ufID); |
2d8f9c75 | 410 | $session = JFactory::getSession(); |
bec3fc7c BS |
411 | $session->set('user', $user); |
412 | ||
cb0e36de | 413 | parent::setUserSession($data); |
bec3fc7c BS |
414 | } |
415 | ||
6a488035 | 416 | /** |
17f443df | 417 | * FIXME: Do something |
ea3ddccf | 418 | * |
419 | * @param string $message | |
6a488035 | 420 | */ |
00be9182 | 421 | public function setMessage($message) { |
6a488035 TO |
422 | } |
423 | ||
bb3a214a | 424 | /** |
b596c3e9 | 425 | * @param \string $username |
426 | * @param \string $password | |
ea3ddccf | 427 | * |
428 | * @return bool | |
bb3a214a | 429 | */ |
b596c3e9 | 430 | public function loadUser($username, $password = NULL) { |
431 | $uid = JUserHelper::getUserId($username); | |
432 | if (empty($uid)) { | |
433 | return FALSE; | |
434 | } | |
435 | $contactID = CRM_Core_BAO_UFMatch::getContactId($uid); | |
436 | if (!empty($password)) { | |
437 | $instance = JFactory::getApplication('site'); | |
be2fb01f | 438 | $params = [ |
b596c3e9 | 439 | 'username' => $username, |
440 | 'password' => $password, | |
be2fb01f | 441 | ]; |
b596c3e9 | 442 | //perform the login action |
443 | $instance->login($params); | |
444 | } | |
445 | ||
8f407be0 AS |
446 | // Save details in Joomla session |
447 | $user = JFactory::getUser($uid); | |
448 | $jsession = JFactory::getSession(); | |
449 | $jsession->set('user', $user); | |
450 | ||
451 | // Save details in Civi session | |
b596c3e9 | 452 | $session = CRM_Core_Session::singleton(); |
453 | $session->set('ufID', $uid); | |
454 | $session->set('userID', $contactID); | |
6a488035 TO |
455 | return TRUE; |
456 | } | |
457 | ||
f22205d7 TO |
458 | public function getUfId($username) { |
459 | jimport('joomla.user.helper'); | |
460 | $uid = JUserHelper::getUserId($username); | |
461 | return empty($uid) ? NULL : $uid; | |
462 | } | |
463 | ||
17f443df CW |
464 | /** |
465 | * FIXME: Use CMS-native approach | |
309310bf | 466 | * @throws \CRM_Core_Exception. |
17f443df | 467 | */ |
00be9182 | 468 | public function permissionDenied() { |
309310bf | 469 | throw new CRM_Core_Exception(ts('You do not have permission to access this page.')); |
6a488035 TO |
470 | } |
471 | ||
17f443df CW |
472 | /** |
473 | * @inheritDoc | |
474 | */ | |
00be9182 | 475 | public function logout() { |
6a488035 | 476 | session_destroy(); |
d42a224c | 477 | CRM_Utils_System::setHttpHeader("Location", "index.php"); |
6a488035 TO |
478 | } |
479 | ||
480 | /** | |
17f443df | 481 | * @inheritDoc |
6a488035 | 482 | */ |
00be9182 | 483 | public function getUFLocale() { |
6a488035 TO |
484 | if (defined('_JEXEC')) { |
485 | $conf = JFactory::getConfig(); | |
4965d8e9 | 486 | $locale = $conf->get('language'); |
6a488035 TO |
487 | return str_replace('-', '_', $locale); |
488 | } | |
489 | return NULL; | |
490 | } | |
491 | ||
fd1f3a26 SV |
492 | /** |
493 | * @inheritDoc | |
494 | */ | |
495 | public function setUFLocale($civicrm_language) { | |
496 | // TODO | |
497 | return TRUE; | |
498 | } | |
499 | ||
bb3a214a | 500 | /** |
17f443df | 501 | * @inheritDoc |
bb3a214a | 502 | */ |
00be9182 | 503 | public function getVersion() { |
6a488035 | 504 | if (class_exists('JVersion')) { |
e7483cbe | 505 | $version = new JVersion(); |
6a488035 TO |
506 | return $version->getShortVersion(); |
507 | } | |
508 | else { | |
509 | return 'Unknown'; | |
510 | } | |
511 | } | |
512 | ||
e1d37cef MW |
513 | public function getJVersion($joomlaBase) { |
514 | // Files may be in different places depending on Joomla version | |
515 | if (!defined('JVERSION')) { | |
516 | // Joomla 3.8.0+ | |
517 | $versionPhp = $joomlaBase . '/libraries/src/Version.php'; | |
518 | if (!file_exists($versionPhp)) { | |
519 | // Joomla < 3.8.0 | |
520 | $versionPhp = $joomlaBase . '/libraries/cms/version/version.php'; | |
521 | } | |
522 | require $versionPhp; | |
523 | $jversion = new JVersion(); | |
524 | define('JVERSION', $jversion->getShortVersion()); | |
525 | } | |
526 | } | |
527 | ||
f3884007 MW |
528 | /** |
529 | * Setup the base path related constant. | |
530 | * @return mixed | |
531 | */ | |
e1d37cef | 532 | public function getBasePath() { |
f3884007 | 533 | global $civicrm_root; |
e23eb52f | 534 | $joomlaPath = explode(DIRECTORY_SEPARATOR . 'administrator', $civicrm_root); |
f3884007 MW |
535 | $joomlaBase = $joomlaPath[0]; |
536 | return $joomlaBase; | |
e1d37cef MW |
537 | } |
538 | ||
f4aaa82a | 539 | /** |
fe482240 | 540 | * Load joomla bootstrap. |
6a488035 | 541 | * |
5a4f6742 CW |
542 | * @param array $params |
543 | * with uid or name and password. | |
544 | * @param bool $loadUser | |
545 | * load cms user?. | |
f4aaa82a EM |
546 | * @param bool|\throw $throwError throw error on failure? |
547 | * @param null $realPath | |
548 | * @param bool $loadDefines | |
549 | * | |
550 | * @return bool | |
6a488035 | 551 | */ |
be2fb01f | 552 | public function loadBootStrap($params = [], $loadUser = TRUE, $throwError = TRUE, $realPath = NULL, $loadDefines = TRUE) { |
e1d37cef | 553 | $joomlaBase = self::getBasePath(); |
6a488035 TO |
554 | |
555 | // load BootStrap here if needed | |
556 | // We are a valid Joomla entry point. | |
53e972a8 | 557 | // dev/core#1384 Use DS to ensure a correct JPATH_BASE in Windows |
353ffa53 | 558 | if (!defined('_JEXEC') && $loadDefines) { |
6a488035 TO |
559 | define('_JEXEC', 1); |
560 | define('DS', DIRECTORY_SEPARATOR); | |
53e972a8 | 561 | define('JPATH_BASE', $joomlaBase . DS . 'administrator'); |
6a488035 TO |
562 | require $joomlaBase . '/administrator/includes/defines.php'; |
563 | } | |
564 | ||
565 | // Get the framework. | |
2cb7adde | 566 | if (file_exists($joomlaBase . '/libraries/import.legacy.php')) { |
2efcf0c2 | 567 | require $joomlaBase . '/libraries/import.legacy.php'; |
2cb7adde | 568 | } |
3a8c9bb6 | 569 | require $joomlaBase . '/libraries/cms.php'; |
e1d37cef | 570 | self::getJVersion($joomlaBase); |
6fde79f5 | 571 | |
8421b502 | 572 | if (version_compare(JVERSION, '3.8', 'lt')) { |
573 | require $joomlaBase . '/libraries/import.php'; | |
574 | require $joomlaBase . '/libraries/joomla/event/dispatcher.php'; | |
575 | } | |
576 | ||
577 | require_once $joomlaBase . '/configuration.php'; | |
578 | ||
481a74f4 | 579 | if (version_compare(JVERSION, '3.0', 'lt')) { |
6fde79f5 BS |
580 | require $joomlaBase . '/libraries/joomla/environment/uri.php'; |
581 | require $joomlaBase . '/libraries/joomla/application/component/helper.php'; | |
582 | } | |
8421b502 | 583 | elseif (version_compare(JVERSION, '3.8', 'lt')) { |
3a8c9bb6 | 584 | jimport('joomla.environment.uri'); |
6fde79f5 BS |
585 | } |
586 | ||
8421b502 | 587 | if (version_compare(JVERSION, '3.8', 'lt')) { |
588 | jimport('joomla.application.cli'); | |
589 | } | |
f4aaa82a | 590 | |
a5291777 TO |
591 | if (!defined('JDEBUG')) { |
592 | define('JDEBUG', FALSE); | |
593 | } | |
26915930 MWMC |
594 | |
595 | // Set timezone for Joomla on Cron | |
596 | $config = JFactory::getConfig(); | |
597 | $timezone = $config->get('offset'); | |
598 | if ($timezone) { | |
599 | date_default_timezone_set($timezone); | |
600 | CRM_Core_Config::singleton()->userSystem->setMySQLTimeZone(); | |
601 | } | |
a5291777 | 602 | |
182f835d | 603 | // CRM-14281 Joomla wasn't available during bootstrap, so hook_civicrm_config never executes. |
604 | $config = CRM_Core_Config::singleton(); | |
605 | CRM_Utils_Hook::config($config); | |
6a488035 TO |
606 | |
607 | return TRUE; | |
608 | } | |
609 | ||
610 | /** | |
17f443df | 611 | * @inheritDoc |
6a488035 TO |
612 | */ |
613 | public function isUserLoggedIn() { | |
614 | $user = JFactory::getUser(); | |
91768280 | 615 | return !$user->guest; |
6a488035 TO |
616 | } |
617 | ||
8caad0ce | 618 | /** |
619 | * @inheritDoc | |
620 | */ | |
621 | public function isUserRegistrationPermitted() { | |
622 | $userParams = JComponentHelper::getParams('com_users'); | |
623 | if (!$userParams->get('allowUserRegistration')) { | |
624 | return FALSE; | |
625 | } | |
626 | return TRUE; | |
627 | } | |
628 | ||
63df6889 HD |
629 | /** |
630 | * @inheritDoc | |
631 | */ | |
1a6630be | 632 | public function isPasswordUserGenerated() { |
63df6889 HD |
633 | return TRUE; |
634 | } | |
635 | ||
6a488035 | 636 | /** |
17f443df | 637 | * @inheritDoc |
6a488035 TO |
638 | */ |
639 | public function getLoggedInUfID() { | |
640 | $user = JFactory::getUser(); | |
641 | return ($user->guest) ? NULL : $user->id; | |
642 | } | |
643 | ||
2b617cb0 | 644 | /** |
17f443df | 645 | * @inheritDoc |
2b617cb0 | 646 | */ |
00be9182 | 647 | public function getLoggedInUniqueIdentifier() { |
2b617cb0 EM |
648 | $user = JFactory::getUser(); |
649 | return $this->getUniqueIdentifierFromUserObject($user); | |
650 | } | |
353ffa53 | 651 | |
cff0c9aa DS |
652 | /** |
653 | * @inheritDoc | |
654 | */ | |
655 | public function getUser($contactID) { | |
656 | $user_details = parent::getUser($contactID); | |
657 | $user = JFactory::getUser($user_details['id']); | |
658 | $user_details['name'] = $user->name; | |
659 | return $user_details; | |
660 | } | |
661 | ||
32998c82 | 662 | /** |
17f443df | 663 | * @inheritDoc |
32998c82 | 664 | */ |
00be9182 | 665 | public function getUserIDFromUserObject($user) { |
32998c82 EM |
666 | return !empty($user->id) ? $user->id : NULL; |
667 | } | |
668 | ||
2b617cb0 | 669 | /** |
17f443df | 670 | * @inheritDoc |
2b617cb0 | 671 | */ |
00be9182 | 672 | public function getUniqueIdentifierFromUserObject($user) { |
2b617cb0 EM |
673 | return ($user->guest) ? NULL : $user->email; |
674 | } | |
675 | ||
29864da4 | 676 | /** |
677 | * @inheritDoc | |
678 | */ | |
679 | public function getTimeZoneString() { | |
680 | $timezone = JFactory::getConfig()->get('offset'); | |
681 | return !$timezone ? date_default_timezone_get() : $timezone; | |
682 | } | |
683 | ||
6a488035 TO |
684 | /** |
685 | * Get a list of all installed modules, including enabled and disabled ones | |
686 | * | |
a6c01b45 CW |
687 | * @return array |
688 | * CRM_Core_Module | |
6a488035 | 689 | */ |
00be9182 | 690 | public function getModules() { |
be2fb01f | 691 | $result = []; |
6a488035 TO |
692 | |
693 | $db = JFactory::getDbo(); | |
e7292422 | 694 | $query = $db->getQuery(TRUE); |
6a488035 TO |
695 | $query->select('type, folder, element, enabled') |
696 | ->from('#__extensions') | |
697 | ->where('type =' . $db->Quote('plugin')); | |
698 | $plugins = $db->setQuery($query)->loadAssocList(); | |
699 | foreach ($plugins as $plugin) { | |
700 | // question: is the folder really a critical part of the plugin's name? | |
be2fb01f | 701 | $name = implode('.', ['joomla', $plugin['type'], $plugin['folder'], $plugin['element']]); |
fe0dbeda | 702 | $result[] = new CRM_Core_Module($name, !empty($plugin['enabled'])); |
6a488035 TO |
703 | } |
704 | ||
705 | return $result; | |
706 | } | |
707 | ||
708 | /** | |
17f443df | 709 | * @inheritDoc |
6a488035 TO |
710 | */ |
711 | public function getLoginURL($destination = '') { | |
712 | $config = CRM_Core_Config::singleton(); | |
713 | $loginURL = $config->userFrameworkBaseURL; | |
714 | $loginURL = str_replace('administrator/', '', $loginURL); | |
715 | $loginURL .= 'index.php?option=com_users&view=login'; | |
091412ab BS |
716 | |
717 | //CRM-14872 append destination | |
481a74f4 | 718 | if (!empty($destination)) { |
92fcb95f | 719 | $loginURL .= '&return=' . urlencode(base64_encode($destination)); |
091412ab | 720 | } |
6a488035 TO |
721 | return $loginURL; |
722 | } | |
f813f78e | 723 | |
bb3a214a | 724 | /** |
17f443df | 725 | * @inheritDoc |
bb3a214a | 726 | */ |
6a488035 | 727 | public function getLoginDestination(&$form) { |
091412ab BS |
728 | $args = NULL; |
729 | ||
730 | $id = $form->get('id'); | |
731 | if ($id) { | |
732 | $args .= "&id=$id"; | |
733 | } | |
734 | else { | |
735 | $gid = $form->get('gid'); | |
736 | if ($gid) { | |
737 | $args .= "&gid=$gid"; | |
738 | } | |
739 | else { | |
740 | // Setup Personal Campaign Page link uses pageId | |
741 | $pageId = $form->get('pageId'); | |
742 | if ($pageId) { | |
743 | $component = $form->get('component'); | |
744 | $args .= "&pageId=$pageId&component=$component&action=add"; | |
745 | } | |
746 | } | |
747 | } | |
748 | ||
749 | $destination = NULL; | |
750 | if ($args) { | |
751 | // append destination so user is returned to form they came from after login | |
92fcb95f | 752 | $args = 'reset=1' . $args; |
48341e06 | 753 | $destination = CRM_Utils_System::url(CRM_Utils_System::currentPath(), $args, TRUE, NULL, FALSE, TRUE); |
091412ab BS |
754 | } |
755 | ||
756 | return $destination; | |
6a488035 | 757 | } |
9977c6f5 | 758 | |
214fbc2c | 759 | /** |
760 | * Determine the location of the CMS root. | |
761 | * | |
762 | * @return string|NULL | |
763 | * local file system path to CMS root, or NULL if it cannot be determined | |
764 | */ | |
765 | public function cmsRootPath() { | |
a93a0366 TO |
766 | global $civicrm_paths; |
767 | if (!empty($civicrm_paths['cms.root']['path'])) { | |
768 | return $civicrm_paths['cms.root']['path']; | |
769 | } | |
770 | ||
214fbc2c | 771 | list($url, $siteName, $siteRoot) = $this->getDefaultSiteSettings(); |
e1d37cef | 772 | if (file_exists("$siteRoot/administrator/index.php")) { |
214fbc2c | 773 | return $siteRoot; |
774 | } | |
775 | return NULL; | |
776 | } | |
777 | ||
9977c6f5 | 778 | /** |
17f443df | 779 | * @inheritDoc |
9977c6f5 | 780 | */ |
70e8beda | 781 | public function getDefaultSiteSettings($dir = NULL) { |
9977c6f5 | 782 | $config = CRM_Core_Config::singleton(); |
783 | $url = preg_replace( | |
784 | '|/administrator|', | |
785 | '', | |
786 | $config->userFrameworkBaseURL | |
787 | ); | |
ad2d96ba | 788 | // CRM-19453 revisited. Under Windows, the pattern wasn't recognised. |
789 | // This is the original pattern, but it doesn't work under Windows. | |
790 | // By setting the pattern to the one used before the change first and only | |
791 | // changing it means that the change code only affects Windows users. | |
792 | $pattern = '|/media/civicrm/.*$|'; | |
793 | if (DIRECTORY_SEPARATOR == '\\') { | |
794 | // This regular expression will handle Windows as well as Linux | |
795 | // and any combination of forward and back slashes in directory | |
796 | // separators. We only apply it if the directory separator is the one | |
797 | // used by Windows. | |
798 | $pattern = '|[\\\\/]media[\\\\/]civicrm[\\\\/].*$|'; | |
799 | } | |
9977c6f5 | 800 | $siteRoot = preg_replace( |
ad2d96ba | 801 | $pattern, |
9977c6f5 | 802 | '', |
803 | $config->imageUploadDir | |
804 | ); | |
be2fb01f | 805 | return [$url, NULL, $siteRoot]; |
9977c6f5 | 806 | } |
59f97da6 EM |
807 | |
808 | /** | |
17f443df | 809 | * @inheritDoc |
59f97da6 | 810 | */ |
00be9182 | 811 | public function getUserRecordUrl($contactID) { |
59f97da6 EM |
812 | $uid = CRM_Core_BAO_UFMatch::getUFId($contactID); |
813 | $userRecordUrl = NULL; | |
55904b50 | 814 | // if logged in user has user edit access, then allow link to other users joomla profile |
a8e5af2a | 815 | if (JFactory::getUser()->authorise('core.edit', 'com_users')) { |
59f97da6 EM |
816 | return CRM_Core_Config::singleton()->userFrameworkBaseURL . "index.php?option=com_users&view=user&task=user.edit&id=" . $uid; |
817 | } | |
818 | elseif (CRM_Core_Session::singleton()->get('userID') == $contactID) { | |
819 | return CRM_Core_Config::singleton()->userFrameworkBaseURL . "index.php?option=com_admin&view=profile&layout=edit&id=" . $uid; | |
820 | } | |
821 | } | |
822 | ||
823 | /** | |
17f443df | 824 | * @inheritDoc |
59f97da6 | 825 | */ |
00be9182 | 826 | public function checkPermissionAddUser() { |
59f97da6 EM |
827 | if (JFactory::getUser()->authorise('core.create', 'com_users')) { |
828 | return TRUE; | |
829 | } | |
830 | } | |
f85b1d20 | 831 | |
03d5592a CW |
832 | /** |
833 | * @inheritDoc | |
834 | */ | |
835 | public function synchronizeUsers() { | |
836 | $config = CRM_Core_Config::singleton(); | |
837 | if (PHP_SAPI != 'cli') { | |
838 | set_time_limit(300); | |
839 | } | |
840 | $id = 'id'; | |
841 | $mail = 'email'; | |
842 | $name = 'name'; | |
843 | ||
d5acf0e0 | 844 | $JUserTable = JTable::getInstance('User', 'JTable'); |
03d5592a CW |
845 | |
846 | $db = $JUserTable->getDbo(); | |
847 | $query = $db->getQuery(TRUE); | |
848 | $query->select($id . ', ' . $mail . ', ' . $name); | |
849 | $query->from($JUserTable->getTableName()); | |
850 | $query->where($mail != ''); | |
851 | ||
852 | $db->setQuery($query); | |
853 | $users = $db->loadObjectList(); | |
854 | ||
855 | $user = new StdClass(); | |
856 | $uf = $config->userFramework; | |
857 | $contactCount = 0; | |
858 | $contactCreated = 0; | |
859 | $contactMatching = 0; | |
860 | for ($i = 0; $i < count($users); $i++) { | |
861 | $user->$id = $users[$i]->$id; | |
862 | $user->$mail = $users[$i]->$mail; | |
863 | $user->$name = $users[$i]->$name; | |
864 | $contactCount++; | |
865 | if ($match = CRM_Core_BAO_UFMatch::synchronizeUFMatch($user, | |
866 | $users[$i]->$id, | |
867 | $users[$i]->$mail, | |
868 | $uf, | |
869 | 1, | |
870 | 'Individual', | |
871 | TRUE | |
872 | ) | |
873 | ) { | |
874 | $contactCreated++; | |
875 | } | |
876 | else { | |
877 | $contactMatching++; | |
878 | } | |
03d5592a CW |
879 | } |
880 | ||
be2fb01f | 881 | return [ |
03d5592a CW |
882 | 'contactCount' => $contactCount, |
883 | 'contactMatching' => $contactMatching, | |
884 | 'contactCreated' => $contactCreated, | |
be2fb01f | 885 | ]; |
03d5592a CW |
886 | } |
887 | ||
38dab72a | 888 | /** |
889 | * Determine the location of the CiviCRM source tree. | |
890 | * | |
891 | * FIXME: | |
892 | * 1. This was pulled out from a bigger function. It should be split | |
893 | * into even smaller pieces and marked abstract. | |
894 | * 2. This would be easier to compute by a calling a CMS API, but | |
895 | * for whatever reason we take the hard way. | |
896 | * | |
897 | * @return array | |
898 | * - url: string. ex: "http://example.com/sites/all/modules/civicrm" | |
899 | * - path: string. ex: "/var/www/sites/all/modules/civicrm" | |
900 | */ | |
901 | public function getCiviSourceStorage() { | |
902 | global $civicrm_root; | |
903 | if (!defined('CIVICRM_UF_BASEURL')) { | |
904 | throw new RuntimeException('Undefined constant: CIVICRM_UF_BASEURL'); | |
905 | } | |
906 | $baseURL = CRM_Utils_File::addTrailingSlash(CIVICRM_UF_BASEURL, '/'); | |
907 | if (CRM_Utils_System::isSSL()) { | |
908 | $baseURL = str_replace('http://', 'https://', $baseURL); | |
909 | } | |
910 | ||
911 | // For Joomla CiviCRM Core files always live within the admistrator folder and $base_url is different on the frontend compared to the backend. | |
912 | if (strpos($baseURL, 'administrator') === FALSE) { | |
913 | $userFrameworkResourceURL = $baseURL . "administrator/components/com_civicrm/civicrm/"; | |
914 | } | |
915 | else { | |
916 | $userFrameworkResourceURL = $baseURL . "components/com_civicrm/civicrm/"; | |
917 | } | |
918 | ||
919 | return [ | |
920 | 'url' => CRM_Utils_File::addTrailingSlash($userFrameworkResourceURL, '/'), | |
921 | 'path' => CRM_Utils_File::addTrailingSlash($civicrm_root), | |
922 | ]; | |
923 | } | |
924 | ||
839834b4 | 925 | /** |
926 | * Return the CMS-specific url for its permissions page | |
927 | * @return array | |
928 | */ | |
929 | public function getCMSPermissionsUrlParams() { | |
930 | $ufAccessURL = ''; | |
931 | $jAccessParams = ''; | |
932 | $config = CRM_Core_Config::singleton(); | |
933 | //condition based on Joomla version; <= 2.5 uses modal window; >= 3.0 uses full page with return value | |
934 | if (version_compare(JVERSION, '3.0', 'lt')) { | |
935 | JHTML::_('behavior.modal'); | |
936 | $ufAccessURL = $config->userFrameworkBaseURL . 'index.php?option=com_config&view=component&component=com_civicrm&tmpl=component'; | |
937 | $jAccessParams = 'rel="{handler: \'iframe\', size: {x: 875, y: 550}, onClose: function() {}}" class="modal"'; | |
938 | } | |
939 | else { | |
940 | $uri = (string) JUri::getInstance(); | |
941 | $return = urlencode(base64_encode($uri)); | |
942 | $ufAccessURL = $config->userFrameworkBaseURL . 'index.php?option=com_config&view=component&component=com_civicrm&return=' . $return; | |
943 | } | |
944 | return [ | |
945 | 'ufAccessURL' => $ufAccessURL, | |
946 | 'jAccessParams' => $jAccessParams, | |
947 | ]; | |
948 | } | |
949 | ||
6a488035 | 950 | } |