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