3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2014
37 * Joomla specific stuff goes here
39 class CRM_Utils_System_Joomla
extends CRM_Utils_System_Base
{
42 public function __construct() {
44 * 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
45 * functions and leave the codebase oblivious to the type of CMS
49 $this->is_drupal
= FALSE;
53 * Create a user of Joomla.
55 * @param array $params
57 * Email id for cms user.
60 * uid if user exists, false otherwise
62 public function createUser(&$params, $mail) {
63 $baseDir = JPATH_SITE
;
64 require_once $baseDir . '/components/com_users/models/registration.php';
66 $userParams = JComponentHelper
::getParams('com_users');
67 $model = new UsersModelRegistration();
70 // get the default usertype
71 $userType = $userParams->get('new_usertype');
76 if (isset($params['name'])) {
77 $fullname = trim($params['name']);
79 elseif (isset($params['contactID'])) {
80 $fullname = trim(CRM_Contact_BAO_Contact
::displayName($params['contactID']));
83 $fullname = trim($params['cms_name']);
86 // Prepare the values for a new Joomla user.
88 $values['name'] = $fullname;
89 $values['username'] = trim($params['cms_name']);
90 $values['password1'] = $values['password2'] = $params['cms_pass'];
91 $values['email1'] = $values['email2'] = trim($params[$mail]);
93 $lang = JFactory
::getLanguage();
94 $lang->load('com_users', $baseDir);
96 $register = $model->register($values);
98 $ufID = JUserHelper
::getUserId($values['username']);
103 * Change user name in host CMS
106 * @param string $ufName User name
108 public function updateCMSName($ufID, $ufName) {
109 $ufID = CRM_Utils_Type
::escape($ufID, 'Integer');
110 $ufName = CRM_Utils_Type
::escape($ufName, 'String');
113 $user = JUser
::getInstance($ufID);
115 $values['email'] = $ufName;
116 $user->bind($values);
122 * Check if username and email exists in the drupal db
124 * @param array $params
125 * Array of name and mail values.
126 * @param array $errors
128 * @param string $emailName
129 * Field label for the 'email'.
133 public function checkUserNameEmailExists(&$params, &$errors, $emailName = 'email') {
134 $config = CRM_Core_Config
::singleton();
136 $dao = new CRM_Core_DAO();
137 $name = $dao->escape(CRM_Utils_Array
::value('name', $params));
138 $email = $dao->escape(CRM_Utils_Array
::value('mail', $params));
139 //don't allow the special characters and min. username length is two
140 //regex \\ to match a single backslash would become '/\\\\/'
141 $isNotValid = (bool) preg_match('/[\<|\>|\"|\'|\%|\;|\(|\)|\&|\\\\|\/]/im', $name);
142 if ($isNotValid ||
strlen($name) < 2) {
143 $errors['cms_name'] = ts('Your username contains invalid characters or is too short');
146 $JUserTable = &JTable
::getInstance('User', 'JTable');
148 $db = $JUserTable->getDbo();
149 $query = $db->getQuery(TRUE);
150 $query->select('username, email');
151 $query->from($JUserTable->getTableName());
152 $query->where('(LOWER(username) = LOWER(\'' . $name . '\')) OR (LOWER(email) = LOWER(\'' . $email . '\'))');
153 $db->setQuery($query, 0, 10);
154 $users = $db->loadAssocList();
162 $dbName = CRM_Utils_Array
::value('username', $row);
163 $dbEmail = CRM_Utils_Array
::value('email', $row);
164 if (strtolower($dbName) == strtolower($name)) {
165 $errors['cms_name'] = ts('The username %1 is already taken. Please select another username.',
169 if (strtolower($dbEmail) == strtolower($email)) {
170 $resetUrl = str_replace('administrator/', '', $config->userFrameworkBaseURL
) . 'index.php?option=com_users&view=reset';
171 $errors[$emailName] = ts('The email address %1 is already registered. <a href="%2">Have you forgotten your password?</a>',
172 array(1 => $email, 2 => $resetUrl)
179 * Sets the title of the page
181 * @param string $title
183 * @param string $pageTitle
187 public function setTitle($title, $pageTitle = NULL) {
192 $template = CRM_Core_Smarty
::singleton();
193 $template->assign('pageTitle', $pageTitle);
195 $document = JFactory
::getDocument();
196 $document->setTitle($title);
202 * Append an additional breadcrumb tag to the existing breadcrumb
204 * @param $breadCrumbs
206 * @internal param string $title
207 * @internal param string $url
211 public function appendBreadCrumb($breadCrumbs) {
212 $template = CRM_Core_Smarty
::singleton();
213 $bc = $template->get_template_vars('breadcrumb');
215 if (is_array($breadCrumbs)) {
216 foreach ($breadCrumbs as $crumbs) {
217 if (stripos($crumbs['url'], 'id%%')) {
218 $args = array('cid', 'mid');
219 foreach ($args as $a) {
220 $val = CRM_Utils_Request
::retrieve($a, 'Positive', CRM_Core_DAO
::$_nullObject,
224 $crumbs['url'] = str_ireplace("%%{$a}%%", $val, $crumbs['url']);
231 $template->assign_by_ref('breadcrumb', $bc);
236 * Reset an additional breadcrumb tag to the existing breadcrumb
238 * @internal param string $bc the new breadcrumb to be appended
242 public function resetBreadCrumb() {
247 * Append a string to the head of the html file
249 * @param null $string
251 * @internal param string $head the new string to be appended
255 public static function addHTMLHead($string = NULL) {
257 $document = JFactory
::getDocument();
258 $document->addCustomTag($string);
265 * @param $url : string, absolute path to file
266 * @param string $region
267 * location within the document: 'html-header', 'page-header', 'page-footer'.
269 * Note: This function is not to be called directly
270 * @see CRM_Core_Region::render()
273 * TRUE if we support this operation in this CMS, FALSE otherwise
275 public function addScriptUrl($url, $region) {
280 * Add an inline script
282 * @param $code : string, javascript code
283 * @param string $region
284 * location within the document: 'html-header', 'page-header', 'page-footer'.
286 * Note: This function is not to be called directly
287 * @see CRM_Core_Region::render()
290 * TRUE if we support this operation in this CMS, FALSE otherwise
292 public function addScript($code, $region) {
299 * @param $url : string, absolute path to file
300 * @param string $region
301 * location within the document: 'html-header', 'page-header', 'page-footer'.
303 * Note: This function is not to be called directly
304 * @see CRM_Core_Region::render()
307 * TRUE if we support this operation in this CMS, FALSE otherwise
309 public function addStyleUrl($url, $region) {
310 if ($region == 'html-header') {
311 $document = JFactory
::getDocument();
312 $document->addStyleSheet($url);
319 * Add an inline style
321 * @param $code : string, css code
322 * @param string $region
323 * location within the document: 'html-header', 'page-header', 'page-footer'.
325 * Note: This function is not to be called directly
326 * @see CRM_Core_Region::render()
329 * TRUE if we support this operation in this CMS, FALSE otherwise
331 public function addStyle($code, $region) {
332 if ($region == 'html-header') {
333 $document = JFactory
::getDocument();
334 $document->addStyleDeclaration($code);
341 * Generate an internal CiviCRM URL
343 * @param string $path
344 * The path being linked to, such as "civicrm/add".
345 * @param string $query
346 * A query string to append to the link.
347 * @param bool $absolute
348 * Whether to force the output to be an absolute link (beginning with http:).
349 * Useful for links that will be displayed outside the site, such as in an
351 * @param string $fragment
352 * A fragment identifier (named anchor) to append to the link.
353 * @param bool $htmlize
354 * whether to convert to html eqivalant.
355 * @param bool $frontend
356 * a gross joomla hack.
358 * @param bool $forceBackend
361 * an HTML string containing a link to the given path.
364 $path = NULL, $query = NULL, $absolute = TRUE,
365 $fragment = NULL, $htmlize = TRUE,
366 $frontend = FALSE, $forceBackend = FALSE
368 $config = CRM_Core_Config
::singleton();
369 $separator = $htmlize ?
'&' : '&';
372 $path = CRM_Utils_String
::stripPathChars($path);
374 if ($config->userFrameworkFrontend
) {
375 $script = 'index.php';
376 if (JRequest
::getVar("Itemid")) {
377 $Itemid = "{$separator}Itemid=" . JRequest
::getVar("Itemid");
381 if (isset($fragment)) {
382 $fragment = '#' . $fragment;
385 if (!isset($config->useFrameworkRelativeBase
)) {
386 $base = parse_url($config->userFrameworkBaseURL
);
387 $config->useFrameworkRelativeBase
= $base['path'];
389 $base = $absolute ?
$config->userFrameworkBaseURL
: $config->useFrameworkRelativeBase
;
391 if (!empty($query)) {
392 $url = "{$base}{$script}?option=com_civicrm{$separator}task={$path}{$Itemid}{$separator}{$query}{$fragment}";
395 $url = "{$base}{$script}?option=com_civicrm{$separator}task={$path}{$Itemid}{$fragment}";
398 // gross hack for joomla, we are in the backend and want to send a frontend url
399 if ($frontend && $config->userFramework
== 'Joomla') {
400 // handle both joomla v1.5 and v1.6, CRM-7939
401 $url = str_replace('/administrator/index2.php', '/index.php', $url);
402 $url = str_replace('/administrator/index.php', '/index.php', $url);
405 $url = str_replace('/administrator/', '/index.php', $url);
407 elseif ($forceBackend) {
408 if (defined('JVERSION')) {
409 $joomlaVersion = JVERSION
;
412 $jversion = new JVersion
;
413 $joomlaVersion = $jversion->getShortVersion();
416 if (version_compare($joomlaVersion, '1.6') >= 0) {
417 $url = str_replace('/index.php', '/administrator/index.php', $url);
424 * Rewrite various system urls to https
429 public function mapConfigToSSL() {
430 // dont need to do anything, let CMS handle their own switch to SSL
435 * Figure out the post url for the form
438 * The default action if one is pre-specified.
441 * the url to post the form
443 public function postURL($action) {
444 if (!empty($action)) {
448 return $this->url(CRM_Utils_Array
::value('task', $_GET),
449 NULL, TRUE, NULL, FALSE
454 * Set the email address of the user
456 * @param object $user
457 * Handle to the user object.
461 public function setEmail(&$user) {
463 $query = "SELECT email FROM #__users WHERE id='$user->id'";
464 $database->setQuery($query);
465 $user->email
= $database->loadResult();
469 * Authenticate the user against the joomla db
471 * @param string $name
473 * @param string $password
474 * The password for the above user name.
475 * @param bool $loadCMSBootstrap
476 * load cms bootstrap?.
479 * [contactID, ufID, uniqueString] if success else false if no auth
481 public function authenticate($name, $password, $loadCMSBootstrap = FALSE) {
482 require_once 'DB.php';
484 $config = CRM_Core_Config
::singleton();
487 if ($loadCMSBootstrap) {
488 $bootStrapParams = array();
489 if ($name && $password) {
490 $bootStrapParams = array(
495 CRM_Utils_System
::loadBootStrap($bootStrapParams, TRUE, TRUE, FALSE);
498 jimport('joomla.application.component.helper');
499 jimport('joomla.database.table');
500 jimport('joomla.user.helper');
502 $JUserTable = JTable
::getInstance('User', 'JTable');
504 $db = $JUserTable->getDbo();
505 $query = $db->getQuery(TRUE);
506 $query->select('id, name, username, email, password');
507 $query->from($JUserTable->getTableName());
508 $query->where('(LOWER(username) = LOWER(\'' . $name . '\')) AND (block = 0)');
509 $db->setQuery($query, 0, 0);
510 $users = $db->loadObjectList();
517 $joomlaBase = dirname(dirname(dirname(dirname(dirname(dirname(dirname(dirname(__FILE__
))))))));
518 if (!defined('JVERSION')) {
519 require $joomlaBase . '/libraries/cms/version/version.php';
520 $jversion = new JVersion
;
521 define('JVERSION', $jversion->getShortVersion());
525 $dbPassword = $row->password
;
527 $dbEmail = $row->email
;
529 if (version_compare(JVERSION
, '2.5.18', 'lt') ||
530 (version_compare(JVERSION
, '3.0', 'ge') && version_compare(JVERSION
, '3.2.1', 'lt'))
532 // now check password
533 if (strpos($dbPassword, ':') === FALSE) {
534 if ($dbPassword != md5($password)) {
539 list($hash, $salt) = explode(':', $dbPassword);
540 $cryptpass = md5($password . $salt);
541 if ($hash != $cryptpass) {
547 if (!JUserHelper
::verifyPassword($password, $dbPassword, $dbId)) {
551 //include additional files required by Joomla 3.2.1+
552 if (version_compare(JVERSION
, '3.2.1', 'ge')) {
553 require_once $joomlaBase . '/libraries/cms/application/helper.php';
554 require_once $joomlaBase . '/libraries/cms/application/cms.php';
555 require_once $joomlaBase . '/libraries/cms/application/administrator.php';
559 CRM_Core_BAO_UFMatch
::synchronizeUFMatch($row, $dbId, $dbEmail, 'Joomla');
560 $contactID = CRM_Core_BAO_UFMatch
::getContactId($dbId);
564 return array($contactID, $dbId, mt_rand());
571 * Set a init session with user object
574 * Array with user specific data.
576 public function setUserSession($data) {
577 list($userID, $ufID) = $data;
578 $user = new JUser($ufID);
579 $session = JFactory
::getSession();
580 $session->set('user', $user);
582 parent
::setUserSession($data);
586 * Set a message in the UF to display to a user
588 * @param string $message
589 * The message to set.
591 public function setMessage($message) {
600 public function loadUser($user) {
604 public function permissionDenied() {
605 CRM_Core_Error
::fatal(ts('You do not have permission to access this page.'));
608 public function logout() {
610 header("Location:index.php");
614 * Get the locale set in the hosting CMS
617 * the used locale or null for none
619 public function getUFLocale() {
620 if (defined('_JEXEC')) {
621 $conf = JFactory
::getConfig();
622 $locale = $conf->get('language');
623 return str_replace('-', '_', $locale);
631 public function getVersion() {
632 if (class_exists('JVersion')) {
633 $version = new JVersion
;
634 return $version->getShortVersion();
642 * Load joomla bootstrap
644 * @param array $params
645 * with uid or name and password.
646 * @param bool $loadUser
648 * @param bool|\throw $throwError throw error on failure?
649 * @param null $realPath
650 * @param bool $loadDefines
654 public function loadBootStrap($params = array(), $loadUser = TRUE, $throwError = TRUE, $realPath = NULL, $loadDefines = TRUE) {
655 // Setup the base path related constant.
656 $joomlaBase = dirname(dirname(dirname(dirname(dirname(dirname(dirname(dirname(__FILE__
))))))));
658 // load BootStrap here if needed
659 // We are a valid Joomla entry point.
660 if (!defined('_JEXEC') && $loadDefines) {
662 define('DS', DIRECTORY_SEPARATOR
);
663 define('JPATH_BASE', $joomlaBase . '/administrator');
664 require $joomlaBase . '/administrator/includes/defines.php';
667 // Get the framework.
668 if (file_exists($joomlaBase . '/libraries/import.legacy.php')) {
669 require $joomlaBase . '/libraries/import.legacy.php';
671 require $joomlaBase . '/libraries/import.php';
672 require $joomlaBase . '/libraries/joomla/event/dispatcher.php';
673 require $joomlaBase . '/configuration.php';
675 // Files may be in different places depending on Joomla version
676 if (!defined('JVERSION')) {
677 require $joomlaBase . '/libraries/cms/version/version.php';
678 $jversion = new JVersion
;
679 define('JVERSION', $jversion->getShortVersion());
682 if (version_compare(JVERSION
, '3.0', 'lt')) {
683 require $joomlaBase . '/libraries/joomla/environment/uri.php';
684 require $joomlaBase . '/libraries/joomla/application/component/helper.php';
687 require $joomlaBase . '/libraries/cms.php';
688 require $joomlaBase . '/libraries/joomla/uri/uri.php';
691 jimport('joomla.application.cli');
693 // CRM-14281 Joomla wasn't available during bootstrap, so hook_civicrm_config never executes.
694 $config = CRM_Core_Config
::singleton();
695 CRM_Utils_Hook
::config($config);
701 * Check is user logged in.
705 public function isUserLoggedIn() {
706 $user = JFactory
::getUser();
707 return ($user->guest
) ?
FALSE : TRUE;
711 * Get currently logged in user uf id.
714 * logged in user uf id.
716 public function getLoggedInUfID() {
717 $user = JFactory
::getUser();
718 return ($user->guest
) ?
NULL : $user->id
;
722 * Get currently logged in user unique identifier - this tends to be the email address or user name.
725 * logged in user unique identifier
727 public function getLoggedInUniqueIdentifier() {
728 $user = JFactory
::getUser();
729 return $this->getUniqueIdentifierFromUserObject($user);
733 * Get User ID from UserFramework system (Joomla)
734 * @param object $user
735 * Object as described by the CMS.
739 public function getUserIDFromUserObject($user) {
740 return !empty($user->id
) ?
$user->id
: NULL;
744 * Get Unique Identifier from UserFramework system (CMS)
745 * @param object $user
746 * Object as described by the User Framework.
748 * $uniqueIdentifer Unique identifier from the user Framework system
750 public function getUniqueIdentifierFromUserObject($user) {
751 return ($user->guest
) ?
NULL : $user->email
;
755 * Get a list of all installed modules, including enabled and disabled ones
760 public function getModules() {
763 $db = JFactory
::getDbo();
764 $query = $db->getQuery(TRUE);
765 $query->select('type, folder, element, enabled')
766 ->from('#__extensions')
767 ->where('type =' . $db->Quote('plugin'));
768 $plugins = $db->setQuery($query)->loadAssocList();
769 foreach ($plugins as $plugin) {
770 // question: is the folder really a critical part of the plugin's name?
771 $name = implode('.', array('joomla', $plugin['type'], $plugin['folder'], $plugin['element']));
772 $result[] = new CRM_Core_Module($name, $plugin['enabled'] ?
TRUE : FALSE);
779 * Get user login URL for hosting CMS (method declared in each CMS system class)
781 * @param string $destination
782 * If present, add destination to querystring (works for Drupal only).
785 * loginURL for the current CMS
788 public function getLoginURL($destination = '') {
789 $config = CRM_Core_Config
::singleton();
790 $loginURL = $config->userFrameworkBaseURL
;
791 $loginURL = str_replace('administrator/', '', $loginURL);
792 $loginURL .= 'index.php?option=com_users&view=login';
794 //CRM-14872 append destination
795 if (!empty($destination)) {
796 $loginURL .= '&return=' . urlencode(base64_encode($destination));
802 * @param CRM_Core_Form $form
804 public function getLoginDestination(&$form) {
807 $id = $form->get('id');
812 $gid = $form->get('gid');
814 $args .= "&gid=$gid";
817 // Setup Personal Campaign Page link uses pageId
818 $pageId = $form->get('pageId');
820 $component = $form->get('component');
821 $args .= "&pageId=$pageId&component=$component&action=add";
828 // append destination so user is returned to form they came from after login
829 $args = 'reset=1' . $args;
830 $destination = CRM_Utils_System
::url(CRM_Utils_System
::currentPath(), $args, TRUE, NULL, TRUE, TRUE);
837 * Return default Site Settings
843 * - $url, (Joomla - non admin url)
847 public function getDefaultSiteSettings($dir) {
848 $config = CRM_Core_Config
::singleton();
852 $config->userFrameworkBaseURL
854 $siteRoot = preg_replace(
855 '|/media/civicrm/.*$|',
857 $config->imageUploadDir
859 return array($url, NULL, $siteRoot);
863 * Get Url to view user record
864 * @param int $contactID
869 public function getUserRecordUrl($contactID) {
870 $uid = CRM_Core_BAO_UFMatch
::getUFId($contactID);
871 $userRecordUrl = NULL;
872 // if logged in user is super user, then he can view other users joomla profile
873 if (JFactory
::getUser()->authorise('core.admin')) {
874 return CRM_Core_Config
::singleton()->userFrameworkBaseURL
. "index.php?option=com_users&view=user&task=user.edit&id=" . $uid;
876 elseif (CRM_Core_Session
::singleton()->get('userID') == $contactID) {
877 return CRM_Core_Config
::singleton()->userFrameworkBaseURL
. "index.php?option=com_admin&view=profile&layout=edit&id=" . $uid;
882 * Is the current user permitted to add a user
885 public function checkPermissionAddUser() {
886 if (JFactory
::getUser()->authorise('core.create', 'com_users')) {
892 * Output code from error function
893 * @param string $content
895 public function outputError($content) {
896 if (class_exists('JErrorPage')) {
897 $error = new Exception($content);
898 JErrorPage
::render($error);
900 elseif (class_exists('JError')) {
901 JError
::raiseError('CiviCRM-001', $content);
904 parent
::outputError($content);
909 * Append to coreResourcesList
911 public function appendCoreResources(&$list) {
912 $list[] = 'js/crm.joomla.js';