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