3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.3 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
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-2013
37 * This class is used to retrieve and display a range of
38 * contacts that match the given criteria (specifically for
39 * results of advanced search options.
42 class CRM_Profile_Selector_Listings
extends CRM_Core_Selector_Base
implements CRM_Core_Selector_API
{
45 * array of supported links, currenly view and edit
50 static $_links = NULL;
53 * we use desc to remind us what that column is, name is used in the tpl
58 static $_columnHeaders;
61 * The sql params we use to get the list of contacts
69 * the public visible fields to be shown to the user
77 * the custom fields for this domain
82 protected $_customFields;
85 * cache the query object
93 * cache the expanded options list if any
101 * The group id that we are editing
108 * Do we enable mapping of users
115 * Do we enable edit link
119 protected $_editLink;
122 * Should we link to the UF Profile
126 protected $_linkToUF;
129 * Store profile ids if multiple profile ids are passed using comma separated.
130 * Currently lets implement this functionality only for dialog mode
132 protected $_profileIds = array();
134 protected $_multiRecordTableName = NULL;
138 * @param string params the params for the where clause
140 * @return CRM_Contact_Selector_Profile
143 function __construct(
151 $this->_params
= $params;
153 if (is_array($ufGroupIds)) {
154 $this->_profileIds
= $ufGroupIds;
155 $this->_gid
= $ufGroupIds[0];
158 $this->_profileIds
= array($ufGroupIds);
159 $this->_gid
= $ufGroupIds;
163 $this->_editLink
= $editLink;
164 $this->_linkToUF
= $linkToUF;
166 //get the details of the uf group
168 $groupId = CRM_Core_DAO
::getFieldValue('CRM_Core_BAO_UFGroup',
169 $this->_gid
, 'limit_listings_group_id'
173 // add group id to params if a uf group belong to a any group
175 if (CRM_Utils_Array
::value('group', $this->_params
)) {
176 $this->_params
['group'][$groupId] = 1;
179 $this->_params
['group'] = array($groupId => 1);
183 $this->_fields
= CRM_Core_BAO_UFGroup
::getListingFields(CRM_Core_Action
::VIEW
,
184 CRM_Core_BAO_UFGroup
::PUBLIC_VISIBILITY |
185 CRM_Core_BAO_UFGroup
::LISTINGS_VISIBILITY
,
186 FALSE, $this->_profileIds
189 $this->_customFields
= &$customFields;
191 $returnProperties = CRM_Contact_BAO_Contact
::makeHierReturnProperties($this->_fields
);
192 $returnProperties['contact_type'] = 1;
193 $returnProperties['contact_sub_type'] = 1;
194 $returnProperties['sort_name'] = 1;
196 $queryParams = CRM_Contact_BAO_Query
::convertFormValues($this->_params
, 1);
197 $this->_query
= new CRM_Contact_BAO_Query($queryParams, $returnProperties, $this->_fields
);
199 //the below is done for query building for multirecord custom field listing
200 //to show all the custom field multi valued records of a particular contact
201 $this->setMultiRecordTableName($this->_fields
);
203 $this->_options
= &$this->_query
->_options
;
208 * This method returns the links that are given for each search row.
214 static function &links($map = FALSE, $editLink = FALSE, $ufLink = FALSE, $gids = NULL) {
215 if (!self
::$_links) {
216 self
::$_links = array();
218 $viewPermission = TRUE;
220 // check view permission for each profile id, in case multiple profile ids are rendered
221 // then view action is disabled if any profile returns false
222 foreach ($gids as $profileId) {
223 $viewPermission = CRM_Core_Permission
::ufGroupValid($profileId, CRM_Core_Permission
::VIEW
);
224 if (!$viewPermission) {
230 if ($viewPermission) {
231 self
::$_links[CRM_Core_Action
::VIEW
] = array(
232 'name' => ts('View'),
233 'url' => 'civicrm/profile/view',
234 'qs' => 'reset=1&id=%%id%%&gid=%%gid%%',
235 'title' => ts('View Profile Details'),
240 self
::$_links[CRM_Core_Action
::UPDATE
] = array(
241 'name' => ts('Edit'),
242 'url' => 'civicrm/profile/edit',
243 'qs' => 'reset=1&id=%%id%%&gid=%%gid%%',
244 'title' => ts('Edit'),
249 self
::$_links[CRM_Core_Action
::PROFILE
] = array(
250 'name' => ts('Website Profile'),
251 'url' => 'user/%%ufID%%',
253 'title' => ts('View Website Profile'),
258 self
::$_links[CRM_Core_Action
::MAP
] = array(
260 'url' => 'civicrm/profile/map',
261 'qs' => 'reset=1&cid=%%id%%&gid=%%gid%%',
262 'title' => ts('Map'),
266 return self
::$_links;
271 * getter for array of the parameters required for creating pager.
276 function getPagerParams($action, &$params) {
278 CRM_Utils_System
::isNull($this->_multiRecordTableName
) ?
ts('Contact %%StatusMessage%%') : ts('Contact Multi Records %%StatusMessage%%');
279 $params['status'] = $status;
280 $params['csvString'] = NULL;
281 $params['rowCount'] = CRM_Utils_Pager
::ROWCOUNT
;
283 $params['buttonTop'] = 'PagerTopButton';
284 $params['buttonBottom'] = 'PagerBottomButton';
289 * returns the column headers as an array of tuples:
290 * (name, sortName (key to the sort array))
292 * @param string $action the action being performed
293 * @param enum $output what should the result set include (web/email/csv)
295 * @return array the column headers that need to be displayed
298 function &getColumnHeaders($action = NULL, $output = NULL) {
299 static $skipFields = array('group', 'tag');
300 $multipleFields = array('url');
301 $direction = CRM_Utils_Sort
::ASCENDING
;
303 if (!isset(self
::$_columnHeaders)) {
304 self
::$_columnHeaders = array(array('name' => ''),
306 'name' => ts('Name'),
307 'sort' => 'sort_name',
308 'direction' => CRM_Utils_Sort
::ASCENDING
,
312 $locationTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Address', 'location_type_id');
314 foreach ($this->_fields
as $name => $field) {
315 // skip pseudo fields
316 if (substr($name, 0, 9) == 'phone_ext') {
320 if (CRM_Utils_Array
::value('in_selector', $field) &&
321 !in_array($name, $skipFields)
324 if (strpos($name, '-') !== FALSE) {
325 $value = explode('-', $name);
326 $fieldName = CRM_Utils_Array
::value(0, $value);
327 $lType = CRM_Utils_Array
::value(1, $value);
328 $type = CRM_Utils_Array
::value(2, $value);
330 if (!in_array($fieldName, $multipleFields)) {
331 if ($lType == 'Primary') {
332 $locationTypeName = 1;
335 $locationTypeName = $locationTypes[$lType];
338 if (in_array($fieldName, array(
339 'phone', 'im', 'email'))) {
341 $name = "`$locationTypeName-$fieldName-$type`";
344 $name = "`$locationTypeName-$fieldName`";
348 $name = "`$locationTypeName-$fieldName`";
352 $name = "website-{$lType}-{$fieldName}";
356 self
::$_columnHeaders[] = array(
357 'name' => $field['title'],
359 'direction' => $direction,
362 $direction = CRM_Utils_Sort
::DONTCARE
;
367 // if we dont have any valid columns, dont add the implicit ones
368 // this allows the template to check on emptiness of column headers
370 self
::$_columnHeaders = array();
373 self
::$_columnHeaders[] = array('desc' => ts('Actions'));
376 return self
::$_columnHeaders;
380 * Returns total number of rows for the query.
384 * @return int Total number of rows
387 function getTotalCount($action) {
388 $additionalWhereClause = 'contact_a.is_deleted = 0';
389 $additionalFromClause = NULL;
392 if ($this->_multiRecordTableName
&&
393 !array_key_exists($this->_multiRecordTableName
, $this->_query
->_whereTables
)) {
394 $additionalFromClause = CRM_Utils_Array
::value($this->_multiRecordTableName
, $this->_query
->_tables
);
398 $countVal = $this->_query
->searchQuery(0, 0, NULL, TRUE, NULL, NULL, NULL,
399 $returnQuery, $additionalWhereClause, NULL, $additionalFromClause
407 $sql = preg_replace('/DISTINCT/', '', $countVal);
408 return CRM_Core_DAO
::singleValueQuery($sql);
413 * Return the qill for this selector
419 return $this->_query
->qill();
423 * returns all the rows in the given offset and rowCount
425 * @param enum $action the action being performed
426 * @param int $offset the row number to start from
427 * @param int $rowCount the number of rows to return
428 * @param string $sort the sql string that describes the sort order
429 * @param enum $output what should the result set include (web/email/csv)
431 * @return int the total number of rows for this action
433 function &getRows($action, $offset, $rowCount, $sort, $output = NULL) {
435 $multipleFields = array('url');
436 //$sort object processing for location fields
438 $vars = $sort->_vars
;
440 foreach ($vars as $key => $field) {
441 $field = $vars[$key];
442 $fieldArray = explode('-', $field['name']);
443 $fieldType = CRM_Utils_Array
::value('2', $fieldArray);
444 if (is_numeric(CRM_Utils_Array
::value('1', $fieldArray))) {
445 if (!in_array($fieldType, $multipleFields)) {
446 $locationType = new CRM_Core_DAO_LocationType();
447 $locationType->id
= $fieldArray[1];
448 $locationType->find(TRUE);
449 if ($fieldArray[0] == 'email' ||
$fieldArray[0] == 'im' ||
$fieldArray[0] == 'phone') {
450 $field['name'] = "`" . $locationType->name
. "-" . $fieldArray[0] . "-1`";
453 $field['name'] = "`" . $locationType->name
. "-" . $fieldArray[0] . "`";
457 $field['name'] = "`website-" . $fieldArray[1] . "-{$fieldType}`";
460 $varArray[$key] = $field;
464 $sort->_vars
= $varArray;
466 $additionalWhereClause = 'contact_a.is_deleted = 0';
468 if ($this->_multiRecordTableName
) {
472 $result = $this->_query
->searchQuery($offset, $rowCount, $sort, NULL, NULL,
473 NULL, NULL, $returnQuery, $additionalWhereClause
477 $resQuery = preg_replace('/GROUP BY contact_a.id[\s]+ORDER BY/', ' ORDER BY', $result);
478 $result = CRM_Core_DAO
::executeQuery($resQuery);
481 // process the result of the query
484 // check if edit is configured in profile settings
486 $editLink = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $this->_gid
, 'is_edit_link');
489 //FIXME : make sure to handle delete separately. CRM-4418
490 $mask = CRM_Core_Action
::mask(array(CRM_Core_Permission
::getPermission()));
491 if ($editLink && ($mask & CRM_Core_Permission
::EDIT
)) {
492 // do not allow edit for anon users in joomla frontend, CRM-4668
493 $config = CRM_Core_Config
::singleton();
494 if (!$config->userFrameworkFrontend
) {
495 $this->_editLink
= TRUE;
498 $links = self
::links($this->_map
, $this->_editLink
, $this->_linkToUF
, $this->_profileIds
);
500 $locationTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Address', 'location_type_id');
503 static $skipFields = array('group', 'tag');
505 foreach ($this->_fields
as $key => $field) {
506 // skip pseudo fields
507 if (substr($key, 0, 9) == 'phone_ext') {
511 if (CRM_Utils_Array
::value('in_selector', $field) &&
512 !in_array($key, $skipFields)
514 if (strpos($key, '-') !== FALSE) {
515 $value = explode('-', $key);
516 $fieldName = CRM_Utils_Array
::value(0, $value);
517 $id = CRM_Utils_Array
::value(1, $value);
518 $type = CRM_Utils_Array
::value(2, $value);
520 if (!in_array($fieldName, $multipleFields)) {
521 $locationTypeName = NULL;
522 if (is_numeric($id)) {
523 $locationTypeName = CRM_Utils_Array
::value($id, $locationTypes);
526 if ($id == 'Primary') {
527 $locationTypeName = 1;
531 if (!$locationTypeName) {
534 $locationTypeName = str_replace(' ', '_', $locationTypeName);
535 if (in_array($fieldName, array(
536 'phone', 'im', 'email'))) {
538 $names[] = "{$locationTypeName}-{$fieldName}-{$type}";
541 $names[] = "{$locationTypeName}-{$fieldName}";
545 $names[] = "{$locationTypeName}-{$fieldName}";
549 $names[] = "website-{$id}-{$fieldName}";
552 elseif ($field['name'] == 'id') {
553 $names[] = 'contact_id';
556 $names[] = $field['name'];
562 $multipleSelectFields = array('preferred_communication_method' => 1);
563 $multiRecordTableId = NULL;
564 if ($this->_multiRecordTableName
) {
565 $multiRecordTableId = "{$this->_multiRecordTableName}_id";
568 // we need to determine of overlay profile should be shown
569 $showProfileOverlay = CRM_Core_BAO_UFGroup
::showOverlayProfile();
571 while ($result->fetch()) {
572 if (isset($result->country
)) {
573 // the query returns the untranslated country name
574 $i18n = CRM_Core_I18n
::singleton();
575 $result->country
= $i18n->translate($result->country
);
579 $row[] = CRM_Contact_BAO_Contact_Utils
::getImage($result->contact_sub_type ?
580 $result->contact_sub_type
: $result->contact_type
,
585 if ($result->sort_name
) {
586 $row['sort_name'] = $result->sort_name
;
593 foreach ($names as $name) {
594 if ($cfID = CRM_Core_BAO_CustomField
::getKeyID($name)) {
595 $row[] = CRM_Core_BAO_CustomField
::getDisplayValue($result->$name,
601 elseif (substr($name, -4) == '-url' &&
602 !empty($result->$name)
604 $url = CRM_Utils_System
::fixURL($result->$name);
605 $typeId = substr($name, 0, -4) . "-website_type_id";
606 $typeName = CRM_Core_PseudoConstant
::getValue('CRM_Core_DAO_Website', 'website_type_id', $result->$typeId);
608 $row[] = "<a href=\"$url\">{$result->$name} (${typeName})</a>";
611 $row[] = "<a href=\"$url\">{$result->$name}</a>";
614 elseif ($name == 'preferred_language') {
615 $row[] = CRM_Core_PseudoConstant
::getValue('CRM_Contact_DAO_Contact', 'preferred_language', $result->$name);
617 elseif ($multipleSelectFields &&
618 array_key_exists($name, $multipleSelectFields)
620 // FIXME: Code related to the old CRM_Quest - should be removed
622 $paramsNew = array($key => $result->$name);
623 if ($key == 'test_tutoring') {
624 $name = array($key => array('newName' => $key, 'groupName' => 'test'));
627 elseif (substr($key, 0, 4) == 'cmr_') {
629 $key => array('newName' => $key,
630 'groupName' => substr($key, 0, -3),
634 $name = array($key => array('newName' => $key, 'groupName' => $key));
636 CRM_Core_OptionGroup
::lookupValues($paramsNew, $name, FALSE);
637 $row[] = $paramsNew[$key];
639 elseif (strpos($name, '-im')) {
640 if (!empty($result->$name)) {
641 $providerId = $name . "-provider_id";
642 $providerName = CRM_Core_PseudoConstant
::getValue('CRM_Core_DAO_IM', 'provider_id', $result->$providerId);
643 $row[] = $result->$name . " ({$providerName})";
649 elseif (strpos($name, '-phone-')) {
650 $phoneExtField = str_replace('phone', 'phone_ext', $name);
651 if (isset($result->$phoneExtField)) {
652 $row[] = $result->$name . " (" . $result->$phoneExtField . ")";
655 $row[] = $result->$name;
658 elseif (in_array($name, array(
659 'addressee', 'email_greeting', 'postal_greeting'))) {
660 $dname = $name . '_display';
661 $row[] = $result->$dname;
663 elseif (in_array($name, array(
664 'birth_date', 'deceased_date'))) {
665 $row[] = CRM_Utils_Date
::customFormat($result->$name);
667 elseif (isset($result->$name)) {
668 $row[] = $result->$name;
674 if (!empty($result->$name)) {
681 'id' => $result->contact_id
,
682 'gid' => implode(',', $this->_profileIds
),
685 // pass record id param to view url for multi record view
686 if ($multiRecordTableId && $newLinks) {
687 if ($result->$multiRecordTableId){
688 if ($newLinks[CRM_Core_Action
::VIEW
]['url'] == 'civicrm/profile/view') {
689 $newLinks[CRM_Core_Action
::VIEW
]['qs'] .= "&multiRecord=view&recordId=%%recordId%%&allFields=1";
690 $params['recordId'] = $result->$multiRecordTableId;
695 if ($this->_linkToUF
) {
696 $ufID = CRM_Core_BAO_UFMatch
::getUFId($result->contact_id
);
698 unset($newLinks[CRM_Core_Action
::PROFILE
]);
701 $params['ufID'] = $ufID;
705 $row[] = CRM_Core_Action
::formLink($newLinks,
718 * name of export file.
720 * @param string $output type of output
722 * @return string name of the file
724 function getExportFileName($output = 'csv') {
725 return ts('CiviCRM Profile Listings');
729 * set the _multiRecordTableName to display the result set
730 * according to multi record custom field values
732 function setMultiRecordTableName($fields) {
733 $customGroupId = $multiRecordTableName = NULL;
734 $selectorSet = FALSE;
736 foreach ($fields as $field => $properties) {
737 if (!CRM_Core_BAO_CustomField
::getKeyID($field)) {
740 if ($cgId = CRM_Core_BAO_CustomField
::isMultiRecordField($field)) {
741 $customGroupId = CRM_Utils_System
::isNull($customGroupId) ?
$cgId : $customGroupId;
743 //if the field is submitted set multiRecordTableName
744 if ($customGroupId) {
745 $isSubmitted = FALSE;
746 foreach ($this->_query
->_params
as $key => $value) {
747 //check the query params 'where' element
748 if ($value[0] == $field) {
755 $this->_multiRecordTableName
= $multiRecordTableName =
756 CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroupId, 'table_name');
757 if ($multiRecordTableName) {
762 if (CRM_Utils_Array
::value('in_selector', $properties)) {
769 if (!isset($customGroupId) ||
!$customGroupId) {
773 //if the field is in selector and not a searchable field
774 //get the proper customvalue table name
776 $this->_multiRecordTableName
= $multiRecordTableName =
777 CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroupId, 'table_name');