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