Merge pull request #3209 from eileenmcnaughton/comments
[civicrm-core.git] / CRM / Core / BAO / CustomGroup.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
06b69b18 4 | CiviCRM version 4.5 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
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
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35
36/**
37 * Business object for managing custom data groups
38 *
39 */
40class CRM_Core_BAO_CustomGroup extends CRM_Core_DAO_CustomGroup {
41
42 /**
43 * class constructor
44 */
45 function __construct() {
46 parent::__construct();
47 }
48
49 /**
50 * takes an associative array and creates a custom group object
51 *
52 * This function is invoked from within the web form layer and also from the api layer
53 *
54 * @param array $params (reference) an assoc array of name/value pairs
55 *
56 * @return object CRM_Core_DAO_CustomGroup object
57 * @access public
58 * @static
59 */
60 static function create(&$params) {
61 // create custom group dao, populate fields and then save.
62 $group = new CRM_Core_DAO_CustomGroup();
63 $group->title = $params['title'];
64
65 if (in_array($params['extends'][0],
66 array(
67 'ParticipantRole',
68 'ParticipantEventName',
69 'ParticipantEventType',
70 )
71 )) {
72 $group->extends = 'Participant';
73 }
74 else {
75 $group->extends = $params['extends'][0];
76 }
77
78 $group->extends_entity_column_id = 'null';
79 if (
80 $params['extends'][0] == 'ParticipantRole' ||
81 $params['extends'][0] == 'ParticipantEventName' ||
82 $params['extends'][0] == 'ParticipantEventType'
83 ) {
84 $group->extends_entity_column_id =
85 CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue', $params['extends'][0], 'value', 'name');
86 }
87
88 //this is format when form get submit.
89 $extendsChildType = CRM_Utils_Array::value(1, $params['extends']);
90 //lets allow user to pass direct child type value, CRM-6893
a7488080 91 if (!empty($params['extends_entity_column_value'])) {
6a488035
TO
92 $extendsChildType = $params['extends_entity_column_value'];
93 }
94 if (!CRM_Utils_System::isNull($extendsChildType)) {
95 $extendsChildType = implode(CRM_Core_DAO::VALUE_SEPARATOR, $extendsChildType);
96 if (CRM_Utils_Array::value(0, $params['extends']) == 'Relationship') {
97 $extendsChildType = str_replace(array('_a_b', '_b_a'), array('', ''), $extendsChildType);
98 }
99 if (substr($extendsChildType, 0, 1) != CRM_Core_DAO::VALUE_SEPARATOR) {
100 $extendsChildType = CRM_Core_DAO::VALUE_SEPARATOR . $extendsChildType . CRM_Core_DAO::VALUE_SEPARATOR;
101 }
102 }
103 else {
104 $extendsChildType = 'null';
105 }
106 $group->extends_entity_column_value = $extendsChildType;
107
108 if (isset($params['id'])) {
109 $oldWeight = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $params['id'], 'weight', 'id');
110 }
111 else {
112 $oldWeight = 0;
113 }
114 $group->weight = CRM_Utils_Weight::updateOtherWeights('CRM_Core_DAO_CustomGroup', $oldWeight, CRM_Utils_Array::value('weight', $params, FALSE));
115 $fields = array('style', 'collapse_display', 'collapse_adv_display', 'help_pre', 'help_post', 'is_active', 'is_multiple');
116 foreach ($fields as $field) {
117 $group->$field = CRM_Utils_Array::value($field, $params, FALSE);
118 }
119 $group->max_multiple = isset($params['is_multiple']) ? (isset($params['max_multiple']) &&
120 $params['max_multiple'] >= '0'
121 ) ? $params['max_multiple'] : 'null' : 'null';
122
123 $tableName = $oldTableName = NULL;
124 if (isset($params['id'])) {
125 $group->id = $params['id'];
126 //check whether custom group was changed from single-valued to multiple-valued
127 $isMultiple = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup',
128 $params['id'],
129 'is_multiple'
130 );
131
8cc574cf 132 if ((!empty($params['is_multiple']) || $isMultiple) &&
6a488035
TO
133 ($params['is_multiple'] != $isMultiple)
134 ) {
135 $oldTableName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup',
136 $params['id'],
137 'table_name'
138 );
139 }
140 }
141 else {
142 $group->created_id = CRM_Utils_Array::value('created_id', $params);
143 $group->created_date = CRM_Utils_Array::value('created_date', $params);
144
145 // we do this only once, so name never changes
146 if (isset($params['name'])) {
147 $group->name = CRM_Utils_String::munge($params['name'], '_', 64);
148 }
149 else {
150 $group->name = CRM_Utils_String::munge($group->title, '_', 64);
151 }
152
8b3b9a2e
ARW
153 if (isset($params['table_name'])) {
154 $tableName = $params['table_name'];
155
156 if (CRM_Core_DAO_AllCoreTables::isCoreTable($tableName)) {
157 // Bad idea. Prevent group creation because it might lead to a broken configuration.
158 CRM_Core_Error::fatal(ts("Cannot create custom table because %1 is already a core table.", array('1' => $tableName)));
159 }
160 }
6a488035
TO
161 }
162
163 // enclose the below in a transaction
164 $transaction = new CRM_Core_Transaction();
165
166 $group->save();
8b3b9a2e
ARW
167 if (!isset($params['id'])) {
168 if (!isset($params['table_name'])) {
6842bb53 169 $munged_title = strtolower(CRM_Utils_String::munge($group->title, '_', 42));
8b3b9a2e
ARW
170 $tableName = "civicrm_value_{$munged_title}_{$group->id}";
171 }
6a488035
TO
172 $group->table_name = $tableName;
173 CRM_Core_DAO::setFieldValue('CRM_Core_DAO_CustomGroup',
174 $group->id,
175 'table_name',
176 $tableName
177 );
178
179 // now create the table associated with this group
180 self::createTable($group);
181 }
182 elseif ($oldTableName) {
183 CRM_Core_BAO_SchemaHandler::changeUniqueToIndex($oldTableName, CRM_Utils_Array::value('is_multiple', $params));
184 }
185
186 if (CRM_Utils_Array::value('overrideFKConstraint', $params) == 1) {
187 $table = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup',
188 $params['id'],
189 'table_name'
190 );
191 CRM_Core_BAO_SchemaHandler::changeFKConstraint($table, self::mapTableName($params['extends'][0]));
192 }
193 $transaction->commit();
194
195 // reset the cache
196 CRM_Utils_System::flushCache();
197
198 if ($tableName) {
199 CRM_Utils_Hook::post('create', 'CustomGroup', $group->id, $group);
200 }
201 else {
202 CRM_Utils_Hook::post('edit', 'CustomGroup', $group->id, $group);
203 }
204
205 return $group;
206 }
207
208 /**
209 * Takes a bunch of params that are needed to match certain criteria and
210 * retrieves the relevant objects. Typically the valid params are only
211 * contact_id. We'll tweak this function to be more full featured over a period
212 * of time. This is the inverse function of create. It also stores all the retrieved
213 * values in the default array
214 *
215 * @param array $params (reference ) an assoc array of name/value pairs
216 * @param array $defaults (reference ) an assoc array to hold the flattened values
217 *
218 * @return object CRM_Core_DAO_CustomGroup object
219 * @access public
220 * @static
221 */
222 static function retrieve(&$params, &$defaults) {
223 return CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_CustomGroup', $params, $defaults);
224 }
225
226 /**
227 * update the is_active flag in the db
228 *
229 * @param int $id id of the database record
230 * @param boolean $is_active value we want to set the is_active field
231 *
232 * @return Object DAO object on sucess, null otherwise
233 * @static
234 * @access public
235 */
236 static function setIsActive($id, $is_active) {
237 // reset the cache
238 CRM_Core_BAO_Cache::deleteGroup('contact fields');
239
240 if (!$is_active) {
241 CRM_Core_BAO_UFField::setUFFieldStatus($id, $is_active);
242 }
243
244 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_CustomGroup', $id, 'is_active', $is_active);
245 }
246
247 /**
248 * Determine if given entity (sub)type has any custom groups
249 *
250 * @param string $extends e.g. "Individual", "Activity"
251 * @param int $columnId e.g. custom-group matching mechanism (usu NULL for matching on sub type-id); see extends_entity_column_id
252 * @param string $columnValue e.g. "Student" or "3" or "3\05"; see extends_entity_column_value
77b97be7
EM
253 *
254 * @return bool
6a488035
TO
255 */
256 public static function hasCustomGroup($extends, $columnId, $columnValue) {
257 $dao = new CRM_Core_DAO_CustomGroup();
258 $dao->extends = $extends;
259 $dao->extends_entity_column_id = $columnId;
260 $escapedValue = CRM_Core_DAO::VALUE_SEPARATOR . CRM_Core_DAO::escapeString($columnValue) . CRM_Core_DAO::VALUE_SEPARATOR;
261 $dao->whereAdd("extends_entity_column_value LIKE \"%$escapedValue%\"");
262 //$dao->extends_entity_column_value = $columnValue;
263 return $dao->find() ? TRUE : FALSE;
264 }
265
266 /**
267 * Determine if there are any CustomGroups for the given $activityTypeId.
268 * If none found, create one.
269 *
270 * @param int $activityTypeId
271 * @return bool TRUE if a group is found or created; FALSE on error
272 */
273 public static function autoCreateByActivityType($activityTypeId) {
274 if (self::hasCustomGroup('Activity', NULL, $activityTypeId)) {
275 return TRUE;
276 }
277 $activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE, FALSE); // everything
278 $params = array(
279 'version' => 3,
280 'extends' => 'Activity',
281 'extends_entity_column_id' => NULL,
282 'extends_entity_column_value' => CRM_Utils_Array::implodePadded(array($activityTypeId)),
283 'title' => ts('%1 Questions', array(1 => $activityTypes[$activityTypeId])),
284 'style' => 'Inline',
285 'is_active' => 1,
286 );
287 $result = civicrm_api('CustomGroup', 'create', $params);
288 return ! $result['is_error'];
289 }
290
291 /**
c43cedc8 292 * Get custom groups/fields data for type of entity in a tree structure representing group->field hierarchy
293 * This may also include entity specific data values.
6a488035
TO
294 *
295 * An array containing all custom groups and their custom fields is returned.
296 *
297 * @param string $entityType - of the contact whose contact type is needed
c43cedc8 298 * @param object $form - not used but required
6a488035
TO
299 * @param int $entityId - optional - id of entity if we need to populate the tree with custom values.
300 * @param int $groupId - optional group id (if we need it for a single group only)
301 * - if groupId is 0 it gets for inline groups only
302 * - if groupId is -1 we get for all groups
c43cedc8 303 * @param string $subType
304 * @param string $subName
305 * @param boolean $fromCache
6a488035 306 *
c43cedc8 307 * @return array $groupTree - array The returned array is keyed by group id and has the custom group table fields
308 * and a subkey 'fields' holding the specific custom fields.
309 * If entityId is passed in the fields keys have a subkey 'customValue' which holds custom data
310 * if set for the given entity. This is structured as an array of values with each one having the keys 'id', 'data'
311 *
312 * @todo - review this - It also returns an array called 'info' with tables, select, from, where keys
313 * The reason for the info array in unclear and it could be determined from parsing the group tree after creation
314 * With caching the performance impact would be small & the function would be cleaner
6a488035
TO
315 *
316 * @access public
317 *
318 * @static
319 *
320 */
0e6e8724
DL
321 public static function &getTree(
322 $entityType,
6a488035
TO
323 &$form,
324 $entityID = NULL,
325 $groupID = NULL,
326 $subType = NULL,
327 $subName = NULL,
63dbed83 328 $fromCache = TRUE,
329 $onlySubType = NULL
6a488035
TO
330 ) {
331 if ($entityID) {
332 $entityID = CRM_Utils_Type::escape($entityID, 'Integer');
333 }
334
335 // create a new tree
336 $strSelect = $strFrom = $strWhere = $orderBy = '';
337 $tableData = array();
338
339 // using tableData to build the queryString
340 $tableData = array(
341 'civicrm_custom_field' =>
342 array(
343 'id',
344 'label',
345 'column_name',
346 'data_type',
347 'html_type',
348 'default_value',
349 'attributes',
350 'is_required',
351 'is_view',
352 'help_pre',
353 'help_post',
354 'options_per_line',
355 'start_date_years',
356 'end_date_years',
357 'date_format',
358 'time_format',
359 'option_group_id',
e41f4660 360 'in_selector'
6a488035
TO
361 ),
362 'civicrm_custom_group' =>
363 array(
364 'id',
365 'name',
366 'table_name',
367 'title',
368 'help_pre',
369 'help_post',
370 'collapse_display',
371 'is_multiple',
372 'extends',
373 'extends_entity_column_id',
374 'extends_entity_column_value',
375 'max_multiple',
376 ),
377 );
378
379 // create select
380 $select = array();
381 foreach ($tableData as $tableName => $tableColumn) {
382 foreach ($tableColumn as $columnName) {
383 $alias = $tableName . "_" . $columnName;
384 $select[] = "{$tableName}.{$columnName} as {$tableName}_{$columnName}";
385 }
386 }
387 $strSelect = "SELECT " . implode(', ', $select);
388
389 // from, where, order by
390 $strFrom = "
391FROM civicrm_custom_group
392LEFT JOIN civicrm_custom_field ON (civicrm_custom_field.custom_group_id = civicrm_custom_group.id)
393";
394
395 // if entity is either individual, organization or household pls get custom groups for 'contact' too.
396 if ($entityType == "Individual" || $entityType == 'Organization' || $entityType == 'Household') {
397 $in = "'$entityType', 'Contact'";
398 }
399 elseif (strpos($entityType, "'") !== FALSE) {
400 // this allows the calling function to send in multiple entity types
401 $in = $entityType;
402 }
403 else {
404 // quote it
405 $in = "'$entityType'";
406 }
407
408 if ($subType) {
409 $subTypeClause = '';
410 if (is_array($subType)) {
411 $subType = implode(',', $subType);
412 }
413 if (strpos($subType, ',')) {
414 $subTypeParts = explode(',', $subType);
415 $subTypeClauses = array();
416 foreach ($subTypeParts as $subTypePart) {
417 $subTypePart = CRM_Core_DAO::VALUE_SEPARATOR . trim($subTypePart, CRM_Core_DAO::VALUE_SEPARATOR) . CRM_Core_DAO::VALUE_SEPARATOR;
418 $subTypeClauses[] = "civicrm_custom_group.extends_entity_column_value LIKE '%$subTypePart%'";
419 }
63dbed83 420
421 if ($onlySubType) {
422 $subTypeClause = '(' . implode(' OR ', $subTypeClauses) . ')';
423 }
424 else {
425 $subTypeClause = '(' . implode(' OR ', $subTypeClauses) . " OR civicrm_custom_group.extends_entity_column_value IS NULL )";
426 }
6a488035
TO
427 }
428 else {
429 $subType = CRM_Core_DAO::VALUE_SEPARATOR . trim($subType, CRM_Core_DAO::VALUE_SEPARATOR) . CRM_Core_DAO::VALUE_SEPARATOR;
430
63dbed83 431 if ($onlySubType) {
432 $subTypeClause = "( civicrm_custom_group.extends_entity_column_value LIKE '%$subType%' )";
433 }
434 else {
435 $subTypeClause = "( civicrm_custom_group.extends_entity_column_value LIKE '%$subType%'
436 OR civicrm_custom_group.extends_entity_column_value IS NULL )";
437 }
6a488035
TO
438 }
439
440 $strWhere = "
441WHERE civicrm_custom_group.is_active = 1
442 AND civicrm_custom_field.is_active = 1
443 AND civicrm_custom_group.extends IN ($in)
444 AND $subTypeClause
445";
446 if ($subName) {
447 $strWhere .= " AND civicrm_custom_group.extends_entity_column_id = {$subName} ";
448 }
449 }
450 else {
451 $strWhere = "
452WHERE civicrm_custom_group.is_active = 1
453 AND civicrm_custom_field.is_active = 1
454 AND civicrm_custom_group.extends IN ($in)
455 AND civicrm_custom_group.extends_entity_column_value IS NULL
456";
457 }
458
459 $params = array();
460 if ($groupID > 0) {
461 // since we want a specific group id we add it to the where clause
462 $strWhere .= " AND civicrm_custom_group.id = %1";
463 $params[1] = array($groupID, 'Integer');
464 }
465 elseif (!$groupID) {
466 // since groupID is false we need to show all Inline groups
467 $strWhere .= " AND civicrm_custom_group.style = 'Inline'";
468 }
469
470 // ensure that the user has access to these custom groups
471 $strWhere .= " AND " . CRM_Core_Permission::customGroupClause(CRM_Core_Permission::VIEW,
472 'civicrm_custom_group.'
473 );
474
475 $orderBy = "
476ORDER BY civicrm_custom_group.weight,
477 civicrm_custom_group.title,
478 civicrm_custom_field.weight,
479 civicrm_custom_field.label
480";
481
482 // final query string
483 $queryString = "$strSelect $strFrom $strWhere $orderBy";
484
485 // lets see if we can retrieve the groupTree from cache
486 $cacheString = $queryString;
487 if ( $groupID > 0 ) {
488 $cacheString .= "_{$groupID}";
489 } else {
490 $cacheString .= "_Inline";
491 }
492
493 $cacheKey = "CRM_Core_DAO_CustomGroup_Query " . md5($cacheString);
c43cedc8 494 $multipleFieldGroupCacheKey = "CRM_Core_DAO_CustomGroup_QueryMultipleFields " . md5($cacheString);
6a488035 495 $cache = CRM_Utils_Cache::singleton();
c43cedc8 496 $tablesWithEntityData = array();
6a488035
TO
497 if ($fromCache) {
498 $groupTree = $cache->get($cacheKey);
c43cedc8 499 $multipleFieldGroups = $cache->get($multipleFieldGroupCacheKey);
6a488035
TO
500 }
501
502 if (empty($groupTree)) {
c43cedc8 503 $groupTree = $multipleFieldGroups =array();
6a488035 504 $crmDAO = CRM_Core_DAO::executeQuery($queryString, $params);
6a488035
TO
505 $customValueTables = array();
506
507 // process records
508 while ($crmDAO->fetch()) {
509 // get the id's
510 $groupID = $crmDAO->civicrm_custom_group_id;
511 $fieldId = $crmDAO->civicrm_custom_field_id;
c43cedc8 512 if($crmDAO->civicrm_custom_group_is_multiple){
513 $multipleFieldGroups[$groupID] = $crmDAO->civicrm_custom_group_table_name;
514 }
6a488035
TO
515 // create an array for groups if it does not exist
516 if (!array_key_exists($groupID, $groupTree)) {
517 $groupTree[$groupID] = array();
518 $groupTree[$groupID]['id'] = $groupID;
519
520 // populate the group information
521 foreach ($tableData['civicrm_custom_group'] as $fieldName) {
522 $fullFieldName = "civicrm_custom_group_$fieldName";
523 if ($fieldName == 'id' ||
524 is_null($crmDAO->$fullFieldName)
525 ) {
526 continue;
527 }
528 // CRM-5507
529 if ($fieldName == 'extends_entity_column_value' && $subType) {
530 $groupTree[$groupID]['subtype'] = trim($subType, CRM_Core_DAO::VALUE_SEPARATOR);
531 }
532 $groupTree[$groupID][$fieldName] = $crmDAO->$fullFieldName;
533 }
534 $groupTree[$groupID]['fields'] = array();
535
536 $customValueTables[$crmDAO->civicrm_custom_group_table_name] = array();
537 }
538
539 // add the fields now (note - the query row will always contain a field)
540 // we only reset this once, since multiple values come is as multiple rows
541 if (!array_key_exists($fieldId, $groupTree[$groupID]['fields'])) {
542 $groupTree[$groupID]['fields'][$fieldId] = array();
543 }
544
545 $customValueTables[$crmDAO->civicrm_custom_group_table_name][$crmDAO->civicrm_custom_field_column_name] = 1;
546 $groupTree[$groupID]['fields'][$fieldId]['id'] = $fieldId;
547 // populate information for a custom field
548 foreach ($tableData['civicrm_custom_field'] as $fieldName) {
549 $fullFieldName = "civicrm_custom_field_$fieldName";
550 if ($fieldName == 'id' ||
551 is_null($crmDAO->$fullFieldName)
552 ) {
553 continue;
554 }
555 $groupTree[$groupID]['fields'][$fieldId][$fieldName] = $crmDAO->$fullFieldName;
556 }
557 }
558
559 if (!empty($customValueTables)) {
560 $groupTree['info'] = array('tables' => $customValueTables);
561 }
562
563 $cache->set($cacheKey, $groupTree);
c43cedc8 564 $cache->set($multipleFieldGroupCacheKey, $multipleFieldGroups);
6a488035 565 }
c43cedc8 566 //entitySelectClauses is an array of select clauses for custom value tables which are not multiple
567 // and have data for the given entities. $entityMultipleSelectClauses is the same for ones with multiple
568 $entitySingleSelectClauses = $entityMultipleSelectClauses = $groupTree['info']['select'] = array();
569 $singleFieldTables = array();
6a488035
TO
570 // now that we have all the groups and fields, lets get the values
571 // since we need to know the table and field names
6a488035 572 // add info to groupTree
c43cedc8 573
574 if (isset($groupTree['info']) && !empty($groupTree['info']) && !empty($groupTree['info']['tables'])) {
6a488035 575 $select = $from = $where = array();
c43cedc8 576 $groupTree['info']['where'] = NULL;
6a488035 577
c43cedc8 578 foreach ($groupTree['info']['tables'] as $table => $fields) {
579 $groupTree['info']['from'][] = $table;
580 $select = array("{$table}.id as {$table}_id",
581 "{$table}.entity_id as {$table}_entity_id");
6a488035
TO
582 foreach ($fields as $column => $dontCare) {
583 $select[] = "{$table}.{$column} as {$table}_{$column}";
584 }
c43cedc8 585 $groupTree['info']['select'] = array_merge($groupTree['info']['select'], $select);
6a488035 586 if ($entityID) {
c43cedc8 587 $groupTree['info']['where'][] = "{$table}.entity_id = $entityID";
588 if(in_array($table, $multipleFieldGroups) && self::customGroupDataExistsForEntity($entityID, $table)){
589 $entityMultipleSelectClauses[$table] = $select;
590 }
591 else{
592 $singleFieldTables[] = $table;
593 $entitySingleSelectClauses = array_merge($entitySingleSelectClauses, $select);
594 }
595
6a488035
TO
596 }
597 }
c43cedc8 598 if ($entityID && !empty($singleFieldTables)) {
e8cb3963 599 self::buildEntityTreeSingleFields($groupTree, $entityID, $entitySingleSelectClauses, $singleFieldTables);
c43cedc8 600 }
601 $multipleFieldTablesWithEntityData = array_keys($entityMultipleSelectClauses);
602 if(!empty($multipleFieldTablesWithEntityData)){
e8cb3963 603 self::buildEntityTreeMultipleFields($groupTree, $entityID, $entityMultipleSelectClauses, $multipleFieldTablesWithEntityData);
c43cedc8 604 }
6a488035 605
c43cedc8 606 }
607 return $groupTree;
608 }
6a488035 609
c43cedc8 610 /**
611 * Check whether the custom group has any data for the given entity.
612 *
613 *
614 * @param integer $entityID id of entity for whom we are checking data for
615 * @param string $table table that we are checking
616 *
617 * @return boolean does this entity have data in this custom table
618 */
bf076628 619 static public function customGroupDataExistsForEntity($entityID, $table, $getCount = FALSE){
c43cedc8 620 $query = "
621 SELECT count(id)
622 FROM $table
623 WHERE entity_id = $entityID
624 ";
625 $recordExists = CRM_Core_DAO::singleValueQuery($query);
bf076628
PJ
626 if ($getCount) {
627 return $recordExists;
628 }
c43cedc8 629 return $recordExists ? TRUE : FALSE;
630 }
6a488035 631
c43cedc8 632/**
633 * Build the group tree for Custom fields which are not 'is_multiple'
634 *
635 * The combination of all these fields in one query with a 'using' join was not working for
636 * multiple fields. These now have a new behaviour (one at a time) but the single fields still use this
637 * mechanism as it seemed to be acceptable in this context
638 *
639 * @param array $groupTree (reference) group tree array which is being built
640 * @param integer $entityID id of entity for whom the tree is being build up.
641 * @param array $entitySingleSelectClauses array of select clauses relevant to the entity
642 * @param array $singleFieldTablesWithEntityData array of tables in which this entity has data
643 */
644 static public function buildEntityTreeSingleFields(&$groupTree, $entityID, $entitySingleSelectClauses, $singleFieldTablesWithEntityData){
645 $select = implode(', ', $entitySingleSelectClauses);
646 $fromSQL = " (SELECT $entityID as entity_id ) as first ";
647 foreach ($singleFieldTablesWithEntityData as $table) {
648 $fromSQL .= "\nLEFT JOIN $table USING (entity_id)";
649 }
6a488035 650
c43cedc8 651 $query = "
652 SELECT $select
653 FROM $fromSQL
654 WHERE first.entity_id = $entityID
655 ";
e8cb3963 656 self::buildTreeEntityDataFromQuery($groupTree, $query, $singleFieldTablesWithEntityData);
c43cedc8 657 }
6a488035 658
c43cedc8 659 /**
660 * Build the group tree for Custom fields which are 'is_multiple'
661 *
662 * This is done one table at a time to avoid Cross-Joins resulting in too many rows being returned
663 *
664 * @param array $groupTree (reference) group tree array which is being built
665 * @param integer $entityID id of entity for whom the tree is being build up.
666 * @param array $entityMultipleSelectClauses array of select clauses relevant to the entity
667 * @param array $multipleFieldTablesWithEntityData array of tables in which this entity has data
668 */
669 static public function buildEntityTreeMultipleFields(&$groupTree, $entityID, $entityMultipleSelectClauses, $multipleFieldTablesWithEntityData){
670 foreach ($entityMultipleSelectClauses as $table => $selectClauses) {
671 $select = implode(',', $selectClauses);
672 $query = "
673 SELECT $select
674 FROM $table
675 WHERE entity_id = $entityID
676 ";
e8cb3963 677 self::buildTreeEntityDataFromQuery($groupTree, $query, array($table));
c43cedc8 678 }
679 }
680
681 /**
682 * Build the tree entity data - starting from a query retrieving the custom fields build the group
683 * tree data for the relevant entity (entity is included in the query).
684 *
685 * This function represents shared code between the buildEntityTreeMultipleFields & the buildEntityTreeSingleFields function
686 *
687 * @param array $groupTree (reference) group tree array which is being built
688 * @param string $query
689 * @param array $includedTables tables to include - required because the function (for historical reasons)
690 * iterates through the group tree
691 */
692 static public function buildTreeEntityDataFromQuery(&$groupTree, $query, $includedTables){
693 $dao = CRM_Core_DAO::executeQuery($query);
694 while ($dao->fetch()) {
695 foreach ($groupTree as $groupID => $group) {
696 if ($groupID === 'info') {
697 continue;
698 }
699 $table = $groupTree[$groupID]['table_name'];
700 //working from the groupTree instead of the table list means we have to iterate & exclude.
701 // this could possibly be re-written as other parts of the function have been refactored
702 // for now we just check if the given table is to be included in this function
703 if( !in_array($table, $includedTables)){
704 continue;
705 }
706 foreach ($group['fields'] as $fieldID => $dontCare) {
707 self::buildCustomFieldData($dao, $groupTree, $table, $groupID, $fieldID);
708 }
709 }
710 }
711 }
712
713 /**
714 * Build the entity-specific custom data into the group tree on a per-field basis
715 *
716 * @param object $dao object representing the custom field to be populated into the groupTree
717 * @param array $groupTree (reference) the group tree being build
718 * @param string $table table name
719 * @param unknown_type $groupID custom group ID
720 * @param unknown_type $fieldID custom field ID
721 */
722 static public function buildCustomFieldData($dao, &$groupTree, $table, $groupID, $fieldID){
723 $column = $groupTree[$groupID]['fields'][$fieldID]['column_name'];
724 $idName = "{$table}_id";
725 $fieldName = "{$table}_{$column}";
726 $dataType = $groupTree[$groupID]['fields'][$fieldID]['data_type'];
727 if ($dataType == 'File') {
728 if (isset($dao->$fieldName)) {
729 $config = CRM_Core_Config::singleton();
730 $fileDAO = new CRM_Core_DAO_File();
731 $fileDAO->id = $dao->$fieldName;
732
733 if ($fileDAO->find(TRUE)) {
734 $entityIDName = "{$table}_entity_id";
735 $customValue['id'] = $dao->$idName;
736 $customValue['data'] = $fileDAO->uri;
737 $customValue['fid'] = $fileDAO->id;
738 $customValue['fileURL'] = CRM_Utils_System::url('civicrm/file', "reset=1&id={$fileDAO->id}&eid={$dao->$entityIDName}");
739 $customValue['displayURL'] = NULL;
740 $deleteExtra = ts('Are you sure you want to delete attached file.');
741 $deleteURL = array(
742 CRM_Core_Action::DELETE =>
743 array(
744 'name' => ts('Delete Attached File'),
745 'url' => 'civicrm/file',
746 'qs' => 'reset=1&id=%%id%%&eid=%%eid%%&fid=%%fid%%&action=delete',
747 'extra' =>
748 'onclick = "if (confirm( \'' . $deleteExtra . '\' ) ) this.href+=\'&amp;confirmed=1\'; else return false;"',
749 ),
750 );
751 $customValue['deleteURL'] = CRM_Core_Action::formLink($deleteURL,
752 CRM_Core_Action::DELETE,
753 array(
754 'id' => $fileDAO->id,
755 'eid' => $dao->$entityIDName,
756 'fid' => $fieldID,
87dab4a4
AH
757 ),
758 ts('more'),
759 FALSE,
760 'file.manage.delete',
761 'File',
762 $fileDAO->id
c43cedc8 763 );
764 $customValue['deleteURLArgs'] = CRM_Core_BAO_File::deleteURLArgs($table, $dao->$entityIDName, $fileDAO->id);
765 $customValue['fileName'] = CRM_Utils_File::cleanFileName(basename($fileDAO->uri));
766 if ($fileDAO->mime_type == "image/jpeg" ||
767 $fileDAO->mime_type == "image/pjpeg" ||
768 $fileDAO->mime_type == "image/gif" ||
769 $fileDAO->mime_type == "image/x-png" ||
770 $fileDAO->mime_type == "image/png"
771 ) {
772 $customValue['displayURL'] = $customValue['fileURL'];
773 $entityId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_EntityFile',
774 $fileDAO->id,
775 'entity_id',
776 'file_id'
777 );
778 $customValue['imageURL'] = str_replace('persist/contribute', 'custom', $config->imageUploadURL) . $fileDAO->uri;
779 list($path) = CRM_Core_BAO_File::path($fileDAO->id, $entityId,
780 NULL, NULL
781 );
a52de115
CB
782 if ($path && file_exists($path)) {
783 list($imageWidth, $imageHeight) = getimagesize($path);
784 list($imageThumbWidth, $imageThumbHeight) = CRM_Contact_BAO_Contact::getThumbSize($imageWidth, $imageHeight);
785 $customValue['imageThumbWidth'] = $imageThumbWidth;
786 $customValue['imageThumbHeight'] = $imageThumbHeight;
787 }
6a488035
TO
788 }
789 }
790 }
c43cedc8 791 else {
792 $customValue = array(
793 'id' => $dao->$idName,
794 'data' => '',
795 );
796 }
797 }
798 else {
799 $customValue = array(
800 'id' => $dao->$idName,
801 'data' => $dao->$fieldName,
802 );
6a488035
TO
803 }
804
c43cedc8 805 if (!array_key_exists('customValue', $groupTree[$groupID]['fields'][$fieldID])) {
806 $groupTree[$groupID]['fields'][$fieldID]['customValue'] = array();
807 }
808 if (empty($groupTree[$groupID]['fields'][$fieldID]['customValue'])) {
809 $groupTree[$groupID]['fields'][$fieldID]['customValue'] = array(1 => $customValue);
810 }
811 else {
812 $groupTree[$groupID]['fields'][$fieldID]['customValue'][] = $customValue;
813 }
6a488035
TO
814 }
815
816 /**
817 * Get the group title.
818 *
819 * @param int $id id of group.
820 *
821 * @return string title
822 *
823 * @access public
824 * @static
825 *
826 */
827 public static function getTitle($id) {
828 return CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $id, 'title');
829 }
830
831 /**
832 * Get custom group details for a group.
833 *
834 * An array containing custom group details (including their custom field) is returned.
835 *
836 * @param int $groupId - group id whose details are needed
837 * @param boolean $searchable - is this field searchable
838 * @param array $extends - which table does it extend if any
839 *
840 * @return array $groupTree - array consisting of all group and field details
841 *
842 * @access public
843 *
844 * @static
845 *
846 */
e41f4660 847 public static function &getGroupDetail($groupId = NULL, $searchable = NULL, &$extends = NULL, $inSelector = NULL) {
6a488035
TO
848 // create a new tree
849 $groupTree = array();
850 $select = $from = $where = $orderBy = '';
851
852 $tableData = array();
853
854 // using tableData to build the queryString
855 $tableData = array(
856 'civicrm_custom_field' =>
857 array(
858 'id',
859 'label',
860 'data_type',
861 'html_type',
862 'default_value',
863 'attributes',
864 'is_required',
865 'help_pre',
866 'help_post',
867 'options_per_line',
868 'is_searchable',
869 'start_date_years',
870 'end_date_years',
871 'is_search_range',
872 'date_format',
873 'time_format',
874 'note_columns',
875 'note_rows',
876 'column_name',
877 'is_view',
878 'option_group_id',
e41f4660 879 'in_selector',
6a488035
TO
880 ),
881 'civicrm_custom_group' =>
882 array(
883 'id',
884 'name',
885 'title',
886 'help_pre',
887 'help_post',
888 'collapse_display',
889 'collapse_adv_display',
890 'extends',
891 'extends_entity_column_value',
892 'table_name',
e41f4660 893 'is_multiple',
6a488035
TO
894 ),
895 );
896
897 // create select
898 $select = "SELECT";
899 $s = array();
900 foreach ($tableData as $tableName => $tableColumn) {
901 foreach ($tableColumn as $columnName) {
902 $s[] = "{$tableName}.{$columnName} as {$tableName}_{$columnName}";
903 }
904 }
905 $select = 'SELECT ' . implode(', ', $s);
906 $params = array();
907 // from, where, order by
908 $from = " FROM civicrm_custom_field, civicrm_custom_group";
909 $where = " WHERE civicrm_custom_field.custom_group_id = civicrm_custom_group.id
910 AND civicrm_custom_group.is_active = 1
911 AND civicrm_custom_field.is_active = 1 ";
912 if ($groupId) {
913 $params[1] = array($groupId, 'Integer');
914 $where .= " AND civicrm_custom_group.id = %1";
915 }
916
917 if ($searchable) {
918 $where .= " AND civicrm_custom_field.is_searchable = 1";
919 }
920
e41f4660
PJ
921 if ($inSelector) {
922 $where .= " AND civicrm_custom_field.in_selector = 1 AND civicrm_custom_group.is_multiple = 1 ";
923 }
924
6a488035
TO
925 if ($extends) {
926 $clause = array();
927 foreach ($extends as $e) {
928 $clause[] = "civicrm_custom_group.extends = '$e'";
929 }
930 $where .= " AND ( " . implode(' OR ', $clause) . " ) ";
931
932 //include case activities customdata if case is enabled
933 if (in_array('Activity', $extends)) {
934 $extendValues = implode(',', array_keys(CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE)));
935 $where .= " AND ( civicrm_custom_group.extends_entity_column_value IS NULL OR REPLACE( civicrm_custom_group.extends_entity_column_value, %2, ' ') IN ($extendValues) ) ";
936 $params[2] = array(CRM_Core_DAO::VALUE_SEPARATOR, 'String');
937 }
938 }
939
940 // ensure that the user has access to these custom groups
941 $where .= " AND " . CRM_Core_Permission::customGroupClause(CRM_Core_Permission::VIEW,
942 'civicrm_custom_group.'
943 );
944
945 $orderBy = " ORDER BY civicrm_custom_group.weight, civicrm_custom_field.weight";
946
947 // final query string
948 $queryString = $select . $from . $where . $orderBy;
949
950 // dummy dao needed
951 $crmDAO = CRM_Core_DAO::executeQuery($queryString, $params);
952
953 // process records
954 while ($crmDAO->fetch()) {
955 $groupId = $crmDAO->civicrm_custom_group_id;
956 $fieldId = $crmDAO->civicrm_custom_field_id;
957
958 // create an array for groups if it does not exist
959 if (!array_key_exists($groupId, $groupTree)) {
960 $groupTree[$groupId] = array();
961 $groupTree[$groupId]['id'] = $groupId;
962
963 foreach ($tableData['civicrm_custom_group'] as $v) {
964 $fullField = "civicrm_custom_group_" . $v;
965
966 if ($v == 'id' || is_null($crmDAO->$fullField)) {
967 continue;
968 }
969
970 $groupTree[$groupId][$v] = $crmDAO->$fullField;
971 }
972
973 $groupTree[$groupId]['fields'] = array();
974 }
975
976 // add the fields now (note - the query row will always contain a field)
977 $groupTree[$groupId]['fields'][$fieldId] = array();
978 $groupTree[$groupId]['fields'][$fieldId]['id'] = $fieldId;
979
980 foreach ($tableData['civicrm_custom_field'] as $v) {
981 $fullField = "civicrm_custom_field_" . $v;
982 if ($v == 'id' || is_null($crmDAO->$fullField)) {
983 continue;
984 }
985 $groupTree[$groupId]['fields'][$fieldId][$v] = $crmDAO->$fullField;
986 }
987 }
988
989 return $groupTree;
990 }
991
992 public static function &getActiveGroups($entityType, $path, $cidToken = '%%cid%%') {
993 // for Group's
994 $customGroupDAO = new CRM_Core_DAO_CustomGroup();
995
e41f4660
PJ
996 // get 'Tab' and 'Tab with table' groups
997 $customGroupDAO->whereAdd("style IN ('Tab', 'Tab with table')");
6a488035
TO
998 $customGroupDAO->whereAdd("is_active = 1");
999
1000 // add whereAdd for entity type
1001 self::_addWhereAdd($customGroupDAO, $entityType, $cidToken);
1002
1003 $groups = array();
1004
1005 $permissionClause = CRM_Core_Permission::customGroupClause(CRM_Core_Permission::VIEW, NULL, TRUE);
1006 $customGroupDAO->whereAdd($permissionClause);
1007
1008 // order by weight
1009 $customGroupDAO->orderBy('weight');
1010 $customGroupDAO->find();
1011
1012 // process each group with menu tab
1013 while ($customGroupDAO->fetch()) {
1014 $group = array();
1015 $group['id'] = $customGroupDAO->id;
1016 $group['path'] = $path;
1017 $group['title'] = "$customGroupDAO->title";
1018 $group['query'] = "reset=1&gid={$customGroupDAO->id}&cid={$cidToken}";
1019 $group['extra'] = array('gid' => $customGroupDAO->id);
1020 $group['table_name'] = $customGroupDAO->table_name;
1021 $groups[] = $group;
1022 }
1023
1024 return $groups;
1025 }
1026
1027 /**
1028 * Get the table name for the entity type
1029 * currently if entity type is 'Contact', 'Individual', 'Household', 'Organization'
1030 * tableName is 'civicrm_contact'
1031 *
1032 * @param string $entityType what entity are we extending here ?
1033 *
1034 * @return string $tableName
1035 *
1036 * @access private
1037 * @static
1038 *
1039 */
1040 private static function _getTableName($entityType) {
1041 $tableName = '';
1042 switch ($entityType) {
1043 case 'Contact':
1044 case 'Individual':
1045 case 'Household':
1046 case 'Organization':
1047 $tableName = 'civicrm_contact';
1048 break;
1049
1050 case 'Contribution':
1051 $tableName = 'civicrm_contribution';
1052 break;
1053
1054 case 'Group':
1055 $tableName = 'civicrm_group';
1056 break;
1057 // DRAFTING: Verify if we cannot make it pluggable
1058
1059 case 'Activity':
1060 $tableName = 'civicrm_activity';
1061 break;
1062
1063 case 'Relationship':
1064 $tableName = 'civicrm_relationship';
1065 break;
1066
1067 case 'Membership':
1068 $tableName = 'civicrm_membership';
1069 break;
1070
1071 case 'Participant':
1072 $tableName = 'civicrm_participant';
1073 break;
1074
1075 case 'Event':
1076 $tableName = 'civicrm_event';
1077 break;
1078
1079 case 'Grant':
1080 $tableName = 'civicrm_grant';
1081 break;
1082 // need to add cases for Location, Address
1083 }
1084
1085 return $tableName;
1086 }
1087
1088 /**
1089 * Get a list of custom groups which extend a given entity type.
1090 * If there are custom-groups which only apply to certain subtypes,
1091 * those WILL be included.
1092 *
1093 * @param $entityType string
1094 * @return CRM_Core_DAO_CustomGroup
1095 */
1096 static function getAllCustomGroupsByBaseEntity($entityType) {
1097 $customGroupDAO = new CRM_Core_DAO_CustomGroup();
1098 self::_addWhereAdd($customGroupDAO, $entityType, NULL, TRUE);
1099 return $customGroupDAO;
1100 }
1101
1102 /**
1103 * Add the whereAdd clause for the DAO depending on the type of entity
1104 * the custom group is extending.
1105 *
1106 * @param object CRM_Core_DAO_CustomGroup (reference) - Custom Group DAO.
1107 * @param string $entityType - what entity are we extending here ?
1108 *
1109 * @return void
1110 *
1111 * @access private
1112 * @static
1113 *
1114 */
1115 private static function _addWhereAdd(&$customGroupDAO, $entityType, $entityID = NULL, $allSubtypes = FALSE) {
1116 $addSubtypeClause = FALSE;
1117
1118 switch ($entityType) {
1119 case 'Contact':
1120 // if contact, get all related to contact
1121 $extendList = "'Contact','Individual','Household','Organization'";
1122 $customGroupDAO->whereAdd("extends IN ( $extendList )");
1123 if (!$allSubtypes) {
1124 $addSubtypeClause = TRUE;
1125 }
1126 break;
1127
1128 case 'Individual':
1129 case 'Household':
1130 case 'Organization':
1131 // is I/H/O then get I/H/O and contact
1132 $extendList = "'Contact','$entityType'";
1133 $customGroupDAO->whereAdd("extends IN ( $extendList )");
1134 if (!$allSubtypes) {
1135 $addSubtypeClause = TRUE;
1136 }
1137 break;
1138
1139 case 'Location':
1140 case 'Address':
1141 case 'Activity':
1142 case 'Contribution':
1143 case 'Membership':
1144 case 'Participant':
1145 $customGroupDAO->whereAdd("extends IN ('$entityType')");
1146 break;
1147 }
1148
1149 if ($addSubtypeClause) {
1150 $csType = is_numeric($entityID) ? CRM_Contact_BAO_Contact::getContactSubType($entityID) : FALSE;
1151
1152 if (!empty($csType)) {
1153 $subtypeClause = array();
1154 foreach ($csType as $subtype) {
1155 $subtype = CRM_Core_DAO::VALUE_SEPARATOR . $subtype . CRM_Core_DAO::VALUE_SEPARATOR;
1156 $subtypeClause[] = "extends_entity_column_value LIKE '%{$subtype}%'";
1157 }
1158 $subtypeClause[] = "extends_entity_column_value IS NULL";
1159 $customGroupDAO->whereAdd("( " . implode(' OR ', $subtypeClause) . " )");
1160 }
1161 else {
1162 $customGroupDAO->whereAdd("extends_entity_column_value IS NULL");
1163 }
1164 }
1165 }
1166
1167 /**
1168 * Delete the Custom Group.
1169 *
1170 * @param $group object the DAO custom group object
1171 * @param $force boolean whether to force the deletion, even if there are custom fields
1172 *
1173 * @return boolean false if field exists for this group, true if group gets deleted.
1174 *
1175 * @access public
1176 * @static
1177 *
1178 */
1179 public static function deleteGroup($group, $force = FALSE) {
1180
1181 //check wheter this contain any custom fields
1182 $customField = new CRM_Core_DAO_CustomField();
1183 $customField->custom_group_id = $group->id;
1184 $customField->find();
1185
1186 // return early if there are custom fields and we're not
1187 // forcing the delete, otherwise delete the fields one by one
1188 while ($customField->fetch()) {
1189 if (!$force) {
1190 return FALSE;
1191 }
1192 CRM_Core_BAO_CustomField::deleteField($customField);
1193 }
1194
1195 // drop the table associated with this custom group
1196 CRM_Core_BAO_SchemaHandler::dropTable($group->table_name);
1197
1198 //delete custom group
1199 $group->delete();
1200
1201 CRM_Utils_Hook::post('delete', 'CustomGroup', $group->id, $group);
1202
1203 return TRUE;
1204 }
1205
1206 static function setDefaults(&$groupTree, &$defaults, $viewMode = FALSE, $inactiveNeeded = FALSE, $action = CRM_Core_Action::NONE) {
1207 foreach ($groupTree as $id => $group) {
1208 if (!isset($group['fields'])) {
1209 continue;
1210 }
1211 $groupId = CRM_Utils_Array::value('id', $group);
1212 foreach ($group['fields'] as $field) {
1213 if (CRM_Utils_Array::value('element_value', $field) !== NULL) {
1214 $value = $field['element_value'];
1215 }
1216 elseif (CRM_Utils_Array::value('default_value', $field) !== NULL &&
1217 ($action != CRM_Core_Action::UPDATE ||
1218 // CRM-7548
1219 !array_key_exists('element_value', $field)
1220 )
1221 ) {
1222 $value = $viewMode ? NULL : $field['default_value'];
1223 }
1224 else {
1225 continue;
1226 }
1227
1228 $fieldId = $field['id'];
1229 $elementName = $field['element_name'];
1230 switch ($field['html_type']) {
1231 case 'Multi-Select':
1232 case 'AdvMulti-Select':
1233 case 'CheckBox':
1234 $defaults[$elementName] = array();
1235 $customOption = CRM_Core_BAO_CustomOption::getCustomOption($field['id'], $inactiveNeeded);
1236 if ($viewMode) {
1237 $checkedData = explode(CRM_Core_DAO::VALUE_SEPARATOR, substr($value, 1, -1));
1238 if (isset($value)) {
1239 foreach ($customOption as $customValue => $customLabel) {
1240 if (in_array($customValue, $checkedData)) {
1241 if ($field['html_type'] == 'CheckBox') {
1242 $defaults[$elementName][$customValue] = 1;
1243 }
1244 else {
1245 $defaults[$elementName][$customValue] = $customValue;
1246 }
1247 }
1248 else {
1249 $defaults[$elementName][$customValue] = 0;
1250 }
1251 }
1252 }
1253 }
1254 else {
1255 if (isset($field['customValue']['data'])) {
1256 $checkedData = explode(CRM_Core_DAO::VALUE_SEPARATOR, substr($field['customValue']['data'], 1, -1));
1257 foreach ($customOption as $val) {
1258 if (in_array($val['value'], $checkedData)) {
1259 if ($field['html_type'] == 'CheckBox') {
1260 $defaults[$elementName][$val['value']] = 1;
1261 }
1262 else {
1263 $defaults[$elementName][$val['value']] = $val['value'];
1264 }
1265 }
1266 else {
1267 $defaults[$elementName][$val['value']] = 0;
1268 }
1269 }
1270 }
1271 else {
1272 $checkedValue = explode(CRM_Core_DAO::VALUE_SEPARATOR, substr($value, 1, -1));
1273 foreach ($customOption as $val) {
1274 if (in_array($val['value'], $checkedValue)) {
1275 if ($field['html_type'] == 'CheckBox') {
1276 $defaults[$elementName][$val['value']] = 1;
1277 }
1278 else {
1279 $defaults[$elementName][$val['value']] = $val['value'];
1280 }
1281 }
1282 }
1283 }
1284 }
1285 break;
1286
1287 case 'Select Date':
1288 if (isset($value)) {
1289 if (empty($field['time_format'])) {
1290 list($defaults[$elementName]) = CRM_Utils_Date::setDateDefaults($value, NULL,
1291 $field['date_format']
1292 );
1293 }
1294 else {
1295 $timeElement = $elementName . '_time';
1296 if (substr($elementName, -1) == ']') {
1297 $timeElement = substr($elementName, 0, -1) . '_time]';
1298 }
1299 list($defaults[$elementName], $defaults[$timeElement]) = CRM_Utils_Date::setDateDefaults($value, NULL, $field['date_format'], $field['time_format']);
1300 }
1301 }
1302 break;
1303
1304 case 'Multi-Select Country':
1305 case 'Multi-Select State/Province':
1306 if (isset($value)) {
1307 $checkedValue = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
1308 foreach ($checkedValue as $val) {
1309 if ($val) {
1310 $defaults[$elementName][$val] = $val;
1311 }
1312 }
1313 }
1314 break;
1315
1316 case 'Select Country':
1317 if ($value) {
1318 $defaults[$elementName] = $value;
1319 }
1320 else {
1321 $config = CRM_Core_Config::singleton();
1322 $defaults[$elementName] = $config->defaultContactCountry;
1323 }
1324 break;
1325
6a488035
TO
1326 default:
1327 if ($field['data_type'] == "Float") {
1328 $defaults[$elementName] = (float)$value;
1329 }
1330 elseif ($field['data_type'] == 'Money' &&
1331 $field['html_type'] == 'Text'
1332 ) {
1333 $defaults[$elementName] = CRM_Utils_Money::format($value, NULL, '%a');
1334 }
1335 else {
1336 $defaults[$elementName] = $value;
1337 }
1338 }
1339 }
1340 }
1341 }
1342
1343 static function postProcess(&$groupTree, &$params, $skipFile = FALSE) {
1344 // Get the Custom form values and groupTree
1345 // first reset all checkbox and radio data
1346 foreach ($groupTree as $groupID => $group) {
1347 if ($groupID === 'info') {
1348 continue;
1349 }
1350 foreach ($group['fields'] as $field) {
1351 $fieldId = $field['id'];
1352
1353 //added Multi-Select option in the below if-statement
1354 if ($field['html_type'] == 'CheckBox' || $field['html_type'] == 'Radio' ||
1355 $field['html_type'] == 'AdvMulti-Select' || $field['html_type'] == 'Multi-Select'
1356 ) {
1357 $groupTree[$groupID]['fields'][$fieldId]['customValue']['data'] = 'NULL';
1358 }
1359
1360 $v = NULL;
1361 foreach ($params as $key => $val) {
1362 if (preg_match('/^custom_(\d+)_?(-?\d+)?$/', $key, $match) &&
1363 $match[1] == $field['id']
1364 ) {
1365 $v = $val;
1366 }
1367 }
1368
1369
1370 if (!isset($groupTree[$groupID]['fields'][$fieldId]['customValue'])) {
1371 // field exists in db so populate value from "form".
1372 $groupTree[$groupID]['fields'][$fieldId]['customValue'] = array();
1373 }
1374
1375 switch ($groupTree[$groupID]['fields'][$fieldId]['html_type']) {
1376
1377 //added for CheckBox
1378
1379 case 'CheckBox':
1380 if (!empty($v)) {
1381 $customValue = array_keys($v);
1382 $groupTree[$groupID]['fields'][$fieldId]['customValue']['data'] = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, $customValue) . CRM_Core_DAO::VALUE_SEPARATOR;
1383 }
1384 else {
1385 $groupTree[$groupID]['fields'][$fieldId]['customValue']['data'] = NULL;
1386 }
1387 break;
1388
1389 //added for Advanced Multi-Select
1390
1391 case 'AdvMulti-Select':
1392 //added for Multi-Select
1393 case 'Multi-Select':
1394 if (!empty($v)) {
1395 $groupTree[$groupID]['fields'][$fieldId]['customValue']['data'] = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, $v) . CRM_Core_DAO::VALUE_SEPARATOR;
1396 }
1397 else {
1398 $groupTree[$groupID]['fields'][$fieldId]['customValue']['data'] = NULL;
1399 }
1400 break;
1401
1402 case 'Select Date':
1403 $date = CRM_Utils_Date::processDate($v);
1404 $groupTree[$groupID]['fields'][$fieldId]['customValue']['data'] = $date;
1405 break;
1406
1407 case 'File':
1408 if ($skipFile) {
1409 continue;
1410 }
1411
1412 //store the file in d/b
1413 $entityId = explode('=', $groupTree['info']['where'][0]);
1414 $fileParams = array('upload_date' => date('Ymdhis'));
1415
1416 if ($groupTree[$groupID]['fields'][$fieldId]['customValue']['fid']) {
1417 $fileParams['id'] = $groupTree[$groupID]['fields'][$fieldId]['customValue']['fid'];
1418 }
1419 if (!empty($v)) {
1420 $fileParams['uri'] = $v['name'];
1421 $fileParams['mime_type'] = $v['type'];
1422 CRM_Core_BAO_File::filePostProcess($v['name'],
1423 $groupTree[$groupID]['fields'][$fieldId]['customValue']['fid'],
1424 $groupTree[$groupID]['table_name'],
1425 trim($entityId[1]),
1426 FALSE,
1427 TRUE,
1428 $fileParams,
1429 'custom_' . $fieldId,
1430 $v['type']
1431 );
1432 }
1433 $defaults = array();
1434 $paramsFile = array(
1435 'entity_table' => $groupTree[$groupID]['table_name'],
1436 'entity_id' => $entityId[1],
1437 );
1438
1439 CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_EntityFile',
1440 $paramsFile,
1441 $defaults
1442 );
1443
1444 $groupTree[$groupID]['fields'][$fieldId]['customValue']['data'] = $defaults['file_id'];
1445 break;
1446
1447 default:
1448 $groupTree[$groupID]['fields'][$fieldId]['customValue']['data'] = $v;
1449 break;
1450 }
1451 }
1452 }
1453 }
1454
1455 /**
1456 * generic function to build all the form elements for a specific group tree
1457 *
7b226831 1458 * @param object $form the form object
1459 * @param array $groupTree the group tree object
1460 * @param boolean $inactiveNeeded return inactive custom groups
1461 * @param string $prefix prefix for custom grouptree assigned to template
6a488035
TO
1462 *
1463 * @return void
1464 * @access public
1465 * @static
1466 */
7b226831 1467 static function buildQuickForm(&$form, &$groupTree, $inactiveNeeded = FALSE, $prefix = '' ) {
6a488035 1468 $form->assign_by_ref("{$prefix}groupTree", $groupTree);
6a488035
TO
1469
1470 // this is fix for date field
1471 $form->assign('currentYear', date('Y'));
1472
1473 foreach ($groupTree as $id => $group) {
6a488035 1474 CRM_Core_ShowHideBlocks::links($form, $group['title'], '', '');
6a488035
TO
1475 foreach ($group['fields'] as $field) {
1476 $required = CRM_Utils_Array::value('is_required', $field);
1477 //fix for CRM-1620
1478 if ($field['data_type'] == 'File') {
bdadc7ac 1479 if (!empty($field['element_value']['data'])) {
6a488035
TO
1480 $required = 0;
1481 }
1482 }
1483
1484 $fieldId = $field['id'];
1485 $elementName = $field['element_name'];
1486 CRM_Core_BAO_CustomField::addQuickFormElement($form, $elementName, $fieldId, $inactiveNeeded, $required);
1487 }
1488 }
fdb90896 1489 if (!empty($form->_stateCountryMap['state_province']) && !empty($form->_stateCountryMap['country'])) {
1490 foreach ($form->_stateCountryMap['state_province'] as $key => $value) {
1491 $stateCountryMap[$key]['state_province'] = $value;
1492 $stateCountryMap[$key]['country'] = $form->_stateCountryMap['country'][$key];
1493 }
1494 CRM_Core_BAO_Address::addStateCountryMap($stateCountryMap);
1495 }
6a488035
TO
1496 }
1497
1498 /**
1499 * Function to extract the get params from the url, validate
1500 * and store it in session
1501 *
1502 * @param CRM_Core_Form $form the form object
1503 * @param string $type the type of custom group we are using
1504 *
1505 * @return void
1506 * @access public
1507 * @static
1508 */
1509 static function extractGetParams(&$form, $type) {
1510 // if not GET params return
1511 if (empty($_GET)) {
1512 return;
1513 }
1514
1515 $groupTree = CRM_Core_BAO_CustomGroup::getTree($type, $form);
1516 $customValue = array();
1517 $htmlType = array('CheckBox', 'Multi-Select', 'AdvMulti-Select', 'Select', 'Radio');
1518
1519 foreach ($groupTree as $group) {
1520 if (!isset($group['fields'])) {
1521 continue;
1522 }
1523 foreach ($group['fields'] as $key => $field) {
1524 $fieldName = 'custom_' . $key;
6fc7508a 1525 $value = CRM_Utils_Request::retrieve($fieldName, 'String', $form, FALSE, NULL, 'GET');
6a488035
TO
1526
1527 if ($value) {
1528 $valid = FALSE;
1529 if (!in_array($field['html_type'], $htmlType) ||
1530 $field['data_type'] == 'Boolean'
1531 ) {
1532 $valid = CRM_Core_BAO_CustomValue::typecheck($field['data_type'], $value);
1533 }
1534 if ($field['html_type'] == 'CheckBox' ||
1535 $field['html_type'] == 'AdvMulti-Select' ||
1536 $field['html_type'] == 'Multi-Select'
1537 ) {
1538 $value = str_replace("|", ",", $value);
1539 $mulValues = explode(',', $value);
1540 $customOption = CRM_Core_BAO_CustomOption::getCustomOption($key, TRUE);
1541 $val = array();
1542 foreach ($mulValues as $v1) {
1543 foreach ($customOption as $coID => $coValue) {
1544 if (strtolower(trim($coValue['label'])) == strtolower(trim($v1))) {
1545 $val[$coValue['value']] = 1;
1546 }
1547 }
1548 }
1549 if (!empty($val)) {
1550 $value = $val;
1551 $valid = TRUE;
1552 }
1553 else {
1554 $value = NULL;
1555 }
1556 }
1557 elseif ($field['html_type'] == 'Select' ||
1558 ($field['html_type'] == 'Radio' &&
1559 $field['data_type'] != 'Boolean'
1560 )
1561 ) {
1562 $customOption = CRM_Core_BAO_CustomOption::getCustomOption($key, TRUE);
1563 foreach ($customOption as $customID => $coValue) {
1564 if (strtolower(trim($coValue['label'])) == strtolower(trim($value))) {
1565 $value = $coValue['value'];
1566 $valid = TRUE;
1567 }
1568 }
1569 }
1570 elseif ($field['data_type'] == 'Date') {
1571 if (!empty($value)) {
1572 $time = NULL;
a7488080 1573 if (!empty($field['time_format'])) {
6fc7508a 1574 $time = CRM_Utils_Request::retrieve($fieldName . '_time', 'String', $form, FALSE, NULL, 'GET');
6a488035
TO
1575 }
1576 list($value, $time) = CRM_Utils_Date::setDateDefaults($value . ' ' . $time);
a7488080 1577 if (!empty($field['time_format'])) {
6a488035
TO
1578 $customValue[$fieldName . '_time'] = $time;
1579 }
1580 }
1581 $valid = TRUE;
1582 }
1583
1584 if ($valid) {
1585 $customValue[$fieldName] = $value;
1586 }
1587 }
1588 }
1589 }
1590
1591 return $customValue;
1592 }
1593
1594 /**
1595 * Function to check the type of custom field type (eg: Used for Individual, Contribution, etc)
1596 * this function is used to get the custom fields of a type (eg: Used for Individual, Contribution, etc )
1597 *
1598 * @param int $customFieldId custom field id
1599 * @param array $removeCustomFieldTypes remove custom fields of a type eg: array("Individual") ;
1600 *
1601 *
1602 * @return boolean false if it matches else true
1603 * @static
1604 * @access public
1605 */
1606 static function checkCustomField($customFieldId, &$removeCustomFieldTypes) {
1607 $query = "SELECT cg.extends as extends
1608 FROM civicrm_custom_group as cg, civicrm_custom_field as cf
1609 WHERE cg.id = cf.custom_group_id
1610 AND cf.id =" . CRM_Utils_Type::escape($customFieldId, 'Integer');
1611
1612 $extends = CRM_Core_DAO::singleValueQuery($query);
1613
1614 if (in_array($extends, $removeCustomFieldTypes)) {
1615 return FALSE;
1616 }
1617 return TRUE;
1618 }
1619
1620 static function mapTableName($table) {
1621 switch ($table) {
1622 case 'Contact':
1623 case 'Individual':
1624 case 'Household':
1625 case 'Organization':
1626 return 'civicrm_contact';
1627
1628 case 'Activity':
1629 return 'civicrm_activity';
1630
1631 case 'Group':
1632 return 'civicrm_group';
1633
1634 case 'Contribution':
1635 return 'civicrm_contribution';
1636
1637 case 'Relationship':
1638 return 'civicrm_relationship';
1639
1640 case 'Event':
1641 return 'civicrm_event';
1642
1643 case 'Membership':
1644 return 'civicrm_membership';
1645
1646 case 'Participant':
1647 case 'ParticipantRole':
1648 case 'ParticipantEventName':
1649 case 'ParticipantEventType':
1650 return 'civicrm_participant';
1651
1652 case 'Grant':
1653 return 'civicrm_grant';
1654
1655 case 'Pledge':
1656 return 'civicrm_pledge';
1657
1658 case 'Address':
1659 return 'civicrm_address';
1660
1661 case 'Campaign':
1662 return 'civicrm_campaign';
1663
1664 default:
1665 $query = "
1666SELECT IF( EXISTS(SELECT name FROM civicrm_contact_type WHERE name like %1), 1, 0 )";
1667 $qParams = array(1 => array($table, 'String'));
1668 $result = CRM_Core_DAO::singleValueQuery($query, $qParams);
1669
1670 if ($result) {
1671 return 'civicrm_contact';
1672 }
1673 else {
1674 $extendObjs = CRM_Core_OptionGroup::values('cg_extend_objects', FALSE, FALSE, FALSE, NULL, 'name');
1675 if (array_key_exists($table, $extendObjs)) {
1676 return $extendObjs[$table];
1677 }
1678 CRM_Core_Error::fatal();
1679 }
1680 }
1681 }
1682
1683 static function createTable($group) {
1684 $params = array(
1685 'name' => $group->table_name,
1686 'is_multiple' => $group->is_multiple ? 1 : 0,
1687 'extends_name' => self::mapTableName($group->extends),
1688 );
1689
1690 $tableParams = CRM_Core_BAO_CustomField::defaultCustomTableSchema($params);
1691
1692 CRM_Core_BAO_SchemaHandler::createTable($tableParams);
1693 }
1694
1695 /**
1696 * Function returns formatted groupTree, sothat form can be easily build in template
1697 *
1698 * @param array $groupTree associated array
1699 * @param int $groupCount group count by default 1, but can varry for multiple value custom data
1700 * @param object form object
1701 *
1702 * @return array $formattedGroupTree
1703 */
1704 static function formatGroupTree(&$groupTree, $groupCount = 1, &$form) {
1705 $formattedGroupTree = array();
1706 $uploadNames = array();
1707
1708 foreach ($groupTree as $key => $value) {
1709 if ($key === 'info') {
1710 continue;
1711 }
1712
1713 // add group information
1714 $formattedGroupTree[$key]['name'] = CRM_Utils_Array::value('name', $value);
1715 $formattedGroupTree[$key]['title'] = CRM_Utils_Array::value('title', $value);
1716 $formattedGroupTree[$key]['help_pre'] = CRM_Utils_Array::value('help_pre', $value);
1717 $formattedGroupTree[$key]['help_post'] = CRM_Utils_Array::value('help_post', $value);
1718 $formattedGroupTree[$key]['collapse_display'] = CRM_Utils_Array::value('collapse_display', $value);
1719 $formattedGroupTree[$key]['collapse_adv_display'] = CRM_Utils_Array::value('collapse_adv_display', $value);
1720
1721 // this params needed of bulding multiple values
1722 $formattedGroupTree[$key]['is_multiple'] = CRM_Utils_Array::value('is_multiple', $value);
1723 $formattedGroupTree[$key]['extends'] = CRM_Utils_Array::value('extends', $value);
1724 $formattedGroupTree[$key]['extends_entity_column_id'] = CRM_Utils_Array::value('extends_entity_column_id', $value);
1725 $formattedGroupTree[$key]['extends_entity_column_value'] = CRM_Utils_Array::value('extends_entity_column_value', $value);
1726 $formattedGroupTree[$key]['subtype'] = CRM_Utils_Array::value('subtype', $value);
1727 $formattedGroupTree[$key]['max_multiple'] = CRM_Utils_Array::value('max_multiple', $value);
1728
1729 // add field information
1730 foreach ($value['fields'] as $k => $properties) {
1731 $properties['element_name'] = "custom_{$k}_-{$groupCount}";
dcf0d348 1732 if (isset($properties['customValue']) && !CRM_Utils_System::isNull($properties['customValue'])) {
6a488035
TO
1733 if (isset($properties['customValue'][$groupCount])) {
1734 $properties['element_name'] = "custom_{$k}_{$properties['customValue'][$groupCount]['id']}";
1735 $formattedGroupTree[$key]['table_id'] = $properties['customValue'][$groupCount]['id'];
1736 if ($properties['data_type'] == 'File') {
1737 $properties['element_value'] = $properties['customValue'][$groupCount];
1738 $uploadNames[] = $properties['element_name'];
1739 }
1740 else {
1741 $properties['element_value'] = $properties['customValue'][$groupCount]['data'];
1742 }
1743 }
1744 }
1745 unset($properties['customValue']);
1746 $formattedGroupTree[$key]['fields'][$k] = $properties;
1747 }
1748 }
1749
1750 if ($form) {
1751 // hack for field type File
1752 $formUploadNames = $form->get('uploadNames');
1753 if (is_array($formUploadNames)) {
1754 $uploadNames = array_unique(array_merge($formUploadNames, $uploadNames));
1755 }
1756
1757 $form->set('uploadNames', $uploadNames);
1758 }
1759
1760 return $formattedGroupTree;
1761 }
1762
1763 /**
1764 * Build custom data view
77b97be7
EM
1765 *
1766 * @param object $form page object
1767 * @param array $groupTree associated array
1768 * @param boolean $returnCount true if customValue count needs to be returned
1769 * @param null $gID
1770 * @param null $prefix
1771 * @param null $customValueId
1772 *
1773 * @return array|int
6a488035 1774 */
e41f4660 1775 static function buildCustomDataView(&$form, &$groupTree, $returnCount = FALSE, $gID = NULL, $prefix = NULL, $customValueId = NULL) {
fcbb756b 1776 $details = array();
6a488035
TO
1777 foreach ($groupTree as $key => $group) {
1778 if ($key === 'info') {
1779 continue;
1780 }
1781
1782 foreach ($group['fields'] as $k => $properties) {
1783 $groupID = $group['id'];
1784 if (!empty($properties['customValue'])) {
1785 foreach ($properties['customValue'] as $values) {
e41f4660
PJ
1786 if (!empty($customValueId) && $customValueId != $values['id']) {
1787 continue;
1788 }
6a488035
TO
1789 $details[$groupID][$values['id']]['title'] = CRM_Utils_Array::value('title', $group);
1790 $details[$groupID][$values['id']]['name'] = CRM_Utils_Array::value('name', $group);
1791 $details[$groupID][$values['id']]['help_pre'] = CRM_Utils_Array::value('help_pre', $group);
1792 $details[$groupID][$values['id']]['help_post'] = CRM_Utils_Array::value('help_post', $group);
1793 $details[$groupID][$values['id']]['collapse_display'] = CRM_Utils_Array::value('collapse_display', $group);
1794 $details[$groupID][$values['id']]['collapse_adv_display'] = CRM_Utils_Array::value('collapse_adv_display', $group);
1795 $details[$groupID][$values['id']]['fields'][$k] = array('field_title' => CRM_Utils_Array::value('label', $properties),
1796 'field_type' => CRM_Utils_Array::value('html_type',
1797 $properties
1798 ),
1799 'field_data_type' => CRM_Utils_Array::value('data_type',
1800 $properties
1801 ),
1802 'field_value' => self::formatCustomValues($values,
1803 $properties
1804 ),
1805 'options_per_line' => CRM_Utils_Array::value('options_per_line',
1806 $properties
1807 ),
1808 );
1809 // also return contact reference contact id if user has view all or edit all contacts perm
1810 if ((CRM_Core_Permission::check('view all contacts') || CRM_Core_Permission::check('edit all contacts'))
1811 && $details[$groupID][$values['id']]['fields'][$k]['field_data_type'] == 'ContactReference'
1812 ) {
1813 $details[$groupID][$values['id']]['fields'][$k]['contact_ref_id'] = CRM_Utils_Array::value('data', $values);
1814 }
1815 }
1816 }
1817 else {
1818 $details[$groupID][0]['title'] = CRM_Utils_Array::value('title', $group);
1819 $details[$groupID][0]['name'] = CRM_Utils_Array::value('name', $group);
1820 $details[$groupID][0]['help_pre'] = CRM_Utils_Array::value('help_pre', $group);
1821 $details[$groupID][0]['help_post'] = CRM_Utils_Array::value('help_post', $group);
1822 $details[$groupID][0]['collapse_display'] = CRM_Utils_Array::value('collapse_display', $group);
1823 $details[$groupID][0]['collapse_adv_display'] = CRM_Utils_Array::value('collapse_adv_display', $group);
1824 $details[$groupID][0]['fields'][$k] = array('field_title' => CRM_Utils_Array::value('label', $properties));
1825 }
1826 }
1827 }
1828
1829 if ($returnCount) {
1830 //return a single value count if group id is passed to function
1831 //else return a groupId and count mapped array
1832 if (!empty($gID)){
1833 return count($details[$gID]);
1834 }
1835 else {
fcbb756b 1836 $countValue = array();
6a488035
TO
1837 foreach( $details as $key => $value ) {
1838 $countValue[$key] = count($details[$key]);
1839 }
1840 return $countValue;
1841 }
1842 }
1843 else {
1844 $form->assign_by_ref("{$prefix}viewCustomData", $details);
1845 return $details;
1846 }
1847 }
1848
1849 /**
1850 * Format custom value according to data, view mode
1851 *
1852 * @param array $values associated array of custom values
1853 * @param array $field associated array
1854 * @param boolean $dncOptionPerLine true if optionPerLine should not be consider
1855 *
77b97be7 1856 * @return array|null|string
6a488035
TO
1857 */
1858 static function formatCustomValues(&$values, &$field, $dncOptionPerLine = FALSE) {
1859 $value = $values['data'];
1860
1861 //changed isset CRM-4601
1862 if (CRM_Utils_System::isNull($value)) {
1863 return;
1864 }
1865
1866 $htmlType = CRM_Utils_Array::value('html_type', $field);
1867 $dataType = CRM_Utils_Array::value('data_type', $field);
1868 $option_group_id = CRM_Utils_Array::value('option_group_id', $field);
1869 $timeFormat = CRM_Utils_Array::value('time_format', $field);
1870 $optionPerLine = CRM_Utils_Array::value('options_per_line', $field);
1871
1872 $freezeString = "";
1873 $freezeStringChecked = "";
1874
1875 switch ($dataType) {
1876 case 'Date':
1877 $customTimeFormat = '';
1878 $customFormat = NULL;
1879
1880 switch ($timeFormat) {
1881 case 1:
1882 $customTimeFormat = '%l:%M %P';
1883 break;
1884
1885 case 2:
1886 $customTimeFormat = '%H:%M';
1887 break;
1888
1889 default:
1890 // if time is not selected remove time from value
1891 $value = substr($value, 0, 10);
1892 }
1893
1894 $supportableFormats = array(
1895 'mm/dd' => "%B %E%f $customTimeFormat",
1896 'dd-mm' => "%E%f %B $customTimeFormat",
1897 'yy' => "%Y $customTimeFormat",
1898 'M yy' => "%b %Y $customTimeFormat",
1899 'yy-mm' => "%Y-%m $customTimeFormat"
1900 );
1901
1902 if ($format = CRM_Utils_Array::value('date_format', $field)) {
1903 if (array_key_exists($format, $supportableFormats)) {
1904 $customFormat = $supportableFormats["$format"];
1905 }
1906 }
1907
1908 $retValue = CRM_Utils_Date::customFormat($value, $customFormat);
1909 break;
1910
1911 case 'Boolean':
1912 if ($value == '1') {
1913 $retValue = $freezeStringChecked . ts('Yes') . "\n";
1914 }
1915 else {
1916 $retValue = $freezeStringChecked . ts('No') . "\n";
1917 }
1918 break;
1919
1920 case 'Link':
1921 if ($value) {
1922 $retValue = CRM_Utils_System::formatWikiURL($value);
1923 }
1924 break;
1925
1926 case 'File':
1927 $retValue = $values;
1928 break;
1929
1930 case 'ContactReference':
a7488080 1931 if (!empty($values['data'])) {
6a488035
TO
1932 $retValue = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $values['data'], 'display_name');
1933 }
1934 break;
1935
1936 case 'Memo':
1937 $retValue = $value;
1938 break;
1939
1940 case 'Float':
1941 if ($htmlType == 'Text') {
1942 $retValue = (float)$value;
1943 break;
1944 }
1945 case 'Money':
1946 if ($htmlType == 'Text') {
1947 $retValue = CRM_Utils_Money::format($value, NULL, '%a');
1948 break;
1949 }
1950 case 'String':
1951 case 'Int':
1952 if (in_array($htmlType, array('Text', 'TextArea'))) {
1953 $retValue = $value;
1954 break;
1955 }
1956 // note that if its not text / textarea, the code falls thru and executes
1957 // the below case also
1958 case 'StateProvince':
1959 case 'Country':
1960 $options = array();
1961 $coDAO = NULL;
1962
1963 //added check for Multi-Select in the below if-statement
1964 $customData[] = $value;
1965
1966 //form custom data for multiple-valued custom data
1967 switch ($htmlType) {
1968 case 'Multi-Select Country':
1969 case 'Select Country':
1970 $customData = $value;
1971 if (!is_array($value)) {
1972 $customData = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
1973 }
1974 $query = "
1975 SELECT id as value, name as label
1976 FROM civicrm_country";
1977 $coDAO = CRM_Core_DAO::executeQuery($query);
1978 break;
1979
1980 case 'Select State/Province':
1981 case 'Multi-Select State/Province':
1982 $customData = $value;
1983 if (!is_array($value)) {
1984 $customData = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
1985 }
1986
1987 $query = "
1988 SELECT id as value, name as label
1989 FROM civicrm_state_province";
1990 $coDAO = CRM_Core_DAO::executeQuery($query);
1991 break;
1992
1993 case 'Select':
1994 $customData = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
1995 if ($option_group_id) {
1996 $options = CRM_Core_BAO_OptionValue::getOptionValuesAssocArray($option_group_id);
1997 }
1998 break;
1999
2000 case 'CheckBox':
2001 case 'AdvMulti-Select':
2002 case 'Multi-Select':
2003 $customData = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
2004 default:
2005 if ($option_group_id) {
2006 $options = CRM_Core_BAO_OptionValue::getOptionValuesAssocArray($option_group_id);
2007 }
2008 }
2009
2010 if (is_object($coDAO)) {
2011 while ($coDAO->fetch()) {
4dba067a
ML
2012 if ($dataType == 'Country') {
2013 // NB: using ts() on a variable here is OK, since the value is pre-determined, not variable
2014 // and already extracted to .pot files.
2015 $options[$coDAO->value] = ts($coDAO->label, array('context' => 'country'));
2016 }
2017 elseif ($dataType == 'StateProvince') {
2018 $options[$coDAO->value] = ts($coDAO->label, array('context' => 'province'));
2019 }
2020 else {
2021 $options[$coDAO->value] = $coDAO->label;
2022 }
6a488035
TO
2023 }
2024 }
2025
2026 CRM_Utils_Hook::customFieldOptions($field['id'], $options, FALSE);
2027
2028 $retValue = NULL;
2029 foreach ($options as $optionValue => $optionLabel) {
2030 if ($dataType == 'Money') {
2031 foreach ($customData as $k => $v) {
2032 $customData[] = CRM_Utils_Money::format($v, NULL, '%a');
2033 }
2034 }
2035
2036 //to show only values that are checked
2037 if (in_array((string) $optionValue, $customData)) {
2038 $checked = in_array($optionValue, $customData) ? $freezeStringChecked : $freezeString;
2039 if (!$optionPerLine || $dncOptionPerLine) {
2040 if ($retValue) {
2041 $retValue .= ", ";
2042 }
2043 $retValue .= $checked . $optionLabel;
2044 }
2045 else {
2046 $retValue[] = $checked . $optionLabel;
2047 }
2048 }
2049 }
2050 break;
2051 }
2052
2053 //special case for option per line formatting
2054 if ($optionPerLine > 1 && is_array($retValue)) {
2055 $rowCounter = 0;
2056 $fieldCounter = 0;
2057 $displayValues = array();
2058 $displayString = '';
2059 foreach ($retValue as $val) {
2060 if ($displayString) {
2061 $displayString .= ", ";
2062 }
2063
2064 $displayString .= $val;
2065 $rowCounter++;
2066 $fieldCounter++;
2067
2068 if (($rowCounter == $optionPerLine) || ($fieldCounter == count($retValue))) {
2069 $displayValues[] = $displayString;
2070 $displayString = '';
2071 $rowCounter = 0;
2072 }
2073 }
2074 $retValue = $displayValues;
2075 }
2076
2077 $retValue = isset($retValue) ? $retValue : NULL;
2078 return $retValue;
2079 }
2080
2081 /**
2082 * Get the custom group titles by custom field ids.
2083 *
2084 * @param array $fieldIds - array of custom field ids.
2085 *
2086 * @return array $groupLabels - array consisting of groups and fields labels with ids.
2087 * @access public
2088 */
2089 public static function getGroupTitles($fieldIds) {
2090 if (!is_array($fieldIds) && empty($fieldIds)) {
2091 return;
2092 }
2093
2094 $groupLabels = array();
2095 $fIds = "(" . implode(',', $fieldIds) . ")";
2096
2097 $query = "
2098SELECT civicrm_custom_group.id as groupID, civicrm_custom_group.title as groupTitle,
2099 civicrm_custom_field.label as fieldLabel, civicrm_custom_field.id as fieldID
2100 FROM civicrm_custom_group, civicrm_custom_field
2101 WHERE civicrm_custom_group.id = civicrm_custom_field.custom_group_id
2102 AND civicrm_custom_field.id IN {$fIds}";
2103
2104 $dao = CRM_Core_DAO::executeQuery($query);
2105 while ($dao->fetch()) {
2106 $groupLabels[$dao->fieldID] = array(
2107 'fieldID' => $dao->fieldID,
2108 'fieldLabel' => $dao->fieldLabel,
2109 'groupID' => $dao->groupID,
2110 'groupTitle' => $dao->groupTitle,
2111 );
2112 }
2113
2114 return $groupLabels;
2115 }
2116
2117 static function dropAllTables() {
2118 $query = "SELECT table_name FROM civicrm_custom_group";
2119 $dao = CRM_Core_DAO::executeQuery($query);
2120
2121 while ($dao->fetch()) {
2122 $query = "DROP TABLE IF EXISTS {$dao->table_name}";
2123 CRM_Core_DAO::executeQuery($query);
2124 }
2125 }
2126
2127 /**
2128 * Check whether custom group is empty or not.
2129 *
2130 * @param int $gID - custom group id.
2131 *
2132 * @return boolean true if empty otherwise false.
2133 * @access public
2134 */
2135 static function isGroupEmpty($gID) {
2136 if (!$gID) {
2137 return;
2138 }
2139
2140 $tableName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup',
2141 $gID,
2142 'table_name'
2143 );
2144
2145 $query = "SELECT count(id) FROM {$tableName} WHERE id IS NOT NULL LIMIT 1";
2146 $value = CRM_Core_DAO::singleValueQuery($query);
2147
2148 if (empty($value)) {
2149 return TRUE;
2150 }
2151
2152 return FALSE;
2153 }
2154
2155 /**
2156 * Get the list of types for objects that a custom group extends to.
2157 *
2158 * @param array $types - var which should have the list appended.
2159 *
2160 * @return array of types.
2161 * @access public
2162 */
2163 static function getExtendedObjectTypes(&$types = array( )) {
2164 static $flag = FALSE, $objTypes = array();
2165
2166 if (!$flag) {
2167 $extendObjs = array();
2168 CRM_Core_OptionValue::getValues(array('name' => 'cg_extend_objects'), $extendObjs);
2169
2170 foreach ($extendObjs as $ovId => $ovValues) {
2171 if ($ovValues['description']) {
2172 // description is expected to be a callback func to subtypes
2173 list($callback, $args) = explode(';', trim($ovValues['description']));
2174
0e6e8724 2175 if (empty($args)) {
6a488035
TO
2176 $args = array();
2177 }
2178
2179 if (!is_array($args)) {
2180 CRM_Core_Error::fatal('Arg is not of type array');
2181 }
2182
2183 list($className) = explode('::', $callback);
2184 require_once (str_replace('_',DIRECTORY_SEPARATOR, $className) . '.php');
2185
2186 $objTypes[$ovValues['value']] = call_user_func_array($callback, $args);
2187 }
2188 }
2189 $flag = TRUE;
2190 }
2191
2192 $types = array_merge($types, $objTypes);
2193 return $objTypes;
2194 }
2195
534a5e67 2196 static function hasReachedMaxLimit($customGroupId, $entityId) {
6a488035
TO
2197 //check whether the group is multiple
2198 $isMultiple = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroupId, 'is_multiple');
2199 $isMultiple = ($isMultiple) ? TRUE : FALSE;
2200 $hasReachedMax = FALSE;
2201 if ($isMultiple &&
2202 ($maxMultiple = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroupId, 'max_multiple'))) {
2203 if (!$maxMultiple) {
2204 $hasReachedMax = FALSE;
2205 } else {
2206 $tableName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroupId, 'table_name');
2207 //count the number of entries for a entity
2208 $sql = "SELECT COUNT(id) FROM {$tableName} WHERE entity_id = %1";
2209 $params = array(1 => array($entityId, 'Integer'));
2210 $count = CRM_Core_DAO::singleValueQuery($sql, $params);
2211
2212 if ($count >= $maxMultiple) {
2213 $hasReachedMax = TRUE;
2214 }
2215 }
2216 }
2217 return $hasReachedMax;
2218 }
2219
9ff5f6c0
N
2220 static function getMultipleFieldGroup() {
2221 $multipleGroup = array();
2222 $dao = new CRM_Core_DAO_CustomGroup();
2223 $dao->is_multiple = 1 ;
2224 $dao->find();
2225 while($dao->fetch()) {
2226 $multipleGroup[$dao->id] = $dao->title;
2227 }
2228 return $multipleGroup;
2229 }
6a488035
TO
2230 }
2231