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