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