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