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