Have a question about CiviCRM? Get it answered quickly at the new CiviCRM Stack Exchange Q+A siteThis forum was archived on 25 November 2017. Learn more.How to get involved.What to do if you think you've found a bug.
<?php/** * Files required for this package */require_once 'api/v3/utils.php';require_once 'CRM/Core/BAO/CustomField.php';require_once 'CRM/Core/BAO/CustomValueTable.php';/** * Sets custom values for an entity. * * * @param $params expected keys are in format custom_fieldID:recordID or custom_groupName:fieldName:recordID * for example: * 'id' => 123, // entity ID. You do not need to specify entity type, we figure it out based on the fields you're using * 'custom_6' => 'foo', // (omitting :id) inserts or updates a field in a single-valued group * 'custom_24' => array('bar', 'baz'), // custom_24 is checkbox or multiselect, so pass items as an array * 'custom_33:5' => value, // in this case custom_33 is part of a multi-valued group, and we're updating record id 5 * 'custom_33:-1' => value, // inserts new record in multi-valued group * 'custom_33:-2' => value, // inserts another new record in multi-valued group * 'custom_some_group:my_field => 'myinfo', // you can use group_name:field_name instead of ID * 'custom_some_big_group:my_other_field:8 => 'myinfo', // updates record ID 8 in my_other_field in multi-valued some_big_group * * * @return array('values' => TRUE) or array('is_error' => 1, 'error_message' => 'what went wrong') * * @access public * */function civicrm_api3_custom_value_create( $params ) { civicrm_api3_verify_mandatory($params, null, array('id')); $create = array('entityID' => $params['id']); // Translate names and //Convert arrays to multi-value strings $sp = CRM_Core_DAO::VALUE_SEPARATOR; foreach ($params as $id => $param) { if (is_array($param)) { $param = $sp . implode($sp, $param) . $sp; } list($c, $id) = explode('_', $id, 2); if ($c != 'custom') { continue; } list($i, $n, $x) = explode(':', $id); if (is_numeric($i)) { $key = $i; $x = $n; } else { // Lookup names if ID was not supplied $key = CRM_Core_BAO_CustomField::getCustomFieldID($i, $n); if (!$key) { continue; } } if ($x && is_numeric($x)) { $key .= '_' . $x; } $create['custom_' . $key] = $param; } $result = CRM_Core_BAO_CustomValueTable::setValues($create); if ($result['is_error']) { return civicrm_api3_create_error($result['error_message']); } return civicrm_api3_create_success(true, $params);}/** * Use this API to get existing custom values for an entity. * * @param $params array specifying the id of the entity * Optionally include entity_type param, i.e. 'entity_type' => 'Activity' * If no entity_type is supplied, it will be determined based on the fields you request. * If no entity_type is supplied and no fields are specified, 'Contact' will be assumed and it will return all custom fields. * Optionally include the desired custom data to be fetched (or else all custom data for this entity will be returned) * Example: 'id' => 123, 'return.custom_6' => 1, 'return.custom_33' => 1 * If you do not know the ID, you may use group name : field name, for example 'return.custom_foo_stuff:my_field' => 1 * (note that custom is not part of the group name in this example; all keys should start with return.custom_) * If names are given instead of IDs, then data will be output in the same format. * * @return array. For fields in single-value custom fieldsets, format will be 'custom_6' => 'foo' * For multi-value fieldsets, format will be 'custom_6:11' => 'foo', 'custom_6:12' => 'bar', 'custom_6:13' => 'baz' * * @access public * **/function civicrm_api3_custom_value_get($params) { civicrm_api3_verify_mandatory($params, null, array('id')); $getParams = array('entityID' => $params['id']); $getParams['entityType'] = $params['entity_type']; foreach ($params as $id => $param) { if ($param && substr($id, 0, 6) == 'return') { list($c, $i) = explode('_', substr($id, 7), 2); if ($c != 'custom') { continue; } if (is_numeric($i)) { $names['custom_' . $i] = 'custom_' . $i; $id = $i; } else { // Lookup names if ID was not supplied list($group, $field) = explode(':', $i, 2); $id = CRM_Core_BAO_CustomField::getCustomFieldID($field, $group); if (!$id) { continue; } $names['custom_' .$id] = 'custom_' . $i; } $getParams['custom_' . $id] = 1; } } $result = CRM_Core_BAO_CustomValueTable::getValues($getParams); if ($result['is_error']) { return civicrm_api3_create_error($result['error_message']); } else { $entity_id = $result['entityID']; unset($result['is_error'], $result['entityID']); // Translate IDs to names if they were given that way and // Convert multi-value strings to arrays $sp = CRM_Core_DAO::VALUE_SEPARATOR; foreach ($result as $id => $value) { if (strpos($value, $sp) !== FALSE) { $value = explode($sp, trim($value, $sp)); } list($c, $i, $n) = explode('_', $id); if ($name = $names[$c .'_'. $i]) { $id = $name; } elseif ($c == 'custom') { $id = $c .'_'. $i; } if ($n && $c == 'custom') { $id .= ':' . $n; } $values[$id] = $value; } return civicrm_api3_create_success(array($entity_id => $values), $params); }}
I think the output should be flat
Array( [is_error] => 0 [version] => 3 [count] => 3 [values] => Array ( [Additional_Info] => Array ( [0] => Array ( [HS_Graduation_Date] => 1998-06-01 00:00:00 ) ) [Single_Stuff] => Array ( [0] => Array ( [Some_text] => text!!! [Some_Date] => 2011-05-25 12:34:00 [Some_More_Info] => Ipsum lorem... ) ) [My_Multi] => Array ( [4] => Array ( [Here_s_some_text] => yea! [Are_you_cool_] => 0 ) [5] => Array ( [Here_s_some_text] => more [Are_you_cool_] => 0 ) [6] => Array ( [Here_s_some_text] => getting there [Are_you_cool_] => 0 ) [7] => Array ( [Here_s_some_text] => ok, ok, you're cool [Are_you_cool_] => 1 ) ) ))
Why would we want to have 'entity_id' be a param when every other API uses 'id'?
Here's some more that I'd like to add:FOR THE GET FUNCITON:-Returning arrays keyed by name is very nice and probably should be the default. However sometimes you want it keyed by group ID and field ID rather than the names. So I propose adding a 'return_format' => 'id' optional param.
-Specifying what you want returned could use some love. I don't really like the format 'return.my_group:some_field'. Since you're specifying the group, why not just leave it at that? Why would you ever not want every field in a group returned?
-Lobo suggests that for multi-valued fields (checkboxes, etc) we should return value => label rather than just an array of values. Makes sense, hopefully there's a BAO to fetch that info.
FOR THE CREATE FUNCTION:Haven't touched this since we changed around the get function to return a nested array. So currently it takes input like this: * 'custom_6' => 'foo', // (omitting :id) inserts or updates a field in a single-valued group * 'custom_24' => array('bar', 'baz'), // custom_24 is checkbox or multiselect, so pass items as an array * 'custom_33:5' => value, // in this case custom_33 is part of a multi-valued group, and we're updating record id 5 * 'custom_33:-1' => value, // inserts new record in multi-valued group * 'custom_33:-2' => value, // inserts another new record in multi-valued group * 'custom_some_group:my_field => 'myinfo', // you can use group_name:field_name instead of ID * 'custom_some_big_group:my_other_field:8 => 'myinfo', // updates record ID 8 in my_other_field in multi-valued some_big_groupPersonally I'm fine with that, but now it's inconsistent with our output. Suggestions?
i checked last nite and php/smarty are not happy with the : separator. The only valid characters in a variable name are: alphanumeric and underscorethis means we wont be able to use $custom_groupName:fieldName