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