Merge pull request #9415 from lcdservices/CRM-19668
[civicrm-core.git] / CRM / Profile / Page / Listings.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
7e9e8871 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
fa938177 6 | Copyright CiviCRM LLC (c) 2004-2016 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
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. |
13 | |
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. |
18 | |
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
fa938177 31 * @copyright CiviCRM LLC (c) 2004-2016
6a488035
TO
32 *
33 */
34
35/**
36 * This implements the profile page for all contacts. It uses a selector
37 * object to do the actual dispay. The fields displayd are controlled by
abdd5e3e 38 * the admin.
6a488035
TO
39 */
40class CRM_Profile_Page_Listings extends CRM_Core_Page {
41
42 /**
abdd5e3e 43 * All the fields that are listings related.
6a488035
TO
44 *
45 * @var array
6a488035
TO
46 */
47 protected $_fields;
48
49 /**
abdd5e3e 50 * The custom fields for this domain.
6a488035
TO
51 *
52 * @var array
6a488035
TO
53 */
54 protected $_customFields;
55
56 /**
abdd5e3e 57 * The input params from the request.
6a488035
TO
58 *
59 * @var array
6a488035
TO
60 */
61 protected $_params;
62
63 /**
abdd5e3e 64 * The group id that we are editing.
6a488035
TO
65 *
66 * @var int
67 */
68 protected $_gid;
69
70 /**
abdd5e3e 71 * State whether to display search form or not.
6a488035
TO
72 *
73 * @var int
74 */
75 protected $_search;
76
77 /**
abdd5e3e 78 * Should we display a map.
6a488035
TO
79 *
80 * @var int
81 */
82 protected $_map;
83
84 /**
85 * Store profile ids if multiple profile ids are passed using comma separated.
86 * Currently lets implement this functionality only for dialog mode
87 */
88 protected $_profileIds = array();
89
90 /**
100fef9d 91 * Extracts the parameters from the request and constructs information for
6a488035
TO
92 * the selector object to do a query
93 *
6a488035 94 */
00be9182 95 public function preProcess() {
6a488035
TO
96
97 $this->_search = TRUE;
98
99 $search = CRM_Utils_Request::retrieve('search', 'Boolean', $this, FALSE, 0, 'GET');
100 if (isset($search) && $search == 0) {
101 $this->_search = FALSE;
102 }
103
104 $this->_gid = $this->get('gid');
105 $this->_profileIds = $this->get('profileIds');
106
107 $gids = explode(',', CRM_Utils_Request::retrieve('gid', 'String', CRM_Core_DAO::$_nullObject, FALSE, 0, 'GET'));
108
109 if ((count($gids) > 1) && !$this->_profileIds && empty($this->_profileIds)) {
110 if (!empty($gids)) {
111 foreach ($gids as $pfId) {
112 $this->_profileIds[] = CRM_Utils_Type::escape($pfId, 'Positive');
113 }
114 }
115
116 // check if we are rendering mixed profiles
117 if (CRM_Core_BAO_UFGroup::checkForMixProfiles($this->_profileIds)) {
118 CRM_Core_Error::fatal(ts('You cannot combine profiles of multiple types.'));
119 }
120
121 $this->_gid = $this->_profileIds[0];
122 $this->set('profileIds', $this->_profileIds);
123 $this->set('gid', $this->_gid);
124 }
125
126 if (!$this->_gid) {
127 $this->_gid = CRM_Utils_Request::retrieve('gid', 'Positive', $this, FALSE, 0, 'GET');
128 }
129
130 if (empty($this->_profileIds)) {
131 $gids = $this->_gid;
132 }
133 else {
134 $gids = $this->_profileIds;
135 }
136
137 $this->_fields = CRM_Core_BAO_UFGroup::getListingFields(CRM_Core_Action::UPDATE,
138 CRM_Core_BAO_UFGroup::PUBLIC_VISIBILITY | CRM_Core_BAO_UFGroup::LISTINGS_VISIBILITY,
139 FALSE, $gids, FALSE, 'Profile',
140 CRM_Core_Permission::SEARCH
141 );
142
143 $this->_customFields = CRM_Core_BAO_CustomField::getFieldsForImport(NULL, FALSE, FALSE, FALSE, TRUE, TRUE);
144 $this->_params = array();
145
146 $resetArray = array(
353ffa53
TO
147 'group',
148 'tag',
149 'preferred_communication_method',
150 'do_not_phone',
151 'do_not_email',
152 'do_not_mail',
153 'do_not_sms',
154 'do_not_trade',
155 'gender',
6a488035
TO
156 );
157
158 foreach ($this->_fields as $name => $field) {
8cc574cf 159 if ((substr($name, 0, 6) == 'custom') && !empty($field['is_search_range'])) {
3130209f
CW
160 $from = CRM_Utils_Request::retrieve($name . '_from', 'String', $this);
161 $to = CRM_Utils_Request::retrieve($name . '_to', 'String', $this);
6a488035
TO
162 $value = array();
163 if ($from && $to) {
164 $value['from'] = $from;
165 $value['to'] = $to;
166 }
167 elseif ($from) {
168 $value['from'] = $from;
169 }
170 elseif ($to) {
171 $value['to'] = $to;
172 }
173 }
174 elseif ((substr($name, 0, 7) == 'custom_') &&
175 (CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField',
176 substr($name, 7), 'html_type'
177 ) == 'TextArea')
178 ) {
179 $value = trim(CRM_Utils_Request::retrieve($name, 'String',
353ffa53
TO
180 $this, FALSE, NULL, 'REQUEST'
181 ));
6a488035
TO
182 if (!empty($value) &&
183 !((substr($value, 0, 1) == '%') &&
184 (substr($value, -1, 1) == '%')
185 )
186 ) {
187 $value = '%' . $value . '%';
188 }
189 }
190 elseif (CRM_Utils_Array::value('html_type', $field) == 'Multi-Select State/Province'
191 || CRM_Utils_Array::value('html_type', $field) == 'Multi-Select Country'
192 ) {
193 $value = CRM_Utils_Request::retrieve($name, 'String', $this, FALSE, NULL, 'REQUEST');
194 if (!is_array($value)) {
195 $value = explode(CRM_Core_DAO::VALUE_SEPARATOR, substr($value, 1, -1));
196 }
197 }
198 elseif ($name == 'contact_sub_type') {
199 $v = CRM_Utils_Request::retrieve($name, 'String', $this, FALSE, NULL, 'REQUEST');
200 if ($v && !is_array($v)) {
201 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, trim($v, CRM_Core_DAO::VALUE_SEPARATOR));
202 }
203 if (!empty($v)) {
204 foreach ($v as $item) {
205 $value[$item] = 1;
206 }
207 }
208 }
209 else {
210 $value = CRM_Utils_Request::retrieve($name, 'String',
211 $this, FALSE, NULL, 'REQUEST'
212 );
213 }
214
215 if (($name == 'group' || $name == 'tag') && !empty($value) && !is_array($value)) {
216 $v = explode(',', $value);
217 $value = array();
218 foreach ($v as $item) {
219 $value[$item] = 1;
220 }
221 }
222
223 $customField = CRM_Utils_Array::value($name, $this->_customFields);
224
8cc574cf 225 if (!empty($_POST) && empty($_POST[$name])) {
6a488035
TO
226 if ($customField) {
227 // reset checkbox/radio because a form does not send null checkbox values
228 if (in_array($customField['html_type'],
e3467d2e 229 array('Multi-Select', 'CheckBox', 'Multi-Select State/Province', 'Multi-Select Country', 'Radio', 'Select')
353ffa53 230 )) {
abdd5e3e 231 // only reset on a POST submission if we don't see any value
6a488035
TO
232 $value = NULL;
233 $this->set($name, $value);
234 }
235 }
236 elseif (in_array($name, $resetArray)) {
237 $value = NULL;
238 $this->set($name, $value);
239 }
240 }
241
242 if (isset($value) && $value != NULL) {
243 if (!is_array($value)) {
244 $value = trim($value);
245 }
3130209f
CW
246 $operator = CRM_Utils_Request::retrieve($name . '_operator', 'String', $this);
247 if ($operator) {
248 $this->_params[$name . '_operator'] = $operator;
249 }
6a488035
TO
250 $this->_params[$name] = $this->_fields[$name]['value'] = $value;
251 }
252 }
253
254 // set the prox params
255 // need to ensure proximity searching is enabled
256 $proximityVars = array(
353ffa53
TO
257 'street_address',
258 'city',
259 'postal_code',
260 'state_province_id',
261 'country_id',
262 'distance',
263 'distance_unit',
6a488035
TO
264 );
265 foreach ($proximityVars as $var) {
266 $value = CRM_Utils_Request::retrieve("prox_{$var}",
267 'String',
268 $this, FALSE, NULL, 'REQUEST'
269 );
270 if ($value) {
271 $this->_params["prox_{$var}"] = $value;
272 }
273 }
274
6a488035
TO
275 // set the params in session
276 $session = CRM_Core_Session::singleton();
277 $session->set('profileParams', $this->_params);
278 }
279
280 /**
100fef9d 281 * Run this page (figure out the action needed and perform it).
6a488035 282 *
6a488035 283 */
00be9182 284 public function run() {
6a488035
TO
285 $this->preProcess();
286
287 $this->assign('recentlyViewed', FALSE);
c5c263ca
AH
288 // override later (if possible):
289 $this->assign('ufGroupName', 'unknown');
6a488035
TO
290
291 if ($this->_gid) {
292 $ufgroupDAO = new CRM_Core_DAO_UFGroup();
293 $ufgroupDAO->id = $this->_gid;
294 if (!$ufgroupDAO->find(TRUE)) {
295 CRM_Core_Error::fatal();
296 }
297 }
298
299 if ($this->_gid) {
300 // set the title of the page
301 if ($ufgroupDAO->title) {
302 CRM_Utils_System::setTitle($ufgroupDAO->title);
303 }
46312a4d
TO
304 if ($ufgroupDAO->name) {
305 $this->assign('ufGroupName', $ufgroupDAO->name);
306 }
6a488035
TO
307 }
308
309 $this->assign('isReset', TRUE);
310
311 $formController = new CRM_Core_Controller_Simple('CRM_Profile_Form_Search',
312 ts('Search Profile'),
313 CRM_Core_Action::ADD
314 );
315 $formController->setEmbedded(TRUE);
316 $formController->set('gid', $this->_gid);
317 $formController->process();
318
319 $searchError = FALSE;
320 // check if there is a POST
321 if (!empty($_POST)) {
322 if ($formController->validate() !== TRUE) {
323 $searchError = TRUE;
324 }
325 }
326
327 // also get the search tpl name
8aac22c8 328 $this->assign('searchTPL', $formController->getHookedTemplateFileName());
6a488035
TO
329
330 $this->assign('search', $this->_search);
331
332 // search if search returned a form error?
8cc574cf 333 if ((empty($_GET['reset']) || !empty($_GET['force'])) &&
6a488035
TO
334 !$searchError
335 ) {
336 $this->assign('isReset', FALSE);
337
338 $gidString = $this->_gid;
339 if (empty($this->_profileIds)) {
340 $gids = $this->_gid;
341 }
342 else {
343 $gids = $this->_profileIds;
344 $gidString = implode(',', $this->_profileIds);
345 }
346
353ffa53 347 $map = 0;
6a488035
TO
348 $linkToUF = 0;
349 $editLink = FALSE;
350 if ($this->_gid) {
353ffa53 351 $map = $ufgroupDAO->is_map;
6a488035
TO
352 $linkToUF = $ufgroupDAO->is_uf_link;
353 $editLink = $ufgroupDAO->is_edit_link;
354 }
355
356 if ($map) {
357 $this->assign('mapURL',
358 CRM_Utils_System::url('civicrm/profile/map',
359 "map=1&gid={$gidString}&reset=1"
360 )
361 );
362 }
a7488080 363 if (!empty($this->_params['group'])) {
6a488035
TO
364 foreach ($this->_params['group'] as $key => $val) {
365 if (!$val) {
366 unset($this->_params['group'][$key]);
367 }
368 }
369 }
370
371 // the selector will override this if the user does have
372 // edit permissions as determined by the mask, CRM-4341
373 // do not allow edit for anon users in joomla frontend, CRM-4668
374 $config = CRM_Core_Config::singleton();
375 if (!CRM_Core_Permission::check('access CiviCRM') ||
376 $config->userFrameworkFrontend == 1
377 ) {
378 $editLink = FALSE;
379 }
380
381 $selector = new CRM_Profile_Selector_Listings($this->_params, $this->_customFields, $gids,
382 $map, $editLink, $linkToUF
383 );
384
385 $controller = new CRM_Core_Selector_Controller($selector,
386 $this->get(CRM_Utils_Pager::PAGE_ID),
387 $this->get(CRM_Utils_Sort::SORT_ID),
388 CRM_Core_Action::VIEW,
389 $this,
390 CRM_Core_Selector_Controller::TEMPLATE
391 );
392 $controller->setEmbedded(TRUE);
393 $controller->run();
394 }
395
abdd5e3e 396 //CRM-6862 -run form controller after
6a488035
TO
397 //selector, since it erase $_POST
398 $formController->run();
399
400 return parent::run();
401 }
402
403 /**
fe482240 404 * Get the list of contacts for a profile.
6a488035 405 *
100fef9d 406 * @param int $gid
77b97be7
EM
407 *
408 * @return array
6a488035 409 */
c3c3e099 410 public static function getProfileContact($gid) {
6a488035
TO
411 $session = CRM_Core_Session::singleton();
412 $params = $session->get('profileParams');
413
414 $details = array();
415 $ufGroupParam = array('id' => $gid);
416 CRM_Core_BAO_UFGroup::retrieve($ufGroupParam, $details);
417
418 // make sure this group can be mapped
419 if (!$details['is_map']) {
420 CRM_Core_Error::statusBounce(ts('This profile does not have the map feature turned on.'));
421 }
422
423 $groupId = CRM_Utils_Array::value('limit_listings_group_id', $details);
424
425 // add group id to params if a uf group belong to a any group
426 if ($groupId) {
a7488080 427 if (!empty($params['group'])) {
6a488035
TO
428 $params['group'][$groupId] = 1;
429 }
430 else {
431 $params['group'] = array($groupId => 1);
432 }
433 }
434
435 $fields = CRM_Core_BAO_UFGroup::getListingFields(
436 CRM_Core_Action::VIEW,
437 CRM_Core_BAO_UFGroup::PUBLIC_VISIBILITY | CRM_Core_BAO_UFGroup::LISTINGS_VISIBILITY,
438 FALSE,
439 $gid
440 );
441
442 $returnProperties = CRM_Contact_BAO_Contact::makeHierReturnProperties($fields);
443 $returnProperties['contact_type'] = 1;
444 $returnProperties['sort_name'] = 1;
445
446 $queryParams = CRM_Contact_BAO_Query::convertFormValues($params, 1);
447 $query = new CRM_Contact_BAO_Query($queryParams, $returnProperties, $fields);
448
449 $additionalWhereClause = 'contact_a.is_deleted = 0';
450
451 $ids = $query->searchQuery(0, 0, NULL,
452 FALSE, FALSE, FALSE,
453 TRUE, FALSE,
454 $additionalWhereClause
455 );
456
457 $contactIds = explode(',', $ids);
458
459 return $contactIds;
460 }
461
ffd93213
EM
462 /**
463 * @param string $suffix
464 *
465 * @return null|string
466 */
00be9182 467 public function checkTemplateFileExists($suffix = '') {
6a488035
TO
468 if ($this->_gid) {
469 $templateFile = "CRM/Profile/Page/{$this->_gid}/Listings.{$suffix}tpl";
470 $template = CRM_Core_Page::getTemplate();
471 if ($template->template_exists($templateFile)) {
472 return $templateFile;
473 }
474
475 // lets see if we have customized by name
476 $ufGroupName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $this->_gid, 'name');
477 if ($ufGroupName) {
478 $templateFile = "CRM/Profile/Page/{$ufGroupName}/Listings.{$suffix}tpl";
479 if ($template->template_exists($templateFile)) {
480 return $templateFile;
481 }
482 }
483 }
484 return NULL;
485 }
486
ffd93213 487 /**
fe482240 488 * Use the form name to create the tpl file name.
ffd93213
EM
489 *
490 * @return string
ffd93213 491 */
00be9182 492 public function getTemplateFileName() {
6a488035
TO
493 $fileName = $this->checkTemplateFileExists();
494 return $fileName ? $fileName : parent::getTemplateFileName();
495 }
496
ffd93213
EM
497 /**
498 * Default extra tpl file basically just replaces .tpl with .extra.tpl
499 * i.e. we dont override
500 *
501 * @return string
ffd93213 502 */
00be9182 503 public function overrideExtraTemplateFileName() {
6a488035
TO
504 $fileName = $this->checkTemplateFileExists('extra.');
505 return $fileName ? $fileName : parent::overrideExtraTemplateFileName();
506 }
96025800 507
6a488035 508}