Merge pull request #5317 from sfe-ev/chainselect-missing-fields
[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,
b42d84aa 1100 $absolute,
1101 $additionalWhereClause
6a488035
TO
1102 );
1103 $params[$index] = $values[$index] = $fileURL['file_url'];
1104 }
1105 else {
1106 $customVal = NULL;
1107 if (isset($dao) && property_exists($dao, 'data_type') &&
1108 ($dao->data_type == 'Int' ||
1109 $dao->data_type == 'Boolean'
1110 )
1111 ) {
1112 $customVal = (int )($details->{$name});
1113 }
1114 elseif (isset($dao) && property_exists($dao, 'data_type')
1115 && $dao->data_type == 'Float'
1116 ) {
1117 $customVal = (float )($details->{$name});
1118 }
1119 elseif (!CRM_Utils_System::isNull(explode(CRM_Core_DAO::VALUE_SEPARATOR,
1120 $details->{$name}
1121 ))) {
1122 $customVal = $details->{$name};
1123 }
1124
1125 //CRM-4582
1126 if (CRM_Utils_System::isNull($customVal)) {
1127 continue;
1128 }
1129
1130 $params[$index] = $customVal;
1131 $values[$index] = CRM_Core_BAO_CustomField::getDisplayValue($customVal,
1132 $cfID,
1133 $options
1134 );
1b4d9e39 1135 if ($field['data_type'] == 'ContactReference') {
6a488035
TO
1136 $params[$index] = $values[$index];
1137 }
1138 if (CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField',
1139 $cfID, 'is_search_range'
1140 )) {
1141 $customFieldName = "{$name}_from";
1142 }
1143 }
1144 }
1145 elseif ($name == 'image_URL') {
77d45291 1146 list($width, $height) = getimagesize(CRM_Utils_String::unstupifyUrl($details->$name));
6a488035
TO
1147 list($thumbWidth, $thumbHeight) = CRM_Contact_BAO_Contact::getThumbSize($width, $height);
1148
1149 $image_URL = '<img src="' . $details->$name . '" height= ' . $thumbHeight . ' width= ' . $thumbWidth . ' />';
1150 $values[$index] = "<a href='#' onclick='contactImagePopUp(\"{$details->$name}\", {$width}, {$height});'>{$image_URL}</a>";
1151 }
1152 elseif (in_array($name, array(
1153 'birth_date', 'deceased_date', 'membership_start_date', 'membership_end_date', 'join_date'))) {
1154 $values[$index] = CRM_Utils_Date::customFormat($details->$name);
1155 $params[$index] = CRM_Utils_Date::isoToMysql($details->$name);
1156 }
1157 else {
1158 $dao = '';
1159 if ($index == 'Campaign') {
1160 $dao = 'CRM_Campaign_DAO_Campaign';
1161 }
1162 elseif ($index == 'Contribution Page') {
1163 $dao = 'CRM_Contribute_DAO_ContributionPage';
1164 }
1165 if ($dao) {
1166 $value = CRM_Core_DAO::getFieldValue($dao, $details->$name, 'title');
1167 }
1168 else {
1169 $value = $details->$name;
1170 }
1171 $values[$index] = $value;
1172 }
1173 }
1174 }
1175 }
1176 elseif (strpos($name, '-') !== FALSE) {
1177 list($fieldName, $id, $type) = CRM_Utils_System::explode('-', $name, 3);
1178
1179 if (!in_array($fieldName, $multipleFields)) {
1180 if ($id == 'Primary') {
1181 // fix for CRM-1543
1182 // not sure why we'd every use Primary location type id
1183 // we need to fix the source if we are using it
1184 // $locationTypeName = CRM_Contact_BAO_Contact::getPrimaryLocationType( $cid );
1185 $locationTypeName = 1;
1186 }
1187 else {
1188 $locationTypeName = CRM_Utils_Array::value($id, $locationTypes);
1189 }
1190
1191 if (!$locationTypeName) {
1192 continue;
1193 }
1194
1195 $detailName = "{$locationTypeName}-{$fieldName}";
1196 $detailName = str_replace(' ', '_', $detailName);
1197
1198 if (in_array($fieldName, array(
1199 'phone', 'im', 'email', 'openid'))) {
1200 if ($type) {
1201 $detailName .= "-{$type}";
1202 }
1203 }
1204
1205 if (in_array($fieldName, array(
1206 'state_province', 'country', 'county'))) {
1207 $values[$index] = $details->$detailName;
1208 $idx = $detailName . '_id';
1209 $params[$index] = $details->$idx;
1210 }
1211 elseif ($fieldName == 'im') {
1212 $providerId = $detailName . '-provider_id';
38913d36
TO
1213 if (isset($imProviders[$details->$providerId])) {
1214 $values[$index] = $details->$detailName . " (" . $imProviders[$details->$providerId] . ")";
6a488035
TO
1215 }
1216 else {
1217 $values[$index] = $details->$detailName;
1218 }
1219 $params[$index] = $details->$detailName;
1220 }
1221 elseif ($fieldName == 'phone') {
1222 $phoneExtField = str_replace('phone', 'phone_ext', $detailName);
1223 if (isset($details->$phoneExtField)) {
1224 $values[$index] = $details->$detailName . " (" . $details->$phoneExtField . ")";
1225 }
1226 else {
1227 $values[$index] = $details->$detailName;
1228 }
1229 $params[$index] = $details->$detailName;
1230 }
1231 else {
1232 $values[$index] = $params[$index] = $details->$detailName;
1233 }
1234 }
1235 else {
1236 $detailName = "website-{$id}-{$fieldName}";
1237 $url = CRM_Utils_System::fixURL($details->$detailName);
1238 if ($details->$detailName) {
1239 $websiteTypeId = "website-{$id}-website_type_id";
1240 $websiteType = $websiteTypes[$details->$websiteTypeId];
1241 $values[$index] = "<a href=\"$url\">{$details->$detailName} ( {$websiteType} )</a>";
1242 }
1243 else {
1244 $values[$index] = '';
1245 }
1246 }
1247 }
1248
1249 if ((CRM_Utils_Array::value('visibility', $field) == 'Public Pages and Listings') &&
1250 CRM_Core_Permission::check('profile listings and forms')
1251 ) {
1252
1253 if (CRM_Utils_System::isNull($params[$index])) {
1254 $params[$index] = $values[$index];
1255 }
1256 if (!isset($params[$index])) {
1257 continue;
1258 }
1259 if (!$customFieldName) {
1260 $fieldName = $field['name'];
1261 }
1262 else {
1263 $fieldName = $customFieldName;
1264 }
1265
1266 $url = NULL;
1267 if (CRM_Core_BAO_CustomField::getKeyID($field['name'])) {
1268 $htmlType = $field['html_type'];
1269 if ($htmlType == 'Link') {
1270 $url = $params[$index];
1271 }
1272 elseif (in_array($htmlType, array(
1273 'CheckBox', 'Multi-Select', 'AdvMulti-Select',
1274 'Multi-Select State/Province', 'Multi-Select Country',
1275 ))) {
1276 $valSeperator = CRM_Core_DAO::VALUE_SEPARATOR;
1277 $selectedOptions = explode($valSeperator, $params[$index]);
1278
1279 foreach ($selectedOptions as $key => $multiOption) {
1280 if ($multiOption) {
1281 $url[] = CRM_Utils_System::url('civicrm/profile',
1282 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1283 urlencode($fieldName) .
1284 '=' .
1285 urlencode($multiOption)
1286 );
1287 }
1288 }
1289 }
1290 else {
1291 $url = CRM_Utils_System::url('civicrm/profile',
1292 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1293 urlencode($fieldName) .
1294 '=' .
1295 urlencode($params[$index])
1296 );
1297 }
1298 }
1299 else {
1300 $url = CRM_Utils_System::url('civicrm/profile',
1301 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1302 urlencode($fieldName) .
1303 '=' .
1304 urlencode($params[$index])
1305 );
1306 }
1307
1308 if ($url &&
1309 !empty($values[$index]) &&
1310 $searchable
1311 ) {
1312
1313 if (is_array($url) && !empty($url)) {
1314 $links = array();
1315 $eachMultiValue = explode(', ', $values[$index]);
1316 foreach ($eachMultiValue as $key => $valueLabel) {
1317 $links[] = '<a href="' . $url[$key] . '">' . $valueLabel . '</a>';
1318 }
1319 $values[$index] = implode(', ', $links);
1320 }
1321 else {
1322 $values[$index] = '<a href="' . $url . '">' . $values[$index] . '</a>';
1323 }
1324 }
1325 }
1326 }
1327 }
1328
1329 /**
1330 * Check if profile Group used by any module.
1331 *
1332 * @param int $id profile Id
1333 *
1334 * @return boolean
1335 *
1336 * @access public
1337 * @static
1338 *
1339 */
1340 public static function usedByModule($id) {
1341 //check whether this group is used by any module(check uf join records)
1342 $sql = "SELECT id
1343 FROM civicrm_uf_join
1344 WHERE civicrm_uf_join.uf_group_id=$id";
1345
1346 $dao = new CRM_Core_DAO();
1347 $dao->query($sql);
1348 if ($dao->fetch()) {
1349 return TRUE;
1350 }
1351 else {
1352 return FALSE;
1353 }
1354 }
1355
1356 /**
1357 * Delete the profile Group.
1358 *
1359 * @param int $id profile Id
1360 *
1361 * @return boolean
1362 *
1363 * @access public
1364 * @static
1365 *
1366 */
1367 public static function del($id) {
1368 //check whether this group contains any profile fields
1369 $profileField = new CRM_Core_DAO_UFField();
1370 $profileField->uf_group_id = $id;
1371 $profileField->find();
1372 while ($profileField->fetch()) {
1373 CRM_Core_BAO_UFField::del($profileField->id);
1374 }
1375
1376 //delete records from uf join table
1377 $ufJoin = new CRM_Core_DAO_UFJoin();
1378 $ufJoin->uf_group_id = $id;
1379 $ufJoin->delete();
1380
1381 //delete profile group
1382 $group = new CRM_Core_DAO_UFGroup();
1383 $group->id = $id;
1384 $group->delete();
1385 return 1;
1386 }
1387
1388 /**
1389 * function to add the UF Group
1390 *
1391 * @param array $params reference array contains the values submitted by the form
1392 * @param array $ids reference array contains the id
1393 *
1394 * @access public
1395 * @static
1396 *
1397 * @return object
1398 */
6a73ef3f 1399 static function add(&$params, $ids = array()) {
6a488035
TO
1400 $fields = array('is_active', 'add_captcha', 'is_map', 'is_update_dupe', 'is_edit_link', 'is_uf_link', 'is_cms_user');
1401 foreach ($fields as $field) {
1402 $params[$field] = CRM_Utils_Array::value($field, $params, FALSE);
1403 }
1404
1405 $params['limit_listings_group_id'] = CRM_Utils_Array::value('group', $params);
1406 $params['add_to_group_id'] = CRM_Utils_Array::value('add_contact_to_group', $params);
1407
f80ef0e2 1408 //CRM-15427
1409 if (!empty($params['group_type']) && is_array($params['group_type'])) {
1410 $params['group_type'] = implode(',', $params['group_type']);
1411 }
6a488035
TO
1412 $ufGroup = new CRM_Core_DAO_UFGroup();
1413 $ufGroup->copyValues($params);
1414
6a73ef3f 1415 $ufGroupID = CRM_Utils_Array::value('ufgroup', $ids, CRM_Utils_Array::value('id', $params));
6a488035
TO
1416 if (!$ufGroupID) {
1417 $ufGroup->name = CRM_Utils_String::munge($ufGroup->title, '_', 56);
1418 }
1419 $ufGroup->id = $ufGroupID;
1420
1421 $ufGroup->save();
1422
1423 if (!$ufGroupID) {
1424 $ufGroup->name = $ufGroup->name . "_{$ufGroup->id}";
1425 $ufGroup->save();
1426 }
1427
1428 return $ufGroup;
1429 }
1430
1431 /**
1432 * Function to make uf join entries for an uf group
1433 *
1434 * @param array $params (reference) an assoc array of name/value pairs
1435 * @param int $ufGroupId ufgroup id
1436 *
1437 * @return void
1438 * @access public
1439 * @static
1440 */
1441 static function createUFJoin(&$params, $ufGroupId) {
1442 $groupTypes = CRM_Utils_Array::value('uf_group_type', $params);
1443
1444 // get ufjoin records for uf group
1445 $ufGroupRecord = CRM_Core_BAO_UFGroup::getUFJoinRecord($ufGroupId);
1446
1447 // get the list of all ufgroup types
1448 $allUFGroupType = CRM_Core_SelectValues::ufGroupTypes();
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($groupTypes)) {
1452 $groupTypes = array();
1453 }
1454
1455 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
1456 if (!is_array($ufGroupRecord)) {
1457 $ufGroupRecord = array();
1458 }
1459
1460 // check which values has to be inserted/deleted for contact
1461 $menuRebuild = FALSE;
1462 foreach ($allUFGroupType as $key => $value) {
1463 $joinParams = array();
1464 $joinParams['uf_group_id'] = $ufGroupId;
1465 $joinParams['module'] = $key;
1466 if ($key == 'User Account') {
1467 $menuRebuild = TRUE;
1468 }
1469 if (array_key_exists($key, $groupTypes) && !in_array($key, $ufGroupRecord)) {
1470 // insert a new record
1471 CRM_Core_BAO_UFGroup::addUFJoin($joinParams);
1472 }
1473 elseif (!array_key_exists($key, $groupTypes) && in_array($key, $ufGroupRecord)) {
1474 // delete a record for existing ufgroup
1475 CRM_Core_BAO_UFGroup::delUFJoin($joinParams);
1476 }
1477 }
1478
1479 //update the weight
1480 $query = "
1481UPDATE civicrm_uf_join
1482SET weight = %1
1483WHERE uf_group_id = %2
1484AND ( entity_id IS NULL OR entity_id <= 0 )
1485";
1486 $p = array(1 => array($params['weight'], 'Integer'),
1487 2 => array($ufGroupId, 'Integer'),
1488 );
1489 CRM_Core_DAO::executeQuery($query, $p);
1490
1491 // do a menu rebuild if we are on drupal, so it gets all the new menu entries
1492 // for user account
1493 $config = CRM_Core_Config::singleton();
1494 if ($menuRebuild &&
1495 $config->userSystem->is_drupal
1496 ) {
1497 menu_rebuild();
1498 }
1499 }
1500
1501 /**
1502 * Function to get the UF Join records for an ufgroup id
1503 *
1504 * @params int $ufGroupId uf group id
1505 * @params int $displayName if set return display name in array
1506 * @params int $status if set return module other than default modules (User Account/User registration/Profile)
1507 *
77b97be7
EM
1508 * @param null $ufGroupId
1509 * @param null $displayName
1510 * @param null $status
1511 *
6a488035
TO
1512 * @return array $ufGroupJoinRecords
1513 *
1514 * @access public
1515 * @static
1516 */
1517 public static function getUFJoinRecord($ufGroupId = NULL, $displayName = NULL, $status = NULL) {
1518 if ($displayName) {
1519 $UFGroupType = array();
1520 $UFGroupType = CRM_Core_SelectValues::ufGroupTypes();
1521 }
1522
1523 $ufJoin = array();
1524 $dao = new CRM_Core_DAO_UFJoin();
1525
1526 if ($ufGroupId) {
1527 $dao->uf_group_id = $ufGroupId;
1528 }
1529
1530 $dao->find();
1531 $ufJoin = array();
1532
1533 while ($dao->fetch()) {
1534 if (!$displayName) {
1535 $ufJoin[$dao->id] = $dao->module;
1536 }
1537 else {
1538 if (isset($UFGroupType[$dao->module])) {
1539 // skip the default modules
1540 if (!$status) {
1541 $ufJoin[$dao->id] = $UFGroupType[$dao->module];
1542 }
1543 // added for CRM-1475
1544 }
1545 elseif (!CRM_Utils_Array::key($dao->module, $ufJoin)) {
1546 $ufJoin[$dao->id] = $dao->module;
1547 }
1548 }
1549 }
1550 return $ufJoin;
1551 }
1552
1553 /**
1554 * Function takes an associative array and creates a ufjoin record for ufgroup
1555 *
1556 * @param array $params (reference) an assoc array of name/value pairs
1557 *
1558 * @return object CRM_Core_BAO_UFJoin object
1559 * @access public
1560 * @static
1561 */
1562 static function addUFJoin(&$params) {
1563 $ufJoin = new CRM_Core_DAO_UFJoin();
1564 $ufJoin->copyValues($params);
1565 $ufJoin->save();
1566 return $ufJoin;
1567 }
1568
1569 /**
1570 * Function to delete the uf join record for an uf group
1571 *
1572 * @param array $params (reference) an assoc array of name/value pairs
1573 *
1574 * @return void
1575 * @access public
1576 * @static
1577 */
1578 static function delUFJoin(&$params) {
1579 $ufJoin = new CRM_Core_DAO_UFJoin();
1580 $ufJoin->copyValues($params);
1581 $ufJoin->delete();
1582 }
1583
1584 /**
1585 * Function to get the weight for ufjoin record
1586 *
1587 * @param int $ufGroupId if $ufGroupId get update weight or add weight
1588 *
1589 * @return int weight of the UFGroup
1590 * @access public
1591 * @static
1592 */
1593 static function getWeight($ufGroupId = NULL) {
1594 //calculate the weight
1595 $p = array();
1596 if (!$ufGroupId) {
1597 $queryString = "SELECT ( MAX(civicrm_uf_join.weight)+1) as new_weight
1598 FROM civicrm_uf_join
1599 WHERE module = 'User Registration' OR module = 'User Account' OR module = 'Profile'";
1600 }
1601 else {
1602 $queryString = "SELECT MAX(civicrm_uf_join.weight) as new_weight
1603 FROM civicrm_uf_join
1604 WHERE civicrm_uf_join.uf_group_id = %1
1605 AND ( entity_id IS NULL OR entity_id <= 0 )";
1606 $p[1] = array($ufGroupId, 'Integer');
1607 }
1608
1609 $dao = CRM_Core_DAO::executeQuery($queryString, $p);
1610 $dao->fetch();
1611 return ($dao->new_weight) ? $dao->new_weight : 1;
1612 }
1613
1614 /**
1615 * Function to get the uf group for a module
1616 *
1617 * @param string $moduleName module name
77b97be7
EM
1618 * @param int $count no to increment the weight
1619 * @param bool $skipPermission
1620 * @param int $op - which operation (view, edit, create, etc) to check permission for
2141efbf 1621 * @param array|NULL $returnFields list of UFGroup fields to return; NULL for default
6a488035 1622 *
77b97be7 1623 * @internal param bool $skipPermision - whether to add permission clause
6a488035
TO
1624 * @return array $ufGroups array of ufgroups for a module
1625 * @access public
1626 * @static
1627 */
2141efbf 1628 public static function getModuleUFGroup($moduleName = NULL, $count = 0, $skipPermission = TRUE, $op = CRM_Core_Permission::VIEW, $returnFields = NULL) {
290d4ccc
DS
1629 $selectFields = array('id', 'title', 'created_id', 'is_active', 'is_reserved', 'group_type');
1630
1631 if (!CRM_Core_Config::isUpgradeMode()) {
1632 // CRM-13555, since description field was added later (4.4), and to avoid any problems with upgrade
1633 $selectFields[] = 'description';
1634 }
7ba38389 1635
1636 if (!empty($returnFields)) {
1637 $selectFields = array_merge($returnFields, array_diff($selectFields, $returnFields));
2141efbf 1638 }
7ba38389 1639
1640 $queryString = 'SELECT civicrm_uf_group.' . implode(', civicrm_uf_group.', $selectFields) . '
6a488035
TO
1641 FROM civicrm_uf_group
1642 LEFT JOIN civicrm_uf_join ON (civicrm_uf_group.id = uf_group_id)';
1643 $p = array();
1644 if ($moduleName) {
1645 $queryString .= ' AND civicrm_uf_group.is_active = 1
1646 WHERE civicrm_uf_join.module = %2';
1647 $p[2] = array($moduleName, 'String');
1648 }
1649
1650
1651 // add permissioning for profiles only if not registration
1652 if (!$skipPermission) {
1653 $permissionClause = CRM_Core_Permission::ufGroupClause($op, 'civicrm_uf_group.');
1654 if (strpos($queryString, 'WHERE') !== FALSE) {
1655 $queryString .= " AND $permissionClause ";
1656 }
1657 else {
1658 $queryString .= " $permissionClause ";
1659 }
1660 }
1661
1662 $queryString .= ' ORDER BY civicrm_uf_join.weight, civicrm_uf_group.title';
1663 $dao = CRM_Core_DAO::executeQuery($queryString, $p);
1664
1665 $ufGroups = array();
1666 while ($dao->fetch()) {
1667 //skip mix profiles in user Registration / User Account
1668 if (($moduleName == 'User Registration' || $moduleName == 'User Account') &&
1669 CRM_Core_BAO_UFField::checkProfileType($dao->id)
1670 ) {
1671 continue;
1672 }
7ba38389 1673 foreach ($selectFields as $key => $field) {
1674 if($field == 'id') {
1675 continue;
1676 }
1677 elseif ($field == 'name') {
1678 $ufGroups[$dao->id][$field] = $dao->title;
1679 continue;
1680 }
1681 $ufGroups[$dao->id][$field] = $dao->$field;
1682 }
6a488035
TO
1683 }
1684
1685 // Allow other modules to alter/override the UFGroups.
1686 CRM_Utils_Hook::buildUFGroupsForModule($moduleName, $ufGroups);
1687
1688 return $ufGroups;
1689 }
1690
1691 /**
1692 * Function to filter ufgroups based on logged in user contact type
1693 *
1694 * @params int $ufGroupId uf group id (profile id)
1695 *
77b97be7
EM
1696 * @param $ufGroupId
1697 * @param null $contactID
1698 *
6a488035
TO
1699 * @return boolean true or false
1700 * @static
1701 * @access public
1702 */
1703 static function filterUFGroups($ufGroupId, $contactID = NULL) {
1704 if (!$contactID) {
1705 $session = CRM_Core_Session::singleton();
1706 $contactID = $session->get('userID');
1707 }
1708
1709 if ($contactID) {
1710 //get the contact type
1711 $contactType = CRM_Contact_BAO_Contact::getContactType($contactID);
1712
1713 //match if exixting contact type is same as profile contact type
1714 $profileType = CRM_Core_BAO_UFField::getProfileType($ufGroupId);
1715
1716 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
1717 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
1718 }
1719
1720 //allow special mix profiles for Contribution and Participant
1721 $specialProfiles = array('Contribution', 'Participant', 'Membership');
1722
1723 if (in_array($profileType, $specialProfiles)) {
1724 return TRUE;
1725 }
1726
1727 if (($contactType == $profileType) || $profileType == 'Contact') {
1728 return TRUE;
1729 }
1730 }
1731
1732 return FALSE;
1733 }
1734
1735 /**
1f177c6b 1736 * Function to add profile field to a form
6a488035 1737 *
c927c151 1738 * @param CRM_Core_Form $form
1f177c6b
CW
1739 * @param array $field properties
1740 * @param int $mode profile mode
1741 * @param int $contactId
77b97be7 1742 * @param bool $online
1f177c6b
CW
1743 * @param string $usedFor for building up prefixed fieldname for special cases (e.g. onBehalf, Honor)
1744 * @param int $rowNumber
77b97be7
EM
1745 * @param string $prefix
1746 *
6a488035
TO
1747 * @return null
1748 * @static
1749 * @access public
1750 */
1751 static function buildProfile(
1752 &$form,
1753 &$field,
1754 $mode,
1755 $contactId = NULL,
1756 $online = FALSE,
133e2c99 1757 $usedFor = NULL,
6a488035
TO
1758 $rowNumber = NULL ,
1759 $prefix = ''
1760 ) {
1761 $defaultValues = array();
1f177c6b
CW
1762 $fieldName = $field['name'];
1763 $title = $field['title'];
1764 $attributes = $field['attributes'];
1765 $rule = $field['rule'];
1766 $view = $field['is_view'];
1767 $required = ($mode == CRM_Profile_Form::MODE_SEARCH) ? FALSE : $field['is_required'];
1768 $search = ($mode == CRM_Profile_Form::MODE_SEARCH) ? TRUE : FALSE;
1769 $isShared = CRM_Utils_Array::value('is_shared', $field, 0);
6a488035
TO
1770
1771 // do not display view fields in drupal registration form
1772 // CRM-4632
1773 if ($view && $mode == CRM_Profile_Form::MODE_REGISTER) {
1774 return;
1775 }
1776
133e2c99 1777 if ($usedFor == 'onbehalf') {
6a488035
TO
1778 $name = "onbehalf[$fieldName]";
1779 }
133e2c99 1780 elseif ($usedFor == 'honor') {
1781 $name = "honor[$fieldName]";
1782 }
6a488035
TO
1783 elseif ($contactId && !$online) {
1784 $name = "field[$contactId][$fieldName]";
1785 }
1786 elseif ($rowNumber) {
1787 $name = "field[$rowNumber][$fieldName]";
1788 }
1789 elseif (!empty($prefix)) {
1790 $name = $prefix ."[$fieldName]";
1791 }
1792 else {
1793 $name = $fieldName;
1794 }
9e1854a1 1795
1f177c6b 1796 $selectAttributes = array('class' => 'crm-select2', 'placeholder' => TRUE);
6a488035
TO
1797
1798 if ($fieldName == 'image_URL' && $mode == CRM_Profile_Form::MODE_EDIT) {
1799 $deleteExtra = ts('Are you sure you want to delete contact image.');
1800 $deleteURL = array(
1801 CRM_Core_Action::DELETE =>
1802 array(
1803 'name' => ts('Delete Contact Image'),
1804 'url' => 'civicrm/contact/image',
1805 'qs' => 'reset=1&id=%%id%%&gid=%%gid%%&action=delete',
1806 'extra' =>
1807 'onclick = "if (confirm( \'' . $deleteExtra . '\' ) ) this.href+=\'&amp;confirmed=1\'; else return false;"',
1808 ),
1809 );
1810 $deleteURL = CRM_Core_Action::formLink($deleteURL,
1811 CRM_Core_Action::DELETE,
1812 array('id' => $form->get('id'),
1813 'gid' => $form->get('gid'),
87dab4a4
AH
1814 ),
1815 ts('more'),
1816 FALSE,
1817 'contact.profileimage.delete',
1818 'Contact',
1819 $form->get('id')
6a488035
TO
1820 );
1821 $form->assign('deleteURL', $deleteURL);
1822 }
1823 $addressOptions = CRM_Core_BAO_Setting::valueOptions(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
1824 'address_options', TRUE, NULL, TRUE
1825 );
1826
1827 if (substr($fieldName, 0, 14) === 'state_province') {
8f9c3cbe 1828 $form->addChainSelect($name, array('label' => $title, 'required' => $required));
6a488035
TO
1829 $config = CRM_Core_Config::singleton();
1830 if (!in_array($mode, array(
1831 CRM_Profile_Form::MODE_EDIT, CRM_Profile_Form::MODE_SEARCH)) &&
1832 $config->defaultContactStateProvince
1833 ) {
1834 $defaultValues[$name] = $config->defaultContactStateProvince;
1835 $form->setDefaults($defaultValues);
1836 }
1837 }
1838 elseif (substr($fieldName, 0, 7) === 'country') {
1f177c6b 1839 $form->add('select', $name, $title, array('' => ts('- select -')) + CRM_Core_PseudoConstant::country(), $required, $selectAttributes);
6a488035
TO
1840 $config = CRM_Core_Config::singleton();
1841 if (!in_array($mode, array(
1842 CRM_Profile_Form::MODE_EDIT, CRM_Profile_Form::MODE_SEARCH)) &&
1843 $config->defaultContactCountry
1844 ) {
1845 $defaultValues[$name] = $config->defaultContactCountry;
1846 $form->setDefaults($defaultValues);
1847 }
1848 }
1849 elseif (substr($fieldName, 0, 6) === 'county') {
1850 if ($addressOptions['county']) {
8f9c3cbe 1851 $form->addChainSelect($name, array('label' => $title, 'required' => $required));
6a488035
TO
1852 }
1853 }
1854 elseif (substr($fieldName, 0, 9) === 'image_URL') {
1855 $form->add('file', $name, $title, $attributes, $required);
1856 $form->addUploadElement($name);
1857 }
1858 elseif (substr($fieldName, 0, 2) === 'im') {
1859 $form->add('text', $name, $title, $attributes, $required);
1860 if (!$contactId) {
133e2c99 1861 if ($usedFor) {
6a488035
TO
1862 if (substr($name, -1) == ']') {
1863 $providerName = substr($name, 0, -1) . '-provider_id]';
1864 }
1865 $form->add('select', $providerName, NULL,
1866 array(
e7e657f0 1867 '' => ts('- select -')) + CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id'), $required
6a488035
TO
1868 );
1869 }
1870 else {
1871 $form->add('select', $name . '-provider_id', $title,
1872 array(
e7e657f0 1873 '' => ts('- select -')) + CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id'), $required
6a488035
TO
1874 );
1875 }
1876
1877 if ($view && $mode != CRM_Profile_Form::MODE_SEARCH) {
1878 $form->freeze($name . '-provider_id');
1879 }
1880 }
1881 }
1882 elseif (($fieldName === 'birth_date') || ($fieldName === 'deceased_date')) {
1883 $form->addDate($name, $title, $required, array('formatType' => 'birth'));
1884 }
1885 elseif (in_array($fieldName, array(
1886 'membership_start_date', 'membership_end_date', 'join_date'))) {
1887 $form->addDate($name, $title, $required, array('formatType' => 'custom'));
1888 }
1889 elseif (CRM_Utils_Array::value('name',$field) == 'membership_type') {
1890 list($orgInfo, $types) = CRM_Member_BAO_MembershipType::getMembershipTypeInfo();
1891 $sel = &$form->addElement('hierselect', $name, $title);
53cfc93c 1892 $select = array('' => ts('- select -') );
1893 if(count($orgInfo) == 1 && $field['is_required']) {
1894 // we only have one org - so we should default to it. Not sure about defaulting to first type
1895 // as it could be missed - so adding a select
1896 // however, possibly that is more similar to the membership form
1897 if(count($types[1]) > 1) {
1898 $types[1] = $select + $types[1];
1899 }
1900 }
1901 else {
1902 $orgInfo = $select + $orgInfo;
1903 }
1904 $sel->setOptions(array($orgInfo, $types));
6a488035
TO
1905 }
1906 elseif (CRM_Utils_Array::value('name',$field) == 'membership_status') {
1907 $form->add('select', $name, $title,
1908 array(
1909 '' => ts('- select -')) + CRM_Member_PseudoConstant::membershipStatus(NULL, NULL, 'label'), $required
1910 );
1911 }
04ffef8d 1912 elseif ($fieldName === 'gender_id') {
6a488035 1913 $genderOptions = array();
26cf88b5 1914 $gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
6a488035
TO
1915 foreach ($gender as $key => $var) {
1916 $genderOptions[$key] = $form->createElement('radio', NULL, ts('Gender'), $var, $key);
1917 }
8a4f27dc 1918 $group = $form->addGroup($genderOptions, $name, $title);
6a488035
TO
1919 if ($required) {
1920 $form->addRule($name, ts('%1 is a required field.', array(1 => $title)), 'required');
1921 }
8a4f27dc 1922 else {
b847e6e7 1923 $group->setAttribute('allowClear', TRUE);
8a4f27dc 1924 }
6a488035 1925 }
f45334bd 1926 elseif ($fieldName === 'prefix_id' || $fieldName === 'suffix_id') {
1f177c6b
CW
1927 $form->addSelect($name, array(
1928 'label' => $title,
1929 'entity' => 'contact',
1930 'field' => $fieldName,
1931 'class' => 'six',
1932 'placeholder' => '',
1933 ), $required);
6a488035
TO
1934 }
1935 elseif ($fieldName === 'contact_sub_type') {
1936 $gId = $form->get('gid') ? $form->get('gid') : CRM_Utils_Array::value('group_id', $field);
133e2c99 1937 if ($usedFor == 'onbehalf') {
6a488035
TO
1938 $profileType = 'Organization';
1939 }
133e2c99 1940 elseif ($usedFor == 'honor') {
1941 $profileType = CRM_Core_BAO_UFField::getProfileType($form->_params['honoree_profile_id']);
1942 }
6a488035
TO
1943 else {
1944 $profileType = $gId ? CRM_Core_BAO_UFField::getProfileType($gId) : NULL;
1945 if ($profileType == 'Contact') {
1946 $profileType = 'Individual';
1947 }
1948 }
1949
1950 $setSubtype = FALSE;
1951 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
1952 $setSubtype = $profileType;
1953 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
1954 }
1955
1956 $subtypes = $profileType ? CRM_Contact_BAO_ContactType::subTypePairs($profileType) : array();
1957
1958 if ($setSubtype) {
1959 $subtypeList = array();
1960 $subtypeList[$setSubtype] = $subtypes[$setSubtype];
1961 }
1962 else {
1963 $subtypeList = $subtypes;
1964 }
1965
1966 $sel = $form->add('select', $name, $title, $subtypeList, $required);
1967 $sel->setMultiple(TRUE);
1968 }
1969 elseif (in_array($fieldName, CRM_Contact_BAO_Contact::$_greetingTypes)) {
1970 //add email greeting, postal greeting, addressee, CRM-4575
1971 $gId = $form->get('gid') ? $form->get('gid') : CRM_Utils_Array::value('group_id', $field);
1972 $profileType = CRM_Core_BAO_UFField::getProfileType($gId, TRUE, FALSE, TRUE);
1973
1974 if (empty($profileType) || in_array($profileType, array(
1975 'Contact', 'Contribution', 'Participant', 'Membership'))) {
1976 $profileType = 'Individual';
1977 }
1978 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
1979 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
1980 }
1981 $greeting = array(
1982 'contact_type' => $profileType,
1983 'greeting_type' => $fieldName,
1984 );
1985 $form->add('select', $name, $title,
1986 array(
1987 '' => ts('- select -')) + CRM_Core_PseudoConstant::greeting($greeting), $required
1988 );
1989 // add custom greeting element
1990 $form->add('text', $fieldName . '_custom', ts('Custom %1', array(1 => ucwords(str_replace('_', ' ', $fieldName)))),
1991 NULL, FALSE
1992 );
1993 }
1994 elseif ($fieldName === 'preferred_communication_method') {
e7e657f0 1995 $communicationFields = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'preferred_communication_method');
6a488035
TO
1996 foreach ($communicationFields as $key => $var) {
1997 if ($key == '') {
1998 continue;
1999 }
2000 $communicationOptions[] = $form->createElement('checkbox', $key, NULL, $var);
2001 }
2002 $form->addGroup($communicationOptions, $name, $title, '<br/>');
2003 }
2004 elseif ($fieldName === 'preferred_mail_format') {
2005 $form->add('select', $name, $title, CRM_Core_SelectValues::pmf());
2006 }
2007 elseif ($fieldName === 'preferred_language') {
c0c9cd82 2008 $form->add('select', $name, $title, array('' => ts('- select -')) + CRM_Contact_BAO_Contact::buildOptions('preferred_language'));
6a488035
TO
2009 }
2010 elseif ($fieldName == 'external_identifier') {
2011 $form->add('text', $name, $title, $attributes, $required);
2012 $contID = $contactId;
2013 if (!$contID) {
2014 $contID = $form->get('id');
2015 }
2016 $form->addRule($name,
2017 ts('External ID already exists in Database.'),
2018 'objectExists',
2019 array('CRM_Contact_DAO_Contact', $contID, 'external_identifier')
2020 );
2021 }
2022 elseif ($fieldName === 'group') {
2023 CRM_Contact_Form_Edit_TagsAndGroups::buildQuickForm($form, $contactId,
2024 CRM_Contact_Form_Edit_TagsAndGroups::GROUP,
2025 TRUE, $required,
2026 $title, NULL, $name
2027 );
2028 }
2029 elseif ($fieldName === 'tag') {
2030 CRM_Contact_Form_Edit_TagsAndGroups::buildQuickForm($form, $contactId,
2031 CRM_Contact_Form_Edit_TagsAndGroups::TAG,
2032 FALSE, $required,
2033 NULL, $title, $name
2034 );
2035 }
2036 elseif (substr($fieldName, 0, 4) === 'url-') {
2037 $form->add('text', $name, $title,
2038 array_merge(CRM_Core_DAO::getAttribute('CRM_Core_DAO_Website', 'url'),
2039 array(
2040 'onfocus' => "if (!this.value) { this.value='http://';} else return false",
2041 'onblur' => "if ( this.value == 'http://') { this.value='';} else return false",
2042 )
2043 ), $required
2044 );
2045
2046 $form->addRule($name, ts('Enter a valid Website.'), 'url');
6a488035
TO
2047 }
2048 // Note should be rendered as textarea
2049 elseif (substr($fieldName, -4) == 'note') {
2050 $form->add('textarea', $name, $title, $attributes, $required);
2051 }
2052 elseif (substr($fieldName, 0, 6) === 'custom') {
2053 $customFieldID = CRM_Core_BAO_CustomField::getKeyID($fieldName);
2054 if ($customFieldID) {
2055 CRM_Core_BAO_CustomField::addQuickFormElement($form, $name, $customFieldID, FALSE, $required, $search, $title);
2056 }
2057 }
2058 elseif (substr($fieldName, 0, 14) === 'address_custom') {
2059 list($fName, $locTypeId) = CRM_Utils_System::explode('-', $fieldName, 2);
2060 $customFieldID = CRM_Core_BAO_CustomField::getKeyID(substr($fName, 8));
2061 if ($customFieldID) {
2062 CRM_Core_BAO_CustomField::addQuickFormElement($form, $name, $customFieldID, FALSE, $required, $search, $title);
2063 }
2064 }
2065 elseif (in_array($fieldName, array(
2066 'receive_date', 'receipt_date', 'thankyou_date', 'cancel_date'))) {
2067 $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime'));
2068 }
2069 elseif ($fieldName == 'send_receipt') {
2070 $form->addElement('checkbox', $name, $title);
2071 }
2072 elseif ($fieldName == 'soft_credit') {
ccec9d6b 2073 $form->addEntityRef("soft_credit_contact_id[$rowNumber]", ts('Soft Credit To'), array('create' => TRUE));
5ee60152 2074 $form->addMoney("soft_credit_amount[{$rowNumber}]", ts('Amount'), FALSE, NULL, FALSE);
6a488035
TO
2075 }
2076 elseif ($fieldName == 'product_name') {
2077 list($products, $options) = CRM_Contribute_BAO_Premium::getPremiumProductInfo();
2078 $sel = &$form->addElement('hierselect', $name, $title);
2079 $products = array(
2080 '0' => ts('- select -')) + $products;
2081 $sel->setOptions(array($products, $options));
2082 }
2083 elseif ($fieldName == 'payment_instrument') {
2084 $form->add('select', $name, $title,
2085 array(''=>ts( '- select -' )) + CRM_Contribute_PseudoConstant::paymentInstrument( ), $required );
2086 }
2087 else if ($fieldName == 'financial_type' ) {
2088 $form->add('select', $name, $title,
2089 array(
2090 '' => ts('- select -')) + CRM_Contribute_PseudoConstant::financialType(), $required
2091 );
2092 }
2093 elseif ($fieldName == 'contribution_status_id') {
aaf5ca44
DG
2094 $contributionStatuses = CRM_Contribute_PseudoConstant::contributionStatus();
2095 $statusName = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
2096 foreach (array(
2097 'In Progress',
2098 'Overdue',
2099 'Refunded'
2100 ) as $suppress) {
2101 unset($contributionStatuses[CRM_Utils_Array::key($suppress, $statusName)]);
2102 }
6a73ef3f 2103
6a488035
TO
2104 $form->add('select', $name, $title,
2105 array(
aaf5ca44 2106 '' => ts('- select -')) + $contributionStatuses, $required
6a488035
TO
2107 );
2108 }
51fa20cb 2109 elseif ($fieldName == 'soft_credit_type') {
9e1854a1 2110 $name = "soft_credit_type[$rowNumber]";
51fa20cb 2111 $form->add('select', $name, $title,
2112 array(
2113 '' => ts('- select -')) + CRM_Core_OptionGroup::values("soft_credit_type")
2114 );
9e1854a1 2115 //CRM-15350: choose SCT field default value as 'Gift' for membership use
2116 //else (for contribution), use configured SCT default value
2117 $SCTDefaultValue = CRM_Core_OptionGroup::getDefaultValue("soft_credit_type");
2118 if ($field['field_type'] == 'Membership') {
2119 $SCTDefaultValue = CRM_Core_OptionGroup::getValue('soft_credit_type', 'Gift', 'name');
2120 }
2121 $form->addElement('hidden', 'sct_default_id', $SCTDefaultValue, array('id' => 'sct_default_id'));
51fa20cb 2122 }
6a488035
TO
2123 elseif ($fieldName == 'currency') {
2124 $form->addCurrency($name, $title, $required);
2125 }
2126 elseif ($fieldName == 'contribution_page_id') {
2127 $form->add('select', $name, $title,
2128 array(
2129 '' => ts('- select -')) + CRM_Contribute_PseudoConstant::contributionPage(), $required, 'class="big"'
2130 );
2131 }
2132 elseif ($fieldName == 'participant_register_date') {
2133 $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime'));
2134 }
2135 elseif ($fieldName == 'activity_status_id') {
2136 $form->add('select', $name, $title,
2137 array(
2138 '' => ts('- select -')) + CRM_Core_PseudoConstant::activityStatus(), $required
2139 );
2140 }
2141 elseif ($fieldName == 'activity_engagement_level') {
2142 $form->add('select', $name, $title,
2143 array(
2144 '' => ts('- select -')) + CRM_Campaign_PseudoConstant::engagementLevel(), $required
2145 );
2146 }
2147 elseif ($fieldName == 'activity_date_time') {
2148 $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime'));
2149 }
2150 elseif ($fieldName == 'participant_status') {
2151 $cond = NULL;
2152 if ($online == TRUE) {
2153 $cond = 'visibility_id = 1';
2154 }
2155 $form->add('select', $name, $title,
2156 array(
2157 '' => ts('- select -')) + CRM_Event_PseudoConstant::participantStatus(NULL, $cond, 'label'), $required
2158 );
2159 }
2160 elseif ($fieldName == 'participant_role') {
a7488080 2161 if (!empty($field['is_multiple'])) {
6a488035
TO
2162 $form->addCheckBox($name, $title, CRM_Event_PseudoConstant::participantRole(), NULL, NULL, NULL, NULL, '&nbsp', TRUE);
2163 }
2164 else {
2165 $form->add('select', $name, $title,
2166 array(
2167 '' => ts('- select -')) + CRM_Event_PseudoConstant::participantRole(), $required
2168 );
2169 }
2170 }
2171 elseif ($fieldName == 'world_region') {
1f177c6b 2172 $form->add('select', $name, $title, CRM_Core_PseudoConstant::worldRegion(), $required, $selectAttributes);
6a488035
TO
2173 }
2174 elseif ($fieldName == 'signature_html') {
2175 $form->addWysiwyg($name, $title, CRM_Core_DAO::getAttribute('CRM_Core_DAO_Email', $fieldName));
2176 }
2177 elseif ($fieldName == 'signature_text') {
2178 $form->add('textarea', $name, $title, CRM_Core_DAO::getAttribute('CRM_Core_DAO_Email', $fieldName));
2179 }
2180 elseif (substr($fieldName, -11) == 'campaign_id') {
2181 if (CRM_Campaign_BAO_Campaign::isCampaignEnable()) {
2182 $campaigns = CRM_Campaign_BAO_Campaign::getCampaigns(CRM_Utils_Array::value($contactId,
2183 $form->_componentCampaigns
2184 ));
2185 $form->add('select', $name, $title,
2186 array(
1f177c6b 2187 '' => ts('- select -')) + $campaigns, $required, 'class="crm-select2 big"'
6a488035
TO
2188 );
2189 }
2190 }
2191 elseif ($fieldName == 'activity_details') {
2192 $form->addWysiwyg($fieldName, $title, array('rows' => 4, 'cols' => 60), $required);
2193 }
2194 elseif ($fieldName == 'activity_duration') {
2195 $form->add('text', $name, $title, $attributes, $required);
2196 $form->addRule($name, ts('Please enter the duration as number of minutes (integers only).'), 'positiveInteger');
2197 }
2198 else {
2199 if (substr($fieldName, 0, 3) === 'is_' or substr($fieldName, 0, 7) === 'do_not_') {
2200 $form->add('advcheckbox', $name, $title, $attributes, $required);
2201 }
2202 else {
2203 $form->add('text', $name, $title, $attributes, $required);
2204 }
2205 }
2206
2207 static $hiddenSubtype = FALSE;
2208 if (!$hiddenSubtype && CRM_Contact_BAO_ContactType::isaSubType($field['field_type'])) {
2209 // In registration mode params are submitted via POST and we don't have any clue
2210 // about profile-id or the profile-type (which could be a subtype)
2211 // To generalize the behavior and simplify the process,
2212 // lets always add the hidden
2213 //subtype value if there is any, and we won't have to
2214 // compute it while processing.
133e2c99 2215 if ($usedFor) {
2216 $form->addElement('hidden', $usedFor . '[contact_sub_type]', $field['field_type']);
6a488035
TO
2217 }
2218 else {
2219 $form->addElement('hidden', 'contact_sub_type_hidden', $field['field_type']);
2220 }
2221 $hiddenSubtype = TRUE;
2222 }
2223
2224 if (($view && $mode != CRM_Profile_Form::MODE_SEARCH) || $isShared) {
2225 $form->freeze($name);
2226 }
2227
2228 //add the rules
2229 if (in_array($fieldName, array(
2230 'non_deductible_amount', 'total_amount', 'fee_amount', 'net_amount'))) {
2231 $form->addRule($name, ts('Please enter a valid amount.'), 'money');
2232 }
6a488035
TO
2233 if ($rule) {
2234 if (!($rule == 'email' && $mode == CRM_Profile_Form::MODE_SEARCH)) {
2235 $form->addRule($name, ts('Please enter a valid %1', array(1 => $title)), $rule);
2236 }
2237 }
2238 }
2239
2240 /**
2241 * Function to set profile defaults
2242 *
2243 * @params int $contactId contact id
2244 * @params array $fields associative array of fields
2245 * @params array $defaults defaults array
2246 * @params boolean $singleProfile true for single profile else false(batch update)
2247 * @params int $componentId id for specific components like contribute, event etc
2248 *
77b97be7
EM
2249 * @param $contactId
2250 * @param $fields
2251 * @param $defaults
2252 * @param bool $singleProfile
2253 * @param null $componentId
2254 * @param null $component
2255 *
6a488035
TO
2256 * @return null
2257 * @static
2258 * @access public
2259 */
2260 static function setProfileDefaults($contactId, &$fields, &$defaults,
2261 $singleProfile = TRUE, $componentId = NULL, $component = NULL
2262 ) {
2263 if (!$componentId) {
2264 //get the contact details
2265 list($contactDetails, $options) = CRM_Contact_BAO_Contact::getHierContactDetails($contactId, $fields);
2266 $details = CRM_Utils_Array::value($contactId, $contactDetails);
2267 $multipleFields = array('website' => 'url');
2268
2269 //start of code to set the default values
2270 foreach ($fields as $name => $field) {
2271 // skip pseudo fields
2272 if (substr($name, 0, 9) == 'phone_ext') {
2273 continue;
2274 }
2275
2276 //set the field name depending upon the profile mode(single/batch)
2277 if ($singleProfile) {
2278 $fldName = $name;
2279 }
2280 else {
2281 $fldName = "field[$contactId][$name]";
2282 }
2283
2284 if ($name == 'group') {
2285 CRM_Contact_Form_Edit_TagsAndGroups::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups::GROUP, $fldName);
2286 }
2287 if ($name == 'tag') {
2288 CRM_Contact_Form_Edit_TagsAndGroups::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups::TAG, $fldName);
2289 }
2290
a7488080 2291 if (!empty($details[$name]) || isset($details[$name])) {
6a488035 2292 //to handle custom data (checkbox) to be written
58f00377 2293 // to handle birth/deceased date, greeting_type and few other fields
2294 if (($name == 'birth_date') || ($name == 'deceased_date')) {
6a488035
TO
2295 list($defaults[$fldName]) = CRM_Utils_Date::setDateDefaults($details[$name], 'birth');
2296 }
2297 elseif (in_array($name, CRM_Contact_BAO_Contact::$_greetingTypes)) {
2298 $defaults[$fldName] = $details[$name . '_id'];
2299 $defaults[$name . '_custom'] = $details[$name . '_custom'];
2300 }
2301 elseif ($name == 'preferred_communication_method') {
2302 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2303 foreach ($v as $item) {
2304 if ($item) {
2305 $defaults[$fldName . "[$item]"] = 1;
2306 }
2307 }
2308 }
8aefc657
RK
2309 elseif ($name == 'contact_sub_type') {
2310 $defaults[$fldName] = explode(CRM_Core_DAO::VALUE_SEPARATOR, trim($details[$name], CRM_Core_DAO::VALUE_SEPARATOR));
2311 }
6a488035
TO
2312 elseif ($name == 'world_region') {
2313 $defaults[$fldName] = $details['worldregion_id'];
2314 }
2315 elseif ($customFieldId = CRM_Core_BAO_CustomField::getKeyID($name)) {
2316 //fix for custom fields
2317 $customFields = CRM_Core_BAO_CustomField::getFields(CRM_Utils_Array::value('contact_type', $details));
2318
2319 // hack to add custom data for components
2320 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
2321 foreach ($components as $value) {
2322 $customFields = CRM_Utils_Array::crmArrayMerge($customFields,
2323 CRM_Core_BAO_CustomField::getFieldsForImport($value)
2324 );
2325 }
2326
2327 switch ($customFields[$customFieldId]['html_type']) {
2328 case 'Multi-Select State/Province':
2329 case 'Multi-Select Country':
2330 case 'AdvMulti-Select':
2331 case 'Multi-Select':
2332 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2333 foreach ($v as $item) {
2334 if ($item) {
2335 $defaults[$fldName][$item] = $item;
2336 }
2337 }
2338 break;
2339
2340 case 'CheckBox':
2341 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2342 foreach ($v as $item) {
2343 if ($item) {
2344 $defaults[$fldName][$item] = 1;
2345 // seems like we need this for QF style checkboxes in profile where its multiindexed
2346 // CRM-2969
2347 $defaults["{$fldName}[{$item}]"] = 1;
2348 }
2349 }
2350 break;
2351
6a488035
TO
2352 case 'Select Date':
2353 // CRM-6681, set defult values according to date and time format (if any).
2354 $dateFormat = NULL;
a7488080 2355 if (!empty($customFields[$customFieldId]['date_format'])) {
fd933dc5 2356 $dateFormat = $customFields[$customFieldId]['date_format'];
6a488035
TO
2357 }
2358
a7488080 2359 if (empty($customFields[$customFieldId]['time_format'])) {
6a488035
TO
2360 list($defaults[$fldName]) = CRM_Utils_Date::setDateDefaults($details[$name], NULL,
2361 $dateFormat
2362 );
2363 }
2364 else {
2365 $timeElement = $fldName . '_time';
2366 if (substr($fldName, -1) == ']') {
2367 $timeElement = substr($fldName, 0, -1) . '_time]';
2368 }
fd933dc5
KJ
2369 list($defaults[$fldName], $defaults[$timeElement]) = CRM_Utils_Date::setDateDefaults($details[$name],
2370 NULL, $dateFormat, $customFields[$customFieldId]['time_format']);
6a488035
TO
2371 }
2372 break;
2373
2374 default:
2375 $defaults[$fldName] = $details[$name];
2376 break;
2377 }
2378 }
2379 else {
2380 $defaults[$fldName] = $details[$name];
2381 }
2382 }
2383 else {
2384 $blocks = array('email', 'phone', 'im', 'openid');
2385 list($fieldName, $locTypeId, $phoneTypeId) = CRM_Utils_System::explode('-', $name, 3);
2386 if (!in_array($fieldName, $multipleFields)) {
2387 if (is_array($details)) {
2388 foreach ($details as $key => $value) {
2389 // when we fixed CRM-5319 - get primary loc
2390 // type as per loc field and removed below code.
2391 $primaryLocationType = FALSE;
2392 if ($locTypeId == 'Primary') {
2393 if (is_array($value) && array_key_exists($fieldName, $value)){
2394 $primaryLocationType = TRUE;
2395 if (in_array($fieldName, $blocks)){
2396 $locTypeId = CRM_Contact_BAO_Contact::getPrimaryLocationType($contactId, FALSE, $fieldName);
2397 }
2398 else{
2399 $locTypeId = CRM_Contact_BAO_Contact::getPrimaryLocationType($contactId, FALSE, 'address');
2400 }
2401 }
2402 }
2403
2404 // fixed for CRM-665
2405 if (is_numeric($locTypeId)) {
2406 if ($primaryLocationType || $locTypeId == CRM_Utils_Array::value('location_type_id', $value)) {
a7488080 2407 if (!empty($value[$fieldName])) {
6a488035
TO
2408 //to handle stateprovince and country
2409 if ($fieldName == 'state_province') {
2410 $defaults[$fldName] = $value['state_province_id'];
2411 }
2412 elseif ($fieldName == 'county') {
2413 $defaults[$fldName] = $value['county_id'];
2414 }
2415 elseif ($fieldName == 'country') {
6a488035
TO
2416 if (!isset($value['country_id']) || !$value['country_id']) {
2417 $config = CRM_Core_Config::singleton();
2418 if ($config->defaultContactCountry) {
2419 $defaults[$fldName] = $config->defaultContactCountry;
2420 }
2421 }
b3071092
DL
2422 else {
2423 $defaults[$fldName] = $value['country_id'];
2424 }
6a488035
TO
2425 }
2426 elseif ($fieldName == 'phone') {
2427 if ($phoneTypeId) {
2428 if (isset($value['phone'][$phoneTypeId])) {
2429 $defaults[$fldName] = $value['phone'][$phoneTypeId];
2430 }
2431 if (isset($value['phone_ext'][$phoneTypeId])) {
2432 $defaults[str_replace('phone', 'phone_ext', $fldName)] = $value['phone_ext'][$phoneTypeId];
2433 }
2434 }
2435 else {
2436 $phoneDefault = CRM_Utils_Array::value('phone', $value);
2437 // CRM-9216
2438 if (!is_array($phoneDefault)) {
2439 $defaults[$fldName] = $phoneDefault;
2440 }
2441 }
2442 }
2443 elseif ($fieldName == 'email') {
2444 //adding the first email (currently we don't support multiple emails of same location type)
2445 $defaults[$fldName] = $value['email'];
2446 }
2447 elseif ($fieldName == 'im') {
2448 //adding the first im (currently we don't support multiple ims of same location type)
2449 $defaults[$fldName] = $value['im'];
2450 $defaults[$fldName . '-provider_id'] = $value['im_provider_id'];
2451 }
2452 else {
2453 $defaults[$fldName] = $value[$fieldName];
2454 }
2455 }
2456 elseif (substr($fieldName, 0, 14) === 'address_custom' &&
2457 CRM_Utils_Array::value(substr($fieldName, 8), $value)
2458 ) {
2459 $defaults[$fldName] = $value[substr($fieldName, 8)];
2460 }
2461 }
2462 }
2463 }
2464 }
2465 }
2466 else {
2467 if (is_array($details)) {
1fd63589
EM
2468 if ($fieldName === 'url'
2469 && !empty($details['website'])
887e764d
PN
2470 && !empty($details['website'][$locTypeId])) {
2471 $defaults[$fldName] = CRM_Utils_Array::value('url', $details['website'][$locTypeId]);
6a488035
TO
2472 }
2473 }
2474 }
2475 }
2476 }
2477 }
2478
2479 //Handling Contribution Part of the batch profile
2480 if (CRM_Core_Permission::access('CiviContribute') && $component == 'Contribute') {
2481 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2482 }
2483
2484 //Handling Event Participation Part of the batch profile
2485 if (CRM_Core_Permission::access('CiviEvent') && $component == 'Event') {
2486 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2487 }
2488
2489 //Handling membership Part of the batch profile
2490 if (CRM_Core_Permission::access('CiviMember') && $component == 'Membership') {
2491 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2492 }
2493
2494 //Handling Activity Part of the batch profile
2495 if ($component == 'Activity') {
2496 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2497 }
2498 }
2499
2500 /**
2501 * Function to get profiles by type eg: pure Individual etc
2502 *
2503 * @param array $types associative array of types eg: types('Individual')
2504 * @param boolean $onlyPure true if only pure profiles are required
2505 *
2506 * @return array $profiles associative array of profiles
2507 * @static
2508 * @access public
2509 */
2510 static function getProfiles($types, $onlyPure = FALSE) {
2511 $profiles = array();
ff4f7744 2512 $ufGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id');
6a488035
TO
2513
2514 CRM_Utils_Hook::aclGroup(CRM_Core_Permission::ADMIN, NULL, 'civicrm_uf_group', $ufGroups, $ufGroups);
2515
2516 // Exclude Batch Data Entry profiles - CRM-10901
2517 $batchProfiles = CRM_Core_BAO_UFGroup::getBatchProfiles();
2518
2519 foreach ($ufGroups as $id => $title) {
2520 $ptype = CRM_Core_BAO_UFField::getProfileType($id, FALSE, $onlyPure);
2521 if (in_array($ptype, $types) && !array_key_exists($id, $batchProfiles)) {
2522 $profiles[$id] = $title;
2523 }
2524 }
2525 return $profiles;
2526 }
2527
2528 /**
2529 * Function to check whether a profile is valid combination of
2530 * required and/or optional profile types
2531 *
2532 * @param array $required array of types those are required
2533 * @param array $optional array of types those are optional
2534 *
2535 * @return array $profiles associative array of profiles
2536 * @static
2537 * @access public
2538 */
2539 static function getValidProfiles($required, $optional = NULL) {
2540 if (!is_array($required) || empty($required)) {
2541 return;
2542 }
2543
2544 $profiles = array();
ff4f7744 2545 $ufGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id');
6a488035
TO
2546
2547 CRM_Utils_Hook::aclGroup(CRM_Core_Permission::ADMIN, NULL, 'civicrm_uf_group', $ufGroups, $ufGroups);
2548
2549 foreach ($ufGroups as $id => $title) {
2550 $type = CRM_Core_BAO_UFField::checkValidProfileType($id, $required, $optional);
2551 if ($type) {
2552 $profiles[$id] = $title;
2553 }
2554 }
2555
2556 return $profiles;
2557 }
2558
2559 /**
2560 * Function to check whether a profile is valid combination of
2561 * required profile fields
2562 *
2563 * @param array $ufId integer id of the profile
2564 * @param array $required array of fields those are required in the profile
2565 *
2566 * @return array $profiles associative array of profiles
2567 * @static
2568 * @access public
2569 */
2570 static function checkValidProfile($ufId, $required = NULL) {
2571 $validProfile = FALSE;
2572 if (!$ufId) {
2573 return $validProfile;
2574 }
2575
2576 if (!CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $ufId, 'is_active')) {
2577 return $validProfile;
2578 }
2579
2580 $profileFields = self::getFields($ufId, FALSE, CRM_Core_Action::VIEW, NULL,
2581 NULL, FALSE, NULL, FALSE, NULL,
2582 CRM_Core_Permission::CREATE, NULL
2583 );
2584
2585 $validProfile = array();
2586 if (!empty($profileFields)) {
2587 $fields = array_keys($profileFields);
2588 foreach ($fields as $val) {
2589 foreach ($required as $key => $field) {
2590 if (strpos($val, $field) === 0) {
2591 unset($required[$key]);
2592 }
2593 }
2594 }
2595
2596 $validProfile = (empty($required)) ? TRUE : FALSE;
2597 }
2598
2599 return $validProfile;
2600 }
2601
2602 /**
2603 * Function to get default value for Register.
2604 *
77b97be7
EM
2605 * @param $fields
2606 * @param $defaults
2607 *
2608 * @return mixed $defaults@static
6a488035
TO
2609 * @access public
2610 */
2611 static function setRegisterDefaults(&$fields, &$defaults) {
b525f1cc 2612 $config = CRM_Core_Config::singleton();
6a488035
TO
2613 foreach ($fields as $name => $field) {
2614 if (substr($name, 0, 8) == 'country-') {
b525f1cc 2615 if (!empty($config->defaultContactCountry)) {
6a488035
TO
2616 $defaults[$name] = $config->defaultContactCountry;
2617 }
2618 }
2619 elseif (substr($name, 0, 15) == 'state_province-') {
b525f1cc 2620 if (!empty($config->defaultContactStateProvince)) {
6a488035
TO
2621 $defaults[$name] = $config->defaultContactStateProvince;
2622 }
2623 }
2624 }
2625 return $defaults;
2626 }
2627
2628 /**
2629 * This function is to make a copy of a profile, including
2630 * all the fields in the profile
2631 *
2632 * @param int $id the profile id to copy
2633 *
2634 * @return void
2635 * @access public
2636 */
2637 static function copy($id) {
2638 $fieldsFix = array('prefix' => array('title' => ts('Copy of ')));
2639 $copy = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFGroup',
2640 array('id' => $id),
2641 NULL,
2642 $fieldsFix
2643 );
2644
2645 if ($pos = strrpos($copy->name, "_{$id}")) {
2646 $copy->name = substr_replace($copy->name, '', $pos);
2647 }
2648 $copy->name = CRM_Utils_String::munge($copy->name, '_', 56) . "_{$copy->id}";
2649 $copy->save();
2650
2651 $copyUFJoin = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFJoin',
2652 array('uf_group_id' => $id),
2653 array('uf_group_id' => $copy->id),
2654 NULL,
2655 'entity_table'
2656 );
2657
2658 $copyUFField = &CRM_Core_DAO::copyGeneric('CRM_Core_BAO_UFField',
2659 array('uf_group_id' => $id),
2660 array('uf_group_id' => $copy->id)
2661 );
2662
2663 $maxWeight = CRM_Utils_Weight::getMax('CRM_Core_DAO_UFJoin', NULL, 'weight');
2664
2665 //update the weight
2666 $query = "
2667UPDATE civicrm_uf_join
2668SET weight = %1
2669WHERE uf_group_id = %2
2670AND ( entity_id IS NULL OR entity_id <= 0 )
2671";
2672 $p = array(1 => array($maxWeight + 1, 'Integer'),
2673 2 => array($copy->id, 'Integer'),
2674 );
2675 CRM_Core_DAO::executeQuery($query, $p);
2676 if ($copy->is_reserved) {
2677 $query = "UPDATE civicrm_uf_group SET is_reserved = 0 WHERE id = %1";
2678 $params = array(1 => array($copy->id, 'Integer'));
2679 CRM_Core_DAO::executeQuery($query, $params);
2680 }
2681 CRM_Utils_Hook::copy('UFGroup', $copy);
2682
2683 return $copy;
2684 }
2685
2686 /**
2687 * Process that send notification e-mails
2688 *
2689 * @params int $contactId contact id
2690 * @params array $values associative array of name/value pair
2691 *
1fd63589
EM
2692 * @param $contactID
2693 * @param $values
2694 *
6a488035
TO
2695 * @return void
2696 * @access public
2697 */
2698
2699 static function commonSendMail($contactID, &$values) {
2700 if (!$contactID || !$values) {
2701 return;
2702
2703 }
2704 $template = CRM_Core_Smarty::singleton();
2705
2706 $displayName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
2707 $contactID,
2708 'display_name'
2709 );
2710
2711 self::profileDisplay($values['id'], $values['values'], $template);
2712 $emailList = explode(',', $values['email']);
2713
2714 $contactLink = CRM_Utils_System::url('civicrm/contact/view',
2715 "reset=1&cid=$contactID",
2716 TRUE, NULL, FALSE, FALSE, TRUE
2717 );
2718
2719 //get the default domain email address.
2720 list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail();
2721
2722 if (!$domainEmailAddress || $domainEmailAddress == 'info@EXAMPLE.ORG') {
2723 $fixUrl = CRM_Utils_System::url('civicrm/admin/domain', 'action=update&reset=1');
2724 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)));
2725 }
2726
2727 foreach ($emailList as $emailTo) {
2728 // FIXME: take the below out of the foreach loop
c6327d7d 2729 CRM_Core_BAO_MessageTemplate::sendTemplate(
6a488035
TO
2730 array(
2731 'groupName' => 'msg_tpl_workflow_uf',
2732 'valueName' => 'uf_notify',
2733 'contactId' => $contactID,
2734 'tplParams' => array(
2735 'displayName' => $displayName,
2736 'currentDate' => date('r'),
2737 'contactLink' => $contactLink,
2738 ),
2739 'from' => "$domainEmailName <$domainEmailAddress>",
2740 'toEmail' => $emailTo,
2741 )
2742 );
2743 }
2744 }
2745
2746 /**
2747 * Given a contact id and a group id, returns the field values from the db
2748 * for this group and notify email only if group's notify field is
2749 * set and field values are not empty
2750 *
2751 * @params $gid group id
2752 * @params $cid contact id
2753 * @params $params associative array
2754 *
1fd63589
EM
2755 * @param $gid
2756 * @param $cid
2757 * @param $params
2758 * @param bool $skipCheck
2759 *
6a488035
TO
2760 * @return array
2761 * @access public
2762 */
2763 function checkFieldsEmptyValues($gid, $cid, $params, $skipCheck = FALSE) {
2764 if ($gid) {
2765 if (CRM_Core_BAO_UFGroup::filterUFGroups($gid, $cid) || $skipCheck) {
2766 $values = array();
2767 $fields = CRM_Core_BAO_UFGroup::getFields($gid, FALSE, CRM_Core_Action::VIEW);
2768 CRM_Core_BAO_UFGroup::getValues($cid, $fields, $values, FALSE, $params, TRUE);
2769
2770 $email = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'notify');
2771
2772 if (!empty($values) &&
2773 !empty($email)
2774 ) {
2775 $val = array(
2776 'id' => $gid,
2777 'values' => $values,
2778 'email' => $email,
2779 );
2780 return $val;
2781 }
2782 }
2783 }
2784 return NULL;
2785 }
2786
2787 /**
2788 * Function to assign uf fields to template
2789 *
2790 * @params int $gid group id
2791 * @params array $values associative array of fields
2792 *
1fd63589
EM
2793 * @param $gid
2794 * @param $values
2795 * @param $template
2796 *
6a488035
TO
2797 * @return void
2798 * @access public
2799 */
2800 function profileDisplay($gid, $values, $template) {
2801 $groupTitle = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'title');
2802 $template->assign('grouptitle', $groupTitle);
2803 if (count($values)) {
2804 $template->assign('values', $values);
2805 }
2806 }
2807
2808 /**
2809 * Format fields for dupe Contact Matching
2810 *
2811 * @param array $params associated array
2812 *
1fd63589
EM
2813 * @param null $contactId
2814 *
6a488035
TO
2815 * @return array $data assoicated formatted array
2816 * @access public
2817 * @static
2818 */
2819 static function formatFields($params, $contactId = NULL) {
2820 if ($contactId) {
2821 // get the primary location type id and email
2822 list($name, $primaryEmail, $primaryLocationType) = CRM_Contact_BAO_Contact_Location::getEmailDetails($contactId);
2823 }
2824 else {
2825 $defaultLocationType = CRM_Core_BAO_LocationType::getDefault();
2826 $primaryLocationType = $defaultLocationType->id;
2827 }
2828
2829 $data = array();
2830 $locationType = array();
2831 $count = 1;
2832 $primaryLocation = 0;
2833 foreach ($params as $key => $value) {
2834 list($fieldName, $locTypeId, $phoneTypeId) = explode('-', $key);
2835
2836 if ($locTypeId == 'Primary') {
2837 $locTypeId = $primaryLocationType;
2838 }
2839
2840 if (is_numeric($locTypeId)) {
2841 if (!in_array($locTypeId, $locationType)) {
2842 $locationType[$count] = $locTypeId;
2843 $count++;
2844 }
2845 $loc = CRM_Utils_Array::key($locTypeId, $locationType);
2846
2847 $data['location'][$loc]['location_type_id'] = $locTypeId;
2848
2849 // if we are getting in a new primary email, dont overwrite the new one
2850 if ($locTypeId == $primaryLocationType) {
a7488080 2851 if (!empty($params['email-' . $primaryLocationType])) {
6a488035
TO
2852 $data['location'][$loc]['email'][$loc]['email'] = $fields['email-' . $primaryLocationType];
2853 }
2854 elseif (isset($primaryEmail)) {
2855 $data['location'][$loc]['email'][$loc]['email'] = $primaryEmail;
2856 }
2857 $primaryLocation++;
2858 }
2859
2860 if ($loc == 1) {
2861 $data['location'][$loc]['is_primary'] = 1;
2862 }
2863 if ($fieldName == 'phone') {
2864 if ($phoneTypeId) {
2865 $data['location'][$loc]['phone'][$loc]['phone_type_id'] = $phoneTypeId;
2866 }
2867 else {
2868 $data['location'][$loc]['phone'][$loc]['phone_type_id'] = '';
2869 }
2870 $data['location'][$loc]['phone'][$loc]['phone'] = $value;
2871 }
2872 elseif ($fieldName == 'email') {
2873 $data['location'][$loc]['email'][$loc]['email'] = $value;
2874 }
2875 elseif ($fieldName == 'im') {
2876 $data['location'][$loc]['im'][$loc]['name'] = $value;
2877 }
2878 else {
2879 if ($fieldName === 'state_province') {
2880 $data['location'][$loc]['address']['state_province_id'] = $value;
2881 }
2882 elseif ($fieldName === 'country') {
2883 $data['location'][$loc]['address']['country_id'] = $value;
2884 }
2885 else {
2886 $data['location'][$loc]['address'][$fieldName] = $value;
2887 }
2888 }
2889 }
2890 else {
67744c4e 2891 // TODO: prefix, suffix and gender translation may no longer be necessary - check inputs
6a488035
TO
2892 if ($key === 'individual_suffix') {
2893 $data['suffix_id'] = $value;
2894 }
2895 elseif ($key === 'individual_prefix') {
2896 $data['prefix_id'] = $value;
2897 }
2898 elseif ($key === 'gender') {
2899 $data['gender_id'] = $value;
2900 }
2901 elseif (substr($key, 0, 6) === 'custom') {
2902 if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
2903 //fix checkbox
2904 if ($customFields[$customFieldID]['html_type'] == 'CheckBox') {
2905 $value = implode(CRM_Core_DAO::VALUE_SEPARATOR, array_keys($value));
2906 }
2907 // fix the date field
2908 if ($customFields[$customFieldID]['data_type'] == 'Date') {
2909 $date = CRM_Utils_Date::format($value);
2910 if (!$date) {
2911 $date = '';
2912 }
2913 $value = $date;
2914 }
2915
2916 $data['custom'][$customFieldID] = array(
2917 'id' => $id,
2918 'value' => $value,
2919 'extends' => $customFields[$customFieldID]['extends'],
2920 'type' => $customFields[$customFieldID]['data_type'],
2921 'custom_field_id' => $customFieldID,
2922 );
2923 }
2924 }
2925 elseif ($key == 'edit') {
2926 continue;
2927 }
2928 else {
2929 $data[$key] = $value;
2930 }
2931 }
2932 }
2933
2934 if (!$primaryLocation) {
2935 $loc++;
2936 $data['location'][$loc]['email'][$loc]['email'] = $primaryEmail;
2937 }
2938
2939
2940 return $data;
2941 }
2942
2943 /**
2944 * calculate the profile type 'group_type' as per profile fields.
2945 *
1fd63589
EM
2946 * @param $gId
2947 * @param bool $includeTypeValues
6a488035
TO
2948 * @param int $ignoreFieldId ignore particular profile field
2949 *
1fd63589 2950 * @internal param int $gid profile id
6a488035
TO
2951 * @return array list of calculated group type
2952 */
2953 static function calculateGroupType($gId, $includeTypeValues = FALSE, $ignoreFieldId = NULL) {
2954 //get the profile fields.
2955 $ufFields = self::getFields($gId, FALSE, NULL, NULL, NULL, TRUE, NULL, TRUE);
2956 return self::_calculateGroupType($ufFields, $includeTypeValues, $ignoreFieldId);
2957 }
2958
2959 /**
2960 * calculate the profile type 'group_type' as per profile fields.
2961 *
1fd63589
EM
2962 * @param $ufFields
2963 * @param bool $includeTypeValues
6a488035
TO
2964 * @param int $ignoreFieldId ignore perticular profile field
2965 *
1fd63589 2966 * @internal param int $gid profile id
6a488035
TO
2967 * @return array list of calculated group type
2968 */
2969 static function _calculateGroupType($ufFields, $includeTypeValues = FALSE, $ignoreFieldId = NULL) {
2970 $groupType = $groupTypeValues = $customFieldIds = array();
2971 if (!empty($ufFields)) {
2972 foreach ($ufFields as $fieldName => $fieldValue) {
2973 //ignore field from group type when provided.
2974 //in case of update profile field.
2975 if ($ignoreFieldId && ($ignoreFieldId == $fieldValue['field_id'])) {
2976 continue;
2977 }
2978 if (!in_array($fieldValue['field_type'], $groupType)) {
2979 $groupType[$fieldValue['field_type']] = $fieldValue['field_type'];
2980 }
2981
2982 if ($includeTypeValues && ($fldId = CRM_Core_BAO_CustomField::getKeyID($fieldName))) {
2983 $customFieldIds[$fldId] = $fldId;
2984 }
2985 }
2986 }
2987
2988 if (!empty($customFieldIds)) {
2989 $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) . ')';
2990
2991 $customGroups = CRM_Core_DAO::executeQuery($query);
2992 while ($customGroups->fetch()) {
2993 if (!$customGroups->extends_entity_column_value) {
2994 continue;
2995 }
2996
2997 $groupTypeName = "{$customGroups->extends}Type";
2998 if ($customGroups->extends == 'Participant' && $customGroups->extends_entity_column_id) {
2999 $groupTypeName = CRM_Core_OptionGroup::getValue('custom_data_type', $customGroups->extends_entity_column_id, 'value', 'String', 'name');
3000 }
3001
3002 foreach (explode(CRM_Core_DAO::VALUE_SEPARATOR, $customGroups->extends_entity_column_value) as $val) {
3003 if ($val) {
3004 $groupTypeValues[$groupTypeName][$val] = $val;
3005 }
3006 }
3007 }
3008
3009 if (!empty($groupTypeValues)) {
3010 $groupType = array_merge($groupType, $groupTypeValues);
3011 }
3012 }
3013
3014 return $groupType;
3015 }
3016
3017 /**
3018 * Update the profile type 'group_type' as per profile fields including group types and group subtype values.
3019 * Build and store string like: group_type1,group_type2[VALUE_SEPERATOR]group_type1Type:1:2:3,group_type2Type:1:2
3020 *
3021 * FIELDS GROUP_TYPE
3022 * BirthDate + Email Individual,Contact
3023 * BirthDate + Subject Individual,Activity
3024 * BirthDate + Subject + SurveyOnlyField Individual,Activity\0ActivityType:28
3025 * BirthDate + Subject + SurveyOnlyField + PhoneOnlyField (Not allowed)
3026 * BirthDate + SurveyOnlyField Individual,Activity\0ActivityType:28
3027 * BirthDate + Subject + SurveyOrPhoneField Individual,Activity\0ActivityType:2:28
3028 * BirthDate + SurveyOrPhoneField Individual,Activity\0ActivityType:2:28
3029 * BirthDate + SurveyOrPhoneField + SurveyOnlyField Individual,Activity\0ActivityType:2:28
3030 * BirthDate + StudentField + Subject + SurveyOnlyField Individual,Activity,Student\0ActivityType:28
3031 *
1fd63589
EM
3032 * @param $gId
3033 * @param Array $groupTypes With key having group type names
6a488035 3034 *
1fd63589 3035 * @internal param int $gid profile id
6a488035
TO
3036 * @return Boolean
3037 */
3038 static function updateGroupTypes($gId, $groupTypes = array(
3039 )) {
3040 if (!is_array($groupTypes) || !$gId) {
3041 return FALSE;
3042 }
3043
3044 // If empty group types set group_type as 'null'
3045 if (empty($groupTypes)) {
3046 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $gId, 'group_type', 'null');
3047 }
3048
1cb28d5d 3049 $componentGroupTypes = array('Contribution', 'Participant', 'Membership', 'Activity', 'Case');
6a488035
TO
3050 $validGroupTypes = array_merge(array('Contact', 'Individual', 'Organization', 'Household'), $componentGroupTypes, CRM_Contact_BAO_ContactType::subTypes());
3051
3052 $gTypes = $gTypeValues = array();
3053
3054 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
3055 // Get valid group type and group subtypes
3056 foreach ($groupTypes as $groupType => $value) {
3057 if (in_array($groupType, $validGroupTypes) && !in_array($groupType, $gTypes)) {
3058 $gTypes[] = $groupType;
3059 }
3060
3061 $subTypesOf = NULL;
3062
3063 if (in_array($groupType, $participantExtends)) {
3064 $subTypesOf = $groupType;
3065 }
3066 elseif (strpos($groupType, 'Type') > 0) {
3067 $subTypesOf = substr($groupType, 0, strpos($groupType, 'Type'));
3068 }
3069 else {
3070 continue;
3071 }
3072
3073 if (!empty($value) &&
3074 (in_array($subTypesOf, $componentGroupTypes) ||
3075 in_array($subTypesOf, $participantExtends)
3076 )
3077 ) {
3078 $gTypeValues[$subTypesOf] = $groupType . ":" . implode(':', $value);
3079 }
3080 }
3081
3082 if (empty($gTypes)) {
3083 return FALSE;
3084 }
3085
3086 // Build String to store group types and group subtypes
3087 $groupTypeString = implode(',', $gTypes);
3088 if (!empty($gTypeValues)) {
3089 $groupTypeString .= CRM_Core_DAO::VALUE_SEPARATOR . implode(',', $gTypeValues);
3090 }
3091
3092 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $gId, 'group_type', $groupTypeString);
3093 }
3094
3095 /**
3096 * Create a "group_type" string
3097 *
3098 * @param array $coreTypes e.g. array('Individual','Contact','Student')
3099 * @param array $subTypes e.g. array('ActivityType' => array(7, 11))
3100 * @param string $delim
1fd63589
EM
3101 *
3102 * @return string
6a488035
TO
3103 * @throws CRM_Core_Exception
3104 */
3105 static function encodeGroupType($coreTypes, $subTypes, $delim = CRM_Core_DAO::VALUE_SEPARATOR) {
3106 $groupTypeExpr = '';
3107 if ($coreTypes) {
3108 $groupTypeExpr .= implode(',', $coreTypes);
3109 }
3110 if ($subTypes) {
99e239bc 3111 //CRM-15427 Allow Multiple subtype filtering
3112 //if (count($subTypes) > 1) {
3113 //throw new CRM_Core_Exception("Multiple subtype filtering is not currently supported by widget.");
3114 //}
6a488035
TO
3115 foreach ($subTypes as $subType => $subTypeIds) {
3116 $groupTypeExpr .= $delim . $subType . ':' . implode(':', $subTypeIds);
3117 }
3118 }
3119 return $groupTypeExpr;
3120 }
3121
3122 /**
3123 * This function is used to setDefault componet specific profile fields.
3124 *
1fd63589
EM
3125 * @param array $fields profile fields.
3126 * @param int $componentId componetID
3127 * @param string $component component name
3128 * @param array $defaults an array of default values.
3129 *
3130 * @param bool $isStandalone
6a488035
TO
3131 *
3132 * @return void.
3133 */
f0385140 3134 public static function setComponentDefaults(&$fields, $componentId, $component, &$defaults, $isStandalone = FALSE) {
6a488035
TO
3135 if (!$componentId ||
3136 !in_array($component, array('Contribute', 'Membership', 'Event', 'Activity'))
3137 ) {
3138 return;
3139 }
3140
3141 $componentBAO = $componentSubType = NULL;
3142 switch ($component) {
3143 case 'Membership':
3144 $componentBAO = 'CRM_Member_BAO_Membership';
3145 $componentBAOName = 'Membership';
3146 $componentSubType = array('membership_type_id');
3147 break;
3148
3149 case 'Contribute':
3150 $componentBAO = 'CRM_Contribute_BAO_Contribution';
3151 $componentBAOName = 'Contribution';
3152 $componentSubType = array( 'financial_type_id' );
3153 break;
3154
3155 case 'Event':
3156 $componentBAO = 'CRM_Event_BAO_Participant';
3157 $componentBAOName = 'Participant';
d623de42 3158 $componentSubType = array('role_id', 'event_id', 'event_type_id');
6a488035
TO
3159 break;
3160
3161 case 'Activity':
3162 $componentBAO = 'CRM_Activity_BAO_Activity';
3163 $componentBAOName = 'Activity';
3164 $componentSubType = array('activity_type_id');
3165 break;
3166 }
3167
3168 $values = array();
3169 $params = array('id' => $componentId);
3170
3171 //get the component values.
3172 CRM_Core_DAO::commonRetrieve($componentBAO, $params, $values);
d623de42
M
3173 if ($componentBAOName == 'Participant') {
3174 $values += array('event_type_id' => CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $values['event_id'], 'event_type_id'));
3175 }
6a488035
TO
3176
3177 $formattedGroupTree = array();
3178 $dateTimeFields = array('participant_register_date', 'activity_date_time', 'receive_date', 'receipt_date', 'cancel_date', 'thankyou_date', 'membership_start_date', 'membership_end_date', 'join_date');
3179 foreach ($fields as $name => $field) {
3180 $fldName = $isStandalone ? $name : "field[$componentId][$name]";
3181 if (in_array($name, $dateTimeFields)) {
3182 $timefldName = $isStandalone ? "{$name}_time" : "field[$componentId][{$name}_time]";
a7488080 3183 if (!empty($values[$name])) {
6a488035
TO
3184 list($defaults[$fldName], $defaults[$timefldName]) = CRM_Utils_Date::setDateDefaults($values[$name]);
3185 }
3186 }
3187 elseif (array_key_exists($name, $values)) {
3188 $defaults[$fldName] = $values[$name];
3189 }
3190 elseif ($name == 'participant_note') {
3191 $noteDetails = CRM_Core_BAO_Note::getNote($componentId, 'civicrm_participant');
3192 $defaults[$fldName] = array_pop($noteDetails);
3193 }
3194 elseif (in_array($name, array(
3195 'financial_type', 'payment_instrument', 'participant_status', 'participant_role'))) {
3196 $defaults[$fldName] = $values["{$name}_id"];
3197 }
3198 elseif ($name == 'membership_type') {
3199 // since membership_type field is a hierselect -
3200 $defaults[$fldName][0] =
3201 CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType',$values['membership_type_id'],'member_of_contact_id','id');
3202 $defaults[$fldName][1] = $values['membership_type_id'];
3203 }
3204 elseif ($name == 'membership_status') {
3205 $defaults[$fldName] = $values['status_id'];
3206 }
3207 elseif ($customFieldInfo = CRM_Core_BAO_CustomField::getKeyID($name, TRUE)) {
3208 if (empty($formattedGroupTree)) {
3209 //get the groupTree as per subTypes.
3210 $groupTree = array();
3211 foreach ($componentSubType as $subType) {
3212 $subTree = CRM_Core_BAO_CustomGroup::getTree($componentBAOName, CRM_Core_DAO::$_nullObject,
3213 $componentId, 0, $values[$subType]
3214 );
3215 $groupTree = CRM_Utils_Array::crmArrayMerge($groupTree, $subTree);
3216 }
3217 $formattedGroupTree = CRM_Core_BAO_CustomGroup::formatGroupTree($groupTree, 1, CRM_Core_DAO::$_nullObject);
3218 CRM_Core_BAO_CustomGroup::setDefaults($formattedGroupTree, $defaults);
3219 }
3220
3221 //FIX ME: We need to loop defaults, but once we move to custom_1_x convention this code can be simplified.
3222 foreach ($defaults as $customKey => $customValue) {
3223 if ($customFieldDetails = CRM_Core_BAO_CustomField::getKeyID($customKey, TRUE)) {
3224 if ($name == 'custom_' . $customFieldDetails[0]) {
3225
3226 //hack to set default for checkbox
3227 //basically this is for weired field name like field[33][custom_19]
3228 //we are converting this field name to array structure and assign value.
3229 $skipValue = FALSE;
3230
3231 foreach ($formattedGroupTree as $tree) {
d623de42
M
3232 if (!empty($tree['fields'][$customFieldDetails[0]])) {
3233 if ('CheckBox' == CRM_Utils_Array::value('html_type', $tree['fields'][$customFieldDetails[0]])) {
3234 $skipValue = TRUE;
3235 $defaults['field'][$componentId][$name] = $customValue;
3236 break;
3237 }
3238 elseif (CRM_Utils_Array::value('data_type', $tree['fields'][$customFieldDetails[0]]) == 'Date') {
3239 $skipValue = TRUE;
6a488035 3240
d623de42
M
3241 // CRM-6681, $default contains formatted date, time values.
3242 $defaults[$fldName] = $customValue;
3243 if (!empty($defaults[$customKey . '_time'])) {
3244 $defaults['field'][$componentId][$name . '_time'] = $defaults[$customKey . '_time'];
3245 }
6a488035
TO
3246 }
3247 }
3248 }
3249
3250 if (!$skipValue || $isStandalone) {
3251 $defaults[$fldName] = $customValue;
3252 }
3253 unset($defaults[$customKey]);
3254 break;
3255 }
3256 }
3257 }
3258 }
3259 }
3260 }
3261
79ae07d9
CW
3262 /**
3263 * @param array|string $profiles - name of profile(s) to create links for
3264 * @param array $appendProfiles - name of profile(s) to append to each link
1fd63589
EM
3265 *
3266 * @return array
79ae07d9 3267 */
a4799f04
CW
3268 static function getCreateLinks($profiles = '', $appendProfiles = array()) {
3269 // Default to contact profiles
3270 if (!$profiles) {
3271 $profiles = array('new_individual', 'new_organization', 'new_household');
3272 }
79ae07d9 3273 $profiles = (array) $profiles;
1a90e0dd 3274 $toGet = array_merge($profiles, (array) $appendProfiles);
79ae07d9
CW
3275 $retrieved = civicrm_api3('uf_group', 'get', array(
3276 'name' => array('IN' => $toGet),
3277 'is_active' => 1,
3278 ));
3279 $links = $append = array();
3280 if (!empty($retrieved['values'])) {
3281 foreach($retrieved['values'] as $id => $profile) {
3282 if (in_array($profile['name'], $profiles)) {
3283 $links[] = array(
3284 'label' => $profile['title'],
a4799f04 3285 'url' => CRM_Utils_System::url('civicrm/profile/create', "reset=1&context=dialog&gid=$id",
486af1e3 3286 NULL, NULL, FALSE, FALSE, TRUE) ,
a4799f04 3287 'type' => ucfirst(str_replace('new_', '', $profile['name'])),
79ae07d9
CW
3288 );
3289 }
3290 else {
3291 $append[] = $id;
3292 }
3293 }
3294 foreach ($append as $id) {
3295 foreach ($links as &$link) {
3296 $link['url'] .= ",$id";
3297 }
3298 }
3299 }
3300 return $links;
3301 }
3302
6a488035
TO
3303 /**
3304 * Function to retrieve groups of profiles
3305 *
3306 * @param integer $profileID id of the profile
3307 *
3308 * @return array returns array
3309 * @static
3310 */
3311 static function profileGroups($profileID) {
3312 $groupTypes = array();
3313 $profileTypes = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $profileID, 'group_type');
3314 if ($profileTypes) {
3315 $groupTypeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $profileTypes);
3316 $groupTypes = explode(',', $groupTypeParts[0]);
3317 }
3318 return $groupTypes;
3319 }
3320
3321 /**
3322 * Function to alter contact params by filtering existing subscribed groups and returns
3323 * unsubscribed groups array for subscription.
3324 *
3325 * @param array $params contact params
3326 * @param int $contactId user contact id
3327 *
3328 * @return array $subscribeGroupIds This contains array of groups for subscription
3329 */
3330 static function getDoubleOptInGroupIds(&$params, $contactId = NULL) {
3331 $config = CRM_Core_Config::singleton();
3332 $subscribeGroupIds = array();
3333
3334 // process further only if profileDoubleOptIn enabled and if groups exist
3335 if (!array_key_exists('group', $params) ||
3336 !self::isProfileDoubleOptin() ||
3337 CRM_Utils_System::isNull($params['group'])
3338 ) {
3339 return $subscribeGroupIds;
3340 }
3341
3342 //check if contact email exist.
3343 $hasEmails = FALSE;
3344 foreach ($params as $name => $value) {
3345 if (strpos($name, 'email-') !== FALSE) {
3346 $hasEmails = TRUE;
3347 break;
3348 }
3349 }
3350
3351 //Proceed furthur only if email present
3352 if (!$hasEmails) {
3353 return $subscribeGroupIds;
3354 }
3355
3356 //do check for already subscriptions.
3357 $contactGroups = array();
3358 if ($contactId) {
3359 $query = "
3360SELECT group_id
3361 FROM civicrm_group_contact
3362 WHERE status = 'Added'
3363 AND contact_id = %1";
3364
3365 $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($contactId, 'Integer')));
3366 while ($dao->fetch()) {
3367 $contactGroups[$dao->group_id] = $dao->group_id;
3368 }
3369 }
3370
3371 //since we don't have names, compare w/ label.
3372 $mailingListGroupType = array_search('Mailing List', CRM_Core_OptionGroup::values('group_type'));
3373
3374 //actual processing start.
3375 foreach ($params['group'] as $groupId => $isSelected) {
3376 //unset group those are not selected.
3377 if (!$isSelected) {
3378 unset($params['group'][$groupId]);
3379 continue;
3380 }
3381
3382 $groupTypes = explode(CRM_Core_DAO::VALUE_SEPARATOR,
3383 CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $groupId, 'group_type', 'id')
3384 );
3385 //get only mailing type group and unset it from params
3386 if (in_array($mailingListGroupType, $groupTypes) && !in_array($groupId, $contactGroups)) {
3387 $subscribeGroupIds[$groupId] = $groupId;
3388 unset($params['group'][$groupId]);
3389 }
3390 }
3391
3392 return $subscribeGroupIds;
3393 }
3394
3395 /**
3396 * Function to check if we are rendering mixed profiles
3397 *
3398 * @param array $profileIds associated array of profile ids
3399 *
3400 * @return boolean $mixProfile true if profile is mixed
3401 * @static
3402 * @access public
3403 */
3404 static function checkForMixProfiles($profileIds) {
3405 $mixProfile = FALSE;
3406
3407 $contactTypes = array('Individual', 'Household', 'Organization');
3408 $subTypes = CRM_Contact_BAO_ContactType::subTypes();
3409
3410 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
3411
3412 $typeCount = array('ctype' => array(), 'subtype' => array());
3413 foreach ($profileIds as $gid) {
3414 $profileType = CRM_Core_BAO_UFField::getProfileType($gid);
3415 // ignore profile of type Contact
3416 if ($profileType == 'Contact') {
3417 continue;
3418 }
3419 if (in_array($profileType, $contactTypes)) {
3420 if (!isset($typeCount['ctype'][$profileType])) {
3421 $typeCount['ctype'][$profileType] = 1;
3422 }
3423
3424 // check if we are rendering profile of different contact types
3425 if (count($typeCount['ctype']) == 2) {
3426 $mixProfile = TRUE;
3427 break;
3428 }
3429 }
3430 elseif (in_array($profileType, $components)) {
3431 $mixProfile = TRUE;
3432 break;
3433 }
3434 else {
3435 if (!isset($typeCount['subtype'][$profileType])) {
3436 $typeCount['subtype'][$profileType] = 1;
3437 }
3438 // check if we are rendering profile of different contact sub types
3439 if (count($typeCount['subtype']) == 2) {
3440 $mixProfile = TRUE;
3441 break;
3442 }
3443 }
3444 }
3445 return $mixProfile;
3446 }
3447
3448 /**
da3c7979 3449 * Function to determine of we show overlay profile or not
6a488035
TO
3450 *
3451 * @return boolean true if profile should be shown else false
3452 * @static
3453 * @access public
3454 */
3455 static function showOverlayProfile() {
3456 $showOverlay = TRUE;
3457
3458 // get the id of overlay profile
3459 $overlayProfileId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', 'summary_overlay', 'id', 'name');
3460 $query = "SELECT count(id) FROM civicrm_uf_field WHERE uf_group_id = {$overlayProfileId} AND visibility IN ('Public Pages', 'Public Pages and Listings') ";
3461
3462 $count = CRM_Core_DAO::singleValueQuery($query);
3463
3464 //check if there are no public fields and use is anonymous
3465 $session = CRM_Core_Session::singleton();
3466 if (!$count && !$session->get('userID')) {
3467 $showOverlay = FALSE;
3468 }
3469
3470 return $showOverlay;
3471 }
3472
3473 /**
3474 * function to get group type values of the profile
3475 *
3476 * @params Integer $profileId Profile Id
3477 * @params String $groupType Group Type
3478 *
1fd63589
EM
3479 * @param $profileId
3480 * @param null $groupType
3481 *
6a488035
TO
3482 * @return Array group type values
3483 * @static
3484 * @access public
3485 */
3486 static function groupTypeValues($profileId, $groupType = NULL) {
3487 $groupTypeValue = array();
3488 $groupTypes = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $profileId, 'group_type');
3489
3490 $groupTypeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $groupTypes);
a7488080 3491 if (empty($groupTypeParts[1])) {
6a488035
TO
3492 return $groupTypeValue;
3493 }
3494 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
3495
3496 foreach (explode(',', $groupTypeParts[1]) as $groupTypeValues) {
3497 $values = array();
3498 $valueParts = explode(':', $groupTypeValues);
3499 if ($groupType &&
3500 ($valueParts[0] != "{$groupType}Type" ||
3501 ($groupType == 'Participant' &&
3502 !in_array($valueParts[0], $participantExtends)
3503 )
3504 )
3505 ) {
3506 continue;
3507 }
3508 foreach ($valueParts as $val) {
3509 if (CRM_Utils_Rule::integer($val)) {
3510 $values[$val] = $val;
3511 }
3512 }
3513 if (!empty($values)) {
3514 $typeName = substr($valueParts[0], 0, -4);
3515 if (in_array($valueParts[0], $participantExtends)) {
3516 $typeName = $valueParts[0];
3517 }
3518 $groupTypeValue[$typeName] = $values;
3519 }
3520 }
3521
3522 return $groupTypeValue;
3523 }
3524
b5c2afd0
EM
3525 /**
3526 * @return bool|object
3527 */
6a488035
TO
3528 static function isProfileDoubleOptin() {
3529 // check for double optin
3530 $config = CRM_Core_Config::singleton();
3531 if (in_array('CiviMail', $config->enableComponents)) {
3532 return CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
3533 'profile_double_optin', NULL, FALSE
3534 );
3535 }
3536 return FALSE;
3537 }
3538
b5c2afd0
EM
3539 /**
3540 * @return bool|object
3541 */
6a488035
TO
3542 static function isProfileAddToGroupDoubleOptin() {
3543 // check for add to group double optin
3544 $config = CRM_Core_Config::singleton();
3545 if (in_array('CiviMail', $config->enableComponents)) {
3546 return CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
3547 'profile_add_to_group_double_optin', NULL, FALSE
3548 );
3549 }
3550 return FALSE;
3551 }
3552
3553 /**
3554 * get profiles used for batch entry
3555 *
3556 * @return array profileIds profile ids
3557 * @static
3558 */
3559 static function getBatchProfiles() {
3560 $query = "SELECT id
3561 FROM civicrm_uf_group
3562 WHERE name IN ('contribution_batch_entry', 'membership_batch_entry')";
3563 $dao = CRM_Core_DAO::executeQuery( $query );
3564 $profileIds = array();
3565 while( $dao->fetch() ) {
3566 $profileIds[$dao->id] = $dao->id;
3567 }
3568 return $profileIds;
3569 }
3570
1fd63589
EM
3571 /**
3572 * @todo what do I do?
3573 * @param $source
3574 * @param $destination
3575 * @param bool $returnMultiSummaryFields
3576 *
3577 * @return array|null
3578 */
6a488035
TO
3579 static function shiftMultiRecordFields(&$source, &$destination, $returnMultiSummaryFields = FALSE) {
3580 $multiSummaryFields = $returnMultiSummaryFields ? array( ) : NULL;
3581 foreach ($source as $field => $properties) {
3582 if (!CRM_Core_BAO_CustomField::getKeyID($field)) {
3583 continue;
3584 }
3585 if (CRM_Core_BAO_CustomField::isMultiRecordField($field)) {
3586 $destination[$field] = $properties;
3587 if ($returnMultiSummaryFields) {
3588 if ($properties['is_multi_summary']) {
3589 $multiSummaryFields[$field] = $properties;
3590 }
3591 }
3592 unset($source[$field]);
3593 }
3594 }
3595 return $multiSummaryFields;
3596 }
3597
3598 /**
3599 * This is function is used to format pseudo fields
3600 *
3601 * @param array $fields associated array of profile fields
3602 *
3603 * @static
3604 */
3605 static function reformatProfileFields(&$fields) {
3606 //reformat fields array
3607 foreach ($fields as $name => $field) {
3608 //reformat phone and extension field
3609 if ( substr($field['name'], 0, 13) == 'phone_and_ext') {
3610 $fieldSuffix = str_replace('phone_and_ext-', '', $field['name']);
3611
3612 // retain existing element properties and just update and replace key
3613 CRM_Utils_Array::crmReplaceKey($fields, $name, "phone-{$fieldSuffix}");
3614 $fields["phone-{$fieldSuffix}"]['name'] = "phone-{$fieldSuffix}";
3615 $fields["phone-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone';
3616
3617 // add additional phone extension field
3618 $fields["phone_ext-{$fieldSuffix}"] = $field;
3619 $fields["phone_ext-{$fieldSuffix}"]['title'] = $field['title'] .' - '.ts('Ext.');
3620 $fields["phone_ext-{$fieldSuffix}"]['name'] = "phone_ext-{$fieldSuffix}";
3621 $fields["phone_ext-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone_ext';
3622 $fields["phone_ext-{$fieldSuffix}"]['skipDisplay'] = 1;
3623 //ignore required for extension field
3624 $fields["phone_ext-{$fieldSuffix}"]['is_required'] = 0;
3625 }
3626 }
3627 }
3628}