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