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