ignore uf_join module for reserved profiles CRM-14488
[civicrm-core.git] / CRM / Core / BAO / UFGroup.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
06b69b18 4 | CiviCRM version 4.5 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
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 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35
36/**
37 *
38 */
39class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup {
40 CONST PUBLIC_VISIBILITY = 1,
41 ADMIN_VISIBILITY = 2,
42 LISTINGS_VISIBILITY = 4;
43
44 /**
45 * cache the match clause used in this transaction
46 *
47 * @var string
48 */
49 static $_matchFields = NULL;
50
51 /**
52 * Takes a bunch of params that are needed to match certain criteria and
53 * retrieves the relevant objects. Typically the valid params are only
54 * contact_id. We'll tweak this function to be more full featured over a period
55 * of time. This is the inverse function of create. It also stores all the retrieved
56 * values in the default array
57 *
58 * @param array $params (reference) an assoc array of name/value pairs
59 * @param array $defaults (reference) an assoc array to hold the flattened values
60 *
61 * @return object CRM_Core_DAO_UFGroup object
62 * @access public
63 * @static
64 */
65 static function retrieve(&$params, &$defaults) {
66 return CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_UFGroup', $params, $defaults);
67 }
68
69 /**
70 * Retrieve the first non-generic contact type
71 *
72 * @param int $id id of uf_group
73 *
74 * @return string contact type
75 */
76 static function getContactType($id) {
77
78 $validTypes = array_filter(array_keys(CRM_Core_SelectValues::contactType()));
79 $validSubTypes = CRM_Contact_BAO_ContactType::subTypeInfo();
80
81 $typesParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $id, 'group_type'));
82 $types = explode(',', $typesParts[0]);
83
84 $cType = NULL;
85 foreach ($types as $type) {
86 if (in_array($type, $validTypes)) {
87 $cType = $type;
88 }
89 elseif (array_key_exists($type, $validSubTypes)) {
90 $cType = CRM_Utils_Array::value('parent', $validSubTypes[$type]);
91 }
92 if ($cType)
93 break;
94 }
95
96 return $cType;
97 }
98
99 /**
100 * Get the form title.
101 *
102 * @param int $id id of uf_form
103 *
104 * @return string title
105 *
106 * @access public
107 * @static
108 *
109 */
110 public static function getTitle($id) {
111 return CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $id, 'title');
112 }
113
114 /**
115 * update the is_active flag in the db
116 *
117 * @param int $id id of the database record
118 * @param boolean $is_active value we want to set the is_active field
119 *
120 * @return Object CRM_Core_DAO_UFGroup object on success, null otherwise
121 * @access public
122 * @static
123 */
124 static function setIsActive($id, $is_active) {
125 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $id, 'is_active', $is_active);
126 }
127
128 /**
129 * get all the registration fields
130 *
da6b46f4
EM
131 * @param int $action what action are we doing
132 * @param int $mode mode
133 *
134 * @param null $ctype
6a488035
TO
135 *
136 * @return array the fields that are needed for registration
137 * @static
138 * @access public
139 */
140 static function getRegistrationFields($action, $mode, $ctype = NULL) {
141 if ($mode & CRM_Profile_Form::MODE_REGISTER) {
142 $ufGroups = CRM_Core_BAO_UFGroup::getModuleUFGroup('User Registration');
143 }
144 else {
145 $ufGroups = CRM_Core_BAO_UFGroup::getModuleUFGroup('Profile');
146 }
147
148 if (!is_array($ufGroups)) {
149 return FALSE;
150 }
151
152 $fields = array();
153
154 foreach ($ufGroups as $id => $title) {
155 if ($ctype) {
156 $fieldType = CRM_Core_BAO_UFField::getProfileType($id);
157 if (($fieldType != 'Contact') &&
158 ($fieldType != $ctype) &&
159 !CRM_Contact_BAO_ContactType::isExtendsContactType($fieldType, $ctype)
160 ) {
161 continue;
162 }
163 if (CRM_Contact_BAO_ContactType::isaSubType($fieldType)) {
164 $profileSubType = $fieldType;
165 }
166 }
167
168 $subset = self::getFields($id, TRUE, $action,
169 NULL, NULL, FALSE, NULL, TRUE, $ctype
170 );
171
172 // we do not allow duplicates. the first field is the winner
173 foreach ($subset as $name => $field) {
a7488080 174 if (empty($fields[$name])) {
6a488035
TO
175 $fields[$name] = $field;
176 }
177 }
178 }
179
180 return $fields;
181 }
182
183 /**
184 * get all the listing fields
185 *
da6b46f4
EM
186 * @param int $action what action are we doing
187 * @param int $visibility visibility of fields we are interested in
188 * @param bool $considerSelector whether to consider the in_selector parameter
189 * @param array $ufGroupIds
6a488035
TO
190 * @param boolean $searchable
191 *
da6b46f4
EM
192 * @param null $restrict
193 * @param bool $skipPermission
194 * @param int $permissionType
6a488035
TO
195 * @return array the fields that are listings related
196 * @static
197 * @access public
198 */
199 static function getListingFields(
200 $action,
201 $visibility,
202 $considerSelector = FALSE,
203 $ufGroupIds = NULL,
204 $searchable = NULL,
205 $restrict = NULL,
206 $skipPermission = FALSE,
207 $permissionType = CRM_Core_Permission::SEARCH
208 ) {
209 if ($ufGroupIds) {
210 $subset = self::getFields($ufGroupIds, FALSE, $action,
211 $visibility, $searchable,
212 FALSE, $restrict,
213 $skipPermission,
214 NULL,
215 $permissionType
216 );
217 if ($considerSelector) {
218 // drop the fields not meant for the selector
219 foreach ($subset as $name => $field) {
220 if (!$field['in_selector']) {
221 unset($subset[$name]);
222 }
223 }
224 }
225 $fields = $subset;
226 }
227 else {
ff4f7744 228 $ufGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id');
6a488035
TO
229
230 $fields = array();
231 foreach ($ufGroups as $id => $title) {
232 $subset = self::getFields($id, FALSE, $action,
233 $visibility, $searchable,
234 FALSE, $restrict,
235 $skipPermission,
236 NULL,
237 $permissionType
238 );
239 if ($considerSelector) {
240 // drop the fields not meant for the selector
241 foreach ($subset as $name => $field) {
242 if (!$field['in_selector'])unset($subset[$name]);
243 }
244 }
245 $fields = array_merge($fields, $subset);
246 }
247 }
248 return $fields;
249 }
250
251 /**
252 * Get all the fields that belong to the group with the name title,
253 * and format for use with buildProfile. This is the SQL analog of
254 * formatUFFields().
255 *
fd31fa4c
EM
256 * @param mix $id the id of the UF group or ids of ufgroup
257 * @param bool|int $register are we interested in registration fields
258 * @param int $action what action are we doing
259 * @param int $visibility visibility of fields we are interested in
6a488035 260 * @param $searchable
fd31fa4c
EM
261 * @param bool $showAll
262 * @param string $restrict should we restrict based on a specified profile type
6a488035 263 *
fd31fa4c
EM
264 * @param bool $skipPermission
265 * @param null $ctype
266 * @param int $permissionType
267 * @param string $orderBy
268 * @param null $orderProfiles
269 *
270 * @internal param bool $showall
6a488035
TO
271 * @return array the fields that belong to this ufgroup(s)
272 * @static
273 * @access public
274 */
275 static function getFields(
276 $id,
277 $register = FALSE,
278 $action = NULL,
279 $visibility = NULL,
280 $searchable = NULL,
281 $showAll = FALSE,
282 $restrict = NULL,
283 $skipPermission = FALSE,
284 $ctype = NULL,
285 $permissionType = CRM_Core_Permission::CREATE,
286 $orderBy = 'field_name',
287 $orderProfiles = NULL
288 ) {
289 if (!is_array($id)) {
290 $id = CRM_Utils_Type::escape($id, 'Positive');
291 $profileIds = array($id);
292 }
293 else {
294 $profileIds = $id;
295 }
296
297 $gids = implode(',', $profileIds);
298 $params = array();
299 if ($restrict) {
f9d8a5d1 300 $query = "SELECT g.* from civicrm_uf_group g
301 LEFT JOIN civicrm_uf_join j ON (j.uf_group_id = g.id)
6a488035 302 WHERE g.id IN ( {$gids} )
f9d8a5d1 303 AND ((j.uf_group_id IN ( {$gids} ) AND j.module = %1) OR g.is_reserved = 1 )
6a488035
TO
304 ";
305 $params = array(1 => array($restrict, 'String'));
306 }
307 else {
308 $query = "SELECT g.* from civicrm_uf_group g WHERE g.id IN ( {$gids} ) ";
309 }
310
311 if (!$showAll) {
312 $query .= " AND g.is_active = 1";
313 }
314
315 // add permissioning for profiles only if not registration
316 if (!$skipPermission) {
317 $permissionClause = CRM_Core_Permission::ufGroupClause($permissionType, 'g.');
318 $query .= " AND $permissionClause ";
319 }
320
321 if ($orderProfiles AND count($profileIds) > 1) {
322 $query .= " ORDER BY FIELD( g.id, {$gids} )";
323 }
324 $group = CRM_Core_DAO::executeQuery($query, $params);
325 $fields = array();
326 $validGroup = FALSE;
327
328 while ($group->fetch()) {
329 $validGroup = TRUE;
330 $query = self::createUFFieldQuery($group->id, $searchable, $showAll, $visibility, $orderBy);
331 $field = CRM_Core_DAO::executeQuery($query);
332
333 $profileType = CRM_Core_BAO_UFField::getProfileType($group->id);
334 $contactActivityProfile = CRM_Core_BAO_UFField::checkContactActivityProfileType($group->id);
335 $importableFields = self::getImportableFields($showAll, $profileType, $contactActivityProfile);
336 list($customFields, $addressCustomFields) = self::getCustomFields($ctype);
337
338 while ($field->fetch()) {
339 list($name, $formattedField) = self::formatUFField($group, $field, $customFields, $addressCustomFields, $importableFields, $permissionType);
340 if ($formattedField !== NULL) {
341 $fields[$name] = $formattedField;
342 }
343 }
344 $field->free();
345 }
346
347 if (empty($fields) && !$validGroup) {
348 CRM_Core_Error::fatal(ts('The requested Profile (gid=%1) is disabled OR it is not configured to be used for \'Profile\' listings in its Settings OR there is no Profile with that ID OR you do not have permission to access this profile. Please contact the site administrator if you need assistance.',
349 array(1 => implode(',', $profileIds))
350 ));
351 }
352 else {
353 self::reformatProfileFields($fields);
354 }
355
356 return $fields;
357 }
358
359 /**
360 * Format a list of UFFields for use with buildProfile. This is the in-memory analog
361 * of getFields().
362 *
363 * @param array $groupArr (mimic CRM_UF_DAO_UFGroup)
364 * @param array $fieldArrs list of fields (each mimics CRM_UF_DAO_UFField)
77b97be7 365 * @param bool $visibility visibility of fields we are interested in
6a488035 366 * @param bool $searchable
77b97be7
EM
367 * @param bool $showAll
368 * @param null $ctype
369 * @param int $permissionType
370 *
371 * @internal param bool $showall
6a488035
TO
372 * @return array
373 * @see getFields
374 */
375 public static function formatUFFields(
376 $groupArr,
377 $fieldArrs,
378 $visibility = NULL,
379 $searchable = NULL,
380 $showAll = FALSE,
381 $ctype = NULL,
382 $permissionType = CRM_Core_Permission::CREATE
383 ) {
384 // $group = new CRM_Core_DAO_UFGroup();
385 // $group->copyValues($groupArr); // no... converts string('') to string('null')
386 $group = (object) $groupArr;
387
388 // Refactoring note: The $fieldArrs here may be slightly different than the $ufFields
389 // used by calculateGroupType, but I don't think the missing fields matter, and -- if
390 // they did -- the obvious fix would produce mutual recursion.
391 $ufGroupType = self::_calculateGroupType($fieldArrs);
392 $profileType = CRM_Core_BAO_UFField::calculateProfileType(implode(',',$ufGroupType));
393 $contactActivityProfile = CRM_Core_BAO_UFField::checkContactActivityProfileTypeByGroupType(implode(',',$ufGroupType));
394 $importableFields = self::getImportableFields($showAll, $profileType, $contactActivityProfile);
395 list($customFields, $addressCustomFields) = self::getCustomFields($ctype);
396
397 $formattedFields = array();
398 foreach ($fieldArrs as $fieldArr) {
6a488035
TO
399 $field = (object) $fieldArr;
400 if (!self::filterUFField($field, $searchable, $showAll, $visibility)) {
401 continue;
402 }
403
404 list($name, $formattedField) = self::formatUFField($group, $field, $customFields, $addressCustomFields, $importableFields, $permissionType);
405 if ($formattedField !== NULL) {
406 $formattedFields[$name] = $formattedField;
407 }
408 }
409 return $formattedFields;
410 }
411
412 /**
413 * Prepare a field for rendering with CRM_Core_BAO_UFGroup::buildProfile.
414 *
415 * @param CRM_Core_DAO_UFGroup|CRM_Core_DAO $group
416 * @param CRM_Core_DAO_UFField|CRM_Core_DAO $field
417 * @param array $addressCustomFields
418 * @param array $importableFields
419 * @param array $customFields
420 * @param int $permissionType eg CRM_Core_Permission::CREATE
421 * @return array
422 */
423 protected static function formatUFField(
424 $group,
425 $field,
426 $customFields,
427 $addressCustomFields,
428 $importableFields,
429 $permissionType = CRM_Core_Permission::CREATE
430 ) {
431 $name = $field->field_name;
432 $title = $field->label;
433
434 $addressCustom = FALSE;
435 if (in_array($permissionType, array(
436 CRM_Core_Permission::CREATE,
437 CRM_Core_Permission::EDIT,
438 )) &&
439 in_array($field->field_name, array_keys($addressCustomFields))
440 ) {
441 $addressCustom = TRUE;
442 $name = "address_{$name}";
443 }
887e764d
PN
444 if ($field->field_name == 'url') {
445 $name .= "-{$field->website_type_id}";
446 }
447 elseif (!empty($field->location_type_id)) {
6a488035
TO
448 $name .= "-{$field->location_type_id}";
449 }
450 else {
451 $locationFields = self::getLocationFields();
452 if (in_array($field->field_name, $locationFields) || $addressCustom) {
453 $name .= '-Primary';
454 }
455 }
456
457 if (isset($field->phone_type_id)) {
458 $name .= "-{$field->phone_type_id}";
459 }
460
461 // No lie: this is bizarre; why do we need to mix so many UFGroup properties into UFFields?
462 // I guess to make field self sufficient with all the required data and avoid additional calls
463 $formattedField = array(
464 'name' => $name,
465 'groupTitle' => $group->title,
4a1143a1 466 'groupName' => $group->name,
6a488035
TO
467 'groupHelpPre' => empty($group->help_pre) ? '' : $group->help_pre,
468 'groupHelpPost' => empty($group->help_post) ? '' : $group->help_post,
469 'title' => $title,
470 'where' => CRM_Utils_Array::value('where', CRM_Utils_Array::value($field->field_name, $importableFields)),
471 'attributes' => CRM_Core_DAO::makeAttribute(CRM_Utils_Array::value($field->field_name, $importableFields)),
472 'is_required' => $field->is_required,
473 'is_view' => $field->is_view,
474 'help_pre' => $field->help_pre,
475 'help_post' => $field->help_post,
476 'visibility' => $field->visibility,
477 'in_selector' => $field->in_selector,
478 'rule' => CRM_Utils_Array::value('rule', CRM_Utils_Array::value($field->field_name, $importableFields)),
479 'location_type_id' => isset($field->location_type_id) ? $field->location_type_id : NULL,
887e764d 480 'website_type_id' => isset($field->website_type_id) ? $field->website_type_id : NULL,
6a488035
TO
481 'phone_type_id' => isset($field->phone_type_id) ? $field->phone_type_id : NULL,
482 'group_id' => $group->id,
cd0dd278
DG
483 'add_to_group_id' => isset($group->add_to_group_id) ? $group->add_to_group_id : NULL,
484 'add_captcha' => isset($group->add_captcha) ? $group->add_captcha : NULL,
6a488035
TO
485 'field_type' => $field->field_type,
486 'field_id' => $field->id,
0c145cc0
DL
487 'pseudoconstant' => CRM_Utils_Array::value(
488 'pseudoconstant',
489 CRM_Utils_Array::value($field->field_name, $importableFields)
490 ),
491 // obsolete this when we remove the name / dbName discrepancy with gender/suffix/prefix
492 'dbName' => CRM_Utils_Array::value(
493 'dbName',
494 CRM_Utils_Array::value($field->field_name, $importableFields)
495 ),
6a488035
TO
496 'skipDisplay' => 0,
497 );
498
499 //adding custom field property
500 if (substr($field->field_name, 0, 6) == 'custom' ||
501 substr($field->field_name, 0, 14) === 'address_custom'
502 ) {
503 // if field is not present in customFields, that means the user
504 // DOES NOT HAVE permission to access that field
505 if (array_key_exists($field->field_name, $customFields)) {
506 $formattedField['is_search_range'] = $customFields[$field->field_name]['is_search_range'];
507 // fix for CRM-1994
508 $formattedField['options_per_line'] = $customFields[$field->field_name]['options_per_line'];
509 $formattedField['data_type'] = $customFields[$field->field_name]['data_type'];
510 $formattedField['html_type'] = $customFields[$field->field_name]['html_type'];
511
512 if (CRM_Utils_Array::value('html_type', $formattedField) == 'Select Date') {
513 $formattedField['date_format'] = $customFields[$field->field_name]['date_format'];
514 $formattedField['time_format'] = $customFields[$field->field_name]['time_format'];
515 }
516
517 $formattedField['is_multi_summary'] = $field->is_multi_summary;
518 return array($name, $formattedField);
519 }
520 else {
521 $formattedField = NULL;
522 return array($name, $formattedField);
523 }
524 }
525 return array($name, $formattedField);
526 }
527
528 /**
529 * Create a query to find all visible UFFields in a UFGroup
530 *
531 * This is the SQL-variant of checkUFFieldDisplayable().
532 *
533 * @param int $groupId
534 * @param bool $searchable
535 * @param bool $showAll
536 * @param int $visibility
537 * @param string $orderBy comma-delimited list of SQL columns
538 * @return string
539 */
540 protected static function createUFFieldQuery($groupId, $searchable, $showAll, $visibility, $orderBy) {
541 $where = " WHERE uf_group_id = {$groupId}";
542
543 if ($searchable) {
544 $where .= " AND is_searchable = 1";
545 }
546
547 if (!$showAll) {
548 $where .= " AND is_active = 1";
549 }
550
551 if ($visibility) {
552 $clause = array();
553 if ($visibility & self::PUBLIC_VISIBILITY) {
554 $clause[] = 'visibility = "Public Pages"';
555 }
556 if ($visibility & self::ADMIN_VISIBILITY) {
557 $clause[] = 'visibility = "User and User Admin Only"';
558 }
559 if ($visibility & self::LISTINGS_VISIBILITY) {
560 $clause[] = 'visibility = "Public Pages and Listings"';
561 }
562 if (!empty($clause)) {
563 $where .= ' AND ( ' . implode(' OR ', $clause) . ' ) ';
564 }
565 }
566
567 $query = "SELECT * FROM civicrm_uf_field $where ORDER BY weight";
568 if ($orderBy) {
569 $query .= ", " . $orderBy;
570 return $query;
571 }
572 return $query;
573 }
574
575 /**
576 * Create a query to find all visible UFFields in a UFGroup
577 *
578 * This is the PHP in-memory variant of createUFFieldQuery().
579 *
580 * @param CRM_Core_DAO_UFField|CRM_Core_DAO $field
581 * @param bool $searchable
582 * @param bool $showAll
583 * @param int $visibility
584 * @return bool TRUE if field is displayable
585 */
586 protected static function filterUFField($field, $searchable, $showAll, $visibility) {
587 if ($searchable && $field->is_searchable != 1) {
588 return FALSE;
589 }
590
591 if (!$showAll && $field->is_active != 1) {
592 return FALSE;
593 }
594
595 if ($visibility) {
596 $allowedVisibilities = array();
597 if ($visibility & self::PUBLIC_VISIBILITY) {
598 $allowedVisibilities[] = 'Public Pages';
599 }
600 if ($visibility & self::ADMIN_VISIBILITY) {
601 $allowedVisibilities[] = 'User and User Admin Only';
602 }
603 if ($visibility & self::LISTINGS_VISIBILITY) {
604 $allowedVisibilities[] = 'Public Pages and Listings';
605 }
606 // !empty($allowedVisibilities) seems silly to me, but it is equivalent to the pre-existing SQL
607 if (!empty($allowedVisibilities) && !in_array($field->visibility, $allowedVisibilities)) {
608 return FALSE;
609 }
610 }
611
612 return TRUE;
613 }
614
615 protected static function getImportableFields($showAll, $profileType, $contactActivityProfile) {
616 if (!$showAll) {
617 $importableFields = CRM_Contact_BAO_Contact::importableFields('All', FALSE, FALSE, FALSE, TRUE, TRUE);
618 }
619 else {
620 $importableFields = CRM_Contact_BAO_Contact::importableFields('All', FALSE, TRUE, FALSE, TRUE, TRUE);
621 }
622
623 if ($profileType == 'Activity' || $contactActivityProfile) {
624 $componentFields = CRM_Activity_BAO_Activity::getProfileFields();
625 }
626 else {
627 $componentFields = CRM_Core_Component::getQueryFields();
628 }
629
630 $importableFields = array_merge($importableFields, $componentFields);
631
632 $importableFields['group']['title'] = ts('Group(s)');
633 $importableFields['group']['where'] = NULL;
634 $importableFields['tag']['title'] = ts('Tag(s)');
635 $importableFields['tag']['where'] = NULL;
636 return $importableFields;
637 }
638
639 public static function getLocationFields() {
640 static $locationFields = array(
641 'street_address',
642 'supplemental_address_1',
643 'supplemental_address_2',
644 'city',
645 'postal_code',
646 'postal_code_suffix',
647 'geo_code_1',
648 'geo_code_2',
649 'state_province',
650 'country',
651 'county',
652 'phone',
653 'phone_and_ext',
654 'email',
655 'im',
656 'address_name',
657 'phone_ext',
658 );
659 return $locationFields;
660 }
661
662 protected static function getCustomFields($ctype) {
663 static $customFieldCache = array();
664 if (!isset($customFieldCache[$ctype])) {
665 $customFields = CRM_Core_BAO_CustomField::getFieldsForImport($ctype, FALSE, FALSE, FALSE, TRUE, TRUE);
666
667 // hack to add custom data for components
1cb28d5d 668 $components = array('Contribution', 'Participant', 'Membership', 'Activity', 'Case');
6a488035
TO
669 foreach ($components as $value) {
670 $customFields = array_merge($customFields, CRM_Core_BAO_CustomField::getFieldsForImport($value));
671 }
672 $addressCustomFields = CRM_Core_BAO_CustomField::getFieldsForImport('Address');
673 $customFields = array_merge($customFields, $addressCustomFields);
674 $customFieldCache[$ctype] = array($customFields, $addressCustomFields);
675 }
676 return $customFieldCache[$ctype];
677 }
678
679 /**
680 * check the data validity
681 *
2a6da8d7
EM
682 * @param int $userID the user id that we are actually editing
683 * @param string $title the title of the group we are interested in
684 * @param bool $register
685 * @param int $action the action of the form
6a488035 686 *
2a6da8d7 687 * @pram boolean $register is this the registrtion form
6a488035
TO
688 * @return boolean true if form is valid
689 * @static
690 * @access public
691 */
692 static function isValid($userID, $title, $register = FALSE, $action = NULL) {
693 if ($register) {
694 $controller = new CRM_Core_Controller_Simple('CRM_Profile_Form_Dynamic',
695 ts('Dynamic Form Creator'),
696 $action
697 );
698 $controller->set('id', $userID);
699 $controller->set('register', 1);
700 $controller->process();
701 return $controller->validate();
702 }
703 else {
704 // make sure we have a valid group
705 $group = new CRM_Core_DAO_UFGroup();
706
707 $group->title = $title;
708
709 if ($group->find(TRUE) && $userID) {
710 $controller = new CRM_Core_Controller_Simple('CRM_Profile_Form_Dynamic', ts('Dynamic Form Creator'), $action);
711 $controller->set('gid', $group->id);
712 $controller->set('id', $userID);
713 $controller->set('register', 0);
714 $controller->process();
715 return $controller->validate();
716 }
717 return TRUE;
718 }
719 }
720
721 /**
722 * get the html for the form that represents this particular group
723 *
2a6da8d7
EM
724 * @param int $userID the user id that we are actually editing
725 * @param string $title the title of the group we are interested in
726 * @param int $action the action of the form
727 * @param boolean $register is this the registration form
728 * @param boolean $reset should we reset the form?
729 * @param int $profileID do we have the profile ID?
730 *
731 * @param bool $doNotProcess
732 * @param null $ctype
6a488035
TO
733 *
734 * @return string the html for the form on success, otherwise empty string
735 * @static
736 * @access public
737 */
738 static function getEditHTML($userID,
739 $title,
740 $action = NULL,
741 $register = FALSE,
742 $reset = FALSE,
743 $profileID = NULL,
744 $doNotProcess = FALSE,
745 $ctype = NULL
746 ) {
747
748 if ($register) {
749 $controller = new CRM_Core_Controller_Simple('CRM_Profile_Form_Dynamic',
750 ts('Dynamic Form Creator'),
751 $action
752 );
753 if ($reset || $doNotProcess) {
754 // hack to make sure we do not process this form
755 $oldQFDefault = CRM_Utils_Array::value('_qf_default',
756 $_POST
757 );
758 unset($_POST['_qf_default']);
759 unset($_REQUEST['_qf_default']);
760 if ($reset) {
761 $controller->reset();
762 }
763 }
764
765 $controller->set('id', $userID);
766 $controller->set('register', 1);
767 $controller->set('skipPermission', 1);
768 $controller->set('ctype', $ctype);
769 $controller->process();
770 if ($doNotProcess || !empty($_POST)) {
771 $controller->validate();
772 }
773 $controller->setEmbedded(TRUE);
774
775 //CRM-5839 - though we want to process form, get the control back.
776 $controller->setSkipRedirection(($doNotProcess) ? FALSE : TRUE);
777
778 $controller->run();
779
780 // we are done processing so restore the POST/REQUEST vars
781 if (($reset || $doNotProcess) && $oldQFDefault) {
782 $_POST['_qf_default'] = $_REQUEST['_qf_default'] = $oldQFDefault;
783 }
784
785 $template = CRM_Core_Smarty::singleton();
786
787 // Hide CRM error messages if they are displayed using drupal form_set_error.
788 if (!empty($_POST)) {
789 $template->assign('suppressForm', TRUE);
790 }
791
792 return trim($template->fetch('CRM/Profile/Form/Dynamic.tpl'));
793 }
794 else {
795 if (!$profileID) {
796 // make sure we have a valid group
797 $group = new CRM_Core_DAO_UFGroup();
798
799 $group->title = $title;
800
801 if ($group->find(TRUE)) {
802 $profileID = $group->id;
803 }
804 }
805
806 if ($profileID) {
807 // make sure profileID and ctype match if ctype exists
808 if ($ctype) {
809 $profileType = CRM_Core_BAO_UFField::getProfileType($profileID);
810 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
811 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
812 }
813
814 if (($profileType != 'Contact') && ($profileType != $ctype)) {
815 return NULL;
816 }
817 }
818
819 $controller = new CRM_Core_Controller_Simple('CRM_Profile_Form_Dynamic',
820 ts('Dynamic Form Creator'),
821 $action
822 );
823 if ($reset) {
824 $controller->reset();
825 }
826 $controller->set('gid', $profileID);
827 $controller->set('id', $userID);
828 $controller->set('register', 0);
829 $controller->set('skipPermission', 1);
830 if ($ctype) {
831 $controller->set('ctype', $ctype);
832 }
833 $controller->process();
834 $controller->setEmbedded(TRUE);
835
836 //CRM-5846 - give the control back to drupal.
837 $controller->setSkipRedirection(($doNotProcess) ? FALSE : TRUE);
838 $controller->run();
839
840 $template = CRM_Core_Smarty::singleton();
841
842 // Hide CRM error messages if they are displayed using drupal form_set_error.
843 if (!empty($_POST) && CRM_Core_Config::singleton()->userFramework == 'Drupal') {
844 if (arg(0) == 'user' || (arg(0) == 'admin' && arg(1) == 'people')) {
845 $template->assign('suppressForm', TRUE);
846 }
847 }
848
849 $templateFile = "CRM/Profile/Form/{$profileID}/Dynamic.tpl";
850 if (!$template->template_exists($templateFile)) {
851 $templateFile = 'CRM/Profile/Form/Dynamic.tpl';
852 }
853 return trim($template->fetch($templateFile));
854 }
855 else {
856 $userEmail = CRM_Contact_BAO_Contact_Location::getEmailDetails($userID);
857
858 // if post not empty then only proceed
859 if (!empty($_POST)) {
860 // get the new email
861 $config = CRM_Core_Config::singleton();
862 $email = CRM_Utils_Array::value('mail', $_POST);
863
864 if (CRM_Utils_Rule::email($email) && ($email != $userEmail[1])) {
865 CRM_Core_BAO_UFMatch::updateContactEmail($userID, $email);
866 }
867 }
868 }
869 }
870 return '';
871 }
872
873 /**
874 * searches for a contact in the db with similar attributes
875 *
876 * @param array $params the list of values to be used in the where clause
2a6da8d7
EM
877 * @param int $id the current contact id (hence excluded from matching)
878 * @param string $contactType
879 *
880 * @internal param bool $flatten should we flatten the input params
6a488035
TO
881 *
882 * @return contact_id if found, null otherwise
883 * @access public
884 * @static
885 */
886 public static function findContact(&$params, $id = NULL, $contactType = 'Individual') {
887 $dedupeParams = CRM_Dedupe_Finder::formatParams($params, $contactType);
888 $dedupeParams['check_permission'] = CRM_Utils_Array::value('check_permission', $params, TRUE);
889 $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, $contactType, 'Supervised', array($id));
890 if (!empty($ids)) {
891 return implode(',', $ids);
892 }
893 else {
894 return NULL;
895 }
896 }
897
898 /**
899 * Given a contact id and a field set, return the values from the db
900 * for this contact
901 *
2a6da8d7
EM
902 * @param $cid
903 * @param array $fields the profile fields of interest
904 * @param array $values the values for the above fields
905 * @param boolean $searchable searchable or not
906 * @param array $componentWhere component condition
907 * @param boolean $absolute return urls in absolute form (useful when sending an email)
908 *
909 * @param null $additionalWhereClause
6a488035 910 *
2a6da8d7 911 * @internal param int $id the contact id
6a488035
TO
912 * @return void
913 * @access public
914 * @static
915 */
916 public static function getValues($cid, &$fields, &$values,
917 $searchable = TRUE, $componentWhere = NULL,
918 $absolute = FALSE, $additionalWhereClause = NULL
919 ) {
920 if (empty($cid) && empty($componentWhere)) {
921 return NULL;
922 }
923
924 // get the contact details (hier)
925 $returnProperties = CRM_Contact_BAO_Contact::makeHierReturnProperties($fields);
926 $params = $cid ? array(array('contact_id', '=', $cid, 0, 0)) : array();
927
928 // add conditions specified by components. eg partcipant_id etc
929 if (!empty($componentWhere)) {
930 $params = array_merge($params, $componentWhere);
931 }
932
933 $query = new CRM_Contact_BAO_Query($params, $returnProperties, $fields);
934 $options = &$query->_options;
935
936 $details = $query->searchQuery( 0, 0, NULL, FALSE, FALSE,
937 FALSE, FALSE, FALSE, $additionalWhereClause);
938 if (!$details->fetch()) {
939 return;
940 }
d9ab802d 941 $query->convertToPseudoNames($details);
6a488035
TO
942 $config = CRM_Core_Config::singleton();
943
b2b0530a 944 $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
e7e657f0 945 $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
cbf48754 946 $websiteTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Website', 'website_type_id');
6a488035
TO
947
948 $multipleFields = array('url');
949 $nullIndex = $nullValueIndex = ' ';
950
951 //start of code to set the default values
952 foreach ($fields as $name => $field) {
953 // fix for CRM-3962
954 if ($name == 'id') {
955 $name = 'contact_id';
956 }
957
958 // skip fields that should not be displayed separately
a7488080 959 if (!empty($field['skipDisplay'])) {
6a488035
TO
960 continue;
961 }
962
963 $index = $field['title'];
964 //handle for the label not set for the field
965 if (empty($field['title'])) {
966 $index = $nullIndex;
967 $nullIndex .= $nullIndex;
968 }
969
970 //handle the case to avoid re-write where the profile field labels are the same
46796b19 971 if (array_key_exists($index, $values)) {
6a488035
TO
972 $index .= $nullValueIndex;
973 $nullValueIndex .= $nullValueIndex;
974 }
975 $params[$index] = $values[$index] = '';
976 $customFieldName = NULL;
977 // hack for CRM-665
978 if (isset($details->$name) || $name == 'group' || $name == 'tag') {
979 // to handle gender / suffix / prefix
04ffef8d 980 if (in_array(substr($name, 0, -3), array('gender', 'prefix', 'suffix'))) {
04ffef8d 981 $params[$index] = $details->$name;
46796b19 982 $values[$index] = $details->$name;
6a488035
TO
983 }
984 elseif (in_array($name, CRM_Contact_BAO_Contact::$_greetingTypes)) {
985 $dname = $name . '_display';
986 $values[$index] = $details->$dname;
987 $name = $name . '_id';
988 $params[$index] = $details->$name;
989 }
990 elseif (in_array($name, array(
991 'state_province', 'country', 'county'))) {
992 $values[$index] = $details->$name;
993 $idx = $name . '_id';
994 $params[$index] = $details->$idx;
995 }
996 elseif ($name === 'preferred_communication_method') {
e7e657f0 997 $communicationFields = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'preferred_communication_method');
6a488035
TO
998 $compref = array();
999 $pref = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details->$name);
1000
1001 foreach ($pref as $k) {
1002 if ($k) {
1003 $compref[] = $communicationFields[$k];
1004 }
1005 }
1006 $params[$index] = $details->$name;
1007 $values[$index] = implode(',', $compref);
1008 }
1009 elseif ($name === 'preferred_language') {
6a488035 1010 $params[$index] = $details->$name;
a8c23526 1011 $values[$index] = CRM_Core_PseudoConstant::getLabel('CRM_Contact_DAO_Contact', 'preferred_language', $details->$name);
6a488035
TO
1012 }
1013 elseif ($name == 'group') {
1014 $groups = CRM_Contact_BAO_GroupContact::getContactGroup($cid, 'Added', NULL, FALSE, TRUE);
1015 $title = $ids = array();
1016
1017 foreach ($groups as $g) {
1018 // CRM-8362: User and User Admin visibility groups should be included in display if user has
1019 // VIEW permission on that group
1020 $groupPerm = CRM_Contact_BAO_Group::checkPermission($g['group_id'], $g['title']);
1021
1022 if ($g['visibility'] != 'User and User Admin Only' ||
1023 CRM_Utils_Array::key(CRM_Core_Permission::VIEW, $groupPerm)
1024 ) {
1025 $title[] = $g['title'];
1026 if ($g['visibility'] == 'Public Pages') {
1027 $ids[] = $g['group_id'];
1028 }
1029 }
1030 }
1031 $values[$index] = implode(', ', $title);
1032 $params[$index] = implode(',', $ids);
1033 }
1034 elseif ($name == 'tag') {
1035 $entityTags = CRM_Core_BAO_EntityTag::getTag($cid);
cd43c5e3 1036 $allTags = CRM_Core_PseudoConstant::get('CRM_Core_DAO_EntityTag', 'tag_id', array('onlyActive' => FALSE));
6a488035
TO
1037 $title = array();
1038 foreach ($entityTags as $tagId) {
1039 $title[] = $allTags[$tagId];
1040 }
1041 $values[$index] = implode(', ', $title);
1042 $params[$index] = implode(',', $entityTags);
1043 }
1044 elseif ($name == 'activity_status_id') {
1045 $activityStatus = CRM_Core_PseudoConstant::activityStatus();
1046 $values[$index] = $activityStatus[$details->$name];
1047 $params[$index] = $details->$name;
1048 }
1049 elseif ($name == 'activity_date_time') {
1050 $values[$index] = CRM_Utils_Date::customFormat($details->$name);
1051 $params[$index] = $details->$name;
1052 }
1053 elseif ($name == 'contact_sub_type') {
1054 $contactSubTypeNames = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details->$name);
1055 if (!empty($contactSubTypeNames)) {
1056 $contactSubTypeLabels = array();
1057 // get all contact subtypes
1058 $allContactSubTypes = CRM_Contact_BAO_ContactType::subTypeInfo();
1059 // build contact subtype labels array
1060 foreach( $contactSubTypeNames as $cstName ) {
1061 if ($cstName) {
1062 $contactSubTypeLabels[] = $allContactSubTypes[$cstName]['label'];
1063 }
1064 }
1065 $values[$index] = implode(',', $contactSubTypeLabels);
1066 }
1067
1068 $params[$index] = $details->$name;
1069 }
1070 else {
1071 if (substr($name, 0, 7) === 'do_not_' || substr($name, 0, 3) === 'is_') {
1072 if ($details->$name) {
1073 $values[$index] = '[ x ]';
1074 }
1075 }
1076 else {
1077 if ($cfID = CRM_Core_BAO_CustomField::getKeyID($name)) {
1078 $htmlType = $field['html_type'];
1079
1080 // field_type is only set when we are retrieving profile values
1081 // when sending email, we call the same function to get custom field
1082 // values etc, i.e. emulating a profile
1083 $fieldType = CRM_Utils_Array::value('field_type', $field);
1084
1085 if ($htmlType == 'File') {
1086 $entityId = $cid;
1087 if (!$cid &&
8cc574cf 1088 $fieldType == 'Activity' && !empty($componentWhere[0][2])) {
6a488035
TO
1089 $entityId = $componentWhere[0][2];
1090 }
1091
1092 $fileURL = CRM_Core_BAO_CustomField::getFileURL($entityId,
1093 $cfID,
1094 NULL,
1095 $absolute
1096 );
1097 $params[$index] = $values[$index] = $fileURL['file_url'];
1098 }
1099 else {
1100 $customVal = NULL;
1101 if (isset($dao) && property_exists($dao, 'data_type') &&
1102 ($dao->data_type == 'Int' ||
1103 $dao->data_type == 'Boolean'
1104 )
1105 ) {
1106 $customVal = (int )($details->{$name});
1107 }
1108 elseif (isset($dao) && property_exists($dao, 'data_type')
1109 && $dao->data_type == 'Float'
1110 ) {
1111 $customVal = (float )($details->{$name});
1112 }
1113 elseif (!CRM_Utils_System::isNull(explode(CRM_Core_DAO::VALUE_SEPARATOR,
1114 $details->{$name}
1115 ))) {
1116 $customVal = $details->{$name};
1117 }
1118
1119 //CRM-4582
1120 if (CRM_Utils_System::isNull($customVal)) {
1121 continue;
1122 }
1123
1124 $params[$index] = $customVal;
1125 $values[$index] = CRM_Core_BAO_CustomField::getDisplayValue($customVal,
1126 $cfID,
1127 $options
1128 );
1b4d9e39 1129 if ($field['data_type'] == 'ContactReference') {
6a488035
TO
1130 $params[$index] = $values[$index];
1131 }
1132 if (CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField',
1133 $cfID, 'is_search_range'
1134 )) {
1135 $customFieldName = "{$name}_from";
1136 }
1137 }
1138 }
1139 elseif ($name == 'image_URL') {
1140 list($width, $height) = getimagesize($details->$name);
1141 list($thumbWidth, $thumbHeight) = CRM_Contact_BAO_Contact::getThumbSize($width, $height);
1142
1143 $image_URL = '<img src="' . $details->$name . '" height= ' . $thumbHeight . ' width= ' . $thumbWidth . ' />';
1144 $values[$index] = "<a href='#' onclick='contactImagePopUp(\"{$details->$name}\", {$width}, {$height});'>{$image_URL}</a>";
1145 }
1146 elseif (in_array($name, array(
1147 'birth_date', 'deceased_date', 'membership_start_date', 'membership_end_date', 'join_date'))) {
1148 $values[$index] = CRM_Utils_Date::customFormat($details->$name);
1149 $params[$index] = CRM_Utils_Date::isoToMysql($details->$name);
1150 }
1151 else {
1152 $dao = '';
1153 if ($index == 'Campaign') {
1154 $dao = 'CRM_Campaign_DAO_Campaign';
1155 }
1156 elseif ($index == 'Contribution Page') {
1157 $dao = 'CRM_Contribute_DAO_ContributionPage';
1158 }
1159 if ($dao) {
1160 $value = CRM_Core_DAO::getFieldValue($dao, $details->$name, 'title');
1161 }
1162 else {
1163 $value = $details->$name;
1164 }
1165 $values[$index] = $value;
1166 }
1167 }
1168 }
1169 }
1170 elseif (strpos($name, '-') !== FALSE) {
1171 list($fieldName, $id, $type) = CRM_Utils_System::explode('-', $name, 3);
1172
1173 if (!in_array($fieldName, $multipleFields)) {
1174 if ($id == 'Primary') {
1175 // fix for CRM-1543
1176 // not sure why we'd every use Primary location type id
1177 // we need to fix the source if we are using it
1178 // $locationTypeName = CRM_Contact_BAO_Contact::getPrimaryLocationType( $cid );
1179 $locationTypeName = 1;
1180 }
1181 else {
1182 $locationTypeName = CRM_Utils_Array::value($id, $locationTypes);
1183 }
1184
1185 if (!$locationTypeName) {
1186 continue;
1187 }
1188
1189 $detailName = "{$locationTypeName}-{$fieldName}";
1190 $detailName = str_replace(' ', '_', $detailName);
1191
1192 if (in_array($fieldName, array(
1193 'phone', 'im', 'email', 'openid'))) {
1194 if ($type) {
1195 $detailName .= "-{$type}";
1196 }
1197 }
1198
1199 if (in_array($fieldName, array(
1200 'state_province', 'country', 'county'))) {
1201 $values[$index] = $details->$detailName;
1202 $idx = $detailName . '_id';
1203 $params[$index] = $details->$idx;
1204 }
1205 elseif ($fieldName == 'im') {
1206 $providerId = $detailName . '-provider_id';
38913d36
TO
1207 if (isset($imProviders[$details->$providerId])) {
1208 $values[$index] = $details->$detailName . " (" . $imProviders[$details->$providerId] . ")";
6a488035
TO
1209 }
1210 else {
1211 $values[$index] = $details->$detailName;
1212 }
1213 $params[$index] = $details->$detailName;
1214 }
1215 elseif ($fieldName == 'phone') {
1216 $phoneExtField = str_replace('phone', 'phone_ext', $detailName);
1217 if (isset($details->$phoneExtField)) {
1218 $values[$index] = $details->$detailName . " (" . $details->$phoneExtField . ")";
1219 }
1220 else {
1221 $values[$index] = $details->$detailName;
1222 }
1223 $params[$index] = $details->$detailName;
1224 }
1225 else {
1226 $values[$index] = $params[$index] = $details->$detailName;
1227 }
1228 }
1229 else {
1230 $detailName = "website-{$id}-{$fieldName}";
1231 $url = CRM_Utils_System::fixURL($details->$detailName);
1232 if ($details->$detailName) {
1233 $websiteTypeId = "website-{$id}-website_type_id";
1234 $websiteType = $websiteTypes[$details->$websiteTypeId];
1235 $values[$index] = "<a href=\"$url\">{$details->$detailName} ( {$websiteType} )</a>";
1236 }
1237 else {
1238 $values[$index] = '';
1239 }
1240 }
1241 }
1242
1243 if ((CRM_Utils_Array::value('visibility', $field) == 'Public Pages and Listings') &&
1244 CRM_Core_Permission::check('profile listings and forms')
1245 ) {
1246
1247 if (CRM_Utils_System::isNull($params[$index])) {
1248 $params[$index] = $values[$index];
1249 }
1250 if (!isset($params[$index])) {
1251 continue;
1252 }
1253 if (!$customFieldName) {
1254 $fieldName = $field['name'];
1255 }
1256 else {
1257 $fieldName = $customFieldName;
1258 }
1259
1260 $url = NULL;
1261 if (CRM_Core_BAO_CustomField::getKeyID($field['name'])) {
1262 $htmlType = $field['html_type'];
1263 if ($htmlType == 'Link') {
1264 $url = $params[$index];
1265 }
1266 elseif (in_array($htmlType, array(
1267 'CheckBox', 'Multi-Select', 'AdvMulti-Select',
1268 'Multi-Select State/Province', 'Multi-Select Country',
1269 ))) {
1270 $valSeperator = CRM_Core_DAO::VALUE_SEPARATOR;
1271 $selectedOptions = explode($valSeperator, $params[$index]);
1272
1273 foreach ($selectedOptions as $key => $multiOption) {
1274 if ($multiOption) {
1275 $url[] = CRM_Utils_System::url('civicrm/profile',
1276 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1277 urlencode($fieldName) .
1278 '=' .
1279 urlencode($multiOption)
1280 );
1281 }
1282 }
1283 }
1284 else {
1285 $url = CRM_Utils_System::url('civicrm/profile',
1286 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1287 urlencode($fieldName) .
1288 '=' .
1289 urlencode($params[$index])
1290 );
1291 }
1292 }
1293 else {
1294 $url = CRM_Utils_System::url('civicrm/profile',
1295 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1296 urlencode($fieldName) .
1297 '=' .
1298 urlencode($params[$index])
1299 );
1300 }
1301
1302 if ($url &&
1303 !empty($values[$index]) &&
1304 $searchable
1305 ) {
1306
1307 if (is_array($url) && !empty($url)) {
1308 $links = array();
1309 $eachMultiValue = explode(', ', $values[$index]);
1310 foreach ($eachMultiValue as $key => $valueLabel) {
1311 $links[] = '<a href="' . $url[$key] . '">' . $valueLabel . '</a>';
1312 }
1313 $values[$index] = implode(', ', $links);
1314 }
1315 else {
1316 $values[$index] = '<a href="' . $url . '">' . $values[$index] . '</a>';
1317 }
1318 }
1319 }
1320 }
1321 }
1322
1323 /**
1324 * Check if profile Group used by any module.
1325 *
1326 * @param int $id profile Id
1327 *
1328 * @return boolean
1329 *
1330 * @access public
1331 * @static
1332 *
1333 */
1334 public static function usedByModule($id) {
1335 //check whether this group is used by any module(check uf join records)
1336 $sql = "SELECT id
1337 FROM civicrm_uf_join
1338 WHERE civicrm_uf_join.uf_group_id=$id";
1339
1340 $dao = new CRM_Core_DAO();
1341 $dao->query($sql);
1342 if ($dao->fetch()) {
1343 return TRUE;
1344 }
1345 else {
1346 return FALSE;
1347 }
1348 }
1349
1350 /**
1351 * Delete the profile Group.
1352 *
1353 * @param int $id profile Id
1354 *
1355 * @return boolean
1356 *
1357 * @access public
1358 * @static
1359 *
1360 */
1361 public static function del($id) {
1362 //check whether this group contains any profile fields
1363 $profileField = new CRM_Core_DAO_UFField();
1364 $profileField->uf_group_id = $id;
1365 $profileField->find();
1366 while ($profileField->fetch()) {
1367 CRM_Core_BAO_UFField::del($profileField->id);
1368 }
1369
1370 //delete records from uf join table
1371 $ufJoin = new CRM_Core_DAO_UFJoin();
1372 $ufJoin->uf_group_id = $id;
1373 $ufJoin->delete();
1374
1375 //delete profile group
1376 $group = new CRM_Core_DAO_UFGroup();
1377 $group->id = $id;
1378 $group->delete();
1379 return 1;
1380 }
1381
1382 /**
1383 * function to add the UF Group
1384 *
1385 * @param array $params reference array contains the values submitted by the form
1386 * @param array $ids reference array contains the id
1387 *
1388 * @access public
1389 * @static
1390 *
1391 * @return object
1392 */
6a73ef3f 1393 static function add(&$params, $ids = array()) {
6a488035
TO
1394 $fields = array('is_active', 'add_captcha', 'is_map', 'is_update_dupe', 'is_edit_link', 'is_uf_link', 'is_cms_user');
1395 foreach ($fields as $field) {
1396 $params[$field] = CRM_Utils_Array::value($field, $params, FALSE);
1397 }
1398
1399 $params['limit_listings_group_id'] = CRM_Utils_Array::value('group', $params);
1400 $params['add_to_group_id'] = CRM_Utils_Array::value('add_contact_to_group', $params);
1401
1402 $ufGroup = new CRM_Core_DAO_UFGroup();
1403 $ufGroup->copyValues($params);
1404
6a73ef3f 1405 $ufGroupID = CRM_Utils_Array::value('ufgroup', $ids, CRM_Utils_Array::value('id', $params));
6a488035
TO
1406 if (!$ufGroupID) {
1407 $ufGroup->name = CRM_Utils_String::munge($ufGroup->title, '_', 56);
1408 }
1409 $ufGroup->id = $ufGroupID;
1410
1411 $ufGroup->save();
1412
1413 if (!$ufGroupID) {
1414 $ufGroup->name = $ufGroup->name . "_{$ufGroup->id}";
1415 $ufGroup->save();
1416 }
1417
1418 return $ufGroup;
1419 }
1420
1421 /**
1422 * Function to make uf join entries for an uf group
1423 *
1424 * @param array $params (reference) an assoc array of name/value pairs
1425 * @param int $ufGroupId ufgroup id
1426 *
1427 * @return void
1428 * @access public
1429 * @static
1430 */
1431 static function createUFJoin(&$params, $ufGroupId) {
1432 $groupTypes = CRM_Utils_Array::value('uf_group_type', $params);
1433
1434 // get ufjoin records for uf group
1435 $ufGroupRecord = CRM_Core_BAO_UFGroup::getUFJoinRecord($ufGroupId);
1436
1437 // get the list of all ufgroup types
1438 $allUFGroupType = CRM_Core_SelectValues::ufGroupTypes();
1439
1440 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
1441 if (!is_array($groupTypes)) {
1442 $groupTypes = array();
1443 }
1444
1445 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
1446 if (!is_array($ufGroupRecord)) {
1447 $ufGroupRecord = array();
1448 }
1449
1450 // check which values has to be inserted/deleted for contact
1451 $menuRebuild = FALSE;
1452 foreach ($allUFGroupType as $key => $value) {
1453 $joinParams = array();
1454 $joinParams['uf_group_id'] = $ufGroupId;
1455 $joinParams['module'] = $key;
1456 if ($key == 'User Account') {
1457 $menuRebuild = TRUE;
1458 }
1459 if (array_key_exists($key, $groupTypes) && !in_array($key, $ufGroupRecord)) {
1460 // insert a new record
1461 CRM_Core_BAO_UFGroup::addUFJoin($joinParams);
1462 }
1463 elseif (!array_key_exists($key, $groupTypes) && in_array($key, $ufGroupRecord)) {
1464 // delete a record for existing ufgroup
1465 CRM_Core_BAO_UFGroup::delUFJoin($joinParams);
1466 }
1467 }
1468
1469 //update the weight
1470 $query = "
1471UPDATE civicrm_uf_join
1472SET weight = %1
1473WHERE uf_group_id = %2
1474AND ( entity_id IS NULL OR entity_id <= 0 )
1475";
1476 $p = array(1 => array($params['weight'], 'Integer'),
1477 2 => array($ufGroupId, 'Integer'),
1478 );
1479 CRM_Core_DAO::executeQuery($query, $p);
1480
1481 // do a menu rebuild if we are on drupal, so it gets all the new menu entries
1482 // for user account
1483 $config = CRM_Core_Config::singleton();
1484 if ($menuRebuild &&
1485 $config->userSystem->is_drupal
1486 ) {
1487 menu_rebuild();
1488 }
1489 }
1490
1491 /**
1492 * Function to get the UF Join records for an ufgroup id
1493 *
1494 * @params int $ufGroupId uf group id
1495 * @params int $displayName if set return display name in array
1496 * @params int $status if set return module other than default modules (User Account/User registration/Profile)
1497 *
77b97be7
EM
1498 * @param null $ufGroupId
1499 * @param null $displayName
1500 * @param null $status
1501 *
6a488035
TO
1502 * @return array $ufGroupJoinRecords
1503 *
1504 * @access public
1505 * @static
1506 */
1507 public static function getUFJoinRecord($ufGroupId = NULL, $displayName = NULL, $status = NULL) {
1508 if ($displayName) {
1509 $UFGroupType = array();
1510 $UFGroupType = CRM_Core_SelectValues::ufGroupTypes();
1511 }
1512
1513 $ufJoin = array();
1514 $dao = new CRM_Core_DAO_UFJoin();
1515
1516 if ($ufGroupId) {
1517 $dao->uf_group_id = $ufGroupId;
1518 }
1519
1520 $dao->find();
1521 $ufJoin = array();
1522
1523 while ($dao->fetch()) {
1524 if (!$displayName) {
1525 $ufJoin[$dao->id] = $dao->module;
1526 }
1527 else {
1528 if (isset($UFGroupType[$dao->module])) {
1529 // skip the default modules
1530 if (!$status) {
1531 $ufJoin[$dao->id] = $UFGroupType[$dao->module];
1532 }
1533 // added for CRM-1475
1534 }
1535 elseif (!CRM_Utils_Array::key($dao->module, $ufJoin)) {
1536 $ufJoin[$dao->id] = $dao->module;
1537 }
1538 }
1539 }
1540 return $ufJoin;
1541 }
1542
1543 /**
1544 * Function takes an associative array and creates a ufjoin record for ufgroup
1545 *
1546 * @param array $params (reference) an assoc array of name/value pairs
1547 *
1548 * @return object CRM_Core_BAO_UFJoin object
1549 * @access public
1550 * @static
1551 */
1552 static function addUFJoin(&$params) {
1553 $ufJoin = new CRM_Core_DAO_UFJoin();
1554 $ufJoin->copyValues($params);
1555 $ufJoin->save();
1556 return $ufJoin;
1557 }
1558
1559 /**
1560 * Function to delete the uf join record for an uf group
1561 *
1562 * @param array $params (reference) an assoc array of name/value pairs
1563 *
1564 * @return void
1565 * @access public
1566 * @static
1567 */
1568 static function delUFJoin(&$params) {
1569 $ufJoin = new CRM_Core_DAO_UFJoin();
1570 $ufJoin->copyValues($params);
1571 $ufJoin->delete();
1572 }
1573
1574 /**
1575 * Function to get the weight for ufjoin record
1576 *
1577 * @param int $ufGroupId if $ufGroupId get update weight or add weight
1578 *
1579 * @return int weight of the UFGroup
1580 * @access public
1581 * @static
1582 */
1583 static function getWeight($ufGroupId = NULL) {
1584 //calculate the weight
1585 $p = array();
1586 if (!$ufGroupId) {
1587 $queryString = "SELECT ( MAX(civicrm_uf_join.weight)+1) as new_weight
1588 FROM civicrm_uf_join
1589 WHERE module = 'User Registration' OR module = 'User Account' OR module = 'Profile'";
1590 }
1591 else {
1592 $queryString = "SELECT MAX(civicrm_uf_join.weight) as new_weight
1593 FROM civicrm_uf_join
1594 WHERE civicrm_uf_join.uf_group_id = %1
1595 AND ( entity_id IS NULL OR entity_id <= 0 )";
1596 $p[1] = array($ufGroupId, 'Integer');
1597 }
1598
1599 $dao = CRM_Core_DAO::executeQuery($queryString, $p);
1600 $dao->fetch();
1601 return ($dao->new_weight) ? $dao->new_weight : 1;
1602 }
1603
1604 /**
1605 * Function to get the uf group for a module
1606 *
1607 * @param string $moduleName module name
77b97be7
EM
1608 * @param int $count no to increment the weight
1609 * @param bool $skipPermission
1610 * @param int $op - which operation (view, edit, create, etc) to check permission for
2141efbf 1611 * @param array|NULL $returnFields list of UFGroup fields to return; NULL for default
6a488035 1612 *
77b97be7 1613 * @internal param bool $skipPermision - whether to add permission clause
6a488035
TO
1614 * @return array $ufGroups array of ufgroups for a module
1615 * @access public
1616 * @static
1617 */
2141efbf 1618 public static function getModuleUFGroup($moduleName = NULL, $count = 0, $skipPermission = TRUE, $op = CRM_Core_Permission::VIEW, $returnFields = NULL) {
290d4ccc
DS
1619 $selectFields = array('id', 'title', 'created_id', 'is_active', 'is_reserved', 'group_type');
1620
1621 if (!CRM_Core_Config::isUpgradeMode()) {
1622 // CRM-13555, since description field was added later (4.4), and to avoid any problems with upgrade
1623 $selectFields[] = 'description';
1624 }
7ba38389 1625
1626 if (!empty($returnFields)) {
1627 $selectFields = array_merge($returnFields, array_diff($selectFields, $returnFields));
2141efbf 1628 }
7ba38389 1629
1630 $queryString = 'SELECT civicrm_uf_group.' . implode(', civicrm_uf_group.', $selectFields) . '
6a488035
TO
1631 FROM civicrm_uf_group
1632 LEFT JOIN civicrm_uf_join ON (civicrm_uf_group.id = uf_group_id)';
1633 $p = array();
1634 if ($moduleName) {
1635 $queryString .= ' AND civicrm_uf_group.is_active = 1
1636 WHERE civicrm_uf_join.module = %2';
1637 $p[2] = array($moduleName, 'String');
1638 }
1639
1640
1641 // add permissioning for profiles only if not registration
1642 if (!$skipPermission) {
1643 $permissionClause = CRM_Core_Permission::ufGroupClause($op, 'civicrm_uf_group.');
1644 if (strpos($queryString, 'WHERE') !== FALSE) {
1645 $queryString .= " AND $permissionClause ";
1646 }
1647 else {
1648 $queryString .= " $permissionClause ";
1649 }
1650 }
1651
1652 $queryString .= ' ORDER BY civicrm_uf_join.weight, civicrm_uf_group.title';
1653 $dao = CRM_Core_DAO::executeQuery($queryString, $p);
1654
1655 $ufGroups = array();
1656 while ($dao->fetch()) {
1657 //skip mix profiles in user Registration / User Account
1658 if (($moduleName == 'User Registration' || $moduleName == 'User Account') &&
1659 CRM_Core_BAO_UFField::checkProfileType($dao->id)
1660 ) {
1661 continue;
1662 }
7ba38389 1663 foreach ($selectFields as $key => $field) {
1664 if($field == 'id') {
1665 continue;
1666 }
1667 elseif ($field == 'name') {
1668 $ufGroups[$dao->id][$field] = $dao->title;
1669 continue;
1670 }
1671 $ufGroups[$dao->id][$field] = $dao->$field;
1672 }
6a488035
TO
1673 }
1674
1675 // Allow other modules to alter/override the UFGroups.
1676 CRM_Utils_Hook::buildUFGroupsForModule($moduleName, $ufGroups);
1677
1678 return $ufGroups;
1679 }
1680
1681 /**
1682 * Function to filter ufgroups based on logged in user contact type
1683 *
1684 * @params int $ufGroupId uf group id (profile id)
1685 *
77b97be7
EM
1686 * @param $ufGroupId
1687 * @param null $contactID
1688 *
6a488035
TO
1689 * @return boolean true or false
1690 * @static
1691 * @access public
1692 */
1693 static function filterUFGroups($ufGroupId, $contactID = NULL) {
1694 if (!$contactID) {
1695 $session = CRM_Core_Session::singleton();
1696 $contactID = $session->get('userID');
1697 }
1698
1699 if ($contactID) {
1700 //get the contact type
1701 $contactType = CRM_Contact_BAO_Contact::getContactType($contactID);
1702
1703 //match if exixting contact type is same as profile contact type
1704 $profileType = CRM_Core_BAO_UFField::getProfileType($ufGroupId);
1705
1706 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
1707 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
1708 }
1709
1710 //allow special mix profiles for Contribution and Participant
1711 $specialProfiles = array('Contribution', 'Participant', 'Membership');
1712
1713 if (in_array($profileType, $specialProfiles)) {
1714 return TRUE;
1715 }
1716
1717 if (($contactType == $profileType) || $profileType == 'Contact') {
1718 return TRUE;
1719 }
1720 }
1721
1722 return FALSE;
1723 }
1724
1725 /**
1726 * Function to build profile form
1727 *
1728 * @params object $form form object
1729 * @params array $field array field properties
1730 * @params int $mode profile mode
1731 * @params int $contactID contact id
133e2c99 1732 * @params string $usedFor for building up prefixed fieldname for special cases (e.g. onBehalf, Honor)
6a488035 1733 *
77b97be7
EM
1734 * @param $form
1735 * @param $field
1736 * @param $mode
1737 * @param null $contactId
1738 * @param bool $online
1739 * @param null $usedFor
1740 * @param null $rowNumber
1741 * @param string $prefix
1742 *
6a488035
TO
1743 * @return null
1744 * @static
1745 * @access public
1746 */
1747 static function buildProfile(
1748 &$form,
1749 &$field,
1750 $mode,
1751 $contactId = NULL,
1752 $online = FALSE,
133e2c99 1753 $usedFor = NULL,
6a488035
TO
1754 $rowNumber = NULL ,
1755 $prefix = ''
1756 ) {
1757 $defaultValues = array();
1758 $fieldName = $field['name'];
1759 $title = $field['title'];
1760 $attributes = $field['attributes'];
1761 $rule = $field['rule'];
1762 $view = $field['is_view'];
1763 $required = ($mode == CRM_Profile_Form::MODE_SEARCH) ? FALSE : $field['is_required'];
1764 $search = ($mode == CRM_Profile_Form::MODE_SEARCH) ? TRUE : FALSE;
1765 $isShared = CRM_Utils_Array::value('is_shared', $field, 0);
1766
1767 // do not display view fields in drupal registration form
1768 // CRM-4632
1769 if ($view && $mode == CRM_Profile_Form::MODE_REGISTER) {
1770 return;
1771 }
1772
133e2c99 1773 if ($usedFor == 'onbehalf') {
6a488035
TO
1774 $name = "onbehalf[$fieldName]";
1775 }
133e2c99 1776 elseif ($usedFor == 'honor') {
1777 $name = "honor[$fieldName]";
1778 }
6a488035
TO
1779 elseif ($contactId && !$online) {
1780 $name = "field[$contactId][$fieldName]";
1781 }
1782 elseif ($rowNumber) {
1783 $name = "field[$rowNumber][$fieldName]";
1784 }
1785 elseif (!empty($prefix)) {
1786 $name = $prefix ."[$fieldName]";
1787 }
1788 else {
1789 $name = $fieldName;
1790 }
1791
1792 if ($fieldName == 'image_URL' && $mode == CRM_Profile_Form::MODE_EDIT) {
1793 $deleteExtra = ts('Are you sure you want to delete contact image.');
1794 $deleteURL = array(
1795 CRM_Core_Action::DELETE =>
1796 array(
1797 'name' => ts('Delete Contact Image'),
1798 'url' => 'civicrm/contact/image',
1799 'qs' => 'reset=1&id=%%id%%&gid=%%gid%%&action=delete',
1800 'extra' =>
1801 'onclick = "if (confirm( \'' . $deleteExtra . '\' ) ) this.href+=\'&amp;confirmed=1\'; else return false;"',
1802 ),
1803 );
1804 $deleteURL = CRM_Core_Action::formLink($deleteURL,
1805 CRM_Core_Action::DELETE,
1806 array('id' => $form->get('id'),
1807 'gid' => $form->get('gid'),
87dab4a4
AH
1808 ),
1809 ts('more'),
1810 FALSE,
1811 'contact.profileimage.delete',
1812 'Contact',
1813 $form->get('id')
6a488035
TO
1814 );
1815 $form->assign('deleteURL', $deleteURL);
1816 }
1817 $addressOptions = CRM_Core_BAO_Setting::valueOptions(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
1818 'address_options', TRUE, NULL, TRUE
1819 );
1820
1821 if (substr($fieldName, 0, 14) === 'state_province') {
1822 $form->add('select', $name, $title,
1823 array(
1824 '' => ts('- select -')) + CRM_Core_PseudoConstant::stateProvince(), $required
1825 );
1826 $config = CRM_Core_Config::singleton();
1827 if (!in_array($mode, array(
1828 CRM_Profile_Form::MODE_EDIT, CRM_Profile_Form::MODE_SEARCH)) &&
1829 $config->defaultContactStateProvince
1830 ) {
1831 $defaultValues[$name] = $config->defaultContactStateProvince;
1832 $form->setDefaults($defaultValues);
1833 }
1834 }
1835 elseif (substr($fieldName, 0, 7) === 'country') {
1836 $form->add('select', $name, $title,
1837 array(
1838 '' => ts('- select -')) + CRM_Core_PseudoConstant::country(), $required
1839 );
1840 $config = CRM_Core_Config::singleton();
1841 if (!in_array($mode, array(
1842 CRM_Profile_Form::MODE_EDIT, CRM_Profile_Form::MODE_SEARCH)) &&
1843 $config->defaultContactCountry
1844 ) {
1845 $defaultValues[$name] = $config->defaultContactCountry;
1846 $form->setDefaults($defaultValues);
1847 }
1848 }
1849 elseif (substr($fieldName, 0, 6) === 'county') {
1850 if ($addressOptions['county']) {
1851 $form->add('select', $name, $title,
1852 array(
75e14bbf 1853 '' => ts('(choose state first)')), $required
6a488035
TO
1854 );
1855 }
1856 }
1857 elseif (substr($fieldName, 0, 9) === 'image_URL') {
1858 $form->add('file', $name, $title, $attributes, $required);
1859 $form->addUploadElement($name);
1860 }
1861 elseif (substr($fieldName, 0, 2) === 'im') {
1862 $form->add('text', $name, $title, $attributes, $required);
1863 if (!$contactId) {
133e2c99 1864 if ($usedFor) {
6a488035
TO
1865 if (substr($name, -1) == ']') {
1866 $providerName = substr($name, 0, -1) . '-provider_id]';
1867 }
1868 $form->add('select', $providerName, NULL,
1869 array(
e7e657f0 1870 '' => ts('- select -')) + CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id'), $required
6a488035
TO
1871 );
1872 }
1873 else {
1874 $form->add('select', $name . '-provider_id', $title,
1875 array(
e7e657f0 1876 '' => ts('- select -')) + CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id'), $required
6a488035
TO
1877 );
1878 }
1879
1880 if ($view && $mode != CRM_Profile_Form::MODE_SEARCH) {
1881 $form->freeze($name . '-provider_id');
1882 }
1883 }
1884 }
1885 elseif (($fieldName === 'birth_date') || ($fieldName === 'deceased_date')) {
1886 $form->addDate($name, $title, $required, array('formatType' => 'birth'));
1887 }
1888 elseif (in_array($fieldName, array(
1889 'membership_start_date', 'membership_end_date', 'join_date'))) {
1890 $form->addDate($name, $title, $required, array('formatType' => 'custom'));
1891 }
1892 elseif (CRM_Utils_Array::value('name',$field) == 'membership_type') {
1893 list($orgInfo, $types) = CRM_Member_BAO_MembershipType::getMembershipTypeInfo();
1894 $sel = &$form->addElement('hierselect', $name, $title);
53cfc93c 1895 $select = array('' => ts('- select -') );
1896 if(count($orgInfo) == 1 && $field['is_required']) {
1897 // we only have one org - so we should default to it. Not sure about defaulting to first type
1898 // as it could be missed - so adding a select
1899 // however, possibly that is more similar to the membership form
1900 if(count($types[1]) > 1) {
1901 $types[1] = $select + $types[1];
1902 }
1903 }
1904 else {
1905 $orgInfo = $select + $orgInfo;
1906 }
1907 $sel->setOptions(array($orgInfo, $types));
6a488035
TO
1908 }
1909 elseif (CRM_Utils_Array::value('name',$field) == 'membership_status') {
1910 $form->add('select', $name, $title,
1911 array(
1912 '' => ts('- select -')) + CRM_Member_PseudoConstant::membershipStatus(NULL, NULL, 'label'), $required
1913 );
1914 }
04ffef8d 1915 elseif ($fieldName === 'gender_id') {
6a488035 1916 $genderOptions = array();
26cf88b5 1917 $gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
6a488035
TO
1918 foreach ($gender as $key => $var) {
1919 $genderOptions[$key] = $form->createElement('radio', NULL, ts('Gender'), $var, $key);
1920 }
8a4f27dc 1921 $group = $form->addGroup($genderOptions, $name, $title);
6a488035
TO
1922 if ($required) {
1923 $form->addRule($name, ts('%1 is a required field.', array(1 => $title)), 'required');
1924 }
8a4f27dc 1925 else {
b847e6e7 1926 $group->setAttribute('allowClear', TRUE);
8a4f27dc 1927 }
6a488035 1928 }
f45334bd 1929 elseif ($fieldName === 'prefix_id' || $fieldName === 'suffix_id') {
6a488035
TO
1930 $form->add('select', $name, $title,
1931 array(
f45334bd 1932 '' => ts('- select -')) + CRM_Core_PseudoConstant::get('CRM_Contact_BAO_Contact', $fieldName), $required
6a488035
TO
1933 );
1934 }
1935 elseif ($fieldName === 'contact_sub_type') {
1936 $gId = $form->get('gid') ? $form->get('gid') : CRM_Utils_Array::value('group_id', $field);
133e2c99 1937 if ($usedFor == 'onbehalf') {
6a488035
TO
1938 $profileType = 'Organization';
1939 }
133e2c99 1940 elseif ($usedFor == 'honor') {
1941 $profileType = CRM_Core_BAO_UFField::getProfileType($form->_params['honoree_profile_id']);
1942 }
6a488035
TO
1943 else {
1944 $profileType = $gId ? CRM_Core_BAO_UFField::getProfileType($gId) : NULL;
1945 if ($profileType == 'Contact') {
1946 $profileType = 'Individual';
1947 }
1948 }
1949
1950 $setSubtype = FALSE;
1951 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
1952 $setSubtype = $profileType;
1953 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
1954 }
1955
1956 $subtypes = $profileType ? CRM_Contact_BAO_ContactType::subTypePairs($profileType) : array();
1957
1958 if ($setSubtype) {
1959 $subtypeList = array();
1960 $subtypeList[$setSubtype] = $subtypes[$setSubtype];
1961 }
1962 else {
1963 $subtypeList = $subtypes;
1964 }
1965
1966 $sel = $form->add('select', $name, $title, $subtypeList, $required);
1967 $sel->setMultiple(TRUE);
1968 }
1969 elseif (in_array($fieldName, CRM_Contact_BAO_Contact::$_greetingTypes)) {
1970 //add email greeting, postal greeting, addressee, CRM-4575
1971 $gId = $form->get('gid') ? $form->get('gid') : CRM_Utils_Array::value('group_id', $field);
1972 $profileType = CRM_Core_BAO_UFField::getProfileType($gId, TRUE, FALSE, TRUE);
1973
1974 if (empty($profileType) || in_array($profileType, array(
1975 'Contact', 'Contribution', 'Participant', 'Membership'))) {
1976 $profileType = 'Individual';
1977 }
1978 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
1979 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
1980 }
1981 $greeting = array(
1982 'contact_type' => $profileType,
1983 'greeting_type' => $fieldName,
1984 );
1985 $form->add('select', $name, $title,
1986 array(
1987 '' => ts('- select -')) + CRM_Core_PseudoConstant::greeting($greeting), $required
1988 );
1989 // add custom greeting element
1990 $form->add('text', $fieldName . '_custom', ts('Custom %1', array(1 => ucwords(str_replace('_', ' ', $fieldName)))),
1991 NULL, FALSE
1992 );
1993 }
1994 elseif ($fieldName === 'preferred_communication_method') {
e7e657f0 1995 $communicationFields = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'preferred_communication_method');
6a488035
TO
1996 foreach ($communicationFields as $key => $var) {
1997 if ($key == '') {
1998 continue;
1999 }
2000 $communicationOptions[] = $form->createElement('checkbox', $key, NULL, $var);
2001 }
2002 $form->addGroup($communicationOptions, $name, $title, '<br/>');
2003 }
2004 elseif ($fieldName === 'preferred_mail_format') {
2005 $form->add('select', $name, $title, CRM_Core_SelectValues::pmf());
2006 }
2007 elseif ($fieldName === 'preferred_language') {
c0c9cd82 2008 $form->add('select', $name, $title, array('' => ts('- select -')) + CRM_Contact_BAO_Contact::buildOptions('preferred_language'));
6a488035
TO
2009 }
2010 elseif ($fieldName == 'external_identifier') {
2011 $form->add('text', $name, $title, $attributes, $required);
2012 $contID = $contactId;
2013 if (!$contID) {
2014 $contID = $form->get('id');
2015 }
2016 $form->addRule($name,
2017 ts('External ID already exists in Database.'),
2018 'objectExists',
2019 array('CRM_Contact_DAO_Contact', $contID, 'external_identifier')
2020 );
2021 }
2022 elseif ($fieldName === 'group') {
2023 CRM_Contact_Form_Edit_TagsAndGroups::buildQuickForm($form, $contactId,
2024 CRM_Contact_Form_Edit_TagsAndGroups::GROUP,
2025 TRUE, $required,
2026 $title, NULL, $name
2027 );
2028 }
2029 elseif ($fieldName === 'tag') {
2030 CRM_Contact_Form_Edit_TagsAndGroups::buildQuickForm($form, $contactId,
2031 CRM_Contact_Form_Edit_TagsAndGroups::TAG,
2032 FALSE, $required,
2033 NULL, $title, $name
2034 );
2035 }
2036 elseif (substr($fieldName, 0, 4) === 'url-') {
2037 $form->add('text', $name, $title,
2038 array_merge(CRM_Core_DAO::getAttribute('CRM_Core_DAO_Website', 'url'),
2039 array(
2040 'onfocus' => "if (!this.value) { this.value='http://';} else return false",
2041 'onblur' => "if ( this.value == 'http://') { this.value='';} else return false",
2042 )
2043 ), $required
2044 );
2045
2046 $form->addRule($name, ts('Enter a valid Website.'), 'url');
6a488035
TO
2047 }
2048 // Note should be rendered as textarea
2049 elseif (substr($fieldName, -4) == 'note') {
2050 $form->add('textarea', $name, $title, $attributes, $required);
2051 }
2052 elseif (substr($fieldName, 0, 6) === 'custom') {
2053 $customFieldID = CRM_Core_BAO_CustomField::getKeyID($fieldName);
2054 if ($customFieldID) {
2055 CRM_Core_BAO_CustomField::addQuickFormElement($form, $name, $customFieldID, FALSE, $required, $search, $title);
2056 }
2057 }
2058 elseif (substr($fieldName, 0, 14) === 'address_custom') {
2059 list($fName, $locTypeId) = CRM_Utils_System::explode('-', $fieldName, 2);
2060 $customFieldID = CRM_Core_BAO_CustomField::getKeyID(substr($fName, 8));
2061 if ($customFieldID) {
2062 CRM_Core_BAO_CustomField::addQuickFormElement($form, $name, $customFieldID, FALSE, $required, $search, $title);
2063 }
2064 }
2065 elseif (in_array($fieldName, array(
2066 'receive_date', 'receipt_date', 'thankyou_date', 'cancel_date'))) {
2067 $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime'));
2068 }
2069 elseif ($fieldName == 'send_receipt') {
2070 $form->addElement('checkbox', $name, $title);
2071 }
2072 elseif ($fieldName == 'soft_credit') {
ccec9d6b 2073 $form->addEntityRef("soft_credit_contact_id[$rowNumber]", ts('Soft Credit To'), array('create' => TRUE));
5ee60152 2074 $form->addMoney("soft_credit_amount[{$rowNumber}]", ts('Amount'), FALSE, NULL, FALSE);
6a488035
TO
2075 }
2076 elseif ($fieldName == 'product_name') {
2077 list($products, $options) = CRM_Contribute_BAO_Premium::getPremiumProductInfo();
2078 $sel = &$form->addElement('hierselect', $name, $title);
2079 $products = array(
2080 '0' => ts('- select -')) + $products;
2081 $sel->setOptions(array($products, $options));
2082 }
2083 elseif ($fieldName == 'payment_instrument') {
2084 $form->add('select', $name, $title,
2085 array(''=>ts( '- select -' )) + CRM_Contribute_PseudoConstant::paymentInstrument( ), $required );
2086 }
2087 else if ($fieldName == 'financial_type' ) {
2088 $form->add('select', $name, $title,
2089 array(
2090 '' => ts('- select -')) + CRM_Contribute_PseudoConstant::financialType(), $required
2091 );
2092 }
2093 elseif ($fieldName == 'contribution_status_id') {
aaf5ca44
DG
2094 $contributionStatuses = CRM_Contribute_PseudoConstant::contributionStatus();
2095 $statusName = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
2096 foreach (array(
2097 'In Progress',
2098 'Overdue',
2099 'Refunded'
2100 ) as $suppress) {
2101 unset($contributionStatuses[CRM_Utils_Array::key($suppress, $statusName)]);
2102 }
6a73ef3f 2103
6a488035
TO
2104 $form->add('select', $name, $title,
2105 array(
aaf5ca44 2106 '' => ts('- select -')) + $contributionStatuses, $required
6a488035
TO
2107 );
2108 }
51fa20cb 2109 elseif ($fieldName == 'soft_credit_type') {
2110 $form->add('select', $name, $title,
2111 array(
2112 '' => ts('- select -')) + CRM_Core_OptionGroup::values("soft_credit_type")
2113 );
2114 $form->addElement('hidden', 'sct_default_id',
2115 CRM_Core_OptionGroup::getDefaultValue("soft_credit_type"),
2116 array('id' => 'sct_default_id')
2117 );
2118 }
6a488035
TO
2119 elseif ($fieldName == 'currency') {
2120 $form->addCurrency($name, $title, $required);
2121 }
2122 elseif ($fieldName == 'contribution_page_id') {
2123 $form->add('select', $name, $title,
2124 array(
2125 '' => ts('- select -')) + CRM_Contribute_PseudoConstant::contributionPage(), $required, 'class="big"'
2126 );
2127 }
2128 elseif ($fieldName == 'participant_register_date') {
2129 $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime'));
2130 }
2131 elseif ($fieldName == 'activity_status_id') {
2132 $form->add('select', $name, $title,
2133 array(
2134 '' => ts('- select -')) + CRM_Core_PseudoConstant::activityStatus(), $required
2135 );
2136 }
2137 elseif ($fieldName == 'activity_engagement_level') {
2138 $form->add('select', $name, $title,
2139 array(
2140 '' => ts('- select -')) + CRM_Campaign_PseudoConstant::engagementLevel(), $required
2141 );
2142 }
2143 elseif ($fieldName == 'activity_date_time') {
2144 $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime'));
2145 }
2146 elseif ($fieldName == 'participant_status') {
2147 $cond = NULL;
2148 if ($online == TRUE) {
2149 $cond = 'visibility_id = 1';
2150 }
2151 $form->add('select', $name, $title,
2152 array(
2153 '' => ts('- select -')) + CRM_Event_PseudoConstant::participantStatus(NULL, $cond, 'label'), $required
2154 );
2155 }
2156 elseif ($fieldName == 'participant_role') {
a7488080 2157 if (!empty($field['is_multiple'])) {
6a488035
TO
2158 $form->addCheckBox($name, $title, CRM_Event_PseudoConstant::participantRole(), NULL, NULL, NULL, NULL, '&nbsp', TRUE);
2159 }
2160 else {
2161 $form->add('select', $name, $title,
2162 array(
2163 '' => ts('- select -')) + CRM_Event_PseudoConstant::participantRole(), $required
2164 );
2165 }
2166 }
2167 elseif ($fieldName == 'world_region') {
2168 $form->add('select', $name, $title,
2169 array(
2170 '' => ts('- select -')) + CRM_Core_PseudoConstant::worldRegion(), $required
2171 );
2172 }
2173 elseif ($fieldName == 'signature_html') {
2174 $form->addWysiwyg($name, $title, CRM_Core_DAO::getAttribute('CRM_Core_DAO_Email', $fieldName));
2175 }
2176 elseif ($fieldName == 'signature_text') {
2177 $form->add('textarea', $name, $title, CRM_Core_DAO::getAttribute('CRM_Core_DAO_Email', $fieldName));
2178 }
2179 elseif (substr($fieldName, -11) == 'campaign_id') {
2180 if (CRM_Campaign_BAO_Campaign::isCampaignEnable()) {
2181 $campaigns = CRM_Campaign_BAO_Campaign::getCampaigns(CRM_Utils_Array::value($contactId,
2182 $form->_componentCampaigns
2183 ));
2184 $form->add('select', $name, $title,
2185 array(
2186 '' => ts('- select -')) + $campaigns, $required, 'class="big"'
2187 );
2188 }
2189 }
2190 elseif ($fieldName == 'activity_details') {
2191 $form->addWysiwyg($fieldName, $title, array('rows' => 4, 'cols' => 60), $required);
2192 }
2193 elseif ($fieldName == 'activity_duration') {
2194 $form->add('text', $name, $title, $attributes, $required);
2195 $form->addRule($name, ts('Please enter the duration as number of minutes (integers only).'), 'positiveInteger');
2196 }
2197 else {
2198 if (substr($fieldName, 0, 3) === 'is_' or substr($fieldName, 0, 7) === 'do_not_') {
2199 $form->add('advcheckbox', $name, $title, $attributes, $required);
2200 }
2201 else {
2202 $form->add('text', $name, $title, $attributes, $required);
2203 }
2204 }
2205
2206 static $hiddenSubtype = FALSE;
2207 if (!$hiddenSubtype && CRM_Contact_BAO_ContactType::isaSubType($field['field_type'])) {
2208 // In registration mode params are submitted via POST and we don't have any clue
2209 // about profile-id or the profile-type (which could be a subtype)
2210 // To generalize the behavior and simplify the process,
2211 // lets always add the hidden
2212 //subtype value if there is any, and we won't have to
2213 // compute it while processing.
133e2c99 2214 if ($usedFor) {
2215 $form->addElement('hidden', $usedFor . '[contact_sub_type]', $field['field_type']);
6a488035
TO
2216 }
2217 else {
2218 $form->addElement('hidden', 'contact_sub_type_hidden', $field['field_type']);
2219 }
2220 $hiddenSubtype = TRUE;
2221 }
2222
2223 if (($view && $mode != CRM_Profile_Form::MODE_SEARCH) || $isShared) {
2224 $form->freeze($name);
2225 }
2226
2227 //add the rules
2228 if (in_array($fieldName, array(
2229 'non_deductible_amount', 'total_amount', 'fee_amount', 'net_amount'))) {
2230 $form->addRule($name, ts('Please enter a valid amount.'), 'money');
2231 }
faf468e7 2232 $stateCountryMap = array();
2233 if (!empty($form->_stateCountryMap['state_province']) && !empty($form->_stateCountryMap['country'])) {
2234 foreach ($form->_stateCountryMap['state_province'] as $key => $value) {
2235 $stateCountryMap[$key]['state_province'] = $value;
2236 $stateCountryMap[$key]['country'] = $form->_stateCountryMap['country'][$key];
2237 }
2238 CRM_Core_BAO_Address::addStateCountryMap($stateCountryMap);
2239 }
6a488035
TO
2240 if ($rule) {
2241 if (!($rule == 'email' && $mode == CRM_Profile_Form::MODE_SEARCH)) {
2242 $form->addRule($name, ts('Please enter a valid %1', array(1 => $title)), $rule);
2243 }
2244 }
2245 }
2246
2247 /**
2248 * Function to set profile defaults
2249 *
2250 * @params int $contactId contact id
2251 * @params array $fields associative array of fields
2252 * @params array $defaults defaults array
2253 * @params boolean $singleProfile true for single profile else false(batch update)
2254 * @params int $componentId id for specific components like contribute, event etc
2255 *
77b97be7
EM
2256 * @param $contactId
2257 * @param $fields
2258 * @param $defaults
2259 * @param bool $singleProfile
2260 * @param null $componentId
2261 * @param null $component
2262 *
6a488035
TO
2263 * @return null
2264 * @static
2265 * @access public
2266 */
2267 static function setProfileDefaults($contactId, &$fields, &$defaults,
2268 $singleProfile = TRUE, $componentId = NULL, $component = NULL
2269 ) {
2270 if (!$componentId) {
2271 //get the contact details
2272 list($contactDetails, $options) = CRM_Contact_BAO_Contact::getHierContactDetails($contactId, $fields);
2273 $details = CRM_Utils_Array::value($contactId, $contactDetails);
2274 $multipleFields = array('website' => 'url');
2275
2276 //start of code to set the default values
2277 foreach ($fields as $name => $field) {
2278 // skip pseudo fields
2279 if (substr($name, 0, 9) == 'phone_ext') {
2280 continue;
2281 }
2282
2283 //set the field name depending upon the profile mode(single/batch)
2284 if ($singleProfile) {
2285 $fldName = $name;
2286 }
2287 else {
2288 $fldName = "field[$contactId][$name]";
2289 }
2290
2291 if ($name == 'group') {
2292 CRM_Contact_Form_Edit_TagsAndGroups::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups::GROUP, $fldName);
2293 }
2294 if ($name == 'tag') {
2295 CRM_Contact_Form_Edit_TagsAndGroups::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups::TAG, $fldName);
2296 }
2297
a7488080 2298 if (!empty($details[$name]) || isset($details[$name])) {
6a488035 2299 //to handle custom data (checkbox) to be written
58f00377 2300 // to handle birth/deceased date, greeting_type and few other fields
2301 if (($name == 'birth_date') || ($name == 'deceased_date')) {
6a488035
TO
2302 list($defaults[$fldName]) = CRM_Utils_Date::setDateDefaults($details[$name], 'birth');
2303 }
2304 elseif (in_array($name, CRM_Contact_BAO_Contact::$_greetingTypes)) {
2305 $defaults[$fldName] = $details[$name . '_id'];
2306 $defaults[$name . '_custom'] = $details[$name . '_custom'];
2307 }
2308 elseif ($name == 'preferred_communication_method') {
2309 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2310 foreach ($v as $item) {
2311 if ($item) {
2312 $defaults[$fldName . "[$item]"] = 1;
2313 }
2314 }
2315 }
2316 elseif ($name == 'world_region') {
2317 $defaults[$fldName] = $details['worldregion_id'];
2318 }
2319 elseif ($customFieldId = CRM_Core_BAO_CustomField::getKeyID($name)) {
2320 //fix for custom fields
2321 $customFields = CRM_Core_BAO_CustomField::getFields(CRM_Utils_Array::value('contact_type', $details));
2322
2323 // hack to add custom data for components
2324 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
2325 foreach ($components as $value) {
2326 $customFields = CRM_Utils_Array::crmArrayMerge($customFields,
2327 CRM_Core_BAO_CustomField::getFieldsForImport($value)
2328 );
2329 }
2330
2331 switch ($customFields[$customFieldId]['html_type']) {
2332 case 'Multi-Select State/Province':
2333 case 'Multi-Select Country':
2334 case 'AdvMulti-Select':
2335 case 'Multi-Select':
2336 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2337 foreach ($v as $item) {
2338 if ($item) {
2339 $defaults[$fldName][$item] = $item;
2340 }
2341 }
2342 break;
2343
2344 case 'CheckBox':
2345 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2346 foreach ($v as $item) {
2347 if ($item) {
2348 $defaults[$fldName][$item] = 1;
2349 // seems like we need this for QF style checkboxes in profile where its multiindexed
2350 // CRM-2969
2351 $defaults["{$fldName}[{$item}]"] = 1;
2352 }
2353 }
2354 break;
2355
6a488035
TO
2356 case 'Select Date':
2357 // CRM-6681, set defult values according to date and time format (if any).
2358 $dateFormat = NULL;
a7488080 2359 if (!empty($customFields[$customFieldId]['date_format'])) {
fd933dc5 2360 $dateFormat = $customFields[$customFieldId]['date_format'];
6a488035
TO
2361 }
2362
a7488080 2363 if (empty($customFields[$customFieldId]['time_format'])) {
6a488035
TO
2364 list($defaults[$fldName]) = CRM_Utils_Date::setDateDefaults($details[$name], NULL,
2365 $dateFormat
2366 );
2367 }
2368 else {
2369 $timeElement = $fldName . '_time';
2370 if (substr($fldName, -1) == ']') {
2371 $timeElement = substr($fldName, 0, -1) . '_time]';
2372 }
fd933dc5
KJ
2373 list($defaults[$fldName], $defaults[$timeElement]) = CRM_Utils_Date::setDateDefaults($details[$name],
2374 NULL, $dateFormat, $customFields[$customFieldId]['time_format']);
6a488035
TO
2375 }
2376 break;
2377
2378 default:
2379 $defaults[$fldName] = $details[$name];
2380 break;
2381 }
2382 }
2383 else {
2384 $defaults[$fldName] = $details[$name];
2385 }
2386 }
2387 else {
2388 $blocks = array('email', 'phone', 'im', 'openid');
2389 list($fieldName, $locTypeId, $phoneTypeId) = CRM_Utils_System::explode('-', $name, 3);
2390 if (!in_array($fieldName, $multipleFields)) {
2391 if (is_array($details)) {
2392 foreach ($details as $key => $value) {
2393 // when we fixed CRM-5319 - get primary loc
2394 // type as per loc field and removed below code.
2395 $primaryLocationType = FALSE;
2396 if ($locTypeId == 'Primary') {
2397 if (is_array($value) && array_key_exists($fieldName, $value)){
2398 $primaryLocationType = TRUE;
2399 if (in_array($fieldName, $blocks)){
2400 $locTypeId = CRM_Contact_BAO_Contact::getPrimaryLocationType($contactId, FALSE, $fieldName);
2401 }
2402 else{
2403 $locTypeId = CRM_Contact_BAO_Contact::getPrimaryLocationType($contactId, FALSE, 'address');
2404 }
2405 }
2406 }
2407
2408 // fixed for CRM-665
2409 if (is_numeric($locTypeId)) {
2410 if ($primaryLocationType || $locTypeId == CRM_Utils_Array::value('location_type_id', $value)) {
a7488080 2411 if (!empty($value[$fieldName])) {
6a488035
TO
2412 //to handle stateprovince and country
2413 if ($fieldName == 'state_province') {
2414 $defaults[$fldName] = $value['state_province_id'];
2415 }
2416 elseif ($fieldName == 'county') {
2417 $defaults[$fldName] = $value['county_id'];
2418 }
2419 elseif ($fieldName == 'country') {
6a488035
TO
2420 if (!isset($value['country_id']) || !$value['country_id']) {
2421 $config = CRM_Core_Config::singleton();
2422 if ($config->defaultContactCountry) {
2423 $defaults[$fldName] = $config->defaultContactCountry;
2424 }
2425 }
b3071092
DL
2426 else {
2427 $defaults[$fldName] = $value['country_id'];
2428 }
6a488035
TO
2429 }
2430 elseif ($fieldName == 'phone') {
2431 if ($phoneTypeId) {
2432 if (isset($value['phone'][$phoneTypeId])) {
2433 $defaults[$fldName] = $value['phone'][$phoneTypeId];
2434 }
2435 if (isset($value['phone_ext'][$phoneTypeId])) {
2436 $defaults[str_replace('phone', 'phone_ext', $fldName)] = $value['phone_ext'][$phoneTypeId];
2437 }
2438 }
2439 else {
2440 $phoneDefault = CRM_Utils_Array::value('phone', $value);
2441 // CRM-9216
2442 if (!is_array($phoneDefault)) {
2443 $defaults[$fldName] = $phoneDefault;
2444 }
2445 }
2446 }
2447 elseif ($fieldName == 'email') {
2448 //adding the first email (currently we don't support multiple emails of same location type)
2449 $defaults[$fldName] = $value['email'];
2450 }
2451 elseif ($fieldName == 'im') {
2452 //adding the first im (currently we don't support multiple ims of same location type)
2453 $defaults[$fldName] = $value['im'];
2454 $defaults[$fldName . '-provider_id'] = $value['im_provider_id'];
2455 }
2456 else {
2457 $defaults[$fldName] = $value[$fieldName];
2458 }
2459 }
2460 elseif (substr($fieldName, 0, 14) === 'address_custom' &&
2461 CRM_Utils_Array::value(substr($fieldName, 8), $value)
2462 ) {
2463 $defaults[$fldName] = $value[substr($fieldName, 8)];
2464 }
2465 }
2466 }
2467 }
2468 }
2469 }
2470 else {
2471 if (is_array($details)) {
1fd63589
EM
2472 if ($fieldName === 'url'
2473 && !empty($details['website'])
887e764d
PN
2474 && !empty($details['website'][$locTypeId])) {
2475 $defaults[$fldName] = CRM_Utils_Array::value('url', $details['website'][$locTypeId]);
6a488035
TO
2476 }
2477 }
2478 }
2479 }
2480 }
2481 }
2482
2483 //Handling Contribution Part of the batch profile
2484 if (CRM_Core_Permission::access('CiviContribute') && $component == 'Contribute') {
2485 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2486 }
2487
2488 //Handling Event Participation Part of the batch profile
2489 if (CRM_Core_Permission::access('CiviEvent') && $component == 'Event') {
2490 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2491 }
2492
2493 //Handling membership Part of the batch profile
2494 if (CRM_Core_Permission::access('CiviMember') && $component == 'Membership') {
2495 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2496 }
2497
2498 //Handling Activity Part of the batch profile
2499 if ($component == 'Activity') {
2500 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2501 }
2502 }
2503
2504 /**
2505 * Function to get profiles by type eg: pure Individual etc
2506 *
2507 * @param array $types associative array of types eg: types('Individual')
2508 * @param boolean $onlyPure true if only pure profiles are required
2509 *
2510 * @return array $profiles associative array of profiles
2511 * @static
2512 * @access public
2513 */
2514 static function getProfiles($types, $onlyPure = FALSE) {
2515 $profiles = array();
ff4f7744 2516 $ufGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id');
6a488035
TO
2517
2518 CRM_Utils_Hook::aclGroup(CRM_Core_Permission::ADMIN, NULL, 'civicrm_uf_group', $ufGroups, $ufGroups);
2519
2520 // Exclude Batch Data Entry profiles - CRM-10901
2521 $batchProfiles = CRM_Core_BAO_UFGroup::getBatchProfiles();
2522
2523 foreach ($ufGroups as $id => $title) {
2524 $ptype = CRM_Core_BAO_UFField::getProfileType($id, FALSE, $onlyPure);
2525 if (in_array($ptype, $types) && !array_key_exists($id, $batchProfiles)) {
2526 $profiles[$id] = $title;
2527 }
2528 }
2529 return $profiles;
2530 }
2531
2532 /**
2533 * Function to check whether a profile is valid combination of
2534 * required and/or optional profile types
2535 *
2536 * @param array $required array of types those are required
2537 * @param array $optional array of types those are optional
2538 *
2539 * @return array $profiles associative array of profiles
2540 * @static
2541 * @access public
2542 */
2543 static function getValidProfiles($required, $optional = NULL) {
2544 if (!is_array($required) || empty($required)) {
2545 return;
2546 }
2547
2548 $profiles = array();
ff4f7744 2549 $ufGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id');
6a488035
TO
2550
2551 CRM_Utils_Hook::aclGroup(CRM_Core_Permission::ADMIN, NULL, 'civicrm_uf_group', $ufGroups, $ufGroups);
2552
2553 foreach ($ufGroups as $id => $title) {
2554 $type = CRM_Core_BAO_UFField::checkValidProfileType($id, $required, $optional);
2555 if ($type) {
2556 $profiles[$id] = $title;
2557 }
2558 }
2559
2560 return $profiles;
2561 }
2562
2563 /**
2564 * Function to check whether a profile is valid combination of
2565 * required profile fields
2566 *
2567 * @param array $ufId integer id of the profile
2568 * @param array $required array of fields those are required in the profile
2569 *
2570 * @return array $profiles associative array of profiles
2571 * @static
2572 * @access public
2573 */
2574 static function checkValidProfile($ufId, $required = NULL) {
2575 $validProfile = FALSE;
2576 if (!$ufId) {
2577 return $validProfile;
2578 }
2579
2580 if (!CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $ufId, 'is_active')) {
2581 return $validProfile;
2582 }
2583
2584 $profileFields = self::getFields($ufId, FALSE, CRM_Core_Action::VIEW, NULL,
2585 NULL, FALSE, NULL, FALSE, NULL,
2586 CRM_Core_Permission::CREATE, NULL
2587 );
2588
2589 $validProfile = array();
2590 if (!empty($profileFields)) {
2591 $fields = array_keys($profileFields);
2592 foreach ($fields as $val) {
2593 foreach ($required as $key => $field) {
2594 if (strpos($val, $field) === 0) {
2595 unset($required[$key]);
2596 }
2597 }
2598 }
2599
2600 $validProfile = (empty($required)) ? TRUE : FALSE;
2601 }
2602
2603 return $validProfile;
2604 }
2605
2606 /**
2607 * Function to get default value for Register.
2608 *
77b97be7
EM
2609 * @param $fields
2610 * @param $defaults
2611 *
2612 * @return mixed $defaults@static
6a488035
TO
2613 * @access public
2614 */
2615 static function setRegisterDefaults(&$fields, &$defaults) {
b525f1cc 2616 $config = CRM_Core_Config::singleton();
6a488035
TO
2617 foreach ($fields as $name => $field) {
2618 if (substr($name, 0, 8) == 'country-') {
b525f1cc 2619 if (!empty($config->defaultContactCountry)) {
6a488035
TO
2620 $defaults[$name] = $config->defaultContactCountry;
2621 }
2622 }
2623 elseif (substr($name, 0, 15) == 'state_province-') {
b525f1cc 2624 if (!empty($config->defaultContactStateProvince)) {
6a488035
TO
2625 $defaults[$name] = $config->defaultContactStateProvince;
2626 }
2627 }
2628 }
2629 return $defaults;
2630 }
2631
2632 /**
2633 * This function is to make a copy of a profile, including
2634 * all the fields in the profile
2635 *
2636 * @param int $id the profile id to copy
2637 *
2638 * @return void
2639 * @access public
2640 */
2641 static function copy($id) {
2642 $fieldsFix = array('prefix' => array('title' => ts('Copy of ')));
2643 $copy = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFGroup',
2644 array('id' => $id),
2645 NULL,
2646 $fieldsFix
2647 );
2648
2649 if ($pos = strrpos($copy->name, "_{$id}")) {
2650 $copy->name = substr_replace($copy->name, '', $pos);
2651 }
2652 $copy->name = CRM_Utils_String::munge($copy->name, '_', 56) . "_{$copy->id}";
2653 $copy->save();
2654
2655 $copyUFJoin = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFJoin',
2656 array('uf_group_id' => $id),
2657 array('uf_group_id' => $copy->id),
2658 NULL,
2659 'entity_table'
2660 );
2661
2662 $copyUFField = &CRM_Core_DAO::copyGeneric('CRM_Core_BAO_UFField',
2663 array('uf_group_id' => $id),
2664 array('uf_group_id' => $copy->id)
2665 );
2666
2667 $maxWeight = CRM_Utils_Weight::getMax('CRM_Core_DAO_UFJoin', NULL, 'weight');
2668
2669 //update the weight
2670 $query = "
2671UPDATE civicrm_uf_join
2672SET weight = %1
2673WHERE uf_group_id = %2
2674AND ( entity_id IS NULL OR entity_id <= 0 )
2675";
2676 $p = array(1 => array($maxWeight + 1, 'Integer'),
2677 2 => array($copy->id, 'Integer'),
2678 );
2679 CRM_Core_DAO::executeQuery($query, $p);
2680 if ($copy->is_reserved) {
2681 $query = "UPDATE civicrm_uf_group SET is_reserved = 0 WHERE id = %1";
2682 $params = array(1 => array($copy->id, 'Integer'));
2683 CRM_Core_DAO::executeQuery($query, $params);
2684 }
2685 CRM_Utils_Hook::copy('UFGroup', $copy);
2686
2687 return $copy;
2688 }
2689
2690 /**
2691 * Process that send notification e-mails
2692 *
2693 * @params int $contactId contact id
2694 * @params array $values associative array of name/value pair
2695 *
1fd63589
EM
2696 * @param $contactID
2697 * @param $values
2698 *
6a488035
TO
2699 * @return void
2700 * @access public
2701 */
2702
2703 static function commonSendMail($contactID, &$values) {
2704 if (!$contactID || !$values) {
2705 return;
2706
2707 }
2708 $template = CRM_Core_Smarty::singleton();
2709
2710 $displayName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
2711 $contactID,
2712 'display_name'
2713 );
2714
2715 self::profileDisplay($values['id'], $values['values'], $template);
2716 $emailList = explode(',', $values['email']);
2717
2718 $contactLink = CRM_Utils_System::url('civicrm/contact/view',
2719 "reset=1&cid=$contactID",
2720 TRUE, NULL, FALSE, FALSE, TRUE
2721 );
2722
2723 //get the default domain email address.
2724 list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail();
2725
2726 if (!$domainEmailAddress || $domainEmailAddress == 'info@EXAMPLE.ORG') {
2727 $fixUrl = CRM_Utils_System::url('civicrm/admin/domain', 'action=update&reset=1');
2728 CRM_Core_Error::fatal(ts('The site administrator needs to enter a valid \'FROM Email Address\' in <a href="%1">Administer CiviCRM &raquo; Communications &raquo; FROM Email Addresses</a>. The email address used may need to be a valid mail account with your email service provider.', array(1 => $fixUrl)));
2729 }
2730
2731 foreach ($emailList as $emailTo) {
2732 // FIXME: take the below out of the foreach loop
c6327d7d 2733 CRM_Core_BAO_MessageTemplate::sendTemplate(
6a488035
TO
2734 array(
2735 'groupName' => 'msg_tpl_workflow_uf',
2736 'valueName' => 'uf_notify',
2737 'contactId' => $contactID,
2738 'tplParams' => array(
2739 'displayName' => $displayName,
2740 'currentDate' => date('r'),
2741 'contactLink' => $contactLink,
2742 ),
2743 'from' => "$domainEmailName <$domainEmailAddress>",
2744 'toEmail' => $emailTo,
2745 )
2746 );
2747 }
2748 }
2749
2750 /**
2751 * Given a contact id and a group id, returns the field values from the db
2752 * for this group and notify email only if group's notify field is
2753 * set and field values are not empty
2754 *
2755 * @params $gid group id
2756 * @params $cid contact id
2757 * @params $params associative array
2758 *
1fd63589
EM
2759 * @param $gid
2760 * @param $cid
2761 * @param $params
2762 * @param bool $skipCheck
2763 *
6a488035
TO
2764 * @return array
2765 * @access public
2766 */
2767 function checkFieldsEmptyValues($gid, $cid, $params, $skipCheck = FALSE) {
2768 if ($gid) {
2769 if (CRM_Core_BAO_UFGroup::filterUFGroups($gid, $cid) || $skipCheck) {
2770 $values = array();
2771 $fields = CRM_Core_BAO_UFGroup::getFields($gid, FALSE, CRM_Core_Action::VIEW);
2772 CRM_Core_BAO_UFGroup::getValues($cid, $fields, $values, FALSE, $params, TRUE);
2773
2774 $email = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'notify');
2775
2776 if (!empty($values) &&
2777 !empty($email)
2778 ) {
2779 $val = array(
2780 'id' => $gid,
2781 'values' => $values,
2782 'email' => $email,
2783 );
2784 return $val;
2785 }
2786 }
2787 }
2788 return NULL;
2789 }
2790
2791 /**
2792 * Function to assign uf fields to template
2793 *
2794 * @params int $gid group id
2795 * @params array $values associative array of fields
2796 *
1fd63589
EM
2797 * @param $gid
2798 * @param $values
2799 * @param $template
2800 *
6a488035
TO
2801 * @return void
2802 * @access public
2803 */
2804 function profileDisplay($gid, $values, $template) {
2805 $groupTitle = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'title');
2806 $template->assign('grouptitle', $groupTitle);
2807 if (count($values)) {
2808 $template->assign('values', $values);
2809 }
2810 }
2811
2812 /**
2813 * Format fields for dupe Contact Matching
2814 *
2815 * @param array $params associated array
2816 *
1fd63589
EM
2817 * @param null $contactId
2818 *
6a488035
TO
2819 * @return array $data assoicated formatted array
2820 * @access public
2821 * @static
2822 */
2823 static function formatFields($params, $contactId = NULL) {
2824 if ($contactId) {
2825 // get the primary location type id and email
2826 list($name, $primaryEmail, $primaryLocationType) = CRM_Contact_BAO_Contact_Location::getEmailDetails($contactId);
2827 }
2828 else {
2829 $defaultLocationType = CRM_Core_BAO_LocationType::getDefault();
2830 $primaryLocationType = $defaultLocationType->id;
2831 }
2832
2833 $data = array();
2834 $locationType = array();
2835 $count = 1;
2836 $primaryLocation = 0;
2837 foreach ($params as $key => $value) {
2838 list($fieldName, $locTypeId, $phoneTypeId) = explode('-', $key);
2839
2840 if ($locTypeId == 'Primary') {
2841 $locTypeId = $primaryLocationType;
2842 }
2843
2844 if (is_numeric($locTypeId)) {
2845 if (!in_array($locTypeId, $locationType)) {
2846 $locationType[$count] = $locTypeId;
2847 $count++;
2848 }
2849 $loc = CRM_Utils_Array::key($locTypeId, $locationType);
2850
2851 $data['location'][$loc]['location_type_id'] = $locTypeId;
2852
2853 // if we are getting in a new primary email, dont overwrite the new one
2854 if ($locTypeId == $primaryLocationType) {
a7488080 2855 if (!empty($params['email-' . $primaryLocationType])) {
6a488035
TO
2856 $data['location'][$loc]['email'][$loc]['email'] = $fields['email-' . $primaryLocationType];
2857 }
2858 elseif (isset($primaryEmail)) {
2859 $data['location'][$loc]['email'][$loc]['email'] = $primaryEmail;
2860 }
2861 $primaryLocation++;
2862 }
2863
2864 if ($loc == 1) {
2865 $data['location'][$loc]['is_primary'] = 1;
2866 }
2867 if ($fieldName == 'phone') {
2868 if ($phoneTypeId) {
2869 $data['location'][$loc]['phone'][$loc]['phone_type_id'] = $phoneTypeId;
2870 }
2871 else {
2872 $data['location'][$loc]['phone'][$loc]['phone_type_id'] = '';
2873 }
2874 $data['location'][$loc]['phone'][$loc]['phone'] = $value;
2875 }
2876 elseif ($fieldName == 'email') {
2877 $data['location'][$loc]['email'][$loc]['email'] = $value;
2878 }
2879 elseif ($fieldName == 'im') {
2880 $data['location'][$loc]['im'][$loc]['name'] = $value;
2881 }
2882 else {
2883 if ($fieldName === 'state_province') {
2884 $data['location'][$loc]['address']['state_province_id'] = $value;
2885 }
2886 elseif ($fieldName === 'country') {
2887 $data['location'][$loc]['address']['country_id'] = $value;
2888 }
2889 else {
2890 $data['location'][$loc]['address'][$fieldName] = $value;
2891 }
2892 }
2893 }
2894 else {
67744c4e 2895 // TODO: prefix, suffix and gender translation may no longer be necessary - check inputs
6a488035
TO
2896 if ($key === 'individual_suffix') {
2897 $data['suffix_id'] = $value;
2898 }
2899 elseif ($key === 'individual_prefix') {
2900 $data['prefix_id'] = $value;
2901 }
2902 elseif ($key === 'gender') {
2903 $data['gender_id'] = $value;
2904 }
2905 elseif (substr($key, 0, 6) === 'custom') {
2906 if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
2907 //fix checkbox
2908 if ($customFields[$customFieldID]['html_type'] == 'CheckBox') {
2909 $value = implode(CRM_Core_DAO::VALUE_SEPARATOR, array_keys($value));
2910 }
2911 // fix the date field
2912 if ($customFields[$customFieldID]['data_type'] == 'Date') {
2913 $date = CRM_Utils_Date::format($value);
2914 if (!$date) {
2915 $date = '';
2916 }
2917 $value = $date;
2918 }
2919
2920 $data['custom'][$customFieldID] = array(
2921 'id' => $id,
2922 'value' => $value,
2923 'extends' => $customFields[$customFieldID]['extends'],
2924 'type' => $customFields[$customFieldID]['data_type'],
2925 'custom_field_id' => $customFieldID,
2926 );
2927 }
2928 }
2929 elseif ($key == 'edit') {
2930 continue;
2931 }
2932 else {
2933 $data[$key] = $value;
2934 }
2935 }
2936 }
2937
2938 if (!$primaryLocation) {
2939 $loc++;
2940 $data['location'][$loc]['email'][$loc]['email'] = $primaryEmail;
2941 }
2942
2943
2944 return $data;
2945 }
2946
2947 /**
2948 * calculate the profile type 'group_type' as per profile fields.
2949 *
1fd63589
EM
2950 * @param $gId
2951 * @param bool $includeTypeValues
6a488035
TO
2952 * @param int $ignoreFieldId ignore particular profile field
2953 *
1fd63589 2954 * @internal param int $gid profile id
6a488035
TO
2955 * @return array list of calculated group type
2956 */
2957 static function calculateGroupType($gId, $includeTypeValues = FALSE, $ignoreFieldId = NULL) {
2958 //get the profile fields.
2959 $ufFields = self::getFields($gId, FALSE, NULL, NULL, NULL, TRUE, NULL, TRUE);
2960 return self::_calculateGroupType($ufFields, $includeTypeValues, $ignoreFieldId);
2961 }
2962
2963 /**
2964 * calculate the profile type 'group_type' as per profile fields.
2965 *
1fd63589
EM
2966 * @param $ufFields
2967 * @param bool $includeTypeValues
6a488035
TO
2968 * @param int $ignoreFieldId ignore perticular profile field
2969 *
1fd63589 2970 * @internal param int $gid profile id
6a488035
TO
2971 * @return array list of calculated group type
2972 */
2973 static function _calculateGroupType($ufFields, $includeTypeValues = FALSE, $ignoreFieldId = NULL) {
2974 $groupType = $groupTypeValues = $customFieldIds = array();
2975 if (!empty($ufFields)) {
2976 foreach ($ufFields as $fieldName => $fieldValue) {
2977 //ignore field from group type when provided.
2978 //in case of update profile field.
2979 if ($ignoreFieldId && ($ignoreFieldId == $fieldValue['field_id'])) {
2980 continue;
2981 }
2982 if (!in_array($fieldValue['field_type'], $groupType)) {
2983 $groupType[$fieldValue['field_type']] = $fieldValue['field_type'];
2984 }
2985
2986 if ($includeTypeValues && ($fldId = CRM_Core_BAO_CustomField::getKeyID($fieldName))) {
2987 $customFieldIds[$fldId] = $fldId;
2988 }
2989 }
2990 }
2991
2992 if (!empty($customFieldIds)) {
2993 $query = 'SELECT DISTINCT(cg.id), cg.extends, cg.extends_entity_column_id, cg.extends_entity_column_value FROM civicrm_custom_group cg LEFT JOIN civicrm_custom_field cf ON cf.custom_group_id = cg.id WHERE cg.extends_entity_column_value IS NOT NULL AND cf.id IN (' . implode(',', $customFieldIds) . ')';
2994
2995 $customGroups = CRM_Core_DAO::executeQuery($query);
2996 while ($customGroups->fetch()) {
2997 if (!$customGroups->extends_entity_column_value) {
2998 continue;
2999 }
3000
3001 $groupTypeName = "{$customGroups->extends}Type";
3002 if ($customGroups->extends == 'Participant' && $customGroups->extends_entity_column_id) {
3003 $groupTypeName = CRM_Core_OptionGroup::getValue('custom_data_type', $customGroups->extends_entity_column_id, 'value', 'String', 'name');
3004 }
3005
3006 foreach (explode(CRM_Core_DAO::VALUE_SEPARATOR, $customGroups->extends_entity_column_value) as $val) {
3007 if ($val) {
3008 $groupTypeValues[$groupTypeName][$val] = $val;
3009 }
3010 }
3011 }
3012
3013 if (!empty($groupTypeValues)) {
3014 $groupType = array_merge($groupType, $groupTypeValues);
3015 }
3016 }
3017
3018 return $groupType;
3019 }
3020
3021 /**
3022 * Update the profile type 'group_type' as per profile fields including group types and group subtype values.
3023 * Build and store string like: group_type1,group_type2[VALUE_SEPERATOR]group_type1Type:1:2:3,group_type2Type:1:2
3024 *
3025 * FIELDS GROUP_TYPE
3026 * BirthDate + Email Individual,Contact
3027 * BirthDate + Subject Individual,Activity
3028 * BirthDate + Subject + SurveyOnlyField Individual,Activity\0ActivityType:28
3029 * BirthDate + Subject + SurveyOnlyField + PhoneOnlyField (Not allowed)
3030 * BirthDate + SurveyOnlyField Individual,Activity\0ActivityType:28
3031 * BirthDate + Subject + SurveyOrPhoneField Individual,Activity\0ActivityType:2:28
3032 * BirthDate + SurveyOrPhoneField Individual,Activity\0ActivityType:2:28
3033 * BirthDate + SurveyOrPhoneField + SurveyOnlyField Individual,Activity\0ActivityType:2:28
3034 * BirthDate + StudentField + Subject + SurveyOnlyField Individual,Activity,Student\0ActivityType:28
3035 *
1fd63589
EM
3036 * @param $gId
3037 * @param Array $groupTypes With key having group type names
6a488035 3038 *
1fd63589 3039 * @internal param int $gid profile id
6a488035
TO
3040 * @return Boolean
3041 */
3042 static function updateGroupTypes($gId, $groupTypes = array(
3043 )) {
3044 if (!is_array($groupTypes) || !$gId) {
3045 return FALSE;
3046 }
3047
3048 // If empty group types set group_type as 'null'
3049 if (empty($groupTypes)) {
3050 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $gId, 'group_type', 'null');
3051 }
3052
1cb28d5d 3053 $componentGroupTypes = array('Contribution', 'Participant', 'Membership', 'Activity', 'Case');
6a488035
TO
3054 $validGroupTypes = array_merge(array('Contact', 'Individual', 'Organization', 'Household'), $componentGroupTypes, CRM_Contact_BAO_ContactType::subTypes());
3055
3056 $gTypes = $gTypeValues = array();
3057
3058 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
3059 // Get valid group type and group subtypes
3060 foreach ($groupTypes as $groupType => $value) {
3061 if (in_array($groupType, $validGroupTypes) && !in_array($groupType, $gTypes)) {
3062 $gTypes[] = $groupType;
3063 }
3064
3065 $subTypesOf = NULL;
3066
3067 if (in_array($groupType, $participantExtends)) {
3068 $subTypesOf = $groupType;
3069 }
3070 elseif (strpos($groupType, 'Type') > 0) {
3071 $subTypesOf = substr($groupType, 0, strpos($groupType, 'Type'));
3072 }
3073 else {
3074 continue;
3075 }
3076
3077 if (!empty($value) &&
3078 (in_array($subTypesOf, $componentGroupTypes) ||
3079 in_array($subTypesOf, $participantExtends)
3080 )
3081 ) {
3082 $gTypeValues[$subTypesOf] = $groupType . ":" . implode(':', $value);
3083 }
3084 }
3085
3086 if (empty($gTypes)) {
3087 return FALSE;
3088 }
3089
3090 // Build String to store group types and group subtypes
3091 $groupTypeString = implode(',', $gTypes);
3092 if (!empty($gTypeValues)) {
3093 $groupTypeString .= CRM_Core_DAO::VALUE_SEPARATOR . implode(',', $gTypeValues);
3094 }
3095
3096 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $gId, 'group_type', $groupTypeString);
3097 }
3098
3099 /**
3100 * Create a "group_type" string
3101 *
3102 * @param array $coreTypes e.g. array('Individual','Contact','Student')
3103 * @param array $subTypes e.g. array('ActivityType' => array(7, 11))
3104 * @param string $delim
1fd63589
EM
3105 *
3106 * @return string
6a488035
TO
3107 * @throws CRM_Core_Exception
3108 */
3109 static function encodeGroupType($coreTypes, $subTypes, $delim = CRM_Core_DAO::VALUE_SEPARATOR) {
3110 $groupTypeExpr = '';
3111 if ($coreTypes) {
3112 $groupTypeExpr .= implode(',', $coreTypes);
3113 }
3114 if ($subTypes) {
3115 if (count($subTypes) > 1) {
3116 throw new CRM_Core_Exception("Multiple subtype filtering is not currently supported by widget.");
3117 }
3118 foreach ($subTypes as $subType => $subTypeIds) {
3119 $groupTypeExpr .= $delim . $subType . ':' . implode(':', $subTypeIds);
3120 }
3121 }
3122 return $groupTypeExpr;
3123 }
3124
3125 /**
3126 * This function is used to setDefault componet specific profile fields.
3127 *
1fd63589
EM
3128 * @param array $fields profile fields.
3129 * @param int $componentId componetID
3130 * @param string $component component name
3131 * @param array $defaults an array of default values.
3132 *
3133 * @param bool $isStandalone
6a488035
TO
3134 *
3135 * @return void.
3136 */
f0385140 3137 public static function setComponentDefaults(&$fields, $componentId, $component, &$defaults, $isStandalone = FALSE) {
6a488035
TO
3138 if (!$componentId ||
3139 !in_array($component, array('Contribute', 'Membership', 'Event', 'Activity'))
3140 ) {
3141 return;
3142 }
3143
3144 $componentBAO = $componentSubType = NULL;
3145 switch ($component) {
3146 case 'Membership':
3147 $componentBAO = 'CRM_Member_BAO_Membership';
3148 $componentBAOName = 'Membership';
3149 $componentSubType = array('membership_type_id');
3150 break;
3151
3152 case 'Contribute':
3153 $componentBAO = 'CRM_Contribute_BAO_Contribution';
3154 $componentBAOName = 'Contribution';
3155 $componentSubType = array( 'financial_type_id' );
3156 break;
3157
3158 case 'Event':
3159 $componentBAO = 'CRM_Event_BAO_Participant';
3160 $componentBAOName = 'Participant';
3161 $componentSubType = array('role_id', 'event_id');
3162 break;
3163
3164 case 'Activity':
3165 $componentBAO = 'CRM_Activity_BAO_Activity';
3166 $componentBAOName = 'Activity';
3167 $componentSubType = array('activity_type_id');
3168 break;
3169 }
3170
3171 $values = array();
3172 $params = array('id' => $componentId);
3173
3174 //get the component values.
3175 CRM_Core_DAO::commonRetrieve($componentBAO, $params, $values);
3176
3177 $formattedGroupTree = array();
3178 $dateTimeFields = array('participant_register_date', 'activity_date_time', 'receive_date', 'receipt_date', 'cancel_date', 'thankyou_date', 'membership_start_date', 'membership_end_date', 'join_date');
3179 foreach ($fields as $name => $field) {
3180 $fldName = $isStandalone ? $name : "field[$componentId][$name]";
3181 if (in_array($name, $dateTimeFields)) {
3182 $timefldName = $isStandalone ? "{$name}_time" : "field[$componentId][{$name}_time]";
a7488080 3183 if (!empty($values[$name])) {
6a488035
TO
3184 list($defaults[$fldName], $defaults[$timefldName]) = CRM_Utils_Date::setDateDefaults($values[$name]);
3185 }
3186 }
3187 elseif (array_key_exists($name, $values)) {
3188 $defaults[$fldName] = $values[$name];
3189 }
3190 elseif ($name == 'participant_note') {
3191 $noteDetails = CRM_Core_BAO_Note::getNote($componentId, 'civicrm_participant');
3192 $defaults[$fldName] = array_pop($noteDetails);
3193 }
3194 elseif (in_array($name, array(
3195 'financial_type', 'payment_instrument', 'participant_status', 'participant_role'))) {
3196 $defaults[$fldName] = $values["{$name}_id"];
3197 }
3198 elseif ($name == 'membership_type') {
3199 // since membership_type field is a hierselect -
3200 $defaults[$fldName][0] =
3201 CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType',$values['membership_type_id'],'member_of_contact_id','id');
3202 $defaults[$fldName][1] = $values['membership_type_id'];
3203 }
3204 elseif ($name == 'membership_status') {
3205 $defaults[$fldName] = $values['status_id'];
3206 }
3207 elseif ($customFieldInfo = CRM_Core_BAO_CustomField::getKeyID($name, TRUE)) {
3208 if (empty($formattedGroupTree)) {
3209 //get the groupTree as per subTypes.
3210 $groupTree = array();
3211 foreach ($componentSubType as $subType) {
3212 $subTree = CRM_Core_BAO_CustomGroup::getTree($componentBAOName, CRM_Core_DAO::$_nullObject,
3213 $componentId, 0, $values[$subType]
3214 );
3215 $groupTree = CRM_Utils_Array::crmArrayMerge($groupTree, $subTree);
3216 }
3217 $formattedGroupTree = CRM_Core_BAO_CustomGroup::formatGroupTree($groupTree, 1, CRM_Core_DAO::$_nullObject);
3218 CRM_Core_BAO_CustomGroup::setDefaults($formattedGroupTree, $defaults);
3219 }
3220
3221 //FIX ME: We need to loop defaults, but once we move to custom_1_x convention this code can be simplified.
3222 foreach ($defaults as $customKey => $customValue) {
3223 if ($customFieldDetails = CRM_Core_BAO_CustomField::getKeyID($customKey, TRUE)) {
3224 if ($name == 'custom_' . $customFieldDetails[0]) {
3225
3226 //hack to set default for checkbox
3227 //basically this is for weired field name like field[33][custom_19]
3228 //we are converting this field name to array structure and assign value.
3229 $skipValue = FALSE;
3230
3231 foreach ($formattedGroupTree as $tree) {
3232 if ('CheckBox' == CRM_Utils_Array::value('html_type', $tree['fields'][$customFieldDetails[0]])) {
3233 $skipValue = TRUE;
3234 $defaults['field'][$componentId][$name] = $customValue;
3235 break;
3236 }
3237 elseif (CRM_Utils_Array::value('data_type', $tree['fields'][$customFieldDetails[0]]) == 'Date') {
3238 $skipValue = TRUE;
3239
3240 // CRM-6681, $default contains formatted date, time values.
3241 $defaults[$fldName] = $customValue;
a7488080 3242 if (!empty($defaults[$customKey . '_time'])) {
6a488035
TO
3243 $defaults['field'][$componentId][$name . '_time'] = $defaults[$customKey . '_time'];
3244 }
3245 }
3246 }
3247
3248 if (!$skipValue || $isStandalone) {
3249 $defaults[$fldName] = $customValue;
3250 }
3251 unset($defaults[$customKey]);
3252 break;
3253 }
3254 }
3255 }
3256 }
3257 }
3258 }
3259
79ae07d9
CW
3260 /**
3261 * @param array|string $profiles - name of profile(s) to create links for
3262 * @param array $appendProfiles - name of profile(s) to append to each link
1fd63589
EM
3263 *
3264 * @return array
79ae07d9 3265 */
a4799f04
CW
3266 static function getCreateLinks($profiles = '', $appendProfiles = array()) {
3267 // Default to contact profiles
3268 if (!$profiles) {
3269 $profiles = array('new_individual', 'new_organization', 'new_household');
3270 }
79ae07d9 3271 $profiles = (array) $profiles;
1a90e0dd 3272 $toGet = array_merge($profiles, (array) $appendProfiles);
79ae07d9
CW
3273 $retrieved = civicrm_api3('uf_group', 'get', array(
3274 'name' => array('IN' => $toGet),
3275 'is_active' => 1,
3276 ));
3277 $links = $append = array();
3278 if (!empty($retrieved['values'])) {
3279 foreach($retrieved['values'] as $id => $profile) {
3280 if (in_array($profile['name'], $profiles)) {
3281 $links[] = array(
3282 'label' => $profile['title'],
a4799f04
CW
3283 'url' => CRM_Utils_System::url('civicrm/profile/create', "reset=1&context=dialog&gid=$id",
3284 NULL, NULL, FALSE, NULL, FALSE) ,
3285 'type' => ucfirst(str_replace('new_', '', $profile['name'])),
79ae07d9
CW
3286 );
3287 }
3288 else {
3289 $append[] = $id;
3290 }
3291 }
3292 foreach ($append as $id) {
3293 foreach ($links as &$link) {
3294 $link['url'] .= ",$id";
3295 }
3296 }
3297 }
3298 return $links;
3299 }
3300
6a488035
TO
3301 /**
3302 * Function to retrieve groups of profiles
3303 *
3304 * @param integer $profileID id of the profile
3305 *
3306 * @return array returns array
3307 * @static
3308 */
3309 static function profileGroups($profileID) {
3310 $groupTypes = array();
3311 $profileTypes = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $profileID, 'group_type');
3312 if ($profileTypes) {
3313 $groupTypeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $profileTypes);
3314 $groupTypes = explode(',', $groupTypeParts[0]);
3315 }
3316 return $groupTypes;
3317 }
3318
3319 /**
3320 * Function to alter contact params by filtering existing subscribed groups and returns
3321 * unsubscribed groups array for subscription.
3322 *
3323 * @param array $params contact params
3324 * @param int $contactId user contact id
3325 *
3326 * @return array $subscribeGroupIds This contains array of groups for subscription
3327 */
3328 static function getDoubleOptInGroupIds(&$params, $contactId = NULL) {
3329 $config = CRM_Core_Config::singleton();
3330 $subscribeGroupIds = array();
3331
3332 // process further only if profileDoubleOptIn enabled and if groups exist
3333 if (!array_key_exists('group', $params) ||
3334 !self::isProfileDoubleOptin() ||
3335 CRM_Utils_System::isNull($params['group'])
3336 ) {
3337 return $subscribeGroupIds;
3338 }
3339
3340 //check if contact email exist.
3341 $hasEmails = FALSE;
3342 foreach ($params as $name => $value) {
3343 if (strpos($name, 'email-') !== FALSE) {
3344 $hasEmails = TRUE;
3345 break;
3346 }
3347 }
3348
3349 //Proceed furthur only if email present
3350 if (!$hasEmails) {
3351 return $subscribeGroupIds;
3352 }
3353
3354 //do check for already subscriptions.
3355 $contactGroups = array();
3356 if ($contactId) {
3357 $query = "
3358SELECT group_id
3359 FROM civicrm_group_contact
3360 WHERE status = 'Added'
3361 AND contact_id = %1";
3362
3363 $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($contactId, 'Integer')));
3364 while ($dao->fetch()) {
3365 $contactGroups[$dao->group_id] = $dao->group_id;
3366 }
3367 }
3368
3369 //since we don't have names, compare w/ label.
3370 $mailingListGroupType = array_search('Mailing List', CRM_Core_OptionGroup::values('group_type'));
3371
3372 //actual processing start.
3373 foreach ($params['group'] as $groupId => $isSelected) {
3374 //unset group those are not selected.
3375 if (!$isSelected) {
3376 unset($params['group'][$groupId]);
3377 continue;
3378 }
3379
3380 $groupTypes = explode(CRM_Core_DAO::VALUE_SEPARATOR,
3381 CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $groupId, 'group_type', 'id')
3382 );
3383 //get only mailing type group and unset it from params
3384 if (in_array($mailingListGroupType, $groupTypes) && !in_array($groupId, $contactGroups)) {
3385 $subscribeGroupIds[$groupId] = $groupId;
3386 unset($params['group'][$groupId]);
3387 }
3388 }
3389
3390 return $subscribeGroupIds;
3391 }
3392
3393 /**
3394 * Function to check if we are rendering mixed profiles
3395 *
3396 * @param array $profileIds associated array of profile ids
3397 *
3398 * @return boolean $mixProfile true if profile is mixed
3399 * @static
3400 * @access public
3401 */
3402 static function checkForMixProfiles($profileIds) {
3403 $mixProfile = FALSE;
3404
3405 $contactTypes = array('Individual', 'Household', 'Organization');
3406 $subTypes = CRM_Contact_BAO_ContactType::subTypes();
3407
3408 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
3409
3410 $typeCount = array('ctype' => array(), 'subtype' => array());
3411 foreach ($profileIds as $gid) {
3412 $profileType = CRM_Core_BAO_UFField::getProfileType($gid);
3413 // ignore profile of type Contact
3414 if ($profileType == 'Contact') {
3415 continue;
3416 }
3417 if (in_array($profileType, $contactTypes)) {
3418 if (!isset($typeCount['ctype'][$profileType])) {
3419 $typeCount['ctype'][$profileType] = 1;
3420 }
3421
3422 // check if we are rendering profile of different contact types
3423 if (count($typeCount['ctype']) == 2) {
3424 $mixProfile = TRUE;
3425 break;
3426 }
3427 }
3428 elseif (in_array($profileType, $components)) {
3429 $mixProfile = TRUE;
3430 break;
3431 }
3432 else {
3433 if (!isset($typeCount['subtype'][$profileType])) {
3434 $typeCount['subtype'][$profileType] = 1;
3435 }
3436 // check if we are rendering profile of different contact sub types
3437 if (count($typeCount['subtype']) == 2) {
3438 $mixProfile = TRUE;
3439 break;
3440 }
3441 }
3442 }
3443 return $mixProfile;
3444 }
3445
3446 /**
3447 * Funtion to determine of we show overlay profile or not
3448 *
3449 * @return boolean true if profile should be shown else false
3450 * @static
3451 * @access public
3452 */
3453 static function showOverlayProfile() {
3454 $showOverlay = TRUE;
3455
3456 // get the id of overlay profile
3457 $overlayProfileId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', 'summary_overlay', 'id', 'name');
3458 $query = "SELECT count(id) FROM civicrm_uf_field WHERE uf_group_id = {$overlayProfileId} AND visibility IN ('Public Pages', 'Public Pages and Listings') ";
3459
3460 $count = CRM_Core_DAO::singleValueQuery($query);
3461
3462 //check if there are no public fields and use is anonymous
3463 $session = CRM_Core_Session::singleton();
3464 if (!$count && !$session->get('userID')) {
3465 $showOverlay = FALSE;
3466 }
3467
3468 return $showOverlay;
3469 }
3470
3471 /**
3472 * function to get group type values of the profile
3473 *
3474 * @params Integer $profileId Profile Id
3475 * @params String $groupType Group Type
3476 *
1fd63589
EM
3477 * @param $profileId
3478 * @param null $groupType
3479 *
6a488035
TO
3480 * @return Array group type values
3481 * @static
3482 * @access public
3483 */
3484 static function groupTypeValues($profileId, $groupType = NULL) {
3485 $groupTypeValue = array();
3486 $groupTypes = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $profileId, 'group_type');
3487
3488 $groupTypeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $groupTypes);
a7488080 3489 if (empty($groupTypeParts[1])) {
6a488035
TO
3490 return $groupTypeValue;
3491 }
3492 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
3493
3494 foreach (explode(',', $groupTypeParts[1]) as $groupTypeValues) {
3495 $values = array();
3496 $valueParts = explode(':', $groupTypeValues);
3497 if ($groupType &&
3498 ($valueParts[0] != "{$groupType}Type" ||
3499 ($groupType == 'Participant' &&
3500 !in_array($valueParts[0], $participantExtends)
3501 )
3502 )
3503 ) {
3504 continue;
3505 }
3506 foreach ($valueParts as $val) {
3507 if (CRM_Utils_Rule::integer($val)) {
3508 $values[$val] = $val;
3509 }
3510 }
3511 if (!empty($values)) {
3512 $typeName = substr($valueParts[0], 0, -4);
3513 if (in_array($valueParts[0], $participantExtends)) {
3514 $typeName = $valueParts[0];
3515 }
3516 $groupTypeValue[$typeName] = $values;
3517 }
3518 }
3519
3520 return $groupTypeValue;
3521 }
3522
3523 static function isProfileDoubleOptin() {
3524 // check for double optin
3525 $config = CRM_Core_Config::singleton();
3526 if (in_array('CiviMail', $config->enableComponents)) {
3527 return CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
3528 'profile_double_optin', NULL, FALSE
3529 );
3530 }
3531 return FALSE;
3532 }
3533
3534 static function isProfileAddToGroupDoubleOptin() {
3535 // check for add to group double optin
3536 $config = CRM_Core_Config::singleton();
3537 if (in_array('CiviMail', $config->enableComponents)) {
3538 return CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
3539 'profile_add_to_group_double_optin', NULL, FALSE
3540 );
3541 }
3542 return FALSE;
3543 }
3544
3545 /**
3546 * get profiles used for batch entry
3547 *
3548 * @return array profileIds profile ids
3549 * @static
3550 */
3551 static function getBatchProfiles() {
3552 $query = "SELECT id
3553 FROM civicrm_uf_group
3554 WHERE name IN ('contribution_batch_entry', 'membership_batch_entry')";
3555 $dao = CRM_Core_DAO::executeQuery( $query );
3556 $profileIds = array();
3557 while( $dao->fetch() ) {
3558 $profileIds[$dao->id] = $dao->id;
3559 }
3560 return $profileIds;
3561 }
3562
1fd63589
EM
3563 /**
3564 * @todo what do I do?
3565 * @param $source
3566 * @param $destination
3567 * @param bool $returnMultiSummaryFields
3568 *
3569 * @return array|null
3570 */
6a488035
TO
3571 static function shiftMultiRecordFields(&$source, &$destination, $returnMultiSummaryFields = FALSE) {
3572 $multiSummaryFields = $returnMultiSummaryFields ? array( ) : NULL;
3573 foreach ($source as $field => $properties) {
3574 if (!CRM_Core_BAO_CustomField::getKeyID($field)) {
3575 continue;
3576 }
3577 if (CRM_Core_BAO_CustomField::isMultiRecordField($field)) {
3578 $destination[$field] = $properties;
3579 if ($returnMultiSummaryFields) {
3580 if ($properties['is_multi_summary']) {
3581 $multiSummaryFields[$field] = $properties;
3582 }
3583 }
3584 unset($source[$field]);
3585 }
3586 }
3587 return $multiSummaryFields;
3588 }
3589
3590 /**
3591 * This is function is used to format pseudo fields
3592 *
3593 * @param array $fields associated array of profile fields
3594 *
3595 * @static
3596 */
3597 static function reformatProfileFields(&$fields) {
3598 //reformat fields array
3599 foreach ($fields as $name => $field) {
3600 //reformat phone and extension field
3601 if ( substr($field['name'], 0, 13) == 'phone_and_ext') {
3602 $fieldSuffix = str_replace('phone_and_ext-', '', $field['name']);
3603
3604 // retain existing element properties and just update and replace key
3605 CRM_Utils_Array::crmReplaceKey($fields, $name, "phone-{$fieldSuffix}");
3606 $fields["phone-{$fieldSuffix}"]['name'] = "phone-{$fieldSuffix}";
3607 $fields["phone-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone';
3608
3609 // add additional phone extension field
3610 $fields["phone_ext-{$fieldSuffix}"] = $field;
3611 $fields["phone_ext-{$fieldSuffix}"]['title'] = $field['title'] .' - '.ts('Ext.');
3612 $fields["phone_ext-{$fieldSuffix}"]['name'] = "phone_ext-{$fieldSuffix}";
3613 $fields["phone_ext-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone_ext';
3614 $fields["phone_ext-{$fieldSuffix}"]['skipDisplay'] = 1;
3615 //ignore required for extension field
3616 $fields["phone_ext-{$fieldSuffix}"]['is_required'] = 0;
3617 }
3618 }
3619 }
3620}