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