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