Add missing comments in CRM/Core
[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 $nullIndex = $nullValueIndex = ' ';
962
963 //start of code to set the default values
964 foreach ($fields as $name => $field) {
965 // fix for CRM-3962
966 if ($name == 'id') {
967 $name = 'contact_id';
968 }
969
970 // skip fields that should not be displayed separately
971 if (!empty($field['skipDisplay'])) {
972 continue;
973 }
974
975 $index = $field['title'];
976 //handle for the label not set for the field
977 if (empty($field['title'])) {
978 $index = $nullIndex;
979 $nullIndex .= $nullIndex;
980 }
981
982 //handle the case to avoid re-write where the profile field labels are the same
983 if (array_key_exists($index, $values)) {
984 $index .= $nullValueIndex;
985 $nullValueIndex .= $nullValueIndex;
986 }
987 $params[$index] = $values[$index] = '';
988 $customFieldName = NULL;
989 // hack for CRM-665
990 if (isset($details->$name) || $name == 'group' || $name == 'tag') {
991 // to handle gender / suffix / prefix
992 if (in_array(substr($name, 0, -3), array('gender', 'prefix', 'suffix'))) {
993 $params[$index] = $details->$name;
994 $values[$index] = $details->$name;
995 }
996 elseif (in_array($name, CRM_Contact_BAO_Contact::$_greetingTypes)) {
997 $dname = $name . '_display';
998 $values[$index] = $details->$dname;
999 $name = $name . '_id';
1000 $params[$index] = $details->$name;
1001 }
1002 elseif (in_array($name, array(
1003 'state_province', 'country', 'county'))) {
1004 $values[$index] = $details->$name;
1005 $idx = $name . '_id';
1006 $params[$index] = $details->$idx;
1007 }
1008 elseif ($name === 'preferred_communication_method') {
1009 $communicationFields = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'preferred_communication_method');
1010 $compref = array();
1011 $pref = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details->$name);
1012
1013 foreach ($pref as $k) {
1014 if ($k) {
1015 $compref[] = $communicationFields[$k];
1016 }
1017 }
1018 $params[$index] = $details->$name;
1019 $values[$index] = implode(',', $compref);
1020 }
1021 elseif ($name === 'preferred_language') {
1022 $params[$index] = $details->$name;
1023 $values[$index] = CRM_Core_PseudoConstant::getLabel('CRM_Contact_DAO_Contact', 'preferred_language', $details->$name);
1024 }
1025 elseif ($name == 'group') {
1026 $groups = CRM_Contact_BAO_GroupContact::getContactGroup($cid, 'Added', NULL, FALSE, TRUE);
1027 $title = $ids = array();
1028
1029 foreach ($groups as $g) {
1030 // CRM-8362: User and User Admin visibility groups should be included in display if user has
1031 // VIEW permission on that group
1032 $groupPerm = CRM_Contact_BAO_Group::checkPermission($g['group_id'], $g['title']);
1033
1034 if ($g['visibility'] != 'User and User Admin Only' ||
1035 CRM_Utils_Array::key(CRM_Core_Permission::VIEW, $groupPerm)
1036 ) {
1037 $title[] = $g['title'];
1038 if ($g['visibility'] == 'Public Pages') {
1039 $ids[] = $g['group_id'];
1040 }
1041 }
1042 }
1043 $values[$index] = implode(', ', $title);
1044 $params[$index] = implode(',', $ids);
1045 }
1046 elseif ($name == 'tag') {
1047 $entityTags = CRM_Core_BAO_EntityTag::getTag($cid);
1048 $allTags = CRM_Core_PseudoConstant::get('CRM_Core_DAO_EntityTag', 'tag_id', array('onlyActive' => FALSE));
1049 $title = array();
1050 foreach ($entityTags as $tagId) {
1051 $title[] = $allTags[$tagId];
1052 }
1053 $values[$index] = implode(', ', $title);
1054 $params[$index] = implode(',', $entityTags);
1055 }
1056 elseif ($name == 'activity_status_id') {
1057 $activityStatus = CRM_Core_PseudoConstant::activityStatus();
1058 $values[$index] = $activityStatus[$details->$name];
1059 $params[$index] = $details->$name;
1060 }
1061 elseif ($name == 'activity_date_time') {
1062 $values[$index] = CRM_Utils_Date::customFormat($details->$name);
1063 $params[$index] = $details->$name;
1064 }
1065 elseif ($name == 'contact_sub_type') {
1066 $contactSubTypeNames = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details->$name);
1067 if (!empty($contactSubTypeNames)) {
1068 $contactSubTypeLabels = array();
1069 // get all contact subtypes
1070 $allContactSubTypes = CRM_Contact_BAO_ContactType::subTypeInfo();
1071 // build contact subtype labels array
1072 foreach( $contactSubTypeNames as $cstName ) {
1073 if ($cstName) {
1074 $contactSubTypeLabels[] = $allContactSubTypes[$cstName]['label'];
1075 }
1076 }
1077 $values[$index] = implode(',', $contactSubTypeLabels);
1078 }
1079
1080 $params[$index] = $details->$name;
1081 }
1082 else {
1083 if (substr($name, 0, 7) === 'do_not_' || substr($name, 0, 3) === 'is_') {
1084 if ($details->$name) {
1085 $values[$index] = '[ x ]';
1086 }
1087 }
1088 else {
1089 if ($cfID = CRM_Core_BAO_CustomField::getKeyID($name)) {
1090 $htmlType = $field['html_type'];
1091
1092 // field_type is only set when we are retrieving profile values
1093 // when sending email, we call the same function to get custom field
1094 // values etc, i.e. emulating a profile
1095 $fieldType = CRM_Utils_Array::value('field_type', $field);
1096
1097 if ($htmlType == 'File') {
1098 $entityId = $cid;
1099 if (!$cid &&
1100 $fieldType == 'Activity' && !empty($componentWhere[0][2])) {
1101 $entityId = $componentWhere[0][2];
1102 }
1103
1104 $fileURL = CRM_Core_BAO_CustomField::getFileURL($entityId,
1105 $cfID,
1106 NULL,
1107 $absolute
1108 );
1109 $params[$index] = $values[$index] = $fileURL['file_url'];
1110 }
1111 else {
1112 $customVal = NULL;
1113 if (isset($dao) && property_exists($dao, 'data_type') &&
1114 ($dao->data_type == 'Int' ||
1115 $dao->data_type == 'Boolean'
1116 )
1117 ) {
1118 $customVal = (int )($details->{$name});
1119 }
1120 elseif (isset($dao) && property_exists($dao, 'data_type')
1121 && $dao->data_type == 'Float'
1122 ) {
1123 $customVal = (float )($details->{$name});
1124 }
1125 elseif (!CRM_Utils_System::isNull(explode(CRM_Core_DAO::VALUE_SEPARATOR,
1126 $details->{$name}
1127 ))) {
1128 $customVal = $details->{$name};
1129 }
1130
1131 //CRM-4582
1132 if (CRM_Utils_System::isNull($customVal)) {
1133 continue;
1134 }
1135
1136 $params[$index] = $customVal;
1137 $values[$index] = CRM_Core_BAO_CustomField::getDisplayValue($customVal,
1138 $cfID,
1139 $options
1140 );
1141 if ($field['data_type'] == 'ContactReference') {
1142 $params[$index] = $values[$index];
1143 }
1144 if (CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField',
1145 $cfID, 'is_search_range'
1146 )) {
1147 $customFieldName = "{$name}_from";
1148 }
1149 }
1150 }
1151 elseif ($name == 'image_URL') {
1152 list($width, $height) = getimagesize($details->$name);
1153 list($thumbWidth, $thumbHeight) = CRM_Contact_BAO_Contact::getThumbSize($width, $height);
1154
1155 $image_URL = '<img src="' . $details->$name . '" height= ' . $thumbHeight . ' width= ' . $thumbWidth . ' />';
1156 $values[$index] = "<a href='#' onclick='contactImagePopUp(\"{$details->$name}\", {$width}, {$height});'>{$image_URL}</a>";
1157 }
1158 elseif (in_array($name, array(
1159 'birth_date', 'deceased_date', 'membership_start_date', 'membership_end_date', 'join_date'))) {
1160 $values[$index] = CRM_Utils_Date::customFormat($details->$name);
1161 $params[$index] = CRM_Utils_Date::isoToMysql($details->$name);
1162 }
1163 else {
1164 $dao = '';
1165 if ($index == 'Campaign') {
1166 $dao = 'CRM_Campaign_DAO_Campaign';
1167 }
1168 elseif ($index == 'Contribution Page') {
1169 $dao = 'CRM_Contribute_DAO_ContributionPage';
1170 }
1171 if ($dao) {
1172 $value = CRM_Core_DAO::getFieldValue($dao, $details->$name, 'title');
1173 }
1174 else {
1175 $value = $details->$name;
1176 }
1177 $values[$index] = $value;
1178 }
1179 }
1180 }
1181 }
1182 elseif (strpos($name, '-') !== FALSE) {
1183 list($fieldName, $id, $type) = CRM_Utils_System::explode('-', $name, 3);
1184
1185 if (!in_array($fieldName, $multipleFields)) {
1186 if ($id == 'Primary') {
1187 // fix for CRM-1543
1188 // not sure why we'd every use Primary location type id
1189 // we need to fix the source if we are using it
1190 // $locationTypeName = CRM_Contact_BAO_Contact::getPrimaryLocationType( $cid );
1191 $locationTypeName = 1;
1192 }
1193 else {
1194 $locationTypeName = CRM_Utils_Array::value($id, $locationTypes);
1195 }
1196
1197 if (!$locationTypeName) {
1198 continue;
1199 }
1200
1201 $detailName = "{$locationTypeName}-{$fieldName}";
1202 $detailName = str_replace(' ', '_', $detailName);
1203
1204 if (in_array($fieldName, array(
1205 'phone', 'im', 'email', 'openid'))) {
1206 if ($type) {
1207 $detailName .= "-{$type}";
1208 }
1209 }
1210
1211 if (in_array($fieldName, array(
1212 'state_province', 'country', 'county'))) {
1213 $values[$index] = $details->$detailName;
1214 $idx = $detailName . '_id';
1215 $params[$index] = $details->$idx;
1216 }
1217 elseif ($fieldName == 'im') {
1218 $providerId = $detailName . '-provider_id';
1219 if (isset($imProviders[$details->$providerId])) {
1220 $values[$index] = $details->$detailName . " (" . $imProviders[$details->$providerId] . ")";
1221 }
1222 else {
1223 $values[$index] = $details->$detailName;
1224 }
1225 $params[$index] = $details->$detailName;
1226 }
1227 elseif ($fieldName == 'phone') {
1228 $phoneExtField = str_replace('phone', 'phone_ext', $detailName);
1229 if (isset($details->$phoneExtField)) {
1230 $values[$index] = $details->$detailName . " (" . $details->$phoneExtField . ")";
1231 }
1232 else {
1233 $values[$index] = $details->$detailName;
1234 }
1235 $params[$index] = $details->$detailName;
1236 }
1237 else {
1238 $values[$index] = $params[$index] = $details->$detailName;
1239 }
1240 }
1241 else {
1242 $detailName = "website-{$id}-{$fieldName}";
1243 $url = CRM_Utils_System::fixURL($details->$detailName);
1244 if ($details->$detailName) {
1245 $websiteTypeId = "website-{$id}-website_type_id";
1246 $websiteType = $websiteTypes[$details->$websiteTypeId];
1247 $values[$index] = "<a href=\"$url\">{$details->$detailName} ( {$websiteType} )</a>";
1248 }
1249 else {
1250 $values[$index] = '';
1251 }
1252 }
1253 }
1254
1255 if ((CRM_Utils_Array::value('visibility', $field) == 'Public Pages and Listings') &&
1256 CRM_Core_Permission::check('profile listings and forms')
1257 ) {
1258
1259 if (CRM_Utils_System::isNull($params[$index])) {
1260 $params[$index] = $values[$index];
1261 }
1262 if (!isset($params[$index])) {
1263 continue;
1264 }
1265 if (!$customFieldName) {
1266 $fieldName = $field['name'];
1267 }
1268 else {
1269 $fieldName = $customFieldName;
1270 }
1271
1272 $url = NULL;
1273 if (CRM_Core_BAO_CustomField::getKeyID($field['name'])) {
1274 $htmlType = $field['html_type'];
1275 if ($htmlType == 'Link') {
1276 $url = $params[$index];
1277 }
1278 elseif (in_array($htmlType, array(
1279 'CheckBox', 'Multi-Select', 'AdvMulti-Select',
1280 'Multi-Select State/Province', 'Multi-Select Country',
1281 ))) {
1282 $valSeperator = CRM_Core_DAO::VALUE_SEPARATOR;
1283 $selectedOptions = explode($valSeperator, $params[$index]);
1284
1285 foreach ($selectedOptions as $key => $multiOption) {
1286 if ($multiOption) {
1287 $url[] = CRM_Utils_System::url('civicrm/profile',
1288 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1289 urlencode($fieldName) .
1290 '=' .
1291 urlencode($multiOption)
1292 );
1293 }
1294 }
1295 }
1296 else {
1297 $url = CRM_Utils_System::url('civicrm/profile',
1298 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1299 urlencode($fieldName) .
1300 '=' .
1301 urlencode($params[$index])
1302 );
1303 }
1304 }
1305 else {
1306 $url = CRM_Utils_System::url('civicrm/profile',
1307 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1308 urlencode($fieldName) .
1309 '=' .
1310 urlencode($params[$index])
1311 );
1312 }
1313
1314 if ($url &&
1315 !empty($values[$index]) &&
1316 $searchable
1317 ) {
1318
1319 if (is_array($url) && !empty($url)) {
1320 $links = array();
1321 $eachMultiValue = explode(', ', $values[$index]);
1322 foreach ($eachMultiValue as $key => $valueLabel) {
1323 $links[] = '<a href="' . $url[$key] . '">' . $valueLabel . '</a>';
1324 }
1325 $values[$index] = implode(', ', $links);
1326 }
1327 else {
1328 $values[$index] = '<a href="' . $url . '">' . $values[$index] . '</a>';
1329 }
1330 }
1331 }
1332 }
1333 }
1334
1335 /**
1336 * Check if profile Group used by any module.
1337 *
1338 * @param int $id profile Id
1339 *
1340 * @return boolean
1341 *
1342 * @access public
1343 * @static
1344 *
1345 */
1346 public static function usedByModule($id) {
1347 //check whether this group is used by any module(check uf join records)
1348 $sql = "SELECT id
1349 FROM civicrm_uf_join
1350 WHERE civicrm_uf_join.uf_group_id=$id";
1351
1352 $dao = new CRM_Core_DAO();
1353 $dao->query($sql);
1354 if ($dao->fetch()) {
1355 return TRUE;
1356 }
1357 else {
1358 return FALSE;
1359 }
1360 }
1361
1362 /**
1363 * Delete the profile Group.
1364 *
1365 * @param int $id profile Id
1366 *
1367 * @return boolean
1368 *
1369 * @access public
1370 * @static
1371 *
1372 */
1373 public static function del($id) {
1374 //check whether this group contains any profile fields
1375 $profileField = new CRM_Core_DAO_UFField();
1376 $profileField->uf_group_id = $id;
1377 $profileField->find();
1378 while ($profileField->fetch()) {
1379 CRM_Core_BAO_UFField::del($profileField->id);
1380 }
1381
1382 //delete records from uf join table
1383 $ufJoin = new CRM_Core_DAO_UFJoin();
1384 $ufJoin->uf_group_id = $id;
1385 $ufJoin->delete();
1386
1387 //delete profile group
1388 $group = new CRM_Core_DAO_UFGroup();
1389 $group->id = $id;
1390 $group->delete();
1391 return 1;
1392 }
1393
1394 /**
1395 * function to add the UF Group
1396 *
1397 * @param array $params reference array contains the values submitted by the form
1398 * @param array $ids reference array contains the id
1399 *
1400 * @access public
1401 * @static
1402 *
1403 * @return object
1404 */
1405 static function add(&$params, $ids = array()) {
1406 $fields = array('is_active', 'add_captcha', 'is_map', 'is_update_dupe', 'is_edit_link', 'is_uf_link', 'is_cms_user');
1407 foreach ($fields as $field) {
1408 $params[$field] = CRM_Utils_Array::value($field, $params, FALSE);
1409 }
1410
1411 $params['limit_listings_group_id'] = CRM_Utils_Array::value('group', $params);
1412 $params['add_to_group_id'] = CRM_Utils_Array::value('add_contact_to_group', $params);
1413
1414 $ufGroup = new CRM_Core_DAO_UFGroup();
1415 $ufGroup->copyValues($params);
1416
1417 $ufGroupID = CRM_Utils_Array::value('ufgroup', $ids, CRM_Utils_Array::value('id', $params));
1418 if (!$ufGroupID) {
1419 $ufGroup->name = CRM_Utils_String::munge($ufGroup->title, '_', 56);
1420 }
1421 $ufGroup->id = $ufGroupID;
1422
1423 $ufGroup->save();
1424
1425 if (!$ufGroupID) {
1426 $ufGroup->name = $ufGroup->name . "_{$ufGroup->id}";
1427 $ufGroup->save();
1428 }
1429
1430 return $ufGroup;
1431 }
1432
1433 /**
1434 * Function to make uf join entries for an uf group
1435 *
1436 * @param array $params (reference) an assoc array of name/value pairs
1437 * @param int $ufGroupId ufgroup id
1438 *
1439 * @return void
1440 * @access public
1441 * @static
1442 */
1443 static function createUFJoin(&$params, $ufGroupId) {
1444 $groupTypes = CRM_Utils_Array::value('uf_group_type', $params);
1445
1446 // get ufjoin records for uf group
1447 $ufGroupRecord = CRM_Core_BAO_UFGroup::getUFJoinRecord($ufGroupId);
1448
1449 // get the list of all ufgroup types
1450 $allUFGroupType = CRM_Core_SelectValues::ufGroupTypes();
1451
1452 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
1453 if (!is_array($groupTypes)) {
1454 $groupTypes = array();
1455 }
1456
1457 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
1458 if (!is_array($ufGroupRecord)) {
1459 $ufGroupRecord = array();
1460 }
1461
1462 // check which values has to be inserted/deleted for contact
1463 $menuRebuild = FALSE;
1464 foreach ($allUFGroupType as $key => $value) {
1465 $joinParams = array();
1466 $joinParams['uf_group_id'] = $ufGroupId;
1467 $joinParams['module'] = $key;
1468 if ($key == 'User Account') {
1469 $menuRebuild = TRUE;
1470 }
1471 if (array_key_exists($key, $groupTypes) && !in_array($key, $ufGroupRecord)) {
1472 // insert a new record
1473 CRM_Core_BAO_UFGroup::addUFJoin($joinParams);
1474 }
1475 elseif (!array_key_exists($key, $groupTypes) && in_array($key, $ufGroupRecord)) {
1476 // delete a record for existing ufgroup
1477 CRM_Core_BAO_UFGroup::delUFJoin($joinParams);
1478 }
1479 }
1480
1481 //update the weight
1482 $query = "
1483 UPDATE civicrm_uf_join
1484 SET weight = %1
1485 WHERE uf_group_id = %2
1486 AND ( entity_id IS NULL OR entity_id <= 0 )
1487 ";
1488 $p = array(1 => array($params['weight'], 'Integer'),
1489 2 => array($ufGroupId, 'Integer'),
1490 );
1491 CRM_Core_DAO::executeQuery($query, $p);
1492
1493 // do a menu rebuild if we are on drupal, so it gets all the new menu entries
1494 // for user account
1495 $config = CRM_Core_Config::singleton();
1496 if ($menuRebuild &&
1497 $config->userSystem->is_drupal
1498 ) {
1499 menu_rebuild();
1500 }
1501 }
1502
1503 /**
1504 * Function to get the UF Join records for an ufgroup id
1505 *
1506 * @params int $ufGroupId uf group id
1507 * @params int $displayName if set return display name in array
1508 * @params int $status if set return module other than default modules (User Account/User registration/Profile)
1509 *
1510 * @param null $ufGroupId
1511 * @param null $displayName
1512 * @param null $status
1513 *
1514 * @return array $ufGroupJoinRecords
1515 *
1516 * @access public
1517 * @static
1518 */
1519 public static function getUFJoinRecord($ufGroupId = NULL, $displayName = NULL, $status = NULL) {
1520 if ($displayName) {
1521 $UFGroupType = array();
1522 $UFGroupType = CRM_Core_SelectValues::ufGroupTypes();
1523 }
1524
1525 $ufJoin = array();
1526 $dao = new CRM_Core_DAO_UFJoin();
1527
1528 if ($ufGroupId) {
1529 $dao->uf_group_id = $ufGroupId;
1530 }
1531
1532 $dao->find();
1533 $ufJoin = array();
1534
1535 while ($dao->fetch()) {
1536 if (!$displayName) {
1537 $ufJoin[$dao->id] = $dao->module;
1538 }
1539 else {
1540 if (isset($UFGroupType[$dao->module])) {
1541 // skip the default modules
1542 if (!$status) {
1543 $ufJoin[$dao->id] = $UFGroupType[$dao->module];
1544 }
1545 // added for CRM-1475
1546 }
1547 elseif (!CRM_Utils_Array::key($dao->module, $ufJoin)) {
1548 $ufJoin[$dao->id] = $dao->module;
1549 }
1550 }
1551 }
1552 return $ufJoin;
1553 }
1554
1555 /**
1556 * Function takes an associative array and creates a ufjoin record for ufgroup
1557 *
1558 * @param array $params (reference) an assoc array of name/value pairs
1559 *
1560 * @return object CRM_Core_BAO_UFJoin object
1561 * @access public
1562 * @static
1563 */
1564 static function addUFJoin(&$params) {
1565 $ufJoin = new CRM_Core_DAO_UFJoin();
1566 $ufJoin->copyValues($params);
1567 $ufJoin->save();
1568 return $ufJoin;
1569 }
1570
1571 /**
1572 * Function to delete the uf join record for an uf group
1573 *
1574 * @param array $params (reference) an assoc array of name/value pairs
1575 *
1576 * @return void
1577 * @access public
1578 * @static
1579 */
1580 static function delUFJoin(&$params) {
1581 $ufJoin = new CRM_Core_DAO_UFJoin();
1582 $ufJoin->copyValues($params);
1583 $ufJoin->delete();
1584 }
1585
1586 /**
1587 * Function to get the weight for ufjoin record
1588 *
1589 * @param int $ufGroupId if $ufGroupId get update weight or add weight
1590 *
1591 * @return int weight of the UFGroup
1592 * @access public
1593 * @static
1594 */
1595 static function getWeight($ufGroupId = NULL) {
1596 //calculate the weight
1597 $p = array();
1598 if (!$ufGroupId) {
1599 $queryString = "SELECT ( MAX(civicrm_uf_join.weight)+1) as new_weight
1600 FROM civicrm_uf_join
1601 WHERE module = 'User Registration' OR module = 'User Account' OR module = 'Profile'";
1602 }
1603 else {
1604 $queryString = "SELECT MAX(civicrm_uf_join.weight) as new_weight
1605 FROM civicrm_uf_join
1606 WHERE civicrm_uf_join.uf_group_id = %1
1607 AND ( entity_id IS NULL OR entity_id <= 0 )";
1608 $p[1] = array($ufGroupId, 'Integer');
1609 }
1610
1611 $dao = CRM_Core_DAO::executeQuery($queryString, $p);
1612 $dao->fetch();
1613 return ($dao->new_weight) ? $dao->new_weight : 1;
1614 }
1615
1616 /**
1617 * Function to get the uf group for a module
1618 *
1619 * @param string $moduleName module name
1620 * @param int $count no to increment the weight
1621 * @param bool $skipPermission
1622 * @param int $op - which operation (view, edit, create, etc) to check permission for
1623 * @param array|NULL $returnFields list of UFGroup fields to return; NULL for default
1624 *
1625 * @internal param bool $skipPermision - whether to add permission clause
1626 * @return array $ufGroups array of ufgroups for a module
1627 * @access public
1628 * @static
1629 */
1630 public static function getModuleUFGroup($moduleName = NULL, $count = 0, $skipPermission = TRUE, $op = CRM_Core_Permission::VIEW, $returnFields = NULL) {
1631 $selectFields = array('id', 'title', 'created_id', 'is_active', 'is_reserved', 'group_type');
1632
1633 if (!CRM_Core_Config::isUpgradeMode()) {
1634 // CRM-13555, since description field was added later (4.4), and to avoid any problems with upgrade
1635 $selectFields[] = 'description';
1636 }
1637
1638 if (!empty($returnFields)) {
1639 $selectFields = array_merge($returnFields, array_diff($selectFields, $returnFields));
1640 }
1641
1642 $queryString = 'SELECT civicrm_uf_group.' . implode(', civicrm_uf_group.', $selectFields) . '
1643 FROM civicrm_uf_group
1644 LEFT JOIN civicrm_uf_join ON (civicrm_uf_group.id = uf_group_id)';
1645 $p = array();
1646 if ($moduleName) {
1647 $queryString .= ' AND civicrm_uf_group.is_active = 1
1648 WHERE civicrm_uf_join.module = %2';
1649 $p[2] = array($moduleName, 'String');
1650 }
1651
1652
1653 // add permissioning for profiles only if not registration
1654 if (!$skipPermission) {
1655 $permissionClause = CRM_Core_Permission::ufGroupClause($op, 'civicrm_uf_group.');
1656 if (strpos($queryString, 'WHERE') !== FALSE) {
1657 $queryString .= " AND $permissionClause ";
1658 }
1659 else {
1660 $queryString .= " $permissionClause ";
1661 }
1662 }
1663
1664 $queryString .= ' ORDER BY civicrm_uf_join.weight, civicrm_uf_group.title';
1665 $dao = CRM_Core_DAO::executeQuery($queryString, $p);
1666
1667 $ufGroups = array();
1668 while ($dao->fetch()) {
1669 //skip mix profiles in user Registration / User Account
1670 if (($moduleName == 'User Registration' || $moduleName == 'User Account') &&
1671 CRM_Core_BAO_UFField::checkProfileType($dao->id)
1672 ) {
1673 continue;
1674 }
1675 foreach ($selectFields as $key => $field) {
1676 if($field == 'id') {
1677 continue;
1678 }
1679 elseif ($field == 'name') {
1680 $ufGroups[$dao->id][$field] = $dao->title;
1681 continue;
1682 }
1683 $ufGroups[$dao->id][$field] = $dao->$field;
1684 }
1685 }
1686
1687 // Allow other modules to alter/override the UFGroups.
1688 CRM_Utils_Hook::buildUFGroupsForModule($moduleName, $ufGroups);
1689
1690 return $ufGroups;
1691 }
1692
1693 /**
1694 * Function to filter ufgroups based on logged in user contact type
1695 *
1696 * @params int $ufGroupId uf group id (profile id)
1697 *
1698 * @param $ufGroupId
1699 * @param null $contactID
1700 *
1701 * @return boolean true or false
1702 * @static
1703 * @access public
1704 */
1705 static function filterUFGroups($ufGroupId, $contactID = NULL) {
1706 if (!$contactID) {
1707 $session = CRM_Core_Session::singleton();
1708 $contactID = $session->get('userID');
1709 }
1710
1711 if ($contactID) {
1712 //get the contact type
1713 $contactType = CRM_Contact_BAO_Contact::getContactType($contactID);
1714
1715 //match if exixting contact type is same as profile contact type
1716 $profileType = CRM_Core_BAO_UFField::getProfileType($ufGroupId);
1717
1718 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
1719 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
1720 }
1721
1722 //allow special mix profiles for Contribution and Participant
1723 $specialProfiles = array('Contribution', 'Participant', 'Membership');
1724
1725 if (in_array($profileType, $specialProfiles)) {
1726 return TRUE;
1727 }
1728
1729 if (($contactType == $profileType) || $profileType == 'Contact') {
1730 return TRUE;
1731 }
1732 }
1733
1734 return FALSE;
1735 }
1736
1737 /**
1738 * Function to build profile form
1739 *
1740 * @params object $form form object
1741 * @params array $field array field properties
1742 * @params int $mode profile mode
1743 * @params int $contactID contact id
1744 * @params string $usedFor for building up prefixed fieldname for special cases (e.g. onBehalf, Honor)
1745 *
1746 * @param $form
1747 * @param $field
1748 * @param $mode
1749 * @param null $contactId
1750 * @param bool $online
1751 * @param null $usedFor
1752 * @param null $rowNumber
1753 * @param string $prefix
1754 *
1755 * @return null
1756 * @static
1757 * @access public
1758 */
1759 static function buildProfile(
1760 &$form,
1761 &$field,
1762 $mode,
1763 $contactId = NULL,
1764 $online = FALSE,
1765 $usedFor = NULL,
1766 $rowNumber = NULL ,
1767 $prefix = ''
1768 ) {
1769 $defaultValues = array();
1770 $fieldName = $field['name'];
1771 $title = $field['title'];
1772 $attributes = $field['attributes'];
1773 $rule = $field['rule'];
1774 $view = $field['is_view'];
1775 $required = ($mode == CRM_Profile_Form::MODE_SEARCH) ? FALSE : $field['is_required'];
1776 $search = ($mode == CRM_Profile_Form::MODE_SEARCH) ? TRUE : FALSE;
1777 $isShared = CRM_Utils_Array::value('is_shared', $field, 0);
1778
1779 // do not display view fields in drupal registration form
1780 // CRM-4632
1781 if ($view && $mode == CRM_Profile_Form::MODE_REGISTER) {
1782 return;
1783 }
1784
1785 if ($usedFor == 'onbehalf') {
1786 $name = "onbehalf[$fieldName]";
1787 }
1788 elseif ($usedFor == 'honor') {
1789 $name = "honor[$fieldName]";
1790 }
1791 elseif ($contactId && !$online) {
1792 $name = "field[$contactId][$fieldName]";
1793 }
1794 elseif ($rowNumber) {
1795 $name = "field[$rowNumber][$fieldName]";
1796 }
1797 elseif (!empty($prefix)) {
1798 $name = $prefix ."[$fieldName]";
1799 }
1800 else {
1801 $name = $fieldName;
1802 }
1803
1804 if ($fieldName == 'image_URL' && $mode == CRM_Profile_Form::MODE_EDIT) {
1805 $deleteExtra = ts('Are you sure you want to delete contact image.');
1806 $deleteURL = array(
1807 CRM_Core_Action::DELETE =>
1808 array(
1809 'name' => ts('Delete Contact Image'),
1810 'url' => 'civicrm/contact/image',
1811 'qs' => 'reset=1&id=%%id%%&gid=%%gid%%&action=delete',
1812 'extra' =>
1813 'onclick = "if (confirm( \'' . $deleteExtra . '\' ) ) this.href+=\'&amp;confirmed=1\'; else return false;"',
1814 ),
1815 );
1816 $deleteURL = CRM_Core_Action::formLink($deleteURL,
1817 CRM_Core_Action::DELETE,
1818 array('id' => $form->get('id'),
1819 'gid' => $form->get('gid'),
1820 ),
1821 ts('more'),
1822 FALSE,
1823 'contact.profileimage.delete',
1824 'Contact',
1825 $form->get('id')
1826 );
1827 $form->assign('deleteURL', $deleteURL);
1828 }
1829 $addressOptions = CRM_Core_BAO_Setting::valueOptions(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
1830 'address_options', TRUE, NULL, TRUE
1831 );
1832
1833 if (substr($fieldName, 0, 14) === 'state_province') {
1834 $form->add('select', $name, $title,
1835 array(
1836 '' => ts('- select -')) + CRM_Core_PseudoConstant::stateProvince(), $required
1837 );
1838 $config = CRM_Core_Config::singleton();
1839 if (!in_array($mode, array(
1840 CRM_Profile_Form::MODE_EDIT, CRM_Profile_Form::MODE_SEARCH)) &&
1841 $config->defaultContactStateProvince
1842 ) {
1843 $defaultValues[$name] = $config->defaultContactStateProvince;
1844 $form->setDefaults($defaultValues);
1845 }
1846 }
1847 elseif (substr($fieldName, 0, 7) === 'country') {
1848 $form->add('select', $name, $title,
1849 array(
1850 '' => ts('- select -')) + CRM_Core_PseudoConstant::country(), $required
1851 );
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 $form->add('select', $name, $title,
1864 array(
1865 '' => ts('(choose state first)')), $required
1866 );
1867 }
1868 }
1869 elseif (substr($fieldName, 0, 9) === 'image_URL') {
1870 $form->add('file', $name, $title, $attributes, $required);
1871 $form->addUploadElement($name);
1872 }
1873 elseif (substr($fieldName, 0, 2) === 'im') {
1874 $form->add('text', $name, $title, $attributes, $required);
1875 if (!$contactId) {
1876 if ($usedFor) {
1877 if (substr($name, -1) == ']') {
1878 $providerName = substr($name, 0, -1) . '-provider_id]';
1879 }
1880 $form->add('select', $providerName, NULL,
1881 array(
1882 '' => ts('- select -')) + CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id'), $required
1883 );
1884 }
1885 else {
1886 $form->add('select', $name . '-provider_id', $title,
1887 array(
1888 '' => ts('- select -')) + CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id'), $required
1889 );
1890 }
1891
1892 if ($view && $mode != CRM_Profile_Form::MODE_SEARCH) {
1893 $form->freeze($name . '-provider_id');
1894 }
1895 }
1896 }
1897 elseif (($fieldName === 'birth_date') || ($fieldName === 'deceased_date')) {
1898 $form->addDate($name, $title, $required, array('formatType' => 'birth'));
1899 }
1900 elseif (in_array($fieldName, array(
1901 'membership_start_date', 'membership_end_date', 'join_date'))) {
1902 $form->addDate($name, $title, $required, array('formatType' => 'custom'));
1903 }
1904 elseif (CRM_Utils_Array::value('name',$field) == 'membership_type') {
1905 list($orgInfo, $types) = CRM_Member_BAO_MembershipType::getMembershipTypeInfo();
1906 $sel = &$form->addElement('hierselect', $name, $title);
1907 $select = array('' => ts('- select -') );
1908 if(count($orgInfo) == 1 && $field['is_required']) {
1909 // we only have one org - so we should default to it. Not sure about defaulting to first type
1910 // as it could be missed - so adding a select
1911 // however, possibly that is more similar to the membership form
1912 if(count($types[1]) > 1) {
1913 $types[1] = $select + $types[1];
1914 }
1915 }
1916 else {
1917 $orgInfo = $select + $orgInfo;
1918 }
1919 $sel->setOptions(array($orgInfo, $types));
1920 }
1921 elseif (CRM_Utils_Array::value('name',$field) == 'membership_status') {
1922 $form->add('select', $name, $title,
1923 array(
1924 '' => ts('- select -')) + CRM_Member_PseudoConstant::membershipStatus(NULL, NULL, 'label'), $required
1925 );
1926 }
1927 elseif ($fieldName === 'gender_id') {
1928 $genderOptions = array();
1929 $gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
1930 foreach ($gender as $key => $var) {
1931 $genderOptions[$key] = $form->createElement('radio', NULL, ts('Gender'), $var, $key);
1932 }
1933 $group = $form->addGroup($genderOptions, $name, $title);
1934 if ($required) {
1935 $form->addRule($name, ts('%1 is a required field.', array(1 => $title)), 'required');
1936 }
1937 else {
1938 $group->setAttribute('allowClear', TRUE);
1939 }
1940 }
1941 elseif ($fieldName === 'prefix_id' || $fieldName === 'suffix_id') {
1942 $form->add('select', $name, $title,
1943 array(
1944 '' => ts('- select -')) + CRM_Core_PseudoConstant::get('CRM_Contact_BAO_Contact', $fieldName), $required
1945 );
1946 }
1947 elseif ($fieldName === 'contact_sub_type') {
1948 $gId = $form->get('gid') ? $form->get('gid') : CRM_Utils_Array::value('group_id', $field);
1949 if ($usedFor == 'onbehalf') {
1950 $profileType = 'Organization';
1951 }
1952 elseif ($usedFor == 'honor') {
1953 $profileType = CRM_Core_BAO_UFField::getProfileType($form->_params['honoree_profile_id']);
1954 }
1955 else {
1956 $profileType = $gId ? CRM_Core_BAO_UFField::getProfileType($gId) : NULL;
1957 if ($profileType == 'Contact') {
1958 $profileType = 'Individual';
1959 }
1960 }
1961
1962 $setSubtype = FALSE;
1963 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
1964 $setSubtype = $profileType;
1965 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
1966 }
1967
1968 $subtypes = $profileType ? CRM_Contact_BAO_ContactType::subTypePairs($profileType) : array();
1969
1970 if ($setSubtype) {
1971 $subtypeList = array();
1972 $subtypeList[$setSubtype] = $subtypes[$setSubtype];
1973 }
1974 else {
1975 $subtypeList = $subtypes;
1976 }
1977
1978 $sel = $form->add('select', $name, $title, $subtypeList, $required);
1979 $sel->setMultiple(TRUE);
1980 }
1981 elseif (in_array($fieldName, CRM_Contact_BAO_Contact::$_greetingTypes)) {
1982 //add email greeting, postal greeting, addressee, CRM-4575
1983 $gId = $form->get('gid') ? $form->get('gid') : CRM_Utils_Array::value('group_id', $field);
1984 $profileType = CRM_Core_BAO_UFField::getProfileType($gId, TRUE, FALSE, TRUE);
1985
1986 if (empty($profileType) || in_array($profileType, array(
1987 'Contact', 'Contribution', 'Participant', 'Membership'))) {
1988 $profileType = 'Individual';
1989 }
1990 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
1991 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
1992 }
1993 $greeting = array(
1994 'contact_type' => $profileType,
1995 'greeting_type' => $fieldName,
1996 );
1997 $form->add('select', $name, $title,
1998 array(
1999 '' => ts('- select -')) + CRM_Core_PseudoConstant::greeting($greeting), $required
2000 );
2001 // add custom greeting element
2002 $form->add('text', $fieldName . '_custom', ts('Custom %1', array(1 => ucwords(str_replace('_', ' ', $fieldName)))),
2003 NULL, FALSE
2004 );
2005 }
2006 elseif ($fieldName === 'preferred_communication_method') {
2007 $communicationFields = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'preferred_communication_method');
2008 foreach ($communicationFields as $key => $var) {
2009 if ($key == '') {
2010 continue;
2011 }
2012 $communicationOptions[] = $form->createElement('checkbox', $key, NULL, $var);
2013 }
2014 $form->addGroup($communicationOptions, $name, $title, '<br/>');
2015 }
2016 elseif ($fieldName === 'preferred_mail_format') {
2017 $form->add('select', $name, $title, CRM_Core_SelectValues::pmf());
2018 }
2019 elseif ($fieldName === 'preferred_language') {
2020 $form->add('select', $name, $title, array('' => ts('- select -')) + CRM_Contact_BAO_Contact::buildOptions('preferred_language'));
2021 }
2022 elseif ($fieldName == 'external_identifier') {
2023 $form->add('text', $name, $title, $attributes, $required);
2024 $contID = $contactId;
2025 if (!$contID) {
2026 $contID = $form->get('id');
2027 }
2028 $form->addRule($name,
2029 ts('External ID already exists in Database.'),
2030 'objectExists',
2031 array('CRM_Contact_DAO_Contact', $contID, 'external_identifier')
2032 );
2033 }
2034 elseif ($fieldName === 'group') {
2035 CRM_Contact_Form_Edit_TagsAndGroups::buildQuickForm($form, $contactId,
2036 CRM_Contact_Form_Edit_TagsAndGroups::GROUP,
2037 TRUE, $required,
2038 $title, NULL, $name
2039 );
2040 }
2041 elseif ($fieldName === 'tag') {
2042 CRM_Contact_Form_Edit_TagsAndGroups::buildQuickForm($form, $contactId,
2043 CRM_Contact_Form_Edit_TagsAndGroups::TAG,
2044 FALSE, $required,
2045 NULL, $title, $name
2046 );
2047 }
2048 elseif (substr($fieldName, 0, 4) === 'url-') {
2049 $form->add('text', $name, $title,
2050 array_merge(CRM_Core_DAO::getAttribute('CRM_Core_DAO_Website', 'url'),
2051 array(
2052 'onfocus' => "if (!this.value) { this.value='http://';} else return false",
2053 'onblur' => "if ( this.value == 'http://') { this.value='';} else return false",
2054 )
2055 ), $required
2056 );
2057
2058 $form->addRule($name, ts('Enter a valid Website.'), 'url');
2059 }
2060 // Note should be rendered as textarea
2061 elseif (substr($fieldName, -4) == 'note') {
2062 $form->add('textarea', $name, $title, $attributes, $required);
2063 }
2064 elseif (substr($fieldName, 0, 6) === 'custom') {
2065 $customFieldID = CRM_Core_BAO_CustomField::getKeyID($fieldName);
2066 if ($customFieldID) {
2067 CRM_Core_BAO_CustomField::addQuickFormElement($form, $name, $customFieldID, FALSE, $required, $search, $title);
2068 }
2069 }
2070 elseif (substr($fieldName, 0, 14) === 'address_custom') {
2071 list($fName, $locTypeId) = CRM_Utils_System::explode('-', $fieldName, 2);
2072 $customFieldID = CRM_Core_BAO_CustomField::getKeyID(substr($fName, 8));
2073 if ($customFieldID) {
2074 CRM_Core_BAO_CustomField::addQuickFormElement($form, $name, $customFieldID, FALSE, $required, $search, $title);
2075 }
2076 }
2077 elseif (in_array($fieldName, array(
2078 'receive_date', 'receipt_date', 'thankyou_date', 'cancel_date'))) {
2079 $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime'));
2080 }
2081 elseif ($fieldName == 'send_receipt') {
2082 $form->addElement('checkbox', $name, $title);
2083 }
2084 elseif ($fieldName == 'soft_credit') {
2085 $form->addEntityRef("soft_credit_contact_id[$rowNumber]", ts('Soft Credit To'), array('create' => TRUE));
2086 $form->addMoney("soft_credit_amount[{$rowNumber}]", ts('Amount'), FALSE, NULL, FALSE);
2087 }
2088 elseif ($fieldName == 'product_name') {
2089 list($products, $options) = CRM_Contribute_BAO_Premium::getPremiumProductInfo();
2090 $sel = &$form->addElement('hierselect', $name, $title);
2091 $products = array(
2092 '0' => ts('- select -')) + $products;
2093 $sel->setOptions(array($products, $options));
2094 }
2095 elseif ($fieldName == 'payment_instrument') {
2096 $form->add('select', $name, $title,
2097 array(''=>ts( '- select -' )) + CRM_Contribute_PseudoConstant::paymentInstrument( ), $required );
2098 }
2099 else if ($fieldName == 'financial_type' ) {
2100 $form->add('select', $name, $title,
2101 array(
2102 '' => ts('- select -')) + CRM_Contribute_PseudoConstant::financialType(), $required
2103 );
2104 }
2105 elseif ($fieldName == 'contribution_status_id') {
2106 $contributionStatuses = CRM_Contribute_PseudoConstant::contributionStatus();
2107 $statusName = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
2108 foreach (array(
2109 'In Progress',
2110 'Overdue',
2111 'Refunded'
2112 ) as $suppress) {
2113 unset($contributionStatuses[CRM_Utils_Array::key($suppress, $statusName)]);
2114 }
2115
2116 $form->add('select', $name, $title,
2117 array(
2118 '' => ts('- select -')) + $contributionStatuses, $required
2119 );
2120 }
2121 elseif ($fieldName == 'soft_credit_type') {
2122 $form->add('select', $name, $title,
2123 array(
2124 '' => ts('- select -')) + CRM_Core_OptionGroup::values("soft_credit_type")
2125 );
2126 $form->addElement('hidden', 'sct_default_id',
2127 CRM_Core_OptionGroup::getDefaultValue("soft_credit_type"),
2128 array('id' => 'sct_default_id')
2129 );
2130 }
2131 elseif ($fieldName == 'currency') {
2132 $form->addCurrency($name, $title, $required);
2133 }
2134 elseif ($fieldName == 'contribution_page_id') {
2135 $form->add('select', $name, $title,
2136 array(
2137 '' => ts('- select -')) + CRM_Contribute_PseudoConstant::contributionPage(), $required, 'class="big"'
2138 );
2139 }
2140 elseif ($fieldName == 'participant_register_date') {
2141 $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime'));
2142 }
2143 elseif ($fieldName == 'activity_status_id') {
2144 $form->add('select', $name, $title,
2145 array(
2146 '' => ts('- select -')) + CRM_Core_PseudoConstant::activityStatus(), $required
2147 );
2148 }
2149 elseif ($fieldName == 'activity_engagement_level') {
2150 $form->add('select', $name, $title,
2151 array(
2152 '' => ts('- select -')) + CRM_Campaign_PseudoConstant::engagementLevel(), $required
2153 );
2154 }
2155 elseif ($fieldName == 'activity_date_time') {
2156 $form->addDateTime($name, $title, $required, array('formatType' => 'activityDateTime'));
2157 }
2158 elseif ($fieldName == 'participant_status') {
2159 $cond = NULL;
2160 if ($online == TRUE) {
2161 $cond = 'visibility_id = 1';
2162 }
2163 $form->add('select', $name, $title,
2164 array(
2165 '' => ts('- select -')) + CRM_Event_PseudoConstant::participantStatus(NULL, $cond, 'label'), $required
2166 );
2167 }
2168 elseif ($fieldName == 'participant_role') {
2169 if (!empty($field['is_multiple'])) {
2170 $form->addCheckBox($name, $title, CRM_Event_PseudoConstant::participantRole(), NULL, NULL, NULL, NULL, '&nbsp', TRUE);
2171 }
2172 else {
2173 $form->add('select', $name, $title,
2174 array(
2175 '' => ts('- select -')) + CRM_Event_PseudoConstant::participantRole(), $required
2176 );
2177 }
2178 }
2179 elseif ($fieldName == 'world_region') {
2180 $form->add('select', $name, $title,
2181 array(
2182 '' => ts('- select -')) + CRM_Core_PseudoConstant::worldRegion(), $required
2183 );
2184 }
2185 elseif ($fieldName == 'signature_html') {
2186 $form->addWysiwyg($name, $title, CRM_Core_DAO::getAttribute('CRM_Core_DAO_Email', $fieldName));
2187 }
2188 elseif ($fieldName == 'signature_text') {
2189 $form->add('textarea', $name, $title, CRM_Core_DAO::getAttribute('CRM_Core_DAO_Email', $fieldName));
2190 }
2191 elseif (substr($fieldName, -11) == 'campaign_id') {
2192 if (CRM_Campaign_BAO_Campaign::isCampaignEnable()) {
2193 $campaigns = CRM_Campaign_BAO_Campaign::getCampaigns(CRM_Utils_Array::value($contactId,
2194 $form->_componentCampaigns
2195 ));
2196 $form->add('select', $name, $title,
2197 array(
2198 '' => ts('- select -')) + $campaigns, $required, 'class="big"'
2199 );
2200 }
2201 }
2202 elseif ($fieldName == 'activity_details') {
2203 $form->addWysiwyg($fieldName, $title, array('rows' => 4, 'cols' => 60), $required);
2204 }
2205 elseif ($fieldName == 'activity_duration') {
2206 $form->add('text', $name, $title, $attributes, $required);
2207 $form->addRule($name, ts('Please enter the duration as number of minutes (integers only).'), 'positiveInteger');
2208 }
2209 else {
2210 if (substr($fieldName, 0, 3) === 'is_' or substr($fieldName, 0, 7) === 'do_not_') {
2211 $form->add('advcheckbox', $name, $title, $attributes, $required);
2212 }
2213 else {
2214 $form->add('text', $name, $title, $attributes, $required);
2215 }
2216 }
2217
2218 static $hiddenSubtype = FALSE;
2219 if (!$hiddenSubtype && CRM_Contact_BAO_ContactType::isaSubType($field['field_type'])) {
2220 // In registration mode params are submitted via POST and we don't have any clue
2221 // about profile-id or the profile-type (which could be a subtype)
2222 // To generalize the behavior and simplify the process,
2223 // lets always add the hidden
2224 //subtype value if there is any, and we won't have to
2225 // compute it while processing.
2226 if ($usedFor) {
2227 $form->addElement('hidden', $usedFor . '[contact_sub_type]', $field['field_type']);
2228 }
2229 else {
2230 $form->addElement('hidden', 'contact_sub_type_hidden', $field['field_type']);
2231 }
2232 $hiddenSubtype = TRUE;
2233 }
2234
2235 if (($view && $mode != CRM_Profile_Form::MODE_SEARCH) || $isShared) {
2236 $form->freeze($name);
2237 }
2238
2239 //add the rules
2240 if (in_array($fieldName, array(
2241 'non_deductible_amount', 'total_amount', 'fee_amount', 'net_amount'))) {
2242 $form->addRule($name, ts('Please enter a valid amount.'), 'money');
2243 }
2244 $stateCountryMap = array();
2245 if (!empty($form->_stateCountryMap['state_province']) && !empty($form->_stateCountryMap['country'])) {
2246 foreach ($form->_stateCountryMap['state_province'] as $key => $value) {
2247 $stateCountryMap[$key]['state_province'] = $value;
2248 $stateCountryMap[$key]['country'] = $form->_stateCountryMap['country'][$key];
2249 }
2250 CRM_Core_BAO_Address::addStateCountryMap($stateCountryMap);
2251 }
2252 if ($rule) {
2253 if (!($rule == 'email' && $mode == CRM_Profile_Form::MODE_SEARCH)) {
2254 $form->addRule($name, ts('Please enter a valid %1', array(1 => $title)), $rule);
2255 }
2256 }
2257 }
2258
2259 /**
2260 * Function to set profile defaults
2261 *
2262 * @params int $contactId contact id
2263 * @params array $fields associative array of fields
2264 * @params array $defaults defaults array
2265 * @params boolean $singleProfile true for single profile else false(batch update)
2266 * @params int $componentId id for specific components like contribute, event etc
2267 *
2268 * @param $contactId
2269 * @param $fields
2270 * @param $defaults
2271 * @param bool $singleProfile
2272 * @param null $componentId
2273 * @param null $component
2274 *
2275 * @return null
2276 * @static
2277 * @access public
2278 */
2279 static function setProfileDefaults($contactId, &$fields, &$defaults,
2280 $singleProfile = TRUE, $componentId = NULL, $component = NULL
2281 ) {
2282 if (!$componentId) {
2283 //get the contact details
2284 list($contactDetails, $options) = CRM_Contact_BAO_Contact::getHierContactDetails($contactId, $fields);
2285 $details = CRM_Utils_Array::value($contactId, $contactDetails);
2286 $multipleFields = array('website' => 'url');
2287
2288 //start of code to set the default values
2289 foreach ($fields as $name => $field) {
2290 // skip pseudo fields
2291 if (substr($name, 0, 9) == 'phone_ext') {
2292 continue;
2293 }
2294
2295 //set the field name depending upon the profile mode(single/batch)
2296 if ($singleProfile) {
2297 $fldName = $name;
2298 }
2299 else {
2300 $fldName = "field[$contactId][$name]";
2301 }
2302
2303 if ($name == 'group') {
2304 CRM_Contact_Form_Edit_TagsAndGroups::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups::GROUP, $fldName);
2305 }
2306 if ($name == 'tag') {
2307 CRM_Contact_Form_Edit_TagsAndGroups::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups::TAG, $fldName);
2308 }
2309
2310 if (!empty($details[$name]) || isset($details[$name])) {
2311 //to handle custom data (checkbox) to be written
2312 // to handle birth/deceased date, greeting_type and few other fields
2313 if (($name == 'birth_date') || ($name == 'deceased_date')) {
2314 list($defaults[$fldName]) = CRM_Utils_Date::setDateDefaults($details[$name], 'birth');
2315 }
2316 elseif (in_array($name, CRM_Contact_BAO_Contact::$_greetingTypes)) {
2317 $defaults[$fldName] = $details[$name . '_id'];
2318 $defaults[$name . '_custom'] = $details[$name . '_custom'];
2319 }
2320 elseif ($name == 'preferred_communication_method') {
2321 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2322 foreach ($v as $item) {
2323 if ($item) {
2324 $defaults[$fldName . "[$item]"] = 1;
2325 }
2326 }
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');
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
3189 $formattedGroupTree = array();
3190 $dateTimeFields = array('participant_register_date', 'activity_date_time', 'receive_date', 'receipt_date', 'cancel_date', 'thankyou_date', 'membership_start_date', 'membership_end_date', 'join_date');
3191 foreach ($fields as $name => $field) {
3192 $fldName = $isStandalone ? $name : "field[$componentId][$name]";
3193 if (in_array($name, $dateTimeFields)) {
3194 $timefldName = $isStandalone ? "{$name}_time" : "field[$componentId][{$name}_time]";
3195 if (!empty($values[$name])) {
3196 list($defaults[$fldName], $defaults[$timefldName]) = CRM_Utils_Date::setDateDefaults($values[$name]);
3197 }
3198 }
3199 elseif (array_key_exists($name, $values)) {
3200 $defaults[$fldName] = $values[$name];
3201 }
3202 elseif ($name == 'participant_note') {
3203 $noteDetails = CRM_Core_BAO_Note::getNote($componentId, 'civicrm_participant');
3204 $defaults[$fldName] = array_pop($noteDetails);
3205 }
3206 elseif (in_array($name, array(
3207 'financial_type', 'payment_instrument', 'participant_status', 'participant_role'))) {
3208 $defaults[$fldName] = $values["{$name}_id"];
3209 }
3210 elseif ($name == 'membership_type') {
3211 // since membership_type field is a hierselect -
3212 $defaults[$fldName][0] =
3213 CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType',$values['membership_type_id'],'member_of_contact_id','id');
3214 $defaults[$fldName][1] = $values['membership_type_id'];
3215 }
3216 elseif ($name == 'membership_status') {
3217 $defaults[$fldName] = $values['status_id'];
3218 }
3219 elseif ($customFieldInfo = CRM_Core_BAO_CustomField::getKeyID($name, TRUE)) {
3220 if (empty($formattedGroupTree)) {
3221 //get the groupTree as per subTypes.
3222 $groupTree = array();
3223 foreach ($componentSubType as $subType) {
3224 $subTree = CRM_Core_BAO_CustomGroup::getTree($componentBAOName, CRM_Core_DAO::$_nullObject,
3225 $componentId, 0, $values[$subType]
3226 );
3227 $groupTree = CRM_Utils_Array::crmArrayMerge($groupTree, $subTree);
3228 }
3229 $formattedGroupTree = CRM_Core_BAO_CustomGroup::formatGroupTree($groupTree, 1, CRM_Core_DAO::$_nullObject);
3230 CRM_Core_BAO_CustomGroup::setDefaults($formattedGroupTree, $defaults);
3231 }
3232
3233 //FIX ME: We need to loop defaults, but once we move to custom_1_x convention this code can be simplified.
3234 foreach ($defaults as $customKey => $customValue) {
3235 if ($customFieldDetails = CRM_Core_BAO_CustomField::getKeyID($customKey, TRUE)) {
3236 if ($name == 'custom_' . $customFieldDetails[0]) {
3237
3238 //hack to set default for checkbox
3239 //basically this is for weired field name like field[33][custom_19]
3240 //we are converting this field name to array structure and assign value.
3241 $skipValue = FALSE;
3242
3243 foreach ($formattedGroupTree as $tree) {
3244 if ('CheckBox' == CRM_Utils_Array::value('html_type', $tree['fields'][$customFieldDetails[0]])) {
3245 $skipValue = TRUE;
3246 $defaults['field'][$componentId][$name] = $customValue;
3247 break;
3248 }
3249 elseif (CRM_Utils_Array::value('data_type', $tree['fields'][$customFieldDetails[0]]) == 'Date') {
3250 $skipValue = TRUE;
3251
3252 // CRM-6681, $default contains formatted date, time values.
3253 $defaults[$fldName] = $customValue;
3254 if (!empty($defaults[$customKey . '_time'])) {
3255 $defaults['field'][$componentId][$name . '_time'] = $defaults[$customKey . '_time'];
3256 }
3257 }
3258 }
3259
3260 if (!$skipValue || $isStandalone) {
3261 $defaults[$fldName] = $customValue;
3262 }
3263 unset($defaults[$customKey]);
3264 break;
3265 }
3266 }
3267 }
3268 }
3269 }
3270 }
3271
3272 /**
3273 * @param array|string $profiles - name of profile(s) to create links for
3274 * @param array $appendProfiles - name of profile(s) to append to each link
3275 *
3276 * @return array
3277 */
3278 static function getCreateLinks($profiles = '', $appendProfiles = array()) {
3279 // Default to contact profiles
3280 if (!$profiles) {
3281 $profiles = array('new_individual', 'new_organization', 'new_household');
3282 }
3283 $profiles = (array) $profiles;
3284 $toGet = array_merge($profiles, (array) $appendProfiles);
3285 $retrieved = civicrm_api3('uf_group', 'get', array(
3286 'name' => array('IN' => $toGet),
3287 'is_active' => 1,
3288 ));
3289 $links = $append = array();
3290 if (!empty($retrieved['values'])) {
3291 foreach($retrieved['values'] as $id => $profile) {
3292 if (in_array($profile['name'], $profiles)) {
3293 $links[] = array(
3294 'label' => $profile['title'],
3295 'url' => CRM_Utils_System::url('civicrm/profile/create', "reset=1&context=dialog&gid=$id",
3296 NULL, NULL, FALSE, NULL, FALSE) ,
3297 'type' => ucfirst(str_replace('new_', '', $profile['name'])),
3298 );
3299 }
3300 else {
3301 $append[] = $id;
3302 }
3303 }
3304 foreach ($append as $id) {
3305 foreach ($links as &$link) {
3306 $link['url'] .= ",$id";
3307 }
3308 }
3309 }
3310 return $links;
3311 }
3312
3313 /**
3314 * Function to retrieve groups of profiles
3315 *
3316 * @param integer $profileID id of the profile
3317 *
3318 * @return array returns array
3319 * @static
3320 */
3321 static function profileGroups($profileID) {
3322 $groupTypes = array();
3323 $profileTypes = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $profileID, 'group_type');
3324 if ($profileTypes) {
3325 $groupTypeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $profileTypes);
3326 $groupTypes = explode(',', $groupTypeParts[0]);
3327 }
3328 return $groupTypes;
3329 }
3330
3331 /**
3332 * Function to alter contact params by filtering existing subscribed groups and returns
3333 * unsubscribed groups array for subscription.
3334 *
3335 * @param array $params contact params
3336 * @param int $contactId user contact id
3337 *
3338 * @return array $subscribeGroupIds This contains array of groups for subscription
3339 */
3340 static function getDoubleOptInGroupIds(&$params, $contactId = NULL) {
3341 $config = CRM_Core_Config::singleton();
3342 $subscribeGroupIds = array();
3343
3344 // process further only if profileDoubleOptIn enabled and if groups exist
3345 if (!array_key_exists('group', $params) ||
3346 !self::isProfileDoubleOptin() ||
3347 CRM_Utils_System::isNull($params['group'])
3348 ) {
3349 return $subscribeGroupIds;
3350 }
3351
3352 //check if contact email exist.
3353 $hasEmails = FALSE;
3354 foreach ($params as $name => $value) {
3355 if (strpos($name, 'email-') !== FALSE) {
3356 $hasEmails = TRUE;
3357 break;
3358 }
3359 }
3360
3361 //Proceed furthur only if email present
3362 if (!$hasEmails) {
3363 return $subscribeGroupIds;
3364 }
3365
3366 //do check for already subscriptions.
3367 $contactGroups = array();
3368 if ($contactId) {
3369 $query = "
3370 SELECT group_id
3371 FROM civicrm_group_contact
3372 WHERE status = 'Added'
3373 AND contact_id = %1";
3374
3375 $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($contactId, 'Integer')));
3376 while ($dao->fetch()) {
3377 $contactGroups[$dao->group_id] = $dao->group_id;
3378 }
3379 }
3380
3381 //since we don't have names, compare w/ label.
3382 $mailingListGroupType = array_search('Mailing List', CRM_Core_OptionGroup::values('group_type'));
3383
3384 //actual processing start.
3385 foreach ($params['group'] as $groupId => $isSelected) {
3386 //unset group those are not selected.
3387 if (!$isSelected) {
3388 unset($params['group'][$groupId]);
3389 continue;
3390 }
3391
3392 $groupTypes = explode(CRM_Core_DAO::VALUE_SEPARATOR,
3393 CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $groupId, 'group_type', 'id')
3394 );
3395 //get only mailing type group and unset it from params
3396 if (in_array($mailingListGroupType, $groupTypes) && !in_array($groupId, $contactGroups)) {
3397 $subscribeGroupIds[$groupId] = $groupId;
3398 unset($params['group'][$groupId]);
3399 }
3400 }
3401
3402 return $subscribeGroupIds;
3403 }
3404
3405 /**
3406 * Function to check if we are rendering mixed profiles
3407 *
3408 * @param array $profileIds associated array of profile ids
3409 *
3410 * @return boolean $mixProfile true if profile is mixed
3411 * @static
3412 * @access public
3413 */
3414 static function checkForMixProfiles($profileIds) {
3415 $mixProfile = FALSE;
3416
3417 $contactTypes = array('Individual', 'Household', 'Organization');
3418 $subTypes = CRM_Contact_BAO_ContactType::subTypes();
3419
3420 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
3421
3422 $typeCount = array('ctype' => array(), 'subtype' => array());
3423 foreach ($profileIds as $gid) {
3424 $profileType = CRM_Core_BAO_UFField::getProfileType($gid);
3425 // ignore profile of type Contact
3426 if ($profileType == 'Contact') {
3427 continue;
3428 }
3429 if (in_array($profileType, $contactTypes)) {
3430 if (!isset($typeCount['ctype'][$profileType])) {
3431 $typeCount['ctype'][$profileType] = 1;
3432 }
3433
3434 // check if we are rendering profile of different contact types
3435 if (count($typeCount['ctype']) == 2) {
3436 $mixProfile = TRUE;
3437 break;
3438 }
3439 }
3440 elseif (in_array($profileType, $components)) {
3441 $mixProfile = TRUE;
3442 break;
3443 }
3444 else {
3445 if (!isset($typeCount['subtype'][$profileType])) {
3446 $typeCount['subtype'][$profileType] = 1;
3447 }
3448 // check if we are rendering profile of different contact sub types
3449 if (count($typeCount['subtype']) == 2) {
3450 $mixProfile = TRUE;
3451 break;
3452 }
3453 }
3454 }
3455 return $mixProfile;
3456 }
3457
3458 /**
3459 * Funtion to determine of we show overlay profile or not
3460 *
3461 * @return boolean true if profile should be shown else false
3462 * @static
3463 * @access public
3464 */
3465 static function showOverlayProfile() {
3466 $showOverlay = TRUE;
3467
3468 // get the id of overlay profile
3469 $overlayProfileId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', 'summary_overlay', 'id', 'name');
3470 $query = "SELECT count(id) FROM civicrm_uf_field WHERE uf_group_id = {$overlayProfileId} AND visibility IN ('Public Pages', 'Public Pages and Listings') ";
3471
3472 $count = CRM_Core_DAO::singleValueQuery($query);
3473
3474 //check if there are no public fields and use is anonymous
3475 $session = CRM_Core_Session::singleton();
3476 if (!$count && !$session->get('userID')) {
3477 $showOverlay = FALSE;
3478 }
3479
3480 return $showOverlay;
3481 }
3482
3483 /**
3484 * function to get group type values of the profile
3485 *
3486 * @params Integer $profileId Profile Id
3487 * @params String $groupType Group Type
3488 *
3489 * @param $profileId
3490 * @param null $groupType
3491 *
3492 * @return Array group type values
3493 * @static
3494 * @access public
3495 */
3496 static function groupTypeValues($profileId, $groupType = NULL) {
3497 $groupTypeValue = array();
3498 $groupTypes = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $profileId, 'group_type');
3499
3500 $groupTypeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $groupTypes);
3501 if (empty($groupTypeParts[1])) {
3502 return $groupTypeValue;
3503 }
3504 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
3505
3506 foreach (explode(',', $groupTypeParts[1]) as $groupTypeValues) {
3507 $values = array();
3508 $valueParts = explode(':', $groupTypeValues);
3509 if ($groupType &&
3510 ($valueParts[0] != "{$groupType}Type" ||
3511 ($groupType == 'Participant' &&
3512 !in_array($valueParts[0], $participantExtends)
3513 )
3514 )
3515 ) {
3516 continue;
3517 }
3518 foreach ($valueParts as $val) {
3519 if (CRM_Utils_Rule::integer($val)) {
3520 $values[$val] = $val;
3521 }
3522 }
3523 if (!empty($values)) {
3524 $typeName = substr($valueParts[0], 0, -4);
3525 if (in_array($valueParts[0], $participantExtends)) {
3526 $typeName = $valueParts[0];
3527 }
3528 $groupTypeValue[$typeName] = $values;
3529 }
3530 }
3531
3532 return $groupTypeValue;
3533 }
3534
3535 /**
3536 * @return bool|object
3537 */
3538 static function isProfileDoubleOptin() {
3539 // check for double optin
3540 $config = CRM_Core_Config::singleton();
3541 if (in_array('CiviMail', $config->enableComponents)) {
3542 return CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
3543 'profile_double_optin', NULL, FALSE
3544 );
3545 }
3546 return FALSE;
3547 }
3548
3549 /**
3550 * @return bool|object
3551 */
3552 static function isProfileAddToGroupDoubleOptin() {
3553 // check for add to group double optin
3554 $config = CRM_Core_Config::singleton();
3555 if (in_array('CiviMail', $config->enableComponents)) {
3556 return CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
3557 'profile_add_to_group_double_optin', NULL, FALSE
3558 );
3559 }
3560 return FALSE;
3561 }
3562
3563 /**
3564 * get profiles used for batch entry
3565 *
3566 * @return array profileIds profile ids
3567 * @static
3568 */
3569 static function getBatchProfiles() {
3570 $query = "SELECT id
3571 FROM civicrm_uf_group
3572 WHERE name IN ('contribution_batch_entry', 'membership_batch_entry')";
3573 $dao = CRM_Core_DAO::executeQuery( $query );
3574 $profileIds = array();
3575 while( $dao->fetch() ) {
3576 $profileIds[$dao->id] = $dao->id;
3577 }
3578 return $profileIds;
3579 }
3580
3581 /**
3582 * @todo what do I do?
3583 * @param $source
3584 * @param $destination
3585 * @param bool $returnMultiSummaryFields
3586 *
3587 * @return array|null
3588 */
3589 static function shiftMultiRecordFields(&$source, &$destination, $returnMultiSummaryFields = FALSE) {
3590 $multiSummaryFields = $returnMultiSummaryFields ? array( ) : NULL;
3591 foreach ($source as $field => $properties) {
3592 if (!CRM_Core_BAO_CustomField::getKeyID($field)) {
3593 continue;
3594 }
3595 if (CRM_Core_BAO_CustomField::isMultiRecordField($field)) {
3596 $destination[$field] = $properties;
3597 if ($returnMultiSummaryFields) {
3598 if ($properties['is_multi_summary']) {
3599 $multiSummaryFields[$field] = $properties;
3600 }
3601 }
3602 unset($source[$field]);
3603 }
3604 }
3605 return $multiSummaryFields;
3606 }
3607
3608 /**
3609 * This is function is used to format pseudo fields
3610 *
3611 * @param array $fields associated array of profile fields
3612 *
3613 * @static
3614 */
3615 static function reformatProfileFields(&$fields) {
3616 //reformat fields array
3617 foreach ($fields as $name => $field) {
3618 //reformat phone and extension field
3619 if ( substr($field['name'], 0, 13) == 'phone_and_ext') {
3620 $fieldSuffix = str_replace('phone_and_ext-', '', $field['name']);
3621
3622 // retain existing element properties and just update and replace key
3623 CRM_Utils_Array::crmReplaceKey($fields, $name, "phone-{$fieldSuffix}");
3624 $fields["phone-{$fieldSuffix}"]['name'] = "phone-{$fieldSuffix}";
3625 $fields["phone-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone';
3626
3627 // add additional phone extension field
3628 $fields["phone_ext-{$fieldSuffix}"] = $field;
3629 $fields["phone_ext-{$fieldSuffix}"]['title'] = $field['title'] .' - '.ts('Ext.');
3630 $fields["phone_ext-{$fieldSuffix}"]['name'] = "phone_ext-{$fieldSuffix}";
3631 $fields["phone_ext-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone_ext';
3632 $fields["phone_ext-{$fieldSuffix}"]['skipDisplay'] = 1;
3633 //ignore required for extension field
3634 $fields["phone_ext-{$fieldSuffix}"]['is_required'] = 0;
3635 }
3636 }
3637 }
3638 }