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