_params = $params;
if (is_array($ufGroupIds)) {
$this->_profileIds = $ufGroupIds;
$this->_gid = $ufGroupIds[0];
}
else {
$this->_profileIds = [$ufGroupIds];
$this->_gid = $ufGroupIds;
}
$this->_map = $map;
$this->_editLink = $editLink;
$this->_linkToUF = $linkToUF;
//get the details of the uf group
if ($this->_gid) {
$groupId = CRM_Core_DAO::getFieldValue('CRM_Core_BAO_UFGroup',
$this->_gid, 'limit_listings_group_id'
);
}
// add group id to params if a uf group belong to a any group
if ($groupId) {
if (!empty($this->_params['group'])) {
$this->_params['group'][$groupId] = 1;
}
else {
$this->_params['group'] = [$groupId => 1];
}
}
$this->_fields = CRM_Core_BAO_UFGroup::getListingFields(CRM_Core_Action::VIEW,
CRM_Core_BAO_UFGroup::PUBLIC_VISIBILITY |
CRM_Core_BAO_UFGroup::LISTINGS_VISIBILITY,
FALSE, $this->_profileIds
);
$this->_customFields = &$customFields;
$returnProperties = CRM_Contact_BAO_Contact::makeHierReturnProperties($this->_fields);
$returnProperties['contact_type'] = 1;
$returnProperties['contact_sub_type'] = 1;
$returnProperties['sort_name'] = 1;
$queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_params, 1);
$this->_query = new CRM_Contact_BAO_Query($queryParams, $returnProperties, $this->_fields);
//the below is done for query building for multirecord custom field listing
//to show all the custom field multi valued records of a particular contact
$this->setMultiRecordTableName($this->_fields);
$this->_options = &$this->_query->_options;
}
/**
* This method returns the links that are given for each search row.
*
* @param bool $map
* @param bool $editLink
* @param bool $ufLink
* @param null $gids
*
* @return array
*/
public static function &links($map = FALSE, $editLink = FALSE, $ufLink = FALSE, $gids = NULL) {
if (!self::$_links) {
self::$_links = [];
$viewPermission = TRUE;
if ($gids) {
// check view permission for each profile id, in case multiple profile ids are rendered
// then view action is disabled if any profile returns false
foreach ($gids as $profileId) {
$viewPermission = CRM_Core_Permission::ufGroupValid($profileId, CRM_Core_Permission::VIEW);
if (!$viewPermission) {
break;
}
}
}
if ($viewPermission) {
self::$_links[CRM_Core_Action::VIEW] = [
'name' => ts('View'),
'url' => 'civicrm/profile/view',
'qs' => 'reset=1&id=%%id%%&gid=%%gid%%',
'title' => ts('View Profile Details'),
];
}
if ($editLink) {
self::$_links[CRM_Core_Action::UPDATE] = [
'name' => ts('Edit'),
'url' => 'civicrm/profile/edit',
'qs' => 'reset=1&id=%%id%%&gid=%%gid%%',
'title' => ts('Edit'),
];
}
if ($ufLink) {
self::$_links[CRM_Core_Action::PROFILE] = [
'name' => ts('Website Profile'),
'url' => 'user/%%ufID%%',
'qs' => ' ',
'title' => ts('View Website Profile'),
];
}
if ($map) {
self::$_links[CRM_Core_Action::MAP] = [
'name' => ts('Map'),
'url' => 'civicrm/profile/map',
'qs' => 'reset=1&cid=%%id%%&gid=%%gid%%',
'title' => ts('Map'),
];
}
}
return self::$_links;
}
/**
* Getter for array of the parameters required for creating pager.
*
* @param $action
* @param array $params
*/
public function getPagerParams($action, &$params) {
$status = CRM_Utils_System::isNull($this->_multiRecordTableName) ? ts('Contact %%StatusMessage%%') : ts('Contact Multi Records %%StatusMessage%%');
$params['status'] = $status;
$params['csvString'] = NULL;
$params['rowCount'] = CRM_Utils_Pager::ROWCOUNT;
$params['buttonTop'] = 'PagerTopButton';
$params['buttonBottom'] = 'PagerBottomButton';
}
/**
* Returns the column headers as an array of tuples:
* (name, sortName (key to the sort array))
*
* @param string $action
* The action being performed.
* @param string $output
* What should the result set include (web/email/csv).
*
* @return array
* the column headers that need to be displayed
*/
public function &getColumnHeaders($action = NULL, $output = NULL) {
static $skipFields = ['group', 'tag'];
$multipleFields = ['url'];
$direction = CRM_Utils_Sort::ASCENDING;
$empty = TRUE;
if (!isset(self::$_columnHeaders)) {
self::$_columnHeaders = [
['name' => ''],
[
'name' => ts('Name'),
'sort' => 'sort_name',
'direction' => CRM_Utils_Sort::ASCENDING,
'field_name' => 'sort_name',
],
];
$locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
foreach ($this->_fields as $name => $field) {
// skip pseudo fields
if (substr($name, 0, 9) == 'phone_ext') {
continue;
}
if (!empty($field['in_selector']) &&
!in_array($name, $skipFields)
) {
if (strpos($name, '-') !== FALSE) {
$value = explode('-', $name);
$fieldName = $value[0] ?? NULL;
$lType = $value[1] ?? NULL;
$type = $value[2] ?? NULL;
if (!in_array($fieldName, $multipleFields)) {
if ($lType == 'Primary') {
$locationTypeName = 1;
}
else {
$locationTypeName = $locationTypes[$lType];
}
if (in_array($fieldName, [
'phone',
'im',
'email',
])) {
if ($type) {
$name = "`$locationTypeName-$fieldName-$type`";
}
else {
$name = "`$locationTypeName-$fieldName`";
}
}
else {
$name = "`$locationTypeName-$fieldName`";
}
}
else {
$name = "website-{$lType}-{$fieldName}";
}
}
self::$_columnHeaders[] = [
'name' => $field['title'],
'sort' => $name,
'direction' => $direction,
'field_name' => CRM_Core_BAO_UFField::isValidFieldName($name) ? $name : $fieldName,
];
$direction = CRM_Utils_Sort::DONTCARE;
$empty = FALSE;
}
}
// if we don't have any valid columns, don't add the implicit ones
// this allows the template to check on emptiness of column headers
if ($empty) {
self::$_columnHeaders = [];
}
else {
self::$_columnHeaders[] = ['desc' => ts('Actions')];
}
}
return self::$_columnHeaders;
}
/**
* Returns total number of rows for the query.
*
* @param int $action
*
* @return int
* Total number of rows
*/
public function getTotalCount($action) {
$additionalWhereClause = 'contact_a.is_deleted = 0';
$additionalFromClause = NULL;
$returnQuery = NULL;
if ($this->_multiRecordTableName &&
!array_key_exists($this->_multiRecordTableName, $this->_query->_whereTables)
) {
$additionalFromClause = $this->_query->_tables[$this->_multiRecordTableName] ?? NULL;
$returnQuery = TRUE;
}
$countVal = $this->_query->searchQuery(0, 0, NULL, TRUE, NULL, NULL, NULL,
$returnQuery, $additionalWhereClause, NULL, $additionalFromClause
);
if (!$returnQuery) {
return $countVal;
}
if ($returnQuery) {
$sql = preg_replace('/DISTINCT/', '', $countVal);
return CRM_Core_DAO::singleValueQuery($sql);
}
}
/**
* Return the qill for this selector.
*
* @return string
*/
public function getQill() {
return $this->_query->qill();
}
/**
* Returns all the rows in the given offset and rowCount.
*
* @param string $action
* The action being performed.
* @param int $offset
* The row number to start from.
* @param int $rowCount
* The number of rows to return.
* @param string $sort
* The sql string that describes the sort order.
* @param string $output
* What should the result set include (web/email/csv).
*
* @param string $extraWhereClause
*
* @return int
* the total number of rows for this action
*/
public function &getRows($action, $offset, $rowCount, $sort, $output = NULL, $extraWhereClause = NULL) {
$multipleFields = ['url'];
//$sort object processing for location fields
if ($sort) {
$vars = $sort->_vars;
$varArray = [];
foreach ($vars as $key => $field) {
$field = $vars[$key];
$fieldArray = explode('-', $field['name']);
$fieldType = $fieldArray['2'] ?? NULL;
if (is_numeric(CRM_Utils_Array::value('1', $fieldArray))) {
if (!in_array($fieldType, $multipleFields)) {
$locationType = new CRM_Core_DAO_LocationType();
$locationType->id = $fieldArray[1];
$locationType->find(TRUE);
if ($fieldArray[0] == 'email' || $fieldArray[0] == 'im' || $fieldArray[0] == 'phone') {
$field['name'] = "`" . $locationType->name . "-" . $fieldArray[0] . "-1`";
}
else {
$field['name'] = "`" . $locationType->name . "-" . $fieldArray[0] . "`";
}
}
else {
$field['name'] = "`website-" . $fieldArray[1] . "-{$fieldType}`";
}
}
$varArray[$key] = $field;
}
$sort->_vars = $varArray;
}
$additionalWhereClause = 'contact_a.is_deleted = 0';
if ($extraWhereClause) {
$additionalWhereClause .= " AND {$extraWhereClause}";
}
$returnQuery = NULL;
if ($this->_multiRecordTableName) {
$returnQuery = TRUE;
}
$this->_query->_useGroupBy = TRUE;
$result = $this->_query->searchQuery($offset, $rowCount, $sort, NULL, NULL,
NULL, NULL, $returnQuery, $additionalWhereClause
);
if ($returnQuery) {
$resQuery = preg_replace('/GROUP BY contact_a.id[\s]+ORDER BY/', ' ORDER BY', $result);
$result = CRM_Core_DAO::executeQuery($resQuery);
}
// process the result of the query
$rows = [];
// check if edit is configured in profile settings
if ($this->_gid) {
$editLink = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $this->_gid, 'is_edit_link');
}
//FIXME : make sure to handle delete separately. CRM-4418
$mask = CRM_Core_Action::mask([CRM_Core_Permission::getPermission()]);
if ($editLink && ($mask & CRM_Core_Permission::EDIT)) {
// do not allow edit for anon users in joomla frontend, CRM-4668
$config = CRM_Core_Config::singleton();
if (!$config->userFrameworkFrontend || CRM_Core_Session::singleton()->getLoggedInContactID()) {
$this->_editLink = TRUE;
}
}
$links = self::links($this->_map, $this->_editLink, $this->_linkToUF, $this->_profileIds);
$locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
$names = [];
static $skipFields = ['group', 'tag'];
foreach ($this->_fields as $key => $field) {
// skip pseudo fields
if (substr($key, 0, 9) == 'phone_ext') {
continue;
}
if (!empty($field['in_selector']) &&
!in_array($key, $skipFields)
) {
if (strpos($key, '-') !== FALSE) {
$value = explode('-', $key);
$fieldName = $value[0] ?? NULL;
$id = $value[1] ?? NULL;
$type = $value[2] ?? NULL;
if (!in_array($fieldName, $multipleFields)) {
$locationTypeName = NULL;
if (is_numeric($id)) {
$locationTypeName = $locationTypes[$id] ?? NULL;
}
else {
if ($id == 'Primary') {
$locationTypeName = 1;
}
}
if (!$locationTypeName) {
continue;
}
$locationTypeName = str_replace(' ', '_', $locationTypeName);
if (in_array($fieldName, [
'phone',
'im',
'email',
])) {
if ($type) {
$names[] = "{$locationTypeName}-{$fieldName}-{$type}";
}
else {
$names[] = "{$locationTypeName}-{$fieldName}";
}
}
else {
$names[] = "{$locationTypeName}-{$fieldName}";
}
}
else {
$names[] = "website-{$id}-{$fieldName}";
}
}
elseif ($field['name'] == 'id') {
$names[] = 'contact_id';
}
else {
$names[] = $field['name'];
}
}
}
$multipleSelectFields = ['preferred_communication_method' => 1];
$multiRecordTableId = NULL;
if ($this->_multiRecordTableName) {
$multiRecordTableId = "{$this->_multiRecordTableName}_id";
}
// we need to determine of overlay profile should be shown
$showProfileOverlay = CRM_Core_BAO_UFGroup::showOverlayProfile();
while ($result->fetch()) {
$this->_query->convertToPseudoNames($result);
if (isset($result->country)) {
// the query returns the untranslated country name
$i18n = CRM_Core_I18n::singleton();
$result->country = $i18n->translate($result->country);
}
$row = [];
$empty = TRUE;
$row[] = CRM_Contact_BAO_Contact_Utils::getImage($result->contact_sub_type ? $result->contact_sub_type : $result->contact_type,
FALSE,
$result->contact_id,
$showProfileOverlay
);
if ($result->sort_name) {
$row[] = $result->sort_name;
$empty = FALSE;
}
else {
continue;
}
foreach ($names as $name) {
if ($cfID = CRM_Core_BAO_CustomField::getKeyID($name)) {
$row[] = CRM_Core_BAO_CustomField::displayValue($result->$name,
$cfID,
$result->contact_id
);
}
elseif (substr($name, -4) == '-url' &&
!empty($result->$name)
) {
$url = CRM_Utils_System::fixURL($result->$name);
$typeId = substr($name, 0, -4) . "-website_type_id";
$typeName = CRM_Core_PseudoConstant::getLabel('CRM_Core_DAO_Website', 'website_type_id', $result->$typeId);
if ($typeName) {
$row[] = "{$result->$name} (${typeName})";
}
else {
$row[] = "{$result->$name}";
}
}
elseif ($name == 'preferred_language') {
$row[] = CRM_Core_PseudoConstant::getLabel('CRM_Contact_DAO_Contact', 'preferred_language', $result->$name);
}
elseif ($multipleSelectFields &&
array_key_exists($name, $multipleSelectFields)
) {
$paramsNew = [$name => $result->$name];
$name = [$name => ['newName' => $name, 'groupName' => $name]];
CRM_Core_OptionGroup::lookupValues($paramsNew, $name, FALSE);
$row[] = $paramsNew[$key];
}
elseif (strpos($name, '-im')) {
if (!empty($result->$name)) {
$providerId = $name . "-provider_id";
$providerName = CRM_Core_PseudoConstant::getLabel('CRM_Core_DAO_IM', 'provider_id', $result->$providerId);
$row[] = $result->$name . " ({$providerName})";
}
else {
$row[] = '';
}
}
elseif (strpos($name, '-phone-')) {
$phoneExtField = str_replace('phone', 'phone_ext', $name);
if (isset($result->$phoneExtField)) {
$row[] = $result->$name . " (" . $result->$phoneExtField . ")";
}
else {
$row[] = $result->$name;
}
}
elseif (in_array($name, [
'addressee',
'email_greeting',
'postal_greeting',
])) {
$dname = $name . '_display';
$row[] = $result->$dname;
}
elseif (in_array($name, [
'birth_date',
'deceased_date',
])) {
$row[] = CRM_Utils_Date::customFormat($result->$name);
}
elseif (isset($result->$name)) {
$row[] = $result->$name;
}
else {
$row[] = '';
}
if (!empty($result->$name)) {
$empty = FALSE;
}
}
$newLinks = $links;
$params = [
'id' => $result->contact_id,
'gid' => implode(',', $this->_profileIds),
];
// pass record id param to view url for multi record view
if ($multiRecordTableId && $newLinks) {
if ($result->$multiRecordTableId) {
if ($newLinks[CRM_Core_Action::VIEW]['url'] == 'civicrm/profile/view') {
$newLinks[CRM_Core_Action::VIEW]['qs'] .= "&multiRecord=view&recordId=%%recordId%%&allFields=1";
$params['recordId'] = $result->$multiRecordTableId;
}
}
}
if ($this->_linkToUF) {
$ufID = CRM_Core_BAO_UFMatch::getUFId($result->contact_id);
if (!$ufID) {
unset($newLinks[CRM_Core_Action::PROFILE]);
}
else {
$params['ufID'] = $ufID;
}
}
$row[] = CRM_Core_Action::formLink($newLinks,
$mask,
$params,
ts('more'),
FALSE,
'profile.selector.row',
'Contact',
$result->contact_id
);
if (!$empty) {
$rows[] = $row;
}
}
return $rows;
}
/**
* Name of export file.
*
* @param string $output
* Type of output.
*
* @return string
* name of the file
*/
public function getExportFileName($output = 'csv') {
return ts('CiviCRM Profile Listings');
}
/**
* Set the _multiRecordTableName to display the result set.
*
* (according to multi record custom field values).
*
* @param array $fields
*/
public function setMultiRecordTableName($fields) {
$customGroupId = $multiRecordTableName = NULL;
$selectorSet = FALSE;
foreach ($fields as $field => $properties) {
if (!CRM_Core_BAO_CustomField::getKeyID($field)) {
continue;
}
if ($cgId = CRM_Core_BAO_CustomField::isMultiRecordField($field)) {
$customGroupId = CRM_Utils_System::isNull($customGroupId) ? $cgId : $customGroupId;
//if the field is submitted set multiRecordTableName
if ($customGroupId) {
$isSubmitted = FALSE;
foreach ($this->_query->_params as $key => $value) {
//check the query params 'where' element
if ($value[0] == $field) {
$isSubmitted = TRUE;
break;
}
}
if ($isSubmitted) {
$this->_multiRecordTableName
= $multiRecordTableName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroupId, 'table_name');
if ($multiRecordTableName) {
return;
}
}
if (!empty($properties['in_selector'])) {
$selectorSet = TRUE;
}
}
}
}
if (!isset($customGroupId) || !$customGroupId) {
return;
}
//if the field is in selector and not a searchable field
//get the proper custom value table name
if ($selectorSet) {
$this->_multiRecordTableName
= $multiRecordTableName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroupId, 'table_name');
}
} //func close
}