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