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