CRM-12328 switched references to group object for add_to_group_id and add_captcha.
[civicrm-core.git] / CRM / Core / BAO / UFGroup.php
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 */
39 class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup {
40 CONST PUBLIC_VISIBILITY = 1,
41 ADMIN_VISIBILITY = 2,
42 LISTINGS_VISIBILITY = 4;
43
44 /**
45 * cache the match clause used in this transaction
46 *
47 * @var string
48 */
49 static $_matchFields = NULL;
50
51 /**
52 * Takes a bunch of params that are needed to match certain criteria and
53 * retrieves the relevant objects. Typically the valid params are only
54 * contact_id. We'll tweak this function to be more full featured over a period
55 * of time. This is the inverse function of create. It also stores all the retrieved
56 * values in the default array
57 *
58 * @param array $params (reference) an assoc array of name/value pairs
59 * @param array $defaults (reference) an assoc array to hold the flattened values
60 *
61 * @return object CRM_Core_DAO_UFGroup object
62 * @access public
63 * @static
64 */
65 static function retrieve(&$params, &$defaults) {
66 return CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_UFGroup', $params, $defaults);
67 }
68
69 /**
70 * Retrieve the first non-generic contact type
71 *
72 * @param int $id id of uf_group
73 *
74 * @return string contact type
75 */
76 static function getContactType($id) {
77
78 $validTypes = array_filter(array_keys(CRM_Core_SelectValues::contactType()));
79 $validSubTypes = CRM_Contact_BAO_ContactType::subTypeInfo();
80
81 $typesParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $id, 'group_type'));
82 $types = explode(',', $typesParts[0]);
83
84 $cType = NULL;
85 foreach ($types as $type) {
86 if (in_array($type, $validTypes)) {
87 $cType = $type;
88 }
89 elseif (array_key_exists($type, $validSubTypes)) {
90 $cType = CRM_Utils_Array::value('parent', $validSubTypes[$type]);
91 }
92 if ($cType)
93 break;
94 }
95
96 return $cType;
97 }
98
99 /**
100 * Get the form title.
101 *
102 * @param int $id id of uf_form
103 *
104 * @return string title
105 *
106 * @access public
107 * @static
108 *
109 */
110 public static function getTitle($id) {
111 return CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $id, 'title');
112 }
113
114 /**
115 * update the is_active flag in the db
116 *
117 * @param int $id id of the database record
118 * @param boolean $is_active value we want to set the is_active field
119 *
120 * @return Object CRM_Core_DAO_UFGroup object on success, null otherwise
121 * @access public
122 * @static
123 */
124 static function setIsActive($id, $is_active) {
125 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $id, 'is_active', $is_active);
126 }
127
128 /**
129 * get all the registration fields
130 *
131 * @param int $action what action are we doing
132 * @param int $mode mode
133 *
134 * @return array the fields that are needed for registration
135 * @static
136 * @access public
137 */
138 static function getRegistrationFields($action, $mode, $ctype = NULL) {
139 if ($mode & CRM_Profile_Form::MODE_REGISTER) {
140 $ufGroups = CRM_Core_BAO_UFGroup::getModuleUFGroup('User Registration');
141 }
142 else {
143 $ufGroups = CRM_Core_BAO_UFGroup::getModuleUFGroup('Profile');
144 }
145
146 if (!is_array($ufGroups)) {
147 return FALSE;
148 }
149
150 $fields = array();
151
152 foreach ($ufGroups as $id => $title) {
153 if ($ctype) {
154 $fieldType = CRM_Core_BAO_UFField::getProfileType($id);
155 if (($fieldType != 'Contact') &&
156 ($fieldType != $ctype) &&
157 !CRM_Contact_BAO_ContactType::isExtendsContactType($fieldType, $ctype)
158 ) {
159 continue;
160 }
161 if (CRM_Contact_BAO_ContactType::isaSubType($fieldType)) {
162 $profileSubType = $fieldType;
163 }
164 }
165
166 $subset = self::getFields($id, TRUE, $action,
167 NULL, NULL, FALSE, NULL, TRUE, $ctype
168 );
169
170 // we do not allow duplicates. the first field is the winner
171 foreach ($subset as $name => $field) {
172 if (!CRM_Utils_Array::value($name, $fields)) {
173 $fields[$name] = $field;
174 }
175 }
176 }
177
178 return $fields;
179 }
180
181 /**
182 * get all the listing fields
183 *
184 * @param int $action what action are we doing
185 * @param int $visibility visibility of fields we are interested in
186 * @param bool $considerSelector whether to consider the in_selector parameter
187 * @param array $ufGroupIds
188 * @param boolean $searchable
189 *
190 * @return array the fields that are listings related
191 * @static
192 * @access public
193 */
194 static function getListingFields(
195 $action,
196 $visibility,
197 $considerSelector = FALSE,
198 $ufGroupIds = NULL,
199 $searchable = NULL,
200 $restrict = NULL,
201 $skipPermission = FALSE,
202 $permissionType = CRM_Core_Permission::SEARCH
203 ) {
204 if ($ufGroupIds) {
205 $subset = self::getFields($ufGroupIds, FALSE, $action,
206 $visibility, $searchable,
207 FALSE, $restrict,
208 $skipPermission,
209 NULL,
210 $permissionType
211 );
212 if ($considerSelector) {
213 // drop the fields not meant for the selector
214 foreach ($subset as $name => $field) {
215 if (!$field['in_selector']) {
216 unset($subset[$name]);
217 }
218 }
219 }
220 $fields = $subset;
221 }
222 else {
223 $ufGroups = CRM_Core_PseudoConstant::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,
450 'groupName' => $group->name,
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,
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,
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 = "
1442 UPDATE civicrm_uf_join
1443 SET weight = %1
1444 WHERE uf_group_id = %2
1445 AND ( 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();
1834 $gender = CRM_Core_PseudoConstant::gender();
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') {
2021 $form->add('select', $name, $title,
2022 array(
2023 '' => ts('- select -')) + CRM_Contribute_PseudoConstant::contributionStatus(), $required
2024 );
2025 }
2026 elseif ($fieldName == 'currency') {
2027 $form->addCurrency($name, $title, $required);
2028 }
2029 elseif ($fieldName == 'contribution_page_id') {
2030 $form->add('select', $name, $title,
2031 array(
2032 '' => ts('- select -')) + CRM_Contribute_PseudoConstant::contributionPage(), $required, 'class="big"'
2033 );
2034 }
2035 elseif ($fieldName == 'participant_register_date') {
2036 $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime'));
2037 }
2038 elseif ($fieldName == 'activity_status_id') {
2039 $form->add('select', $name, $title,
2040 array(
2041 '' => ts('- select -')) + CRM_Core_PseudoConstant::activityStatus(), $required
2042 );
2043 }
2044 elseif ($fieldName == 'activity_engagement_level') {
2045 $form->add('select', $name, $title,
2046 array(
2047 '' => ts('- select -')) + CRM_Campaign_PseudoConstant::engagementLevel(), $required
2048 );
2049 }
2050 elseif ($fieldName == 'activity_date_time') {
2051 $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime'));
2052 }
2053 elseif ($fieldName == 'participant_status') {
2054 $cond = NULL;
2055 if ($online == TRUE) {
2056 $cond = 'visibility_id = 1';
2057 }
2058 $form->add('select', $name, $title,
2059 array(
2060 '' => ts('- select -')) + CRM_Event_PseudoConstant::participantStatus(NULL, $cond, 'label'), $required
2061 );
2062 }
2063 elseif ($fieldName == 'participant_role') {
2064 if (CRM_Utils_Array::value('is_multiple', $field)) {
2065 $form->addCheckBox($name, $title, CRM_Event_PseudoConstant::participantRole(), NULL, NULL, NULL, NULL, '&nbsp', TRUE);
2066 }
2067 else {
2068 $form->add('select', $name, $title,
2069 array(
2070 '' => ts('- select -')) + CRM_Event_PseudoConstant::participantRole(), $required
2071 );
2072 }
2073 }
2074 elseif ($fieldName == 'world_region') {
2075 $form->add('select', $name, $title,
2076 array(
2077 '' => ts('- select -')) + CRM_Core_PseudoConstant::worldRegion(), $required
2078 );
2079 }
2080 elseif ($fieldName == 'signature_html') {
2081 $form->addWysiwyg($name, $title, CRM_Core_DAO::getAttribute('CRM_Core_DAO_Email', $fieldName));
2082 }
2083 elseif ($fieldName == 'signature_text') {
2084 $form->add('textarea', $name, $title, CRM_Core_DAO::getAttribute('CRM_Core_DAO_Email', $fieldName));
2085 }
2086 elseif (substr($fieldName, -11) == 'campaign_id') {
2087 if (CRM_Campaign_BAO_Campaign::isCampaignEnable()) {
2088 $campaigns = CRM_Campaign_BAO_Campaign::getCampaigns(CRM_Utils_Array::value($contactId,
2089 $form->_componentCampaigns
2090 ));
2091 $form->add('select', $name, $title,
2092 array(
2093 '' => ts('- select -')) + $campaigns, $required, 'class="big"'
2094 );
2095 }
2096 }
2097 elseif ($fieldName == 'activity_details') {
2098 $form->addWysiwyg($fieldName, $title, array('rows' => 4, 'cols' => 60), $required);
2099 }
2100 elseif ($fieldName == 'activity_duration') {
2101 $form->add('text', $name, $title, $attributes, $required);
2102 $form->addRule($name, ts('Please enter the duration as number of minutes (integers only).'), 'positiveInteger');
2103 }
2104 else {
2105 if (substr($fieldName, 0, 3) === 'is_' or substr($fieldName, 0, 7) === 'do_not_') {
2106 $form->add('advcheckbox', $name, $title, $attributes, $required);
2107 }
2108 else {
2109 $form->add('text', $name, $title, $attributes, $required);
2110 }
2111 }
2112
2113 static $hiddenSubtype = FALSE;
2114 if (!$hiddenSubtype && CRM_Contact_BAO_ContactType::isaSubType($field['field_type'])) {
2115 // In registration mode params are submitted via POST and we don't have any clue
2116 // about profile-id or the profile-type (which could be a subtype)
2117 // To generalize the behavior and simplify the process,
2118 // lets always add the hidden
2119 //subtype value if there is any, and we won't have to
2120 // compute it while processing.
2121 if ($onBehalf) {
2122 $form->addElement('hidden', 'onbehalf[contact_sub_type]', $field['field_type']);
2123 }
2124 else {
2125 $form->addElement('hidden', 'contact_sub_type_hidden', $field['field_type']);
2126 }
2127 $hiddenSubtype = TRUE;
2128 }
2129
2130 if (($view && $mode != CRM_Profile_Form::MODE_SEARCH) || $isShared) {
2131 $form->freeze($name);
2132 }
2133
2134 //add the rules
2135 if (in_array($fieldName, array(
2136 'non_deductible_amount', 'total_amount', 'fee_amount', 'net_amount'))) {
2137 $form->addRule($name, ts('Please enter a valid amount.'), 'money');
2138 }
2139
2140 if ($rule) {
2141 if (!($rule == 'email' && $mode == CRM_Profile_Form::MODE_SEARCH)) {
2142 $form->addRule($name, ts('Please enter a valid %1', array(1 => $title)), $rule);
2143 }
2144 }
2145 }
2146
2147 /**
2148 * Function to set profile defaults
2149 *
2150 * @params int $contactId contact id
2151 * @params array $fields associative array of fields
2152 * @params array $defaults defaults array
2153 * @params boolean $singleProfile true for single profile else false(batch update)
2154 * @params int $componentId id for specific components like contribute, event etc
2155 *
2156 * @return null
2157 * @static
2158 * @access public
2159 */
2160 static function setProfileDefaults($contactId, &$fields, &$defaults,
2161 $singleProfile = TRUE, $componentId = NULL, $component = NULL
2162 ) {
2163 if (!$componentId) {
2164 //get the contact details
2165 list($contactDetails, $options) = CRM_Contact_BAO_Contact::getHierContactDetails($contactId, $fields);
2166 $details = CRM_Utils_Array::value($contactId, $contactDetails);
2167 $multipleFields = array('website' => 'url');
2168
2169 //start of code to set the default values
2170 foreach ($fields as $name => $field) {
2171 // skip pseudo fields
2172 if (substr($name, 0, 9) == 'phone_ext') {
2173 continue;
2174 }
2175
2176 //set the field name depending upon the profile mode(single/batch)
2177 if ($singleProfile) {
2178 $fldName = $name;
2179 }
2180 else {
2181 $fldName = "field[$contactId][$name]";
2182 }
2183
2184 if ($name == 'group') {
2185 CRM_Contact_Form_Edit_TagsAndGroups::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups::GROUP, $fldName);
2186 }
2187 if ($name == 'tag') {
2188 CRM_Contact_Form_Edit_TagsAndGroups::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups::TAG, $fldName);
2189 }
2190
2191 if (CRM_Utils_Array::value($name, $details) || isset($details[$name])) {
2192 //to handle custom data (checkbox) to be written
2193 // to handle gender / suffix / prefix / greeting_type
2194 if ($name == 'gender') {
2195 $defaults[$fldName] = $details['gender_id'];
2196 }
2197 elseif ($name == 'individual_prefix') {
2198 $defaults[$fldName] = $details['individual_prefix_id'];
2199 }
2200 elseif ($name == 'individual_suffix') {
2201 $defaults[$fldName] = $details['individual_suffix_id'];
2202 }
2203 elseif (($name == 'birth_date') || ($name == 'deceased_date')) {
2204 list($defaults[$fldName]) = CRM_Utils_Date::setDateDefaults($details[$name], 'birth');
2205 }
2206 elseif (in_array($name, CRM_Contact_BAO_Contact::$_greetingTypes)) {
2207 $defaults[$fldName] = $details[$name . '_id'];
2208 $defaults[$name . '_custom'] = $details[$name . '_custom'];
2209 }
2210 elseif ($name == 'preferred_communication_method') {
2211 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2212 foreach ($v as $item) {
2213 if ($item) {
2214 $defaults[$fldName . "[$item]"] = 1;
2215 }
2216 }
2217 }
2218 elseif ($name == 'world_region') {
2219 $defaults[$fldName] = $details['worldregion_id'];
2220 }
2221 elseif ($customFieldId = CRM_Core_BAO_CustomField::getKeyID($name)) {
2222 //fix for custom fields
2223 $customFields = CRM_Core_BAO_CustomField::getFields(CRM_Utils_Array::value('contact_type', $details));
2224
2225 // hack to add custom data for components
2226 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
2227 foreach ($components as $value) {
2228 $customFields = CRM_Utils_Array::crmArrayMerge($customFields,
2229 CRM_Core_BAO_CustomField::getFieldsForImport($value)
2230 );
2231 }
2232
2233 switch ($customFields[$customFieldId]['html_type']) {
2234 case 'Multi-Select State/Province':
2235 case 'Multi-Select Country':
2236 case 'AdvMulti-Select':
2237 case 'Multi-Select':
2238 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2239 foreach ($v as $item) {
2240 if ($item) {
2241 $defaults[$fldName][$item] = $item;
2242 }
2243 }
2244 break;
2245
2246 case 'CheckBox':
2247 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2248 foreach ($v as $item) {
2249 if ($item) {
2250 $defaults[$fldName][$item] = 1;
2251 // seems like we need this for QF style checkboxes in profile where its multiindexed
2252 // CRM-2969
2253 $defaults["{$fldName}[{$item}]"] = 1;
2254 }
2255 }
2256 break;
2257
2258 case 'Autocomplete-Select':
2259 if ($customFields[$customFieldId]['data_type'] == 'ContactReference') {
2260 if (is_numeric($details[$name])) {
2261 $defaults[$fldName . '_id'] = $details[$name];
2262 $defaults[$fldName] = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $details[$name], 'sort_name');
2263 }
2264 }
2265 else {
2266 $label = CRM_Core_BAO_CustomOption::getOptionLabel($customFieldId, $details[$name]);
2267 $defaults[$fldName . '_id'] = $details[$name];
2268 $defaults[$fldName] = $label;
2269 }
2270 break;
2271
2272 case 'Select Date':
2273 // CRM-6681, set defult values according to date and time format (if any).
2274 $dateFormat = NULL;
2275 if (CRM_Utils_Array::value('date_format', $field)) {
2276 $dateFormat = $field['date_format'];
2277 }
2278
2279 if (!CRM_Utils_Array::value('time_format', $field)) {
2280 list($defaults[$fldName]) = CRM_Utils_Date::setDateDefaults($details[$name], NULL,
2281 $dateFormat
2282 );
2283 }
2284 else {
2285 $timeElement = $fldName . '_time';
2286 if (substr($fldName, -1) == ']') {
2287 $timeElement = substr($fldName, 0, -1) . '_time]';
2288 }
2289 list($defaults[$fldName], $defaults[$timeElement]) = CRM_Utils_Date::setDateDefaults($details[$name], NULL, $dateFormat, $field['time_format']);
2290 }
2291 break;
2292
2293 default:
2294 $defaults[$fldName] = $details[$name];
2295 break;
2296 }
2297 }
2298 else {
2299 $defaults[$fldName] = $details[$name];
2300 }
2301 }
2302 else {
2303 $blocks = array('email', 'phone', 'im', 'openid');
2304 list($fieldName, $locTypeId, $phoneTypeId) = CRM_Utils_System::explode('-', $name, 3);
2305 if (!in_array($fieldName, $multipleFields)) {
2306 if (is_array($details)) {
2307 foreach ($details as $key => $value) {
2308 // when we fixed CRM-5319 - get primary loc
2309 // type as per loc field and removed below code.
2310 $primaryLocationType = FALSE;
2311 if ($locTypeId == 'Primary') {
2312 if (is_array($value) && array_key_exists($fieldName, $value)){
2313 $primaryLocationType = TRUE;
2314 if (in_array($fieldName, $blocks)){
2315 $locTypeId = CRM_Contact_BAO_Contact::getPrimaryLocationType($contactId, FALSE, $fieldName);
2316 }
2317 else{
2318 $locTypeId = CRM_Contact_BAO_Contact::getPrimaryLocationType($contactId, FALSE, 'address');
2319 }
2320 }
2321 }
2322
2323 // fixed for CRM-665
2324 if (is_numeric($locTypeId)) {
2325 if ($primaryLocationType || $locTypeId == CRM_Utils_Array::value('location_type_id', $value)) {
2326 if (CRM_Utils_Array::value($fieldName, $value)) {
2327 //to handle stateprovince and country
2328 if ($fieldName == 'state_province') {
2329 $defaults[$fldName] = $value['state_province_id'];
2330 }
2331 elseif ($fieldName == 'county') {
2332 $defaults[$fldName] = $value['county_id'];
2333 }
2334 elseif ($fieldName == 'country') {
2335 $defaults[$fldName] = $value['country_id'];
2336 if (!isset($value['country_id']) || !$value['country_id']) {
2337 $config = CRM_Core_Config::singleton();
2338 if ($config->defaultContactCountry) {
2339 $defaults[$fldName] = $config->defaultContactCountry;
2340 }
2341 }
2342 }
2343 elseif ($fieldName == 'phone') {
2344 if ($phoneTypeId) {
2345 if (isset($value['phone'][$phoneTypeId])) {
2346 $defaults[$fldName] = $value['phone'][$phoneTypeId];
2347 }
2348 if (isset($value['phone_ext'][$phoneTypeId])) {
2349 $defaults[str_replace('phone', 'phone_ext', $fldName)] = $value['phone_ext'][$phoneTypeId];
2350 }
2351 }
2352 else {
2353 $phoneDefault = CRM_Utils_Array::value('phone', $value);
2354 // CRM-9216
2355 if (!is_array($phoneDefault)) {
2356 $defaults[$fldName] = $phoneDefault;
2357 }
2358 }
2359 }
2360 elseif ($fieldName == 'email') {
2361 //adding the first email (currently we don't support multiple emails of same location type)
2362 $defaults[$fldName] = $value['email'];
2363 }
2364 elseif ($fieldName == 'im') {
2365 //adding the first im (currently we don't support multiple ims of same location type)
2366 $defaults[$fldName] = $value['im'];
2367 $defaults[$fldName . '-provider_id'] = $value['im_provider_id'];
2368 }
2369 else {
2370 $defaults[$fldName] = $value[$fieldName];
2371 }
2372 }
2373 elseif (substr($fieldName, 0, 14) === 'address_custom' &&
2374 CRM_Utils_Array::value(substr($fieldName, 8), $value)
2375 ) {
2376 $defaults[$fldName] = $value[substr($fieldName, 8)];
2377 }
2378 }
2379 }
2380 }
2381 }
2382 }
2383 else {
2384 if (is_array($details)) {
2385 if ($fieldName === 'url') {
2386 if (!empty($details['website'])) {
2387 foreach ($details['website'] as $val) {
2388 $defaults[$fldName] = CRM_Utils_Array::value('url', $val);
2389 $defaults[$fldName . '-website_type_id'] = $val['website_type_id'];
2390 }
2391 }
2392 }
2393 }
2394 }
2395 }
2396 }
2397 }
2398
2399 //Handling Contribution Part of the batch profile
2400 if (CRM_Core_Permission::access('CiviContribute') && $component == 'Contribute') {
2401 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2402 }
2403
2404 //Handling Event Participation Part of the batch profile
2405 if (CRM_Core_Permission::access('CiviEvent') && $component == 'Event') {
2406 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2407 }
2408
2409 //Handling membership Part of the batch profile
2410 if (CRM_Core_Permission::access('CiviMember') && $component == 'Membership') {
2411 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2412 }
2413
2414 //Handling Activity Part of the batch profile
2415 if ($component == 'Activity') {
2416 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2417 }
2418 }
2419
2420 /**
2421 * Function to get profiles by type eg: pure Individual etc
2422 *
2423 * @param array $types associative array of types eg: types('Individual')
2424 * @param boolean $onlyPure true if only pure profiles are required
2425 *
2426 * @return array $profiles associative array of profiles
2427 * @static
2428 * @access public
2429 */
2430 static function getProfiles($types, $onlyPure = FALSE) {
2431 $profiles = array();
2432 $ufGroups = CRM_Core_PseudoConstant::ufgroup();
2433
2434 CRM_Utils_Hook::aclGroup(CRM_Core_Permission::ADMIN, NULL, 'civicrm_uf_group', $ufGroups, $ufGroups);
2435
2436 // Exclude Batch Data Entry profiles - CRM-10901
2437 $batchProfiles = CRM_Core_BAO_UFGroup::getBatchProfiles();
2438
2439 foreach ($ufGroups as $id => $title) {
2440 $ptype = CRM_Core_BAO_UFField::getProfileType($id, FALSE, $onlyPure);
2441 if (in_array($ptype, $types) && !array_key_exists($id, $batchProfiles)) {
2442 $profiles[$id] = $title;
2443 }
2444 }
2445 return $profiles;
2446 }
2447
2448 /**
2449 * Function to check whether a profile is valid combination of
2450 * required and/or optional profile types
2451 *
2452 * @param array $required array of types those are required
2453 * @param array $optional array of types those are optional
2454 *
2455 * @return array $profiles associative array of profiles
2456 * @static
2457 * @access public
2458 */
2459 static function getValidProfiles($required, $optional = NULL) {
2460 if (!is_array($required) || empty($required)) {
2461 return;
2462 }
2463
2464 $profiles = array();
2465 $ufGroups = CRM_Core_PseudoConstant::ufgroup();
2466
2467 CRM_Utils_Hook::aclGroup(CRM_Core_Permission::ADMIN, NULL, 'civicrm_uf_group', $ufGroups, $ufGroups);
2468
2469 foreach ($ufGroups as $id => $title) {
2470 $type = CRM_Core_BAO_UFField::checkValidProfileType($id, $required, $optional);
2471 if ($type) {
2472 $profiles[$id] = $title;
2473 }
2474 }
2475
2476 return $profiles;
2477 }
2478
2479 /**
2480 * Function to check whether a profile is valid combination of
2481 * required profile fields
2482 *
2483 * @param array $ufId integer id of the profile
2484 * @param array $required array of fields those are required in the profile
2485 *
2486 * @return array $profiles associative array of profiles
2487 * @static
2488 * @access public
2489 */
2490 static function checkValidProfile($ufId, $required = NULL) {
2491 $validProfile = FALSE;
2492 if (!$ufId) {
2493 return $validProfile;
2494 }
2495
2496 if (!CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $ufId, 'is_active')) {
2497 return $validProfile;
2498 }
2499
2500 $profileFields = self::getFields($ufId, FALSE, CRM_Core_Action::VIEW, NULL,
2501 NULL, FALSE, NULL, FALSE, NULL,
2502 CRM_Core_Permission::CREATE, NULL
2503 );
2504
2505 $validProfile = array();
2506 if (!empty($profileFields)) {
2507 $fields = array_keys($profileFields);
2508 foreach ($fields as $val) {
2509 foreach ($required as $key => $field) {
2510 if (strpos($val, $field) === 0) {
2511 unset($required[$key]);
2512 }
2513 }
2514 }
2515
2516 $validProfile = (empty($required)) ? TRUE : FALSE;
2517 }
2518
2519 return $validProfile;
2520 }
2521
2522 /**
2523 * Function to get default value for Register.
2524 *
2525 * @return $defaults
2526 * @static
2527 * @access public
2528 */
2529 static function setRegisterDefaults(&$fields, &$defaults) {
2530 foreach ($fields as $name => $field) {
2531 if (substr($name, 0, 8) == 'country-') {
2532 $config = CRM_Core_Config::singleton();
2533 if ($config->defaultContactCountry) {
2534 $defaults[$name] = $config->defaultContactCountry;
2535 }
2536 }
2537 elseif (substr($name, 0, 15) == 'state_province-') {
2538 if ($config->defaultContactStateProvince) {
2539 $defaults[$name] = $config->defaultContactStateProvince;
2540 }
2541 }
2542 }
2543 return $defaults;
2544 }
2545
2546 /**
2547 * This function is to make a copy of a profile, including
2548 * all the fields in the profile
2549 *
2550 * @param int $id the profile id to copy
2551 *
2552 * @return void
2553 * @access public
2554 */
2555 static function copy($id) {
2556 $fieldsFix = array('prefix' => array('title' => ts('Copy of ')));
2557 $copy = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFGroup',
2558 array('id' => $id),
2559 NULL,
2560 $fieldsFix
2561 );
2562
2563 if ($pos = strrpos($copy->name, "_{$id}")) {
2564 $copy->name = substr_replace($copy->name, '', $pos);
2565 }
2566 $copy->name = CRM_Utils_String::munge($copy->name, '_', 56) . "_{$copy->id}";
2567 $copy->save();
2568
2569 $copyUFJoin = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFJoin',
2570 array('uf_group_id' => $id),
2571 array('uf_group_id' => $copy->id),
2572 NULL,
2573 'entity_table'
2574 );
2575
2576 $copyUFField = &CRM_Core_DAO::copyGeneric('CRM_Core_BAO_UFField',
2577 array('uf_group_id' => $id),
2578 array('uf_group_id' => $copy->id)
2579 );
2580
2581 $maxWeight = CRM_Utils_Weight::getMax('CRM_Core_DAO_UFJoin', NULL, 'weight');
2582
2583 //update the weight
2584 $query = "
2585 UPDATE civicrm_uf_join
2586 SET weight = %1
2587 WHERE uf_group_id = %2
2588 AND ( entity_id IS NULL OR entity_id <= 0 )
2589 ";
2590 $p = array(1 => array($maxWeight + 1, 'Integer'),
2591 2 => array($copy->id, 'Integer'),
2592 );
2593 CRM_Core_DAO::executeQuery($query, $p);
2594 if ($copy->is_reserved) {
2595 $query = "UPDATE civicrm_uf_group SET is_reserved = 0 WHERE id = %1";
2596 $params = array(1 => array($copy->id, 'Integer'));
2597 CRM_Core_DAO::executeQuery($query, $params);
2598 }
2599 CRM_Utils_Hook::copy('UFGroup', $copy);
2600
2601 return $copy;
2602 }
2603
2604 /**
2605 * Process that send notification e-mails
2606 *
2607 * @params int $contactId contact id
2608 * @params array $values associative array of name/value pair
2609 *
2610 * @return void
2611 * @access public
2612 */
2613
2614 static function commonSendMail($contactID, &$values) {
2615 if (!$contactID || !$values) {
2616 return;
2617
2618 }
2619 $template = CRM_Core_Smarty::singleton();
2620
2621 $displayName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
2622 $contactID,
2623 'display_name'
2624 );
2625
2626 self::profileDisplay($values['id'], $values['values'], $template);
2627 $emailList = explode(',', $values['email']);
2628
2629 $contactLink = CRM_Utils_System::url('civicrm/contact/view',
2630 "reset=1&cid=$contactID",
2631 TRUE, NULL, FALSE, FALSE, TRUE
2632 );
2633
2634 //get the default domain email address.
2635 list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail();
2636
2637 if (!$domainEmailAddress || $domainEmailAddress == 'info@EXAMPLE.ORG') {
2638 $fixUrl = CRM_Utils_System::url('civicrm/admin/domain', 'action=update&reset=1');
2639 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)));
2640 }
2641
2642 foreach ($emailList as $emailTo) {
2643 // FIXME: take the below out of the foreach loop
2644 CRM_Core_BAO_MessageTemplates::sendTemplate(
2645 array(
2646 'groupName' => 'msg_tpl_workflow_uf',
2647 'valueName' => 'uf_notify',
2648 'contactId' => $contactID,
2649 'tplParams' => array(
2650 'displayName' => $displayName,
2651 'currentDate' => date('r'),
2652 'contactLink' => $contactLink,
2653 ),
2654 'from' => "$domainEmailName <$domainEmailAddress>",
2655 'toEmail' => $emailTo,
2656 )
2657 );
2658 }
2659 }
2660
2661 /**
2662 * Given a contact id and a group id, returns the field values from the db
2663 * for this group and notify email only if group's notify field is
2664 * set and field values are not empty
2665 *
2666 * @params $gid group id
2667 * @params $cid contact id
2668 * @params $params associative array
2669 *
2670 * @return array
2671 * @access public
2672 */
2673 function checkFieldsEmptyValues($gid, $cid, $params, $skipCheck = FALSE) {
2674 if ($gid) {
2675 if (CRM_Core_BAO_UFGroup::filterUFGroups($gid, $cid) || $skipCheck) {
2676 $values = array();
2677 $fields = CRM_Core_BAO_UFGroup::getFields($gid, FALSE, CRM_Core_Action::VIEW);
2678 CRM_Core_BAO_UFGroup::getValues($cid, $fields, $values, FALSE, $params, TRUE);
2679
2680 $email = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'notify');
2681
2682 if (!empty($values) &&
2683 !empty($email)
2684 ) {
2685 $val = array(
2686 'id' => $gid,
2687 'values' => $values,
2688 'email' => $email,
2689 );
2690 return $val;
2691 }
2692 }
2693 }
2694 return NULL;
2695 }
2696
2697 /**
2698 * Function to assign uf fields to template
2699 *
2700 * @params int $gid group id
2701 * @params array $values associative array of fields
2702 *
2703 * @return void
2704 * @access public
2705 */
2706 function profileDisplay($gid, $values, $template) {
2707 $groupTitle = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'title');
2708 $template->assign('grouptitle', $groupTitle);
2709 if (count($values)) {
2710 $template->assign('values', $values);
2711 }
2712 }
2713
2714 /**
2715 * Format fields for dupe Contact Matching
2716 *
2717 * @param array $params associated array
2718 *
2719 * @return array $data assoicated formatted array
2720 * @access public
2721 * @static
2722 */
2723 static function formatFields($params, $contactId = NULL) {
2724 if ($contactId) {
2725 // get the primary location type id and email
2726 list($name, $primaryEmail, $primaryLocationType) = CRM_Contact_BAO_Contact_Location::getEmailDetails($contactId);
2727 }
2728 else {
2729 $defaultLocationType = CRM_Core_BAO_LocationType::getDefault();
2730 $primaryLocationType = $defaultLocationType->id;
2731 }
2732
2733 $data = array();
2734 $locationType = array();
2735 $count = 1;
2736 $primaryLocation = 0;
2737 foreach ($params as $key => $value) {
2738 list($fieldName, $locTypeId, $phoneTypeId) = explode('-', $key);
2739
2740 if ($locTypeId == 'Primary') {
2741 $locTypeId = $primaryLocationType;
2742 }
2743
2744 if (is_numeric($locTypeId)) {
2745 if (!in_array($locTypeId, $locationType)) {
2746 $locationType[$count] = $locTypeId;
2747 $count++;
2748 }
2749 $loc = CRM_Utils_Array::key($locTypeId, $locationType);
2750
2751 $data['location'][$loc]['location_type_id'] = $locTypeId;
2752
2753 // if we are getting in a new primary email, dont overwrite the new one
2754 if ($locTypeId == $primaryLocationType) {
2755 if (CRM_Utils_Array::value('email-' . $primaryLocationType, $params)) {
2756 $data['location'][$loc]['email'][$loc]['email'] = $fields['email-' . $primaryLocationType];
2757 }
2758 elseif (isset($primaryEmail)) {
2759 $data['location'][$loc]['email'][$loc]['email'] = $primaryEmail;
2760 }
2761 $primaryLocation++;
2762 }
2763
2764 if ($loc == 1) {
2765 $data['location'][$loc]['is_primary'] = 1;
2766 }
2767 if ($fieldName == 'phone') {
2768 if ($phoneTypeId) {
2769 $data['location'][$loc]['phone'][$loc]['phone_type_id'] = $phoneTypeId;
2770 }
2771 else {
2772 $data['location'][$loc]['phone'][$loc]['phone_type_id'] = '';
2773 }
2774 $data['location'][$loc]['phone'][$loc]['phone'] = $value;
2775 }
2776 elseif ($fieldName == 'email') {
2777 $data['location'][$loc]['email'][$loc]['email'] = $value;
2778 }
2779 elseif ($fieldName == 'im') {
2780 $data['location'][$loc]['im'][$loc]['name'] = $value;
2781 }
2782 else {
2783 if ($fieldName === 'state_province') {
2784 $data['location'][$loc]['address']['state_province_id'] = $value;
2785 }
2786 elseif ($fieldName === 'country') {
2787 $data['location'][$loc]['address']['country_id'] = $value;
2788 }
2789 else {
2790 $data['location'][$loc]['address'][$fieldName] = $value;
2791 }
2792 }
2793 }
2794 else {
2795 if ($key === 'individual_suffix') {
2796 $data['suffix_id'] = $value;
2797 }
2798 elseif ($key === 'individual_prefix') {
2799 $data['prefix_id'] = $value;
2800 }
2801 elseif ($key === 'gender') {
2802 $data['gender_id'] = $value;
2803 }
2804 elseif (substr($key, 0, 6) === 'custom') {
2805 if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
2806 //fix checkbox
2807 if ($customFields[$customFieldID]['html_type'] == 'CheckBox') {
2808 $value = implode(CRM_Core_DAO::VALUE_SEPARATOR, array_keys($value));
2809 }
2810 // fix the date field
2811 if ($customFields[$customFieldID]['data_type'] == 'Date') {
2812 $date = CRM_Utils_Date::format($value);
2813 if (!$date) {
2814 $date = '';
2815 }
2816 $value = $date;
2817 }
2818
2819 $data['custom'][$customFieldID] = array(
2820 'id' => $id,
2821 'value' => $value,
2822 'extends' => $customFields[$customFieldID]['extends'],
2823 'type' => $customFields[$customFieldID]['data_type'],
2824 'custom_field_id' => $customFieldID,
2825 );
2826 }
2827 }
2828 elseif ($key == 'edit') {
2829 continue;
2830 }
2831 else {
2832 $data[$key] = $value;
2833 }
2834 }
2835 }
2836
2837 if (!$primaryLocation) {
2838 $loc++;
2839 $data['location'][$loc]['email'][$loc]['email'] = $primaryEmail;
2840 }
2841
2842
2843 return $data;
2844 }
2845
2846 /**
2847 * calculate the profile type 'group_type' as per profile fields.
2848 *
2849 * @param int $gid profile id
2850 * @param int $ignoreFieldId ignore particular profile field
2851 *
2852 * @return array list of calculated group type
2853 */
2854 static function calculateGroupType($gId, $includeTypeValues = FALSE, $ignoreFieldId = NULL) {
2855 //get the profile fields.
2856 $ufFields = self::getFields($gId, FALSE, NULL, NULL, NULL, TRUE, NULL, TRUE);
2857 return self::_calculateGroupType($ufFields, $includeTypeValues, $ignoreFieldId);
2858 }
2859
2860 /**
2861 * calculate the profile type 'group_type' as per profile fields.
2862 *
2863 * @param int $gid profile id
2864 * @param int $ignoreFieldId ignore perticular profile field
2865 *
2866 * @return array list of calculated group type
2867 */
2868 static function _calculateGroupType($ufFields, $includeTypeValues = FALSE, $ignoreFieldId = NULL) {
2869 $groupType = $groupTypeValues = $customFieldIds = array();
2870 if (!empty($ufFields)) {
2871 foreach ($ufFields as $fieldName => $fieldValue) {
2872 //ignore field from group type when provided.
2873 //in case of update profile field.
2874 if ($ignoreFieldId && ($ignoreFieldId == $fieldValue['field_id'])) {
2875 continue;
2876 }
2877 if (!in_array($fieldValue['field_type'], $groupType)) {
2878 $groupType[$fieldValue['field_type']] = $fieldValue['field_type'];
2879 }
2880
2881 if ($includeTypeValues && ($fldId = CRM_Core_BAO_CustomField::getKeyID($fieldName))) {
2882 $customFieldIds[$fldId] = $fldId;
2883 }
2884 }
2885 }
2886
2887 if (!empty($customFieldIds)) {
2888 $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) . ')';
2889
2890 $customGroups = CRM_Core_DAO::executeQuery($query);
2891 while ($customGroups->fetch()) {
2892 if (!$customGroups->extends_entity_column_value) {
2893 continue;
2894 }
2895
2896 $groupTypeName = "{$customGroups->extends}Type";
2897 if ($customGroups->extends == 'Participant' && $customGroups->extends_entity_column_id) {
2898 $groupTypeName = CRM_Core_OptionGroup::getValue('custom_data_type', $customGroups->extends_entity_column_id, 'value', 'String', 'name');
2899 }
2900
2901 foreach (explode(CRM_Core_DAO::VALUE_SEPARATOR, $customGroups->extends_entity_column_value) as $val) {
2902 if ($val) {
2903 $groupTypeValues[$groupTypeName][$val] = $val;
2904 }
2905 }
2906 }
2907
2908 if (!empty($groupTypeValues)) {
2909 $groupType = array_merge($groupType, $groupTypeValues);
2910 }
2911 }
2912
2913 return $groupType;
2914 }
2915
2916 /**
2917 * Update the profile type 'group_type' as per profile fields including group types and group subtype values.
2918 * Build and store string like: group_type1,group_type2[VALUE_SEPERATOR]group_type1Type:1:2:3,group_type2Type:1:2
2919 *
2920 * FIELDS GROUP_TYPE
2921 * BirthDate + Email Individual,Contact
2922 * BirthDate + Subject Individual,Activity
2923 * BirthDate + Subject + SurveyOnlyField Individual,Activity\0ActivityType:28
2924 * BirthDate + Subject + SurveyOnlyField + PhoneOnlyField (Not allowed)
2925 * BirthDate + SurveyOnlyField Individual,Activity\0ActivityType:28
2926 * BirthDate + Subject + SurveyOrPhoneField Individual,Activity\0ActivityType:2:28
2927 * BirthDate + SurveyOrPhoneField Individual,Activity\0ActivityType:2:28
2928 * BirthDate + SurveyOrPhoneField + SurveyOnlyField Individual,Activity\0ActivityType:2:28
2929 * BirthDate + StudentField + Subject + SurveyOnlyField Individual,Activity,Student\0ActivityType:28
2930 *
2931 * @param Integer $gid profile id
2932 * @param Array $groupTypes With key having group type names
2933 *
2934 * @return Boolean
2935 */
2936 static function updateGroupTypes($gId, $groupTypes = array(
2937 )) {
2938 if (!is_array($groupTypes) || !$gId) {
2939 return FALSE;
2940 }
2941
2942 // If empty group types set group_type as 'null'
2943 if (empty($groupTypes)) {
2944 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $gId, 'group_type', 'null');
2945 }
2946
2947 $componentGroupTypes = array('Contribution', 'Participant', 'Membership', 'Activity');
2948 $validGroupTypes = array_merge(array('Contact', 'Individual', 'Organization', 'Household'), $componentGroupTypes, CRM_Contact_BAO_ContactType::subTypes());
2949
2950 $gTypes = $gTypeValues = array();
2951
2952 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
2953 // Get valid group type and group subtypes
2954 foreach ($groupTypes as $groupType => $value) {
2955 if (in_array($groupType, $validGroupTypes) && !in_array($groupType, $gTypes)) {
2956 $gTypes[] = $groupType;
2957 }
2958
2959 $subTypesOf = NULL;
2960
2961 if (in_array($groupType, $participantExtends)) {
2962 $subTypesOf = $groupType;
2963 }
2964 elseif (strpos($groupType, 'Type') > 0) {
2965 $subTypesOf = substr($groupType, 0, strpos($groupType, 'Type'));
2966 }
2967 else {
2968 continue;
2969 }
2970
2971 if (!empty($value) &&
2972 (in_array($subTypesOf, $componentGroupTypes) ||
2973 in_array($subTypesOf, $participantExtends)
2974 )
2975 ) {
2976 $gTypeValues[$subTypesOf] = $groupType . ":" . implode(':', $value);
2977 }
2978 }
2979
2980 if (empty($gTypes)) {
2981 return FALSE;
2982 }
2983
2984 // Build String to store group types and group subtypes
2985 $groupTypeString = implode(',', $gTypes);
2986 if (!empty($gTypeValues)) {
2987 $groupTypeString .= CRM_Core_DAO::VALUE_SEPARATOR . implode(',', $gTypeValues);
2988 }
2989
2990 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $gId, 'group_type', $groupTypeString);
2991 }
2992
2993 /**
2994 * Create a "group_type" string
2995 *
2996 * @param array $coreTypes e.g. array('Individual','Contact','Student')
2997 * @param array $subTypes e.g. array('ActivityType' => array(7, 11))
2998 * @param string $delim
2999 * @throws CRM_Core_Exception
3000 */
3001 static function encodeGroupType($coreTypes, $subTypes, $delim = CRM_Core_DAO::VALUE_SEPARATOR) {
3002 $groupTypeExpr = '';
3003 if ($coreTypes) {
3004 $groupTypeExpr .= implode(',', $coreTypes);
3005 }
3006 if ($subTypes) {
3007 if (count($subTypes) > 1) {
3008 throw new CRM_Core_Exception("Multiple subtype filtering is not currently supported by widget.");
3009 }
3010 foreach ($subTypes as $subType => $subTypeIds) {
3011 $groupTypeExpr .= $delim . $subType . ':' . implode(':', $subTypeIds);
3012 }
3013 }
3014 return $groupTypeExpr;
3015 }
3016
3017 /**
3018 * This function is used to setDefault componet specific profile fields.
3019 *
3020 * @param array $fields profile fields.
3021 * @param int $componentId componetID
3022 * @param string $component component name
3023 * @param array $defaults an array of default values.
3024 *
3025 * @return void.
3026 */
3027 function setComponentDefaults(&$fields, $componentId, $component, &$defaults, $isStandalone = FALSE) {
3028 if (!$componentId ||
3029 !in_array($component, array('Contribute', 'Membership', 'Event', 'Activity'))
3030 ) {
3031 return;
3032 }
3033
3034 $componentBAO = $componentSubType = NULL;
3035 switch ($component) {
3036 case 'Membership':
3037 $componentBAO = 'CRM_Member_BAO_Membership';
3038 $componentBAOName = 'Membership';
3039 $componentSubType = array('membership_type_id');
3040 break;
3041
3042 case 'Contribute':
3043 $componentBAO = 'CRM_Contribute_BAO_Contribution';
3044 $componentBAOName = 'Contribution';
3045 $componentSubType = array( 'financial_type_id' );
3046 break;
3047
3048 case 'Event':
3049 $componentBAO = 'CRM_Event_BAO_Participant';
3050 $componentBAOName = 'Participant';
3051 $componentSubType = array('role_id', 'event_id');
3052 break;
3053
3054 case 'Activity':
3055 $componentBAO = 'CRM_Activity_BAO_Activity';
3056 $componentBAOName = 'Activity';
3057 $componentSubType = array('activity_type_id');
3058 break;
3059 }
3060
3061 $values = array();
3062 $params = array('id' => $componentId);
3063
3064 //get the component values.
3065 CRM_Core_DAO::commonRetrieve($componentBAO, $params, $values);
3066
3067 $formattedGroupTree = array();
3068 $dateTimeFields = array('participant_register_date', 'activity_date_time', 'receive_date', 'receipt_date', 'cancel_date', 'thankyou_date', 'membership_start_date', 'membership_end_date', 'join_date');
3069 foreach ($fields as $name => $field) {
3070 $fldName = $isStandalone ? $name : "field[$componentId][$name]";
3071 if (in_array($name, $dateTimeFields)) {
3072 $timefldName = $isStandalone ? "{$name}_time" : "field[$componentId][{$name}_time]";
3073 if (CRM_Utils_Array::value($name, $values)) {
3074 list($defaults[$fldName], $defaults[$timefldName]) = CRM_Utils_Date::setDateDefaults($values[$name]);
3075 }
3076 }
3077 elseif (array_key_exists($name, $values)) {
3078 $defaults[$fldName] = $values[$name];
3079 }
3080 elseif ($name == 'participant_note') {
3081 $noteDetails = CRM_Core_BAO_Note::getNote($componentId, 'civicrm_participant');
3082 $defaults[$fldName] = array_pop($noteDetails);
3083 }
3084 elseif (in_array($name, array(
3085 'financial_type', 'payment_instrument', 'participant_status', 'participant_role'))) {
3086 $defaults[$fldName] = $values["{$name}_id"];
3087 }
3088 elseif ($name == 'membership_type') {
3089 // since membership_type field is a hierselect -
3090 $defaults[$fldName][0] =
3091 CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType',$values['membership_type_id'],'member_of_contact_id','id');
3092 $defaults[$fldName][1] = $values['membership_type_id'];
3093 }
3094 elseif ($name == 'membership_status') {
3095 $defaults[$fldName] = $values['status_id'];
3096 }
3097 elseif ($customFieldInfo = CRM_Core_BAO_CustomField::getKeyID($name, TRUE)) {
3098 if (empty($formattedGroupTree)) {
3099 //get the groupTree as per subTypes.
3100 $groupTree = array();
3101 foreach ($componentSubType as $subType) {
3102 $subTree = CRM_Core_BAO_CustomGroup::getTree($componentBAOName, CRM_Core_DAO::$_nullObject,
3103 $componentId, 0, $values[$subType]
3104 );
3105 $groupTree = CRM_Utils_Array::crmArrayMerge($groupTree, $subTree);
3106 }
3107 $formattedGroupTree = CRM_Core_BAO_CustomGroup::formatGroupTree($groupTree, 1, CRM_Core_DAO::$_nullObject);
3108 CRM_Core_BAO_CustomGroup::setDefaults($formattedGroupTree, $defaults);
3109 }
3110
3111 //FIX ME: We need to loop defaults, but once we move to custom_1_x convention this code can be simplified.
3112 foreach ($defaults as $customKey => $customValue) {
3113 if ($customFieldDetails = CRM_Core_BAO_CustomField::getKeyID($customKey, TRUE)) {
3114 if ($name == 'custom_' . $customFieldDetails[0]) {
3115
3116 //hack to set default for checkbox
3117 //basically this is for weired field name like field[33][custom_19]
3118 //we are converting this field name to array structure and assign value.
3119 $skipValue = FALSE;
3120
3121 foreach ($formattedGroupTree as $tree) {
3122 if ('CheckBox' == CRM_Utils_Array::value('html_type', $tree['fields'][$customFieldDetails[0]])) {
3123 $skipValue = TRUE;
3124 $defaults['field'][$componentId][$name] = $customValue;
3125 break;
3126 }
3127 elseif (CRM_Utils_Array::value('data_type', $tree['fields'][$customFieldDetails[0]]) == 'Date') {
3128 $skipValue = TRUE;
3129
3130 // CRM-6681, $default contains formatted date, time values.
3131 $defaults[$fldName] = $customValue;
3132 if (CRM_Utils_Array::value($customKey . '_time', $defaults)) {
3133 $defaults['field'][$componentId][$name . '_time'] = $defaults[$customKey . '_time'];
3134 }
3135 }
3136 }
3137
3138 if (!$skipValue || $isStandalone) {
3139 $defaults[$fldName] = $customValue;
3140 }
3141 unset($defaults[$customKey]);
3142 break;
3143 }
3144 }
3145 }
3146 }
3147 }
3148 }
3149
3150 /**
3151 * Function to retrieve reserved profiles
3152 *
3153 * @param string $name name if the reserve profile
3154 * @param array $extraProfiles associated array of profile id's that needs to merge
3155 *
3156 * @return array $reservedProfiles returns associated array
3157 * @static
3158 */
3159 static function getReservedProfiles($type = 'Contact', $extraProfiles = NULL) {
3160 $reservedProfiles = array();
3161 $profileNames = array();
3162 if ($type == 'Contact') {
3163 $whereClause = 'name IN ( "new_individual", "new_organization", "new_household" )';
3164 if (CRM_Contact_BAO_ContactType::isActive('Individual')) {
3165 $profileNames[] = '"new_individual"';
3166 }
3167 if (CRM_Contact_BAO_ContactType::isActive('Household')) {
3168 $profileNames[] = '"new_household"';
3169 }
3170 if (CRM_Contact_BAO_ContactType::isActive('Organization')) {
3171 $profileNames[] = '"new_organization"';
3172 }
3173 }
3174 if (!empty($profileNames)) {
3175 $whereClause = 'name IN ( ' . implode(',', $profileNames) . ' ) AND is_reserved = 1';
3176 }
3177 else {
3178 $whereClause = 'is_reserved = 1';
3179 }
3180
3181 $query = "SELECT id, title FROM civicrm_uf_group WHERE {$whereClause}";
3182
3183 $dao = CRM_Core_DAO::executeQuery($query);
3184 while ($dao->fetch()) {
3185 $key = $dao->id;
3186 if ($extraProfiles) {
3187 $key .= ',' . implode(',', $extraProfiles);
3188 }
3189 $reservedProfiles[$key] = $dao->title;
3190 }
3191 return $reservedProfiles;
3192 }
3193
3194 /**
3195 * Function to retrieve groups of profiles
3196 *
3197 * @param integer $profileID id of the profile
3198 *
3199 * @return array returns array
3200 * @static
3201 */
3202 static function profileGroups($profileID) {
3203 $groupTypes = array();
3204 $profileTypes = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $profileID, 'group_type');
3205 if ($profileTypes) {
3206 $groupTypeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $profileTypes);
3207 $groupTypes = explode(',', $groupTypeParts[0]);
3208 }
3209 return $groupTypes;
3210 }
3211
3212 /**
3213 * Function to alter contact params by filtering existing subscribed groups and returns
3214 * unsubscribed groups array for subscription.
3215 *
3216 * @param array $params contact params
3217 * @param int $contactId user contact id
3218 *
3219 * @return array $subscribeGroupIds This contains array of groups for subscription
3220 */
3221 static function getDoubleOptInGroupIds(&$params, $contactId = NULL) {
3222 $config = CRM_Core_Config::singleton();
3223 $subscribeGroupIds = array();
3224
3225 // process further only if profileDoubleOptIn enabled and if groups exist
3226 if (!array_key_exists('group', $params) ||
3227 !self::isProfileDoubleOptin() ||
3228 CRM_Utils_System::isNull($params['group'])
3229 ) {
3230 return $subscribeGroupIds;
3231 }
3232
3233 //check if contact email exist.
3234 $hasEmails = FALSE;
3235 foreach ($params as $name => $value) {
3236 if (strpos($name, 'email-') !== FALSE) {
3237 $hasEmails = TRUE;
3238 break;
3239 }
3240 }
3241
3242 //Proceed furthur only if email present
3243 if (!$hasEmails) {
3244 return $subscribeGroupIds;
3245 }
3246
3247 //do check for already subscriptions.
3248 $contactGroups = array();
3249 if ($contactId) {
3250 $query = "
3251 SELECT group_id
3252 FROM civicrm_group_contact
3253 WHERE status = 'Added'
3254 AND contact_id = %1";
3255
3256 $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($contactId, 'Integer')));
3257 while ($dao->fetch()) {
3258 $contactGroups[$dao->group_id] = $dao->group_id;
3259 }
3260 }
3261
3262 //since we don't have names, compare w/ label.
3263 $mailingListGroupType = array_search('Mailing List', CRM_Core_OptionGroup::values('group_type'));
3264
3265 //actual processing start.
3266 foreach ($params['group'] as $groupId => $isSelected) {
3267 //unset group those are not selected.
3268 if (!$isSelected) {
3269 unset($params['group'][$groupId]);
3270 continue;
3271 }
3272
3273 $groupTypes = explode(CRM_Core_DAO::VALUE_SEPARATOR,
3274 CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $groupId, 'group_type', 'id')
3275 );
3276 //get only mailing type group and unset it from params
3277 if (in_array($mailingListGroupType, $groupTypes) && !in_array($groupId, $contactGroups)) {
3278 $subscribeGroupIds[$groupId] = $groupId;
3279 unset($params['group'][$groupId]);
3280 }
3281 }
3282
3283 return $subscribeGroupIds;
3284 }
3285
3286 /**
3287 * Function to check if we are rendering mixed profiles
3288 *
3289 * @param array $profileIds associated array of profile ids
3290 *
3291 * @return boolean $mixProfile true if profile is mixed
3292 * @static
3293 * @access public
3294 */
3295 static function checkForMixProfiles($profileIds) {
3296 $mixProfile = FALSE;
3297
3298 $contactTypes = array('Individual', 'Household', 'Organization');
3299 $subTypes = CRM_Contact_BAO_ContactType::subTypes();
3300
3301 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
3302
3303 $typeCount = array('ctype' => array(), 'subtype' => array());
3304 foreach ($profileIds as $gid) {
3305 $profileType = CRM_Core_BAO_UFField::getProfileType($gid);
3306 // ignore profile of type Contact
3307 if ($profileType == 'Contact') {
3308 continue;
3309 }
3310 if (in_array($profileType, $contactTypes)) {
3311 if (!isset($typeCount['ctype'][$profileType])) {
3312 $typeCount['ctype'][$profileType] = 1;
3313 }
3314
3315 // check if we are rendering profile of different contact types
3316 if (count($typeCount['ctype']) == 2) {
3317 $mixProfile = TRUE;
3318 break;
3319 }
3320 }
3321 elseif (in_array($profileType, $components)) {
3322 $mixProfile = TRUE;
3323 break;
3324 }
3325 else {
3326 if (!isset($typeCount['subtype'][$profileType])) {
3327 $typeCount['subtype'][$profileType] = 1;
3328 }
3329 // check if we are rendering profile of different contact sub types
3330 if (count($typeCount['subtype']) == 2) {
3331 $mixProfile = TRUE;
3332 break;
3333 }
3334 }
3335 }
3336 return $mixProfile;
3337 }
3338
3339 /**
3340 * Funtion to determine of we show overlay profile or not
3341 *
3342 * @return boolean true if profile should be shown else false
3343 * @static
3344 * @access public
3345 */
3346 static function showOverlayProfile() {
3347 $showOverlay = TRUE;
3348
3349 // get the id of overlay profile
3350 $overlayProfileId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', 'summary_overlay', 'id', 'name');
3351 $query = "SELECT count(id) FROM civicrm_uf_field WHERE uf_group_id = {$overlayProfileId} AND visibility IN ('Public Pages', 'Public Pages and Listings') ";
3352
3353 $count = CRM_Core_DAO::singleValueQuery($query);
3354
3355 //check if there are no public fields and use is anonymous
3356 $session = CRM_Core_Session::singleton();
3357 if (!$count && !$session->get('userID')) {
3358 $showOverlay = FALSE;
3359 }
3360
3361 return $showOverlay;
3362 }
3363
3364 /**
3365 * function to get group type values of the profile
3366 *
3367 * @params Integer $profileId Profile Id
3368 * @params String $groupType Group Type
3369 *
3370 * @return Array group type values
3371 * @static
3372 * @access public
3373 */
3374 static function groupTypeValues($profileId, $groupType = NULL) {
3375 $groupTypeValue = array();
3376 $groupTypes = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $profileId, 'group_type');
3377
3378 $groupTypeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $groupTypes);
3379 if (!CRM_Utils_Array::value(1, $groupTypeParts)) {
3380 return $groupTypeValue;
3381 }
3382 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
3383
3384 foreach (explode(',', $groupTypeParts[1]) as $groupTypeValues) {
3385 $values = array();
3386 $valueParts = explode(':', $groupTypeValues);
3387 if ($groupType &&
3388 ($valueParts[0] != "{$groupType}Type" ||
3389 ($groupType == 'Participant' &&
3390 !in_array($valueParts[0], $participantExtends)
3391 )
3392 )
3393 ) {
3394 continue;
3395 }
3396 foreach ($valueParts as $val) {
3397 if (CRM_Utils_Rule::integer($val)) {
3398 $values[$val] = $val;
3399 }
3400 }
3401 if (!empty($values)) {
3402 $typeName = substr($valueParts[0], 0, -4);
3403 if (in_array($valueParts[0], $participantExtends)) {
3404 $typeName = $valueParts[0];
3405 }
3406 $groupTypeValue[$typeName] = $values;
3407 }
3408 }
3409
3410 return $groupTypeValue;
3411 }
3412
3413 static function isProfileDoubleOptin() {
3414 // check for double optin
3415 $config = CRM_Core_Config::singleton();
3416 if (in_array('CiviMail', $config->enableComponents)) {
3417 return CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
3418 'profile_double_optin', NULL, FALSE
3419 );
3420 }
3421 return FALSE;
3422 }
3423
3424 static function isProfileAddToGroupDoubleOptin() {
3425 // check for add to group double optin
3426 $config = CRM_Core_Config::singleton();
3427 if (in_array('CiviMail', $config->enableComponents)) {
3428 return CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
3429 'profile_add_to_group_double_optin', NULL, FALSE
3430 );
3431 }
3432 return FALSE;
3433 }
3434
3435 /**
3436 * get profiles used for batch entry
3437 *
3438 * @return array profileIds profile ids
3439 * @static
3440 */
3441 static function getBatchProfiles() {
3442 $query = "SELECT id
3443 FROM civicrm_uf_group
3444 WHERE name IN ('contribution_batch_entry', 'membership_batch_entry')";
3445 $dao = CRM_Core_DAO::executeQuery( $query );
3446 $profileIds = array();
3447 while( $dao->fetch() ) {
3448 $profileIds[$dao->id] = $dao->id;
3449 }
3450 return $profileIds;
3451 }
3452
3453 static function shiftMultiRecordFields(&$source, &$destination, $returnMultiSummaryFields = FALSE) {
3454 $multiSummaryFields = $returnMultiSummaryFields ? array( ) : NULL;
3455 foreach ($source as $field => $properties) {
3456 if (!CRM_Core_BAO_CustomField::getKeyID($field)) {
3457 continue;
3458 }
3459 if (CRM_Core_BAO_CustomField::isMultiRecordField($field)) {
3460 $destination[$field] = $properties;
3461 if ($returnMultiSummaryFields) {
3462 if ($properties['is_multi_summary']) {
3463 $multiSummaryFields[$field] = $properties;
3464 }
3465 }
3466 unset($source[$field]);
3467 }
3468 }
3469 return $multiSummaryFields;
3470 }
3471
3472 /**
3473 * This is function is used to format pseudo fields
3474 *
3475 * @param array $fields associated array of profile fields
3476 *
3477 * @static
3478 */
3479 static function reformatProfileFields(&$fields) {
3480 //reformat fields array
3481 foreach ($fields as $name => $field) {
3482 //reformat phone and extension field
3483 if ( substr($field['name'], 0, 13) == 'phone_and_ext') {
3484 $fieldSuffix = str_replace('phone_and_ext-', '', $field['name']);
3485
3486 // retain existing element properties and just update and replace key
3487 CRM_Utils_Array::crmReplaceKey($fields, $name, "phone-{$fieldSuffix}");
3488 $fields["phone-{$fieldSuffix}"]['name'] = "phone-{$fieldSuffix}";
3489 $fields["phone-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone';
3490
3491 // add additional phone extension field
3492 $fields["phone_ext-{$fieldSuffix}"] = $field;
3493 $fields["phone_ext-{$fieldSuffix}"]['title'] = $field['title'] .' - '.ts('Ext.');
3494 $fields["phone_ext-{$fieldSuffix}"]['name'] = "phone_ext-{$fieldSuffix}";
3495 $fields["phone_ext-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone_ext';
3496 $fields["phone_ext-{$fieldSuffix}"]['skipDisplay'] = 1;
3497 //ignore required for extension field
3498 $fields["phone_ext-{$fieldSuffix}"]['is_required'] = 0;
3499 }
3500 }
3501 }
3502 }