/** * Set variables up before form is built. * * @return void */ public function preProcess() { $this->_addProfileBottom = CRM_Utils_Array::value('addProfileBottom', $_GET, FALSE); $this->_profileBottomNum = CRM_Utils_Array::value('addProfileNum', $_GET, 0); $this->_addProfileBottomAdd = CRM_Utils_Array::value('addProfileBottomAdd', $_GET, FALSE); $this->_profileBottomNumAdd = CRM_Utils_Array::value('addProfileNumAdd', $_GET, 0); parent::preProcess(); $this->assign('addProfileBottom', $this->_addProfileBottom); $this->assign('profileBottomNum', $this->_profileBottomNum); $urlParams = "id={$this->_id}&addProfileBottom=1&qfKey={$this->controller->_key}"; $this->assign('addProfileParams', $urlParams); if ($addProfileBottom = CRM_Utils_Array::value('custom_post_id_multiple', $_POST)) { foreach (array_keys($addProfileBottom) as $profileNum) { self::buildMultipleProfileBottom($this, $profileNum); } } $this->assign('perm', 0); $ufGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id'); $ufCreate = CRM_ACL_API::group(CRM_Core_Permission::CREATE, NULL, 'civicrm_uf_group', $ufGroups); $ufEdit = CRM_ACL_API::group(CRM_Core_Permission::EDIT, NULL, 'civicrm_uf_group', $ufGroups); $checkPermission = array(array('administer CiviCRM', 'manage event profiles')); if (CRM_Core_Permission::check($checkPermission) || !empty($ufCreate) || !empty($ufEdit)) { $this->assign('perm', 1); } $this->assign('addProfileBottomAdd', $this->_addProfileBottomAdd); $this->assign('profileBottomNumAdd', $this->_profileBottomNumAdd); $urlParamsAdd = "id={$this->_id}&addProfileBottomAdd=1&qfKey={$this->controller->_key}"; $this->assign('addProfileParamsAdd', $urlParamsAdd); if ($addProfileBottomAdd = CRM_Utils_Array::value('additional_custom_post_id_multiple', $_POST)) { foreach (array_keys($addProfileBottomAdd) as $profileNum) { self::buildMultipleProfileBottom($this, $profileNum, 'additional_', ts('Profile for Additional Participants')); } } }
/** * fill the acl contact cache for this contact id if empty * * @param int $id contact id * @param string $type the type of operation (view|edit) * @param boolean $force should we force a recompute * * @return void * @access public * @static */ static function cache($userID, $type = CRM_Core_Permission::VIEW, $force = false) { static $_processed = array(); if ($type = CRM_Core_Permission::VIEW) { $operationClause = " operation IN ( 'Edit', 'View' ) "; $operation = 'View'; } else { $operationClause = " operation = 'Edit' "; $operation = 'Edit'; } if (!$force) { if (CRM_Utils_Array::value($userID, $_processed)) { return; } // run a query to see if the cache is filled $sql = "\nSELECT count(id)\nFROM civicrm_acl_contact_cache\nWHERE user_id = %1\nAND {$operationClause}\n"; $params = array(1 => array($userID, 'Integer')); $count = CRM_Core_DAO::singleValueQuery($sql, $params); if ($count > 0) { $_processed[$userID] = 1; return; } } $tables = array(); $whereTables = array(); require_once 'CRM/ACL/API.php'; $permission = CRM_ACL_API::whereClause($type, $tables, $whereTables, $userID); require_once "CRM/Contact/BAO/Query.php"; $from = CRM_Contact_BAO_Query::fromClause($whereTables); $query = "\nSELECT DISTINCT(contact_a.id) as id\n {$from}\nWHERE {$permission}\n"; $values = array(); $dao = CRM_Core_DAO::executeQuery($query); while ($dao->fetch()) { $values[] = "( {$userID}, {$dao->id}, '{$operation}' )"; } // now store this in the table while (!empty($values)) { $processed = true; $input = array_splice($values, 0, self::NUM_CONTACTS_TO_INSERT); $str = implode(',', $input); $sql = "REPLACE INTO civicrm_acl_contact_cache ( user_id, contact_id, operation ) VALUES {$str};"; CRM_Core_DAO::executeQuery($sql); } CRM_Core_DAO::executeQuery('DELETE FROM civicrm_acl_contact_cache WHERE contact_id IN (SELECT id FROM civicrm_contact WHERE is_deleted = 1)'); $_processed[$userID] = 1; return; }
public static function event($type = CRM_Core_Permission::VIEW, $eventID = NULL) { $events = CRM_Event_PseudoConstant::event(NULL, TRUE); $includeEvents = array(); // check if user has all powerful permission if (self::check('register for events')) { $includeEvents = array_keys($events); } if ($type == CRM_Core_Permission::VIEW && self::check('view event info')) { $includeEvents = array_keys($events); } $permissionedEvents = CRM_ACL_API::group($type, NULL, 'civicrm_event', $events, $includeEvents); if (!$eventID) { return $permissionedEvents; } return array_search($eventID, $permissionedEvents) === FALSE ? NULL : $eventID; }
/** * Get all groups from database, filtered by permissions * for this user * * @param string $groupType * Type of group(Access/Mailing). * @param bool $excludeHidden * Exclude hidden groups. * * * @return array * array reference of all groups. */ public function group($groupType = NULL, $excludeHidden = TRUE) { if (!isset($this->_viewPermissionedGroups)) { $this->_viewPermissionedGroups = $this->_editPermissionedGroups = array(); } $groupKey = $groupType ? $groupType : 'all'; if (!isset($this->_viewPermissionedGroups[$groupKey])) { $this->_viewPermissionedGroups[$groupKey] = $this->_editPermissionedGroups[$groupKey] = array(); $groups = CRM_Core_PseudoConstant::allGroup($groupType, $excludeHidden); if ($this->check('edit all contacts')) { // this is the most powerful permission, so we return // immediately rather than dilute it further $this->_editAdminUser = $this->_viewAdminUser = TRUE; $this->_editPermission = $this->_viewPermission = TRUE; $this->_editPermissionedGroups[$groupKey] = $groups; $this->_viewPermissionedGroups[$groupKey] = $groups; return $this->_viewPermissionedGroups[$groupKey]; } elseif ($this->check('view all contacts')) { $this->_viewAdminUser = TRUE; $this->_viewPermission = TRUE; $this->_viewPermissionedGroups[$groupKey] = $groups; } $ids = CRM_ACL_API::group(CRM_Core_Permission::VIEW, NULL, 'civicrm_saved_search', $groups); if (!empty($ids)) { foreach (array_values($ids) as $id) { $title = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $id, 'title'); $this->_viewPermissionedGroups[$groupKey][$id] = $title; $this->_viewPermission = TRUE; } } $ids = CRM_ACL_API::group(CRM_Core_Permission::EDIT, NULL, 'civicrm_saved_search', $groups); if (!empty($ids)) { foreach (array_values($ids) as $id) { $title = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $id, 'title'); $this->_editPermissionedGroups[$groupKey][$id] = $title; $this->_viewPermissionedGroups[$groupKey][$id] = $title; $this->_editPermission = TRUE; $this->_viewPermission = TRUE; } } } return $this->_viewPermissionedGroups[$groupKey]; }
static function whereClause(&$params, $sortBy = TRUE, $excludeHidden = TRUE) { $values = array(); $clauses = array(); $title = CRM_Utils_Array::value('title', $params); if ($title) { $clauses[] = "groups.title LIKE %1"; if (strpos($title, '%') !== FALSE) { $params[1] = array($title, 'String', FALSE); } else { $params[1] = array($title, 'String', TRUE); } } $groupType = CRM_Utils_Array::value('group_type', $params); if ($groupType) { $types = explode(',', $groupType); if (!empty($types)) { $clauses[] = 'groups.group_type LIKE %2'; $typeString = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, $types) . CRM_Core_DAO::VALUE_SEPARATOR; $params[2] = array($typeString, 'String', TRUE); } } $visibility = CRM_Utils_Array::value('visibility', $params); if ($visibility) { $clauses[] = 'groups.visibility = %3'; $params[3] = array($visibility, 'String'); } $groupStatus = CRM_Utils_Array::value('status', $params); if ($groupStatus) { switch ($groupStatus) { case 1: $clauses[] = 'groups.is_active = 1'; $params[4] = array($groupStatus, 'Integer'); break; case 2: $clauses[] = 'groups.is_active = 0'; $params[4] = array($groupStatus, 'Integer'); break; case 3: $clauses[] = '(groups.is_active = 0 OR groups.is_active = 1 )'; break; } } $parentsOnly = CRM_Utils_Array::value('parentsOnly', $params); if ($parentsOnly) { $clauses[] = 'groups.parents IS NULL'; } // only show child groups of a specific parent group $parent_id = CRM_Utils_Array::value('parent_id', $params); if ($parent_id) { $clauses[] = 'groups.id IN (SELECT child_group_id FROM civicrm_group_nesting WHERE parent_group_id = %5)'; $params[5] = array($parent_id, 'Integer'); } if ($createdBy = CRM_Utils_Array::value('created_by', $params)) { $clauses[] = "createdBy.sort_name LIKE %6"; if (strpos($createdBy, '%') !== FALSE) { $params[6] = array($createdBy, 'String', FALSE); } else { $params[6] = array($createdBy, 'String', TRUE); } } /* if ( $sortBy && $this->_sortByCharacter !== null ) { $clauses[] = "groups.title LIKE '" . strtolower(CRM_Core_DAO::escapeWildCardString($this->_sortByCharacter)) . "%'"; } // dont do a the below assignement when doing a // AtoZ pager clause if ( $sortBy ) { if ( count( $clauses ) > 1 ) { $this->assign( 'isSearch', 1 ); } else { $this->assign( 'isSearch', 0 ); } } */ if (empty($clauses)) { $clauses[] = 'groups.is_active = 1'; } if ($excludeHidden) { $clauses[] = 'groups.is_hidden = 0'; } //CRM-12209 if (!CRM_Core_Permission::check('view all contacts')) { //get the allowed groups for the current user $groups = CRM_ACL_API::group(CRM_ACL_API::VIEW); if (!empty($groups)) { $groupList = implode(', ', array_values($groups)); $clauses[] = "groups.id IN ( {$groupList} ) "; } } return implode(' AND ', $clauses); }
/** * make sure that the user has permission to access this event * * @param int $id the id of the event * @param int $name the name or title of the event * * @return string the permission that the user has (or null) * @access public * @static */ static function checkPermission($eventId = null, $type = CRM_Core_Permission::VIEW) { static $permissions = null; if (empty($permissions)) { require_once 'CRM/ACL/API.php'; require_once 'CRM/Event/PseudoConstant.php'; $allEvents = CRM_Event_PseudoConstant::event(null, true); $createdEvents = array(); $session =& CRM_Core_Session::singleton(); if ($userID = $session->get('userID')) { $createdEvents = array_keys(CRM_Event_PseudoConstant::event(null, true, "created_id={$userID}")); } // Note: for a multisite setup, a user with edit all events, can edit all events // including those from other sites if (CRM_Core_Permission::check('edit all events')) { $permissions[CRM_Core_Permission::EDIT] = array_keys($allEvents); } else { $permissions[CRM_Core_Permission::EDIT] =& CRM_ACL_API::group(CRM_Core_Permission::EDIT, null, 'civicrm_event', $allEvents, $createdEvents); } if (CRM_Core_Permission::check('edit all events')) { $permissions[CRM_Core_Permission::VIEW] = array_keys($allEvents); } else { if (CRM_Core_Permission::check('access CiviEvent') && CRM_Core_Permission::check('view event participants')) { // use case: allow "view all events" but NOT "edit all events" // so for a normal site allow users with these two permissions to view all events AND // at the same time also allow any hook to override if needed. $createdEvents = array_keys($allEvents); } $permissions[CRM_Core_Permission::VIEW] =& CRM_ACL_API::group(CRM_Core_Permission::VIEW, null, 'civicrm_event', $allEvents, $createdEvents); } $permissions[CRM_Core_Permission::DELETE] = array(); if (CRM_Core_Permission::check('delete in CiviEvent')) { // Note: we want to restrict the scope of delete permission to // events that are editable/viewable (usecase multisite). // We can remove array_intersect once we have ACL support for delete functionality. $permissions[CRM_Core_Permission::DELETE] = array_intersect($permissions[CRM_Core_Permission::EDIT], $permissions[CRM_Core_Permission::VIEW]); } } if ($eventId) { return in_array($eventId, $permissions[$type]) ? true : false; } return $permissions; }
/** * Class constructor. */ public function __construct() { parent::__construct(); $this->addClass('crm-report-form'); if ($this->_tagFilter) { $this->buildTagFilter(); } if ($this->_exposeContactID) { if (array_key_exists('civicrm_contact', $this->_columns)) { $this->_columns['civicrm_contact']['fields']['exposed_id'] = array('name' => 'id', 'title' => 'Contact ID', 'no_repeat' => TRUE); } } if ($this->_groupFilter) { $this->buildGroupFilter(); } // Get all custom groups $allGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_CustomField', 'custom_group_id'); // Get the custom groupIds for which the user has VIEW permission // If the user has 'access all custom data' permission, we'll leave $permCustomGroupIds empty // and addCustomDataToColumns() will allow access to all custom groups. $permCustomGroupIds = array(); if (!CRM_Core_Permission::check('access all custom data')) { $permCustomGroupIds = CRM_ACL_API::group(CRM_Core_Permission::VIEW, NULL, 'civicrm_custom_group', $allGroups, NULL); // do not allow custom data for reports if user doesn't have // permission to access custom data. if (!empty($this->_customGroupExtends) && empty($permCustomGroupIds)) { $this->_customGroupExtends = array(); } } // merge custom data columns to _columns list, if any $this->addCustomDataToColumns(TRUE, $permCustomGroupIds); // add / modify display columns, filters ..etc CRM_Utils_Hook::alterReportVar('columns', $this->_columns, $this); //assign currencyColumn variable to tpl $this->assign('currencyColumn', $this->_currencyColumn); }
/** * Populate $this->_permissionWhereClause with permission related clause and update other * query related properties. * * Function calls ACL permission class and hooks to filter the query appropriately * * Note that these 2 params were in the code when extracted from another function * and a second round extraction would be to make them properties of the class * * @param bool $onlyDeleted * Only get deleted contacts. * @param bool $count * Return Count only. */ public function generatePermissionClause($onlyDeleted = FALSE, $count = FALSE) { if (!$this->_skipPermission) { $this->_permissionWhereClause = CRM_ACL_API::whereClause(CRM_Core_Permission::VIEW, $this->_tables, $this->_whereTables, NULL, $onlyDeleted, $this->_skipDeleteClause); // regenerate fromClause since permission might have added tables if ($this->_permissionWhereClause) { //fix for row count in qill (in contribute/membership find) if (!$count) { $this->_useDistinct = TRUE; } //CRM-15231 $this->_fromClause = self::fromClause($this->_tables, NULL, NULL, $this->_primaryLocation, $this->_mode); $this->_simpleFromClause = self::fromClause($this->_whereTables, NULL, NULL, $this->_primaryLocation, $this->_mode); // note : this modifies _fromClause and _simpleFromClause $this->includePseudoFieldsJoin($this->_sort); } } else { // add delete clause if needed even if we are skipping permission // CRM-7639 if (!$this->_skipDeleteClause) { if (CRM_Core_Permission::check('access deleted contacts') and $onlyDeleted) { $this->_permissionWhereClause = '(contact_a.is_deleted)'; } else { // CRM-6181 $this->_permissionWhereClause = '(contact_a.is_deleted = 0)'; } } } }
/** * Set variables up before form is built. * * @return void */ public function preProcess() { $config = CRM_Core_Config::singleton(); if (in_array('CiviEvent', $config->enableComponents)) { $this->assign('CiviEvent', TRUE); } CRM_Core_Form_RecurringEntity::preProcess('civicrm_event'); $this->_action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, 'add', 'REQUEST'); $this->assign('action', $this->_action); $this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this, FALSE, NULL, 'GET'); if ($this->_id) { $this->_isRepeatingEvent = CRM_Core_BAO_RecurringEntity::getParentFor($this->_id, 'civicrm_event'); $this->assign('eventId', $this->_id); if (!empty($this->_addBlockName) && empty($this->_addProfileBottom) && empty($this->_addProfileBottomAdd)) { $this->add('hidden', 'id', $this->_id); } $this->_single = TRUE; $params = array('id' => $this->_id); CRM_Event_BAO_Event::retrieve($params, $eventInfo); // its an update mode, do a permission check if (!CRM_Event_BAO_Event::checkPermission($this->_id, CRM_Core_Permission::EDIT)) { CRM_Core_Error::fatal(ts('You do not have permission to access this page.')); } $participantListingID = CRM_Utils_Array::value('participant_listing_id', $eventInfo); //CRM_Core_DAO::getFieldValue( 'CRM_Event_DAO_Event', $this->_id, 'participant_listing_id' ); if ($participantListingID) { $participantListingURL = CRM_Utils_System::url('civicrm/event/participant', "reset=1&id={$this->_id}", TRUE, NULL, TRUE, TRUE); $this->assign('participantListingURL', $participantListingURL); } $this->assign('isOnlineRegistration', CRM_Utils_Array::value('is_online_registration', $eventInfo)); $this->assign('id', $this->_id); } // figure out whether we’re handling an event or an event template if ($this->_id) { $this->_isTemplate = CRM_Utils_Array::value('is_template', $eventInfo); } elseif ($this->_action & CRM_Core_Action::ADD) { $this->_isTemplate = CRM_Utils_Request::retrieve('is_template', 'Boolean', $this); } $this->assign('isTemplate', $this->_isTemplate); if ($this->_id) { if ($this->_isTemplate) { $title = CRM_Utils_Array::value('template_title', $eventInfo); CRM_Utils_System::setTitle(ts('Edit Event Template') . " - {$title}"); } else { $configureText = ts('Configure Event'); $title = CRM_Utils_Array::value('title', $eventInfo); //If it is a repeating event change title if ($this->_isRepeatingEvent) { $configureText = 'Configure Repeating Event'; } CRM_Utils_System::setTitle($configureText . " - {$title}"); } $this->assign('title', $title); } elseif ($this->_action & CRM_Core_Action::ADD) { if ($this->_isTemplate) { $title = ts('New Event Template'); CRM_Utils_System::setTitle($title); } else { $title = ts('New Event'); CRM_Utils_System::setTitle($title); } $this->assign('title', $title); } if (CRM_Core_Permission::check('view event participants') && CRM_Core_Permission::check('view all contacts')) { $statusTypes = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 1', 'label'); $statusTypesPending = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 0', 'label'); $findParticipants['statusCounted'] = implode(', ', array_values($statusTypes)); $findParticipants['statusNotCounted'] = implode(', ', array_values($statusTypesPending)); $this->assign('findParticipants', $findParticipants); } $this->_templateId = (int) CRM_Utils_Request::retrieve('template_id', 'Integer', $this); //Is a repeating event if ($this->_isRepeatingEvent) { $isRepeatingEntity = TRUE; $this->assign('isRepeatingEntity', $isRepeatingEntity); } // CRM-16776 - show edit/copy/create buttons for Profiles if user has required permission. $ufGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id'); $ufCreate = CRM_ACL_API::group(CRM_Core_Permission::CREATE, NULL, 'civicrm_uf_group', $ufGroups); $ufEdit = CRM_ACL_API::group(CRM_Core_Permission::EDIT, NULL, 'civicrm_uf_group', $ufGroups); $checkPermission = array(array('administer CiviCRM', 'manage event profiles')); if (CRM_Core_Permission::check($checkPermission) || !empty($ufCreate) || !empty($ufEdit)) { $this->assign('perm', TRUE); } // also set up tabs CRM_Event_Form_ManageEvent_TabHeader::build($this); // Set Done button URL and breadcrumb. Templates go back to Manage Templates, // otherwise go to Manage Event for new event or ManageEventEdit if event if exists. $breadCrumb = array(); if (!$this->_isTemplate) { if ($this->_id) { $this->_doneUrl = CRM_Utils_System::url(CRM_Utils_System::currentPath(), "action=update&reset=1&id={$this->_id}"); } else { $this->_doneUrl = CRM_Utils_System::url('civicrm/event/manage', 'reset=1'); $breadCrumb = array(array('title' => ts('Manage Events'), 'url' => $this->_doneUrl)); } } else { $this->_doneUrl = CRM_Utils_System::url('civicrm/admin/eventTemplate', 'reset=1'); $breadCrumb = array(array('title' => ts('Manage Event Templates'), 'url' => $this->_doneUrl)); } CRM_Utils_System::appendBreadCrumb($breadCrumb); }
/** * create and query the db for an contact search * * @param int $offset the offset for the query * @param int $rowCount the number of rows to return * @param string $sort the order by string * @param boolean $count is this a count only query ? * @param boolean $includeContactIds should we include contact ids? * @param boolean $sortByChar if true returns the distinct array of first characters for search results * @param boolean $groupContacts if true, use a single mysql group_concat statement to get the contact ids * @param boolean $returnQuery should we return the query as a string * @param string $additionalWhereClause if the caller wants to further restrict the search (used for components) * * @return CRM_Contact_DAO_Contact * @access public */ function searchQuery($offset = 0, $rowCount = 0, $sort = null, $count = false, $includeContactIds = false, $sortByChar = false, $groupContacts = false, $returnQuery = false, $additionalWhereClause = null, $sortOrder = null) { require_once 'CRM/Core/Permission.php'; if ($includeContactIds) { $this->_includeContactIds = true; $this->_whereClause = $this->whereClause(); } // hack for now, add permission only if we are in search // FIXME: we should actually filter out deleted contacts (unless requested to do the opposite) $permission = ' ( 1 ) '; $onlyDeleted = false; $onlyDeleted = in_array(array('deleted_contacts', '=', '1', '0', '0'), $this->_params); // if we’re explicitely looking for a certain contact’s contribs, events, etc. // and that contact happens to be deleted, set $onlyDeleted to true foreach ($this->_params as $values) { list($name, $op, $value, $_, $_) = $values; if ($name == 'contact_id' and $op == '=') { if (CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $value, 'is_deleted')) { $onlyDeleted = true; } break; } } if (!$this->_skipPermission) { require_once 'CRM/ACL/API.php'; $permission = CRM_ACL_API::whereClause(CRM_Core_Permission::VIEW, $this->_tables, $this->_whereTables, null, $onlyDeleted, $this->_skipDeleteClause); // CRM_Core_Error::debug( 'p', $permission ); // CRM_Core_Error::debug( 't', $this->_tables ); // CRM_Core_Error::debug( 'w', $this->_whereTables ); // regenerate fromClause since permission might have added tables if ($permission) { //fix for row count in qill (in contribute/membership find) if (!$count) { $this->_useDistinct = true; } $this->_fromClause = self::fromClause($this->_tables, null, null, $this->_primaryLocation, $this->_mode); $this->_simpleFromClause = self::fromClause($this->_whereTables, null, null, $this->_primaryLocation, $this->_mode); } } list($select, $from, $where) = $this->query($count, $sortByChar, $groupContacts); if (empty($where)) { $where = "WHERE {$permission}"; } else { $where = "{$where} AND {$permission}"; } // CRM_Core_Error::debug( 't', $this ); // CRM_Core_Error::debug( 'w', $where ); // CRM_Core_Error::debug( 'a', $additionalWhereClause ); if ($additionalWhereClause) { $where = $where . ' AND ' . $additionalWhereClause; } $order = $orderBy = $limit = ''; if (!$count) { $config = CRM_Core_Config::singleton(); if ($config->includeOrderByClause) { if ($sort) { if (is_string($sort)) { $orderBy = $sort; } else { $orderBy = trim($sort->orderBy()); } if (!empty($orderBy)) { // this is special case while searching for // changelog CRM-1718 if (preg_match('/sort_name/i', $orderBy)) { $orderBy = str_replace('sort_name', 'contact_a.sort_name', $orderBy); } $order = " ORDER BY {$orderBy}"; if ($sortOrder) { $order .= " {$sortOrder}"; } } } else { if ($sortByChar) { $orderBy = " ORDER BY LEFT(contact_a.sort_name, 1) asc"; } else { $orderBy = " ORDER BY contact_a.sort_name asc"; } } } if ($rowCount > 0 && $offset >= 0) { $limit = " LIMIT {$offset}, {$rowCount} "; // ok here is a first hack at an optimization, lets get all the contact ids // that are restricted and we'll then do the final clause with it // CRM-5954 $limitSelect = $this->_useDistinct ? 'SELECT DISTINCT(contact_a.id) as id' : 'SELECT contact_a.id as id'; $doOpt = true; // hack for order clause if ($orderBy) { $fieldOrder = explode(' ', $orderBy); $field = $fieldOrder[0]; $dir = CRM_Utils_Array::value(1, $fieldOrder); if ($field) { switch ($field) { case 'sort_name': break; case 'city': case 'postal_code': $this->_whereTables["civicrm_address"] = 1; $limitSelect .= ", civicrm_address.{$field} as {$field}"; break; case 'country': case 'state_province': $this->_whereTables["civicrm_{$field}"] = 1; $limitSelect .= ", civicrm_{$field}.name as {$field}"; break; case 'email': $this->_whereTables["civicrm_email"] = 1; $limitSelect .= ", civicrm_email.email as email"; break; default: $doOpt = false; } } } if ($doOpt) { $this->_simpleFromClause = self::fromClause($this->_whereTables, null, null, $this->_primaryLocation, $this->_mode); $limitQuery = "{$limitSelect} {$this->_simpleFromClause} {$where} {$order} {$limit}"; $limitDAO = CRM_Core_DAO::executeQuery($limitQuery); $limitIDs = array(); while ($limitDAO->fetch()) { $limitIDs[] = $limitDAO->id; } if (empty($limitIDs)) { $limitClause = ' AND ( 0 ) '; } else { $limitClause = ' AND contact_a.id IN ( ' . implode(',', $limitIDs) . ' ) '; } $where .= $limitClause; // reset limit clause since we already restrict what records we want $limit = null; } } } // building the query string $groupBy = null; if (!$count) { if (isset($this->_groupByComponentClause)) { $groupBy = $this->_groupByComponentClause; } else { if ($this->_useGroupBy) { $groupBy = ' GROUP BY contact_a.id'; } } } if ($this->_mode & CRM_Contact_BAO_Query::MODE_ACTIVITY && !$count) { $groupBy = 'GROUP BY civicrm_activity.id '; } $query = "{$select} {$from} {$where} {$groupBy} {$order} {$limit}"; // CRM_Core_Error::debug('query', $query); // CRM_Core_Error::debug('query', $where); if ($returnQuery) { return $query; } if ($count) { return CRM_Core_DAO::singleValueQuery($query); } $dao =& CRM_Core_DAO::executeQuery($query); if ($groupContacts) { $ids = array(); while ($dao->fetch()) { $ids[] = $dao->id; } return implode(',', $ids); } return $dao; }
/** * given a permission string, check for access requirements * * @param string $str the permission to check * * @return boolean true if yes, else false * @static * @access public */ static function check($str) { static $isAdmin = null; if ($isAdmin === null) { $session =& CRM_Core_Session::singleton(); if ($session->get('new_install') == 1 && $session->get('goahead') == 'yes') { return true; } } require_once 'CRM/ACL/API.php'; return $isAdmin ? true : CRM_ACL_API::check($str, null); }
public static function event($type = CRM_Core_Permission::VIEW, $eventID = null) { require_once 'CRM/Event/PseudoConstant.php'; $events = CRM_Event_PseudoConstant::event(null, true); $includeEvents = array(); // check if user has all powerful permission if (self::check('register for events')) { $includeEvents = array_keys($events); } if ($type == CRM_Core_Permission::VIEW && self::check('view event info')) { $includeEvents = array_keys($events); } require_once 'CRM/ACL/API.php'; $permissionedEvents = CRM_ACL_API::group($type, null, 'civicrm_event', $events, $includeEvents); if (!$eventID) { return $permissionedEvents; } return array_search($eventID, $permissionedEvents) === false ? null : $eventID; }
/** * create and query the db for an contact search * * @param int $offset the offset for the query * @param int $rowCount the number of rows to return * @param string $sort the order by string * @param boolean $count is this a count only query ? * @param boolean $includeContactIds should we include contact ids? * @param boolean $sortByChar if true returns the distinct array of first characters for search results * @param boolean $groupContacts if true, use a single mysql group_concat statement to get the contact ids * @param boolean $returnQuery should we return the query as a string * @param string $additionalWhereClause if the caller wants to further restrict the search (used for components) * * @return CRM_Contact_DAO_Contact * @access public */ function searchQuery($offset = 0, $rowCount = 0, $sort = null, $count = false, $includeContactIds = false, $sortByChar = false, $groupContacts = false, $returnQuery = false, $additionalWhereClause = null) { require_once 'CRM/Core/Permission.php'; if ($includeContactIds) { $this->_includeContactIds = true; $this->_whereClause = $this->whereClause(); } // hack for now, add permission only if we are in search $permission = ' ( 1 ) '; if (!$this->_skipPermission) { require_once 'CRM/ACL/API.php'; $permission = CRM_ACL_API::whereClause(CRM_Core_Permission::VIEW, $this->_tables, $this->_whereTables); // CRM_Core_Error::debug( 'p', $permission ); // CRM_Core_Error::debug( 't', $this->_tables ); // CRM_Core_Error::debug( 'w', $this->_whereTables ); // regenerate fromClause since permission might have added tables if ($permission) { //fix for row count in qill (in contribute/membership find) if (!$count) { $this->_useDistinct = true; } $this->_fromClause = self::fromClause($this->_tables, null, null, $this->_primaryLocation, $this->_mode); $this->_simpleFromClause = self::fromClause($this->_whereTables, null, null, $this->_primaryLocation, $this->_mode); } } list($select, $from, $where) = $this->query($count, $sortByChar, $groupContacts); if (empty($where)) { $where = "WHERE {$permission}"; } else { $where = "{$where} AND {$permission}"; } if ($additionalWhereClause) { $where = $where . ' AND ' . $additionalWhereClause; } $order = $orderBy = $limit = ''; if (!$count) { $config =& CRM_Core_Config::singleton(); if ($config->includeOrderByClause) { if ($sort) { if (is_string($sort)) { $orderBy = $sort; } else { $orderBy = trim($sort->orderBy()); } if (!empty($orderBy)) { // this is special case while searching for // changelog CRM-1718 if (preg_match('/sort_name/i', $orderBy)) { $orderBy = str_replace('sort_name', 'contact_a.sort_name', $orderBy); } $order = " ORDER BY {$orderBy}"; } } else { if ($sortByChar) { $orderBy = " ORDER BY LEFT(contact_a.sort_name, 1) asc"; } else { $orderBy = " ORDER BY contact_a.sort_name asc"; } } } if ($rowCount > 0 && $offset >= 0) { $limit = " LIMIT {$offset}, {$rowCount} "; // ok here is a first hack at an optimization, lets get all the contact ids // that are restricted and we'll then do the final clause with it $limitSelect = $this->_useDistinct ? 'SELECT DISTINCT(contact_a.id) as id' : 'SELECT contact_a.id as id'; $doOpt = true; // hack for order clause if ($orderBy) { list($field, $dir) = split(' ', $orderBy); if ($field) { switch ($field) { case 'sort_name': break; case 'city': case 'postal_code': $this->_whereTables["civicrm_address"] = 1; $limitSelect .= ", civicrm_address.{$field} as {$field}"; break; case 'country': case 'state_province': $this->_whereTables["civicrm_{$field}"] = 1; $limitSelect .= ", civicrm_{$field}.name as {$field}"; break; case 'email': $this->_whereTables["civicrm_email"] = 1; $limitSelect .= ", civicrm_email.email as email"; break; default: $doOpt = false; } } } if ($doOpt) { $this->_simpleFromClause = self::fromClause($this->_whereTables, null, null, $this->_primaryLocation, $this->_mode); $limitQuery = "{$limitSelect} {$this->_simpleFromClause} {$where} {$order} {$limit}"; $limitDAO = CRM_Core_DAO::executeQuery($limitQuery); $limitIDs = array(); while ($limitDAO->fetch()) { $limitIDs[] = $limitDAO->id; } if (empty($limitIDs)) { $limitClause = ' AND ( 0 ) '; } else { $limitClause = ' AND contact_a.id IN ( ' . implode(',', $limitIDs) . ' ) '; } $where .= $limitClause; // reset limit clause since we already restrict what records we want $limit = null; } } } // building the query string $groupBy = null; if (!$count) { if (isset($this->_groupByComponentClause)) { $groupBy = $this->_groupByComponentClause; } else { if ($this->_useGroupBy) { $groupBy = ' GROUP BY contact_a.id'; } } } $query = "{$select} {$from} {$where} {$groupBy} {$order} {$limit}"; //CRM_Core_Error::debug('query', $query); exit(); if ($returnQuery) { return $query; } if ($count) { return CRM_Core_DAO::singleValueQuery($query, CRM_Core_DAO::$_nullArray); } $dao =& CRM_Core_DAO::executeQuery($query); if ($groupContacts) { $ids = array(); while ($dao->fetch()) { $ids[] = $dao->id; } return implode(',', $ids); } return $dao; }
/** * Get permission relevant clauses. * CRM-12209 * * @param bool $force * * @return array */ public static function getPermissionClause($force = FALSE) { static $clause = 1; static $retrieved = FALSE; if ((!$retrieved || $force) && !CRM_Core_Permission::check('view all contacts') && !CRM_Core_Permission::check('edit all contacts')) { //get the allowed groups for the current user $groups = CRM_ACL_API::group(CRM_ACL_API::VIEW); if (!empty($groups)) { $groupList = implode(', ', array_values($groups)); $clause = "groups.id IN ( {$groupList} ) "; } else { $clause = '1 = 0'; } } $retrieved = TRUE; return $clause; }
/** * make sure that the user has permission to access this group * * @param int $id the id of the object * @param int $name the name or title of the object * * @return string the permission that the user has (or null) * @access public * @static */ static function checkPermission($id, $title) { $allGroups = CRM_Core_PseudoConstant::allGroup(); $permissions = NULL; if (CRM_Core_Permission::check('edit all contacts') || CRM_ACL_API::groupPermission(CRM_ACL_API::EDIT, $id, NULL, 'civicrm_saved_search', $allGroups)) { $permissions[] = CRM_Core_Permission::EDIT; } if (CRM_Core_Permission::check('view all contacts') || CRM_ACL_API::groupPermission(CRM_ACL_API::VIEW, $id, NULL, 'civicrm_saved_search', $allGroups)) { $permissions[] = CRM_Core_Permission::VIEW; } if (!empty($permissions) && CRM_Core_Permission::check('delete contacts')) { // Note: using !empty() in if condition, restricts the scope of delete // permission to groups/contacts that are editable/viewable. // We can remove this !empty condition once we have ACL support for delete functionality. $permissions[] = CRM_Core_Permission::DELETE; } return $permissions; }
/** * Build the form object. * * @return void */ public function buildQuickForm() { $this->add('hidden', 'gid', $this->_gid); switch ($this->_mode) { case self::MODE_CREATE: case self::MODE_EDIT: case self::MODE_REGISTER: CRM_Utils_Hook::buildProfile($this->_ufGroup['name']); break; case self::MODE_SEARCH: CRM_Utils_Hook::searchProfile($this->_ufGroup['name']); break; default: } //lets have single status message, CRM-4363 $return = FALSE; $statusMessage = NULL; if ($this->_multiRecord & CRM_Core_Action::ADD && $this->_maxRecordLimit) { return; } if ($this->_multiRecord & CRM_Core_Action::DELETE) { if (!$this->_recordExists) { CRM_Core_Session::setStatus(ts('The record %1 doesnot exists', array(1 => $this->_recordId)), ts('Record doesnot exists'), 'alert'); } else { $this->assign('deleteRecord', TRUE); } return; } CRM_Core_BAO_Address::checkContactSharedAddressFields($this->_fields, $this->_id); // we should not allow component and mix profiles in search mode if ($this->_mode != self::MODE_REGISTER) { //check for mix profile fields (eg: individual + other contact type) if (CRM_Core_BAO_UFField::checkProfileType($this->_gid)) { if ($this->_mode & self::MODE_EDIT && $this->_isContactActivityProfile) { $errors = self::validateContactActivityProfile($this->_activityId, $this->_id, $this->_gid); if (!empty($errors)) { $statusMessage = array_pop($errors); $return = TRUE; } } else { $statusMessage = ts('Profile search, view and edit are not supported for Profiles which include fields for more than one record type.'); $return = TRUE; } } $profileType = CRM_Core_BAO_UFField::getProfileType($this->_gid); if ($this->_id) { $contactTypes = CRM_Contact_BAO_Contact::getContactTypes($this->_id); $contactType = $contactTypes[0]; array_shift($contactTypes); $contactSubtypes = $contactTypes; $profileSubType = FALSE; if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) { $profileSubType = $profileType; $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType); } if ($profileType != 'Contact' && !$this->_isContactActivityProfile && ($profileSubType && !empty($contactSubtypes) && !in_array($profileSubType, $contactSubtypes) || $profileType != $contactType)) { $return = TRUE; if (!$statusMessage) { $statusMessage = ts("This profile is configured for contact type '%1'. It cannot be used to edit contacts of other types.", array(1 => $profileSubType ? $profileSubType : $profileType)); } } } if (in_array($profileType, array("Membership", "Participant", "Contribution"))) { $return = TRUE; if (!$statusMessage) { $statusMessage = ts('Profile is not configured for the selected action.'); } } } //lets have single status message, $this->assign('statusMessage', $statusMessage); if ($return) { return FALSE; } $this->assign('id', $this->_id); $this->assign('mode', $this->_mode); $this->assign('action', $this->_action); $this->assign('fields', $this->_fields); $this->assign('fieldset', isset($this->_fieldset) ? $this->_fieldset : ""); // should we restrict what we display $admin = TRUE; if ($this->_mode == self::MODE_EDIT) { $admin = FALSE; // show all fields that are visibile: // if we are a admin OR the same user OR acl-user with access to the profile // or we have checksum access to this contact (i.e. the user without a login) - CRM-5909 if (CRM_Core_Permission::check('administer users') || $this->_id == $this->_currentUserID || $this->_isPermissionedChecksum || in_array($this->_gid, CRM_ACL_API::group(CRM_Core_Permission::EDIT, NULL, 'civicrm_uf_group', CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id')))) { $admin = TRUE; } } // if false, user is not logged-in. $anonUser = FALSE; if (!$this->_currentUserID) { $defaultLocationType = CRM_Core_BAO_LocationType::getDefault(); $primaryLocationType = $defaultLocationType->id; $anonUser = TRUE; } $this->assign('anonUser', $anonUser); $addCaptcha = array(); $emailPresent = FALSE; // add the form elements foreach ($this->_fields as $name => $field) { // make sure that there is enough permission to expose this field if (!$admin && $field['visibility'] == 'User and User Admin Only') { unset($this->_fields[$name]); continue; } // since the CMS manages the email field, suppress the email display if in // register mode which occur within the CMS form if ($this->_mode == self::MODE_REGISTER && substr($name, 0, 5) == 'email') { unset($this->_fields[$name]); continue; } list($prefixName, $index) = CRM_Utils_System::explode('-', $name, 2); CRM_Core_BAO_UFGroup::buildProfile($this, $field, $this->_mode); if ($field['add_to_group_id']) { $addToGroupId = $field['add_to_group_id']; } //build array for captcha if ($field['add_captcha']) { $addCaptcha[$field['group_id']] = $field['add_captcha']; } if ($name == 'email-Primary' || ($name == 'email-' . isset($primaryLocationType) ? $primaryLocationType : "")) { $emailPresent = TRUE; $this->_mail = $name; } } // add captcha only for create mode. if ($this->_mode == self::MODE_CREATE) { // suppress captcha for logged in users only if ($this->_currentUserID) { $this->_isAddCaptcha = FALSE; } elseif (!$this->_isAddCaptcha && !empty($addCaptcha)) { $this->_isAddCaptcha = TRUE; } if ($this->_gid) { $dao = new CRM_Core_DAO_UFGroup(); $dao->id = $this->_gid; $dao->addSelect(); $dao->addSelect('is_update_dupe'); if ($dao->find(TRUE)) { if ($dao->is_update_dupe) { $this->_isUpdateDupe = $dao->is_update_dupe; } } } } else { $this->_isAddCaptcha = FALSE; } //finally add captcha to form. if ($this->_isAddCaptcha) { $captcha = CRM_Utils_ReCAPTCHA::singleton(); $captcha->add($this); } $this->assign("isCaptcha", $this->_isAddCaptcha); if ($this->_mode != self::MODE_SEARCH) { if (isset($addToGroupId)) { $this->_ufGroup['add_to_group_id'] = $addToGroupId; } } //let's do set defaults for the profile $this->setDefaultsValues(); $action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, NULL); if ($this->_mode == self::MODE_CREATE) { CRM_Core_BAO_CMSUser::buildForm($this, $this->_gid, $emailPresent, $action); } else { $this->assign('showCMS', FALSE); } $this->assign('groupId', $this->_gid); // if view mode pls freeze it with the done button. if ($this->_action & CRM_Core_Action::VIEW) { $this->freeze(); } if ($this->_context == 'dialog') { $this->addElement('submit', $this->_duplicateButtonName, ts('Save Matching Contact')); } }
/** * Check API for ACL permission. * * @param array $apiRequest * * @return bool */ public function checkACLPermission($apiRequest) { switch ($apiRequest['entity']) { case 'UFGroup': case 'UFField': $ufGroups = \CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id'); $aclCreate = \CRM_ACL_API::group(\CRM_Core_Permission::CREATE, NULL, 'civicrm_uf_group', $ufGroups); $aclEdit = \CRM_ACL_API::group(\CRM_Core_Permission::EDIT, NULL, 'civicrm_uf_group', $ufGroups); $ufGroupId = $apiRequest['entity'] == 'UFGroup' ? $apiRequest['params']['id'] : $apiRequest['params']['uf_group_id']; if (in_array($ufGroupId, $aclEdit) or $aclCreate) { return TRUE; } break; //CRM-16777: Disable schedule reminder with ACLs. //CRM-16777: Disable schedule reminder with ACLs. case 'ActionSchedule': $events = \CRM_Event_BAO_Event::getEvents(); $aclEdit = \CRM_ACL_API::group(\CRM_Core_Permission::EDIT, NULL, 'civicrm_event', $events); $param = array('id' => $apiRequest['params']['id']); $eventId = \CRM_Core_BAO_ActionSchedule::retrieve($param, $value = array()); if (in_array($eventId->entity_value, $aclEdit)) { return TRUE; } break; } return FALSE; }
/** * make sure that the user has permission to access this group * * @param int $id the id of the object * @param int $name the name or title of the object * * @return string the permission that the user has (or null) * @access public * @static */ static function checkPermission($id, $title) { require_once 'CRM/ACL/API.php'; require_once 'CRM/Core/Permission.php'; $allGroups = CRM_Core_PseudoConstant::allGroup(); $permissions = null; if (CRM_Core_Permission::check('edit all contacts') || CRM_ACL_API::groupPermission(CRM_ACL_API::EDIT, $id, null, 'civicrm_saved_search', $allGroups)) { $permissions[] = CRM_Core_Permission::EDIT; } if (CRM_Core_Permission::check('view all contacts') || CRM_ACL_API::groupPermission(CRM_ACL_API::VIEW, $id, null, 'civicrm_saved_search', $allGroups)) { $permissions[] = CRM_Core_Permission::VIEW; } if (CRM_Core_Permission::check('delete contacts')) { $permissions[] = CRM_Core_Permission::DELETE; } return $permissions; }
/** * Get all groups from database, filtered by permissions * for this user * * @param string $groupType type of group(Access/Mailing) * @param boolen $excludeHidden exclude hidden groups. * * @access public * @static * * @return array - array reference of all groups. * */ public static function &group($groupType = null, $excludeHidden = true) { if (!isset(self::$_viewPermissionedGroups)) { self::$_viewPermissionedGroups = self::$_editPermissionedGroups = array(); $groups =& CRM_Core_PseudoConstant::allGroup($groupType, $excludeHidden); if (self::check('edit all contacts')) { // this is the most powerful permission, so we return // immediately rather than dilute it further self::$_editAdminUser = self::$_viewAdminUser = true; self::$_editPermission = self::$_viewPermission = true; self::$_editPermissionedGroups = $groups; self::$_viewPermissionedGroups = $groups; return self::$_viewPermissionedGroups; } else { if (self::check('view all contacts')) { self::$_viewAdminUser = true; self::$_viewPermission = true; self::$_viewPermissionedGroups = $groups; } } require_once 'CRM/ACL/API.php'; $ids = CRM_ACL_API::group(CRM_Core_Permission::VIEW, null, 'civicrm_saved_search', $groups); foreach (array_values($ids) as $id) { $title = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $id, 'title'); self::$_viewPermissionedGroups[$id] = $title; self::$_viewPermission = true; } $ids = CRM_ACL_API::group(CRM_Core_Permission::EDIT, null, 'civicrm_saved_search', $groups); foreach (array_values($ids) as $id) { $title = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $id, 'title'); self::$_editPermissionedGroups[$id] = $title; self::$_viewPermissionedGroups[$id] = $title; self::$_editPermission = true; self::$_viewPermission = true; } } return self::$_viewPermissionedGroups; }
/** * create and query the db for an contact search * * @param int $offset the offset for the query * @param int $rowCount the number of rows to return * @param string $sort the order by string * @param boolean $count is this a count only query ? * @param boolean $includeContactIds should we include contact ids? * @param boolean $sortByChar if true returns the distinct array of first characters for search results * @param boolean $groupContacts if true, use a single mysql group_concat statement to get the contact ids * @param boolean $returnQuery should we return the query as a string * @param string $additionalWhereClause if the caller wants to further restrict the search (used for components) * @param string $additionalFromClause should be clause with proper joins, effective to reduce where clause load. * * @return CRM_Contact_DAO_Contact * @access public */ function searchQuery($offset = 0, $rowCount = 0, $sort = NULL, $count = FALSE, $includeContactIds = FALSE, $sortByChar = FALSE, $groupContacts = FALSE, $returnQuery = FALSE, $additionalWhereClause = NULL, $sortOrder = NULL, $additionalFromClause = NULL, $skipOrderAndLimit = FALSE) { if ($includeContactIds) { $this->_includeContactIds = TRUE; $this->_whereClause = $this->whereClause(); } // hack for now, add permission only if we are in search // FIXME: we should actually filter out deleted contacts (unless requested to do the opposite) $permission = ' ( 1 ) '; $onlyDeleted = FALSE; $onlyDeleted = in_array(array('deleted_contacts', '=', '1', '0', '0'), $this->_params); // if we’re explicitely looking for a certain contact’s contribs, events, etc. // and that contact happens to be deleted, set $onlyDeleted to true foreach ($this->_params as $values) { list($name, $op, $value, $_, $_) = $values; if ($name == 'contact_id' and $op == '=') { if (CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $value, 'is_deleted')) { $onlyDeleted = TRUE; } break; } } if (!$this->_skipPermission) { $permission = CRM_ACL_API::whereClause(CRM_Core_Permission::VIEW, $this->_tables, $this->_whereTables, NULL, $onlyDeleted, $this->_skipDeleteClause); // CRM_Core_Error::debug( 'p', $permission ); // CRM_Core_Error::debug( 't', $this->_tables ); // CRM_Core_Error::debug( 'w', $this->_whereTables ); // regenerate fromClause since permission might have added tables if ($permission) { //fix for row count in qill (in contribute/membership find) if (!$count) { $this->_useDistinct = TRUE; } $this->_fromClause = self::fromClause($this->_tables, NULL, NULL, $this->_primaryLocation, $this->_mode); $this->_simpleFromClause = self::fromClause($this->_whereTables, NULL, NULL, $this->_primaryLocation, $this->_mode); } } else { // add delete clause if needed even if we are skipping permission // CRM-7639 if (!$this->_skipDeleteClause) { if (CRM_Core_Permission::check('access deleted contacts') and $onlyDeleted) { $permission = '(contact_a.is_deleted)'; } else { // CRM-6181 $permission = '(contact_a.is_deleted = 0)'; } } } list($select, $from, $where, $having) = $this->query($count, $sortByChar, $groupContacts); //additional from clause should be w/ proper joins. if ($additionalFromClause) { $from .= "\n" . $additionalFromClause; } if (empty($where)) { $where = "WHERE {$permission}"; } else { $where = "{$where} AND {$permission}"; } // CRM_Core_Error::debug( 't', $this ); // CRM_Core_Error::debug( 'w', $where ); // CRM_Core_Error::debug( 'a', $additionalWhereClause ); if ($additionalWhereClause) { $where = $where . ' AND ' . $additionalWhereClause; } // building the query string $groupBy = NULL; if (!$count) { if (isset($this->_groupByComponentClause)) { $groupBy = $this->_groupByComponentClause; } elseif ($this->_useGroupBy) { $groupBy = ' GROUP BY contact_a.id'; } } if ($this->_mode & CRM_Contact_BAO_Query::MODE_ACTIVITY && !$count) { $groupBy = 'GROUP BY civicrm_activity.id '; } $order = $orderBy = $limit = ''; if (!$count) { $config = CRM_Core_Config::singleton(); if ($config->includeOrderByClause || isset($this->_distinctComponentClause)) { if ($sort) { if (is_string($sort)) { $orderBy = $sort; } else { $orderBy = trim($sort->orderBy()); } if (!empty($orderBy)) { // this is special case while searching for // changelog CRM-1718 if (preg_match('/sort_name/i', $orderBy)) { $orderBy = str_replace('sort_name', 'contact_a.sort_name', $orderBy); } $order = " ORDER BY {$orderBy}"; if ($sortOrder) { $order .= " {$sortOrder}"; } // always add contact_a.id to the ORDER clause // so the order is deterministic if (strpos('contact_a.id', $order) === FALSE) { $order .= ", contact_a.id"; } } } elseif ($sortByChar) { $order = " ORDER BY UPPER(LEFT(contact_a.sort_name, 1)) asc"; } else { $order = " ORDER BY contact_a.sort_name asc, contact_a.id"; } } $doOpt = TRUE; // hack for order clause if ($order) { $fieldStr = trim(str_replace('ORDER BY', '', $order)); $fieldOrder = explode(' ', $fieldStr); $field = $fieldOrder[0]; if ($field) { switch ($field) { case 'sort_name': case 'id': case 'contact_a.sort_name': case 'contact_a.id': break; case 'city': case 'postal_code': $this->_whereTables["civicrm_address"] = 1; $order = str_replace($field, "civicrm_address.{$field}", $order); break; case 'country': case 'state_province': $this->_whereTables["civicrm_{$field}"] = 1; $order = str_replace($field, "civicrm_{$field}.name", $order); break; case 'email': $this->_whereTables["civicrm_email"] = 1; $order = str_replace($field, "civicrm_email.{$field}", $order); break; default: $doOpt = FALSE; } } } if ($rowCount > 0 && $offset >= 0) { $limit = " LIMIT {$offset}, {$rowCount} "; // ok here is a first hack at an optimization, lets get all the contact ids // that are restricted and we'll then do the final clause with it // CRM-5954 if (isset($this->_distinctComponentClause)) { if (strpos($this->_distinctComponentClause, 'DISTINCT') == FALSE) { $limitSelect = "SELECT DISTINCT {$this->_distinctComponentClause}"; } else { $limitSelect = "SELECT {$this->_distinctComponentClause}"; } } else { $limitSelect = 'SELECT DISTINCT contact_a.id as id'; } if ($doOpt) { $this->_simpleFromClause = self::fromClause($this->_whereTables, NULL, NULL, $this->_primaryLocation, $this->_mode); if ($additionalFromClause) { $this->_simpleFromClause .= "\n" . $additionalFromClause; } // if we are doing a transform, do it here // CRM-7969 $having = NULL; if ($this->_displayRelationshipType) { $this->filterRelatedContacts($this->_simpleFromClause, $where, $having); } $limitQuery = "{$limitSelect} {$this->_simpleFromClause} {$where} {$groupBy} {$order} {$limit}"; $limitDAO = CRM_Core_DAO::executeQuery($limitQuery); $limitIDs = array(); while ($limitDAO->fetch()) { $limitIDs[] = $limitDAO->id; } if (empty($limitIDs)) { $limitClause = ' AND ( 0 ) '; } else { if (isset($this->_distinctComponentClause)) { $limitClause = " AND {$this->_distinctComponentClause} IN ( "; } else { $limitClause = ' AND contact_a.id IN ( '; } $limitClause .= implode(',', $limitIDs) . ' ) '; } $where .= $limitClause; // reset limit clause since we already restrict what records we want $limit = NULL; } } } // if we are doing a transform, do it here // use the $from, $where and $having to get the contact ID if ($this->_displayRelationshipType) { $this->filterRelatedContacts($from, $where, $having); } if ($skipOrderAndLimit) { $query = "{$select} {$from} {$where} {$having} {$groupBy}"; } else { $query = "{$select} {$from} {$where} {$having} {$groupBy} {$order} {$limit}"; } // CRM_Core_Error::debug('query', $query); // CRM_Core_Error::debug('query', $where); // CRM_Core_Error::debug('this', $this ); if ($returnQuery) { return $query; } if ($count) { return CRM_Core_DAO::singleValueQuery($query); } $dao = CRM_Core_DAO::executeQuery($query); if ($groupContacts) { $ids = array(); while ($dao->fetch()) { $ids[] = $dao->id; } return implode(',', $ids); } return $dao; }
/** * Set up an acl allowing contact to see 2 specified groups * - $this->_permissionedGroup & $this->_permissionedDisabledGroup * * You need to have pre-created these groups & created the user e.g * $this->createLoggedInUser(); * $this->_permissionedDisabledGroup = $this->groupCreate(array('title' => 'pick-me-disabled', 'is_active' => 0, 'name' => 'pick-me-disabled')); * $this->_permissionedGroup = $this->groupCreate(array('title' => 'pick-me-active', 'is_active' => 1, 'name' => 'pick-me-active')); * * @param bool $isProfile */ public function setupACL($isProfile = FALSE) { global $_REQUEST; $_REQUEST = $this->_params; CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM'); $optionGroupID = $this->callAPISuccessGetValue('option_group', array('return' => 'id', 'name' => 'acl_role')); $optionValue = $this->callAPISuccess('option_value', 'create', array('option_group_id' => $optionGroupID, 'label' => 'pick me', 'value' => 55)); CRM_Core_DAO::executeQuery("\n TRUNCATE civicrm_acl_cache\n "); CRM_Core_DAO::executeQuery("\n TRUNCATE civicrm_acl_contact_cache\n "); CRM_Core_DAO::executeQuery("\n INSERT INTO civicrm_acl_entity_role (\n `acl_role_id`, `entity_table`, `entity_id`, `is_active`\n ) VALUES (55, 'civicrm_group', {$this->_permissionedGroup}, 1);\n "); if ($isProfile) { CRM_Core_DAO::executeQuery("\n INSERT INTO civicrm_acl (\n `name`, `entity_table`, `entity_id`, `operation`, `object_table`, `object_id`, `is_active`\n )\n VALUES (\n 'view picked', 'civicrm_acl_role', 55, 'Edit', 'civicrm_uf_group', 0, 1\n );\n "); } else { CRM_Core_DAO::executeQuery("\n INSERT INTO civicrm_acl (\n `name`, `entity_table`, `entity_id`, `operation`, `object_table`, `object_id`, `is_active`\n )\n VALUES (\n 'view picked', 'civicrm_group', {$this->_permissionedGroup} , 'Edit', 'civicrm_saved_search', {$this->_permissionedGroup}, 1\n );\n "); CRM_Core_DAO::executeQuery("\n INSERT INTO civicrm_acl (\n `name`, `entity_table`, `entity_id`, `operation`, `object_table`, `object_id`, `is_active`\n )\n VALUES (\n 'view picked', 'civicrm_group', {$this->_permissionedGroup}, 'Edit', 'civicrm_saved_search', {$this->_permissionedDisabledGroup}, 1\n );\n "); } $this->_loggedInUser = CRM_Core_Session::singleton()->get('userID'); $this->callAPISuccess('group_contact', 'create', array('group_id' => $this->_permissionedGroup, 'contact_id' => $this->_loggedInUser)); if (!$isProfile) { //flush cache CRM_ACL_BAO_Cache::resetCache(); CRM_Contact_BAO_Group::getPermissionClause(TRUE); CRM_ACL_API::groupPermission('whatever', 9999, NULL, 'civicrm_saved_search', NULL, NULL, TRUE); } }
/** * Fill the acl contact cache for this contact id if empty. * * @param int $userID * @param int|string $type the type of operation (view|edit) * @param bool $force * Should we force a recompute. */ public static function cache($userID, $type = CRM_Core_Permission::VIEW, $force = FALSE) { static $_processed = array(); if ($type = CRM_Core_Permission::VIEW) { $operationClause = " operation IN ( 'Edit', 'View' ) "; $operation = 'View'; } else { $operationClause = " operation = 'Edit' "; $operation = 'Edit'; } if (!$force) { if (!empty($_processed[$userID])) { return; } // run a query to see if the cache is filled $sql = "\nSELECT count(id)\nFROM civicrm_acl_contact_cache\nWHERE user_id = %1\nAND {$operationClause}\n"; $params = array(1 => array($userID, 'Integer')); $count = CRM_Core_DAO::singleValueQuery($sql, $params); if ($count > 0) { $_processed[$userID] = 1; return; } } $tables = array(); $whereTables = array(); $permission = CRM_ACL_API::whereClause($type, $tables, $whereTables, $userID); $from = CRM_Contact_BAO_Query::fromClause($whereTables); CRM_Core_DAO::executeQuery("\nINSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation )\nSELECT {$userID} as user_id, contact_a.id as contact_id, '{$operation}' as operation\n {$from}\nWHERE {$permission}\nGROUP BY contact_a.id\nON DUPLICATE KEY UPDATE\n user_id=VALUES(user_id),\n contact_id=VALUES(contact_id),\n operation=VALUES(operation)"); $_processed[$userID] = 1; }
/** * Function to actually build the form * * @return void * @access public */ public function buildQuickForm() { //lets have single status message, CRM-4363 $return = false; $statusMessage = null; //we should not allow component and mix profiles in search mode if ($this->_mode != self::MODE_REGISTER) { //check for mix profile fields (eg: individual + other contact type) if (CRM_Core_BAO_UFField::checkProfileType($this->_gid)) { $statusMessage = ts('Profile search, view and edit are not supported for Profiles which include fields for more than one record type.'); } $profileType = CRM_Core_BAO_UFField::getProfileType($this->_gid); if ($this->_id) { list($contactType, $contactSubType) = CRM_Contact_BAO_Contact::getContactTypes($this->_id); $profileSubType = false; if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) { $profileSubType = $profileType; $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType); } if ($profileType != 'Contact' && ($profileSubType && $contactSubType && $profileSubType != $contactSubType || $profileType != $contactType)) { $return = true; if (!$statusMessage) { $statusMessage = ts("This profile is configured for contact type '%1'. It cannot be used to edit contacts of other types.", array(1 => $profileSubType ? $profileSubType : $profileType)); } } } if (in_array($profileType, array("Membership", "Participant", "Contribution"))) { $return = true; if (!$statusMessage) { $statusMessage = ts('Profile is not configured for the selected action.'); } } } //lets have sigle status message, $this->assign('statusMessage', $statusMessage); if ($return) { return false; } $sBlocks = array(); $hBlocks = array(); $config =& CRM_Core_Config::singleton(); $this->assign('id', $this->_id); $this->assign('mode', $this->_mode); $this->assign('action', $this->_action); $this->assign_by_ref('fields', $this->_fields); $this->assign('fieldset', isset($this->_fieldset) ? $this->_fieldset : ""); // do we need inactive options ? if ($this->_action & CRM_Core_Action::VIEW) { $inactiveNeeded = true; } else { $inactiveNeeded = false; } $session =& CRM_Core_Session::singleton(); // should we restrict what we display $admin = true; if ($this->_mode == self::MODE_EDIT) { $admin = false; // show all fields that are visibile: // if we are a admin OR the same user OR acl-user with access to the profile require_once 'CRM/ACL/API.php'; if (CRM_Core_Permission::check('administer users') || $this->_id == $session->get('userID') || in_array($this->_gid, CRM_ACL_API::group(CRM_Core_Permission::EDIT, null, 'civicrm_uf_group', CRM_Core_PseudoConstant::ufGroup()))) { $admin = true; } } $userID = $session->get('userID'); $anonUser = false; // if false, user is not logged-in. if (!$userID) { require_once 'CRM/Core/BAO/LocationType.php'; $defaultLocationType =& CRM_Core_BAO_LocationType::getDefault(); $primaryLocationType = $defaultLocationType->id; $anonUser = true; $this->assign('anonUser', true); } $addCaptcha = array(); $emailPresent = false; // cache the state country fields. based on the results, we could use our javascript solution // in create or register mode $stateCountryMap = array(); // add the form elements foreach ($this->_fields as $name => $field) { // make sure that there is enough permission to expose this field if (!$admin && $field['visibility'] == 'User and User Admin Only' || CRM_Utils_Array::value('is_view', $field)) { unset($this->_fields[$name]); continue; } // since the CMS manages the email field, suppress the email display if in // register mode which occur within the CMS form if ($this->_mode == self::MODE_REGISTER && substr($name, 0, 5) == 'email') { unset($this->_fields[$name]); continue; } list($prefixName, $index) = CRM_Utils_System::explode('-', $name, 2); if ($prefixName == 'state_province' || $prefixName == 'country') { if (!array_key_exists($index, $stateCountryMap)) { $stateCountryMap[$index] = array(); } $stateCountryMap[$index][$prefixName] = $name; } CRM_Core_BAO_UFGroup::buildProfile($this, $field, $this->_mode); if ($field['add_to_group_id']) { $addToGroupId = $field['add_to_group_id']; } //build array for captcha if ($field['add_captcha']) { $addCaptcha[$field['group_id']] = $field['add_captcha']; } if ($name == 'email-Primary' || ($name == 'email-' . isset($primaryLocationType) ? $primaryLocationType : "")) { $emailPresent = true; $this->_mail = $name; } } // add captcha only for create mode. if ($this->_mode == self::MODE_CREATE) { if (!$this->_isAddCaptcha && !empty($addCaptcha)) { $this->_isAddCaptcha = true; } } else { $this->_isAddCaptcha = false; } //finally add captcha to form. if ($this->_isAddCaptcha) { require_once 'CRM/Utils/ReCAPTCHA.php'; $captcha =& CRM_Utils_ReCAPTCHA::singleton(); $captcha->add($this); } $this->assign("isCaptcha", $this->_isAddCaptcha); if ($this->_mode != self::MODE_SEARCH) { if (isset($addToGroupId)) { $this->add('hidden', "group[{$addToGroupId}]", 1); $this->_addToGroupID = $addToGroupId; } } // also do state country js require_once 'CRM/Core/BAO/Address.php'; CRM_Core_BAO_Address::addStateCountryMap($stateCountryMap, $this->_defaults); $action = CRM_Utils_Request::retrieve('action', 'String', $this, false, null); if ($this->_mode == self::MODE_CREATE) { require_once 'CRM/Core/BAO/CMSUser.php'; CRM_Core_BAO_CMSUser::buildForm($this, $this->_gid, $emailPresent, $action); } else { $this->assign('showCMS', false); } $this->assign('groupId', $this->_gid); // now fix all state country selectors require_once 'CRM/Core/BAO/Address.php'; CRM_Core_BAO_Address::fixAllStateSelects($this, $this->_defaults); // if view mode pls freeze it with the done button. if ($this->_action & CRM_Core_Action::VIEW) { $this->freeze(); } if ($this->_context == 'dialog') { $this->addElement('submit', $this->_duplicateButtonName, ts('Save Matching Contact')); } }