3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
19 * This implements the profile page for all contacts. It uses a selector
20 * object to do the actual display. The fields displayed are controlled by
23 class CRM_Profile_Page_Listings
extends CRM_Core_Page
{
26 * All the fields that are listings related.
33 * The custom fields for this domain.
37 protected $_customFields;
40 * The input params from the request.
47 * The group id that we are editing.
54 * State whether to display search form or not.
61 * Should we display a map.
68 * Store profile ids if multiple profile ids are passed using comma separated.
69 * Currently lets implement this functionality only for dialog mode
72 protected $_profileIds = [];
75 * Extracts the parameters from the request and constructs information for
76 * the selector object to do a query
79 public function preProcess() {
81 $this->_search
= TRUE;
83 $search = CRM_Utils_Request
::retrieve('search', 'Boolean', $this, FALSE, 0, 'GET');
84 if (isset($search) && $search == 0) {
85 $this->_search
= FALSE;
88 $this->_gid
= $this->get('gid');
89 $this->_profileIds
= $this->get('profileIds');
91 $gids = explode(',', CRM_Utils_Request
::retrieve('gid', 'String', CRM_Core_DAO
::$_nullObject, FALSE, 0, 'GET'));
93 if ((count($gids) > 1) && !$this->_profileIds
&& empty($this->_profileIds
)) {
95 foreach ($gids as $pfId) {
96 $this->_profileIds
[] = CRM_Utils_Type
::escape($pfId, 'Positive');
100 // check if we are rendering mixed profiles
101 if (CRM_Core_BAO_UFGroup
::checkForMixProfiles($this->_profileIds
)) {
102 CRM_Core_Error
::statusBounce(ts('You cannot combine profiles of multiple types.'));
105 $this->_gid
= $this->_profileIds
[0];
106 $this->set('profileIds', $this->_profileIds
);
107 $this->set('gid', $this->_gid
);
111 $this->_gid
= CRM_Utils_Request
::retrieve('gid', 'Positive', $this, FALSE, 0, 'GET');
114 if (empty($this->_profileIds
)) {
118 $gids = $this->_profileIds
;
121 $this->_fields
= CRM_Core_BAO_UFGroup
::getListingFields(CRM_Core_Action
::UPDATE
,
122 CRM_Core_BAO_UFGroup
::PUBLIC_VISIBILITY | CRM_Core_BAO_UFGroup
::LISTINGS_VISIBILITY
,
123 FALSE, $gids, FALSE, 'Profile',
124 CRM_Core_Permission
::SEARCH
127 $this->_customFields
= CRM_Core_BAO_CustomField
::getFieldsForImport(NULL, FALSE, FALSE, FALSE, TRUE, TRUE);
133 'preferred_communication_method',
142 foreach ($this->_fields
as $name => $field) {
143 if ((substr($name, 0, 6) == 'custom') && !empty($field['is_search_range'])) {
144 $from = CRM_Utils_Request
::retrieve($name . '_from', 'String', $this);
145 $to = CRM_Utils_Request
::retrieve($name . '_to', 'String', $this);
148 $value[$name . '_from'] = $from;
149 $value[$name . '_to'] = $to;
152 $value[$name . '_from'] = $from;
155 $value[$name . '_to'] = $to;
158 elseif ((substr($name, 0, 7) == 'custom_') &&
159 (CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomField',
160 substr($name, 7), 'html_type'
163 $value = trim(CRM_Utils_Request
::retrieve($name, 'String',
164 $this, FALSE, NULL, 'REQUEST'
166 if (!empty($value) &&
167 !((substr($value, 0, 1) == '%') &&
168 (substr($value, -1, 1) == '%')
171 $value = '%' . $value . '%';
174 elseif (CRM_Utils_Array
::value('html_type', $field) == 'Multi-Select State/Province'
175 || CRM_Utils_Array
::value('html_type', $field) == 'Multi-Select Country'
177 $value = CRM_Utils_Request
::retrieve($name, 'String', $this, FALSE, NULL, 'REQUEST');
178 if (!is_array($value)) {
179 $value = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, substr($value, 1, -1));
182 elseif ($name == 'contact_sub_type') {
183 $v = CRM_Utils_Request
::retrieve($name, 'String', $this, FALSE, NULL, 'REQUEST');
184 if ($v && !is_array($v)) {
185 $v = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, trim($v, CRM_Core_DAO
::VALUE_SEPARATOR
));
188 foreach ($v as $item) {
194 $value = CRM_Utils_Request
::retrieve($name, 'String',
195 $this, FALSE, NULL, 'REQUEST'
199 if (($name == 'group' ||
$name == 'tag') && !empty($value) && !is_array($value)) {
200 $v = explode(',', $value);
202 foreach ($v as $item) {
207 $customField = $this->_customFields
[$name] ??
NULL;
209 if (!empty($_POST) && empty($_POST[$name])) {
211 // reset checkbox/radio because a form does not send null checkbox values
212 if (in_array($customField['html_type'],
213 ['Multi-Select', 'CheckBox', 'Multi-Select State/Province', 'Multi-Select Country', 'Radio', 'Select']
215 // only reset on a POST submission if we don't see any value
217 $this->set($name, $value);
220 elseif (in_array($name, $resetArray)) {
222 $this->set($name, $value);
226 if (isset($value) && $value != NULL) {
227 if (!is_array($value)) {
228 $value = trim($value);
230 $operator = CRM_Utils_Request
::retrieve($name . '_operator', 'String', $this);
232 $this->_params
[$name . '_operator'] = $operator;
234 if ((substr($name, 0, 6) == 'custom') && !empty($field['is_search_range'])) {
235 $this->_params +
= $value;
238 $this->_params
[$name] = $this->_fields
[$name]['value'] = $value;
243 // set the prox params
244 // need to ensure proximity searching is enabled
254 foreach ($proximityVars as $var) {
255 $value = CRM_Utils_Request
::retrieve("prox_{$var}",
257 $this, FALSE, NULL, 'REQUEST'
260 $this->_params
["prox_{$var}"] = $value;
264 // set the params in session
265 $session = CRM_Core_Session
::singleton();
266 $session->set('profileParams', $this->_params
);
270 * Run this page (figure out the action needed and perform it).
273 public function run() {
276 $this->assign('recentlyViewed', FALSE);
277 // override later (if possible):
278 $this->assign('ufGroupName', 'unknown');
281 $ufgroupDAO = new CRM_Core_DAO_UFGroup();
282 $ufgroupDAO->id
= $this->_gid
;
283 if (!$ufgroupDAO->find(TRUE)) {
284 CRM_Core_Error
::statusBounce(ts('Unable to find matching UF Group'));
289 // set the title of the page
290 if ($ufgroupDAO->title
) {
291 CRM_Utils_System
::setTitle($ufgroupDAO->title
);
293 if ($ufgroupDAO->name
) {
294 $this->assign('ufGroupName', $ufgroupDAO->name
);
298 $this->assign('isReset', TRUE);
300 $formController = new CRM_Core_Controller_Simple('CRM_Profile_Form_Search',
301 ts('Search Profile'),
304 $formController->setEmbedded(TRUE);
305 $formController->set('gid', $this->_gid
);
306 $formController->process();
308 $searchError = FALSE;
309 // check if there is a POST
310 if (!empty($_POST)) {
311 if ($formController->validate() !== TRUE) {
316 // also get the search tpl name
317 $this->assign('searchTPL', $formController->getHookedTemplateFileName());
319 $this->assign('search', $this->_search
);
321 // search if search returned a form error?
322 if ((empty($_GET['reset']) ||
!empty($_GET['force'])) &&
325 $this->assign('isReset', FALSE);
327 $gidString = $this->_gid
;
328 if (empty($this->_profileIds
)) {
332 $gids = $this->_profileIds
;
333 $gidString = implode(',', $this->_profileIds
);
340 $map = $ufgroupDAO->is_map
;
341 $linkToUF = $ufgroupDAO->is_uf_link
;
342 $editLink = $ufgroupDAO->is_edit_link
;
346 $this->assign('mapURL',
347 CRM_Utils_System
::url('civicrm/profile/map',
348 "map=1&gid={$gidString}&reset=1"
352 if (!empty($this->_params
['group'])) {
353 foreach ($this->_params
['group'] as $key => $val) {
355 unset($this->_params
['group'][$key]);
360 // the selector will override this if the user does have
361 // edit permissions as determined by the mask, CRM-4341
362 // do not allow edit for anon users in joomla frontend, CRM-4668
363 $config = CRM_Core_Config
::singleton();
364 if (!CRM_Core_Permission
::check('access CiviCRM') ||
365 $config->userFrameworkFrontend
== 1
370 $selector = new CRM_Profile_Selector_Listings($this->_params
, $this->_customFields
, $gids,
371 $map, $editLink, $linkToUF
374 $controller = new CRM_Core_Selector_Controller($selector,
375 $this->get(CRM_Utils_Pager
::PAGE_ID
),
376 $this->get(CRM_Utils_Sort
::SORT_ID
),
377 CRM_Core_Action
::VIEW
,
379 CRM_Core_Selector_Controller
::TEMPLATE
381 $controller->setEmbedded(TRUE);
385 //CRM-6862 -run form controller after
386 //selector, since it erase $_POST
387 $formController->run();
389 return parent
::run();
393 * Get the list of contacts for a profile.
399 public static function getProfileContact($gid) {
400 $session = CRM_Core_Session
::singleton();
401 $params = $session->get('profileParams');
404 $ufGroupParam = ['id' => $gid];
405 CRM_Core_BAO_UFGroup
::retrieve($ufGroupParam, $details);
407 // make sure this group can be mapped
408 if (!$details['is_map']) {
409 CRM_Core_Error
::statusBounce(ts('This profile does not have the map feature turned on.'));
412 $groupId = $details['limit_listings_group_id'] ??
NULL;
414 // add group id to params if a uf group belong to a any group
416 if (!empty($params['group'])) {
417 $params['group'][$groupId] = 1;
420 $params['group'] = [$groupId => 1];
424 $fields = CRM_Core_BAO_UFGroup
::getListingFields(
425 CRM_Core_Action
::VIEW
,
426 CRM_Core_BAO_UFGroup
::PUBLIC_VISIBILITY | CRM_Core_BAO_UFGroup
::LISTINGS_VISIBILITY
,
431 $returnProperties = CRM_Contact_BAO_Contact
::makeHierReturnProperties($fields);
432 $returnProperties['contact_type'] = 1;
433 $returnProperties['sort_name'] = 1;
435 $queryParams = CRM_Contact_BAO_Query
::convertFormValues($params, 1);
436 $query = new CRM_Contact_BAO_Query($queryParams, $returnProperties, $fields);
438 $additionalWhereClause = 'contact_a.is_deleted = 0';
440 $ids = $query->searchQuery(0, 0, NULL,
443 $additionalWhereClause
446 $contactIds = explode(',', $ids);
452 * @param string $suffix
454 * @return null|string
456 public function checkTemplateFileExists($suffix = '') {
458 $templateFile = "CRM/Profile/Page/{$this->_gid}/Listings.{$suffix}tpl";
459 $template = CRM_Core_Page
::getTemplate();
460 if ($template->template_exists($templateFile)) {
461 return $templateFile;
464 // lets see if we have customized by name
465 $ufGroupName = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $this->_gid
, 'name');
467 $templateFile = "CRM/Profile/Page/{$ufGroupName}/Listings.{$suffix}tpl";
468 if ($template->template_exists($templateFile)) {
469 return $templateFile;
477 * Use the form name to create the tpl file name.
481 public function getTemplateFileName() {
482 $fileName = $this->checkTemplateFileExists();
483 return $fileName ?
$fileName : parent
::getTemplateFileName();
487 * Default extra tpl file basically just replaces .tpl with .extra.tpl
488 * i.e. we dont override
492 public function overrideExtraTemplateFileName() {
493 $fileName = $this->checkTemplateFileExists('extra.');
494 return $fileName ?
$fileName : parent
::overrideExtraTemplateFileName();