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