CRM-15792 fix along with api test
authoratif-shaikh <shaikh388@gmail.com>
Mon, 23 Feb 2015 14:07:45 +0000 (19:37 +0530)
committeratif-shaikh <shaikh388@gmail.com>
Mon, 23 Feb 2015 14:07:45 +0000 (19:37 +0530)
----------------------------------------
* CRM-15792: Loss of data when creating / updating custom datetime fields through the API
  https://issues.civicrm.org/jira/browse/CRM-15792

CRM/Core/BAO/CustomField.php
api/v3/utils.php
tests/phpunit/api/v3/ContactTest.php

index bf96c1cb1aa32aac48f6f21bed3cc9ac14152d4e..17b461639c7fdea7010d5f95ba51f45573ff316e 100644 (file)
@@ -278,7 +278,8 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
     $customField->is_searchable = CRM_Utils_Array::value('is_searchable', $params, FALSE);
     $customField->in_selector = CRM_Utils_Array::value('in_selector', $params, FALSE);
     $customField->is_search_range = CRM_Utils_Array::value('is_search_range', $params, FALSE);
-    $customField->is_active = CRM_Utils_Array::value('is_active', $params, FALSE);
+    //CRM-15792 - Custom field gets disabled if is_active not set
+    $customField->is_active = CRM_Utils_Array::value('is_active', $params, TRUE);
     $customField->is_view = CRM_Utils_Array::value('is_view', $params, FALSE);
     $customField->save();
 
index 6333488201559d1cf5bf79889ba8e7bf02b593e7..863c85503c360ec405a5b9cbe55b16d6690960cf 100644 (file)
@@ -1457,7 +1457,20 @@ function _civicrm_api3_custom_data_get(&$returnArray, $entity, $entity_id, $grou
  * @throws Exception
  */
 function _civicrm_api3_validate_fields($entity, $action, &$params, $fields, $errorMode = FALSE) {
+  //CRM-15792 handle datetime for custom fields below code handles chain api call
+  $chainApikeys = array_flip(preg_grep("/^api./", array_keys($params)));
+  if (!empty($chainApikeys) && is_array($chainApikeys)) {
+    foreach ($chainApikeys as $key => $value) {
+      if (is_array($params[$key])) {
+        $chainApiParams = array_intersect_key($fields, $params[$key]);
+        $customFields = array_fill_keys(array_keys($params[$key]), $key);
+      }
+    }
+  }
   $fields = array_intersect_key($fields, $params);
+  if (!empty($chainApiParams)) {
+    $fields = array_merge($fields, $chainApiParams);
+  }
   foreach ($fields as $fieldName => $fieldInfo) {
     switch (CRM_Utils_Array::value('type', $fieldInfo)) {
       case CRM_Utils_Type::T_INT:
@@ -1465,11 +1478,17 @@ function _civicrm_api3_validate_fields($entity, $action, &$params, $fields, $err
         _civicrm_api3_validate_integer($params, $fieldName, $fieldInfo, $entity);
         break;
 
-      case 4:
-      case 12:
+      case CRM_Utils_Type::T_DATE:
+      case CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME:
       case CRM_Utils_Type::T_TIMESTAMP:
         //field is of type date or datetime
-        _civicrm_api3_validate_date($params, $fieldName, $fieldInfo);
+        if (!empty($customFields) && array_key_exists($fieldName, $customFields)) {
+          $dateParams = &$params[$customFields[$fieldName]];
+        }
+        else {
+          $dateParams = &$params;
+        }
+        _civicrm_api3_validate_date($dateParams, $fieldName, $fieldInfo);
         break;
 
       case 32:
@@ -1815,7 +1834,7 @@ function _civicrm_api_get_custom_fields($entity, &$params) {
     // Regular fields have a 'name' property
     $value['name'] = 'custom_' . $key;
     $value['title'] = $value['label'];
-    $value['type'] = _getStandardTypeFromCustomDataType($value['data_type'], $value);
+    $value['type'] = _getStandardTypeFromCustomDataType($value);
     $ret['custom_' . $key] = $value;
   }
   return $ret;
@@ -1828,8 +1847,10 @@ function _civicrm_api_get_custom_fields($entity, &$params) {
  *
  * @return int
  */
-function _getStandardTypeFromCustomDataType($dataType, $value) {
-  if ($dataType == 'Date' && isset($value['time_format']) && $value['time_format'] > 0) {
+function _getStandardTypeFromCustomDataType($value) {
+  $dataType = $value['data_type'];
+  //CRM-15792 - If date custom field contains timeformat change type to DateTime
+  if ($value['data_type'] == 'Date' && isset($value['time_format']) && $value['time_format'] > 0) {
     $dataType = 'DateTime';
   }
   $mapping = array(
index f9d97e93942c1f60e20e9bc486ebc8b20ed70a05..d0f4addb44a704d88a85fb78addd8e64e62c0b5a 100644 (file)
@@ -357,6 +357,77 @@ class api_v3_ContactTest extends CiviUnitTestCase {
     $this->customGroupDelete($ids['custom_group_id']);
   }
 
+  /**
+   * CRM-15792 - create/update datetime field for contact.
+   */
+  public function testCreateContactCustomFldDateTime() {
+    $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'datetime_test_group'));
+    $dateTime = CRM_Utils_Date::currentDBDate();
+    //check date custom field is saved along with time when time_format is set
+    $params = array(
+      'first_name' => 'abc3',
+      'last_name' => 'xyz3',
+      'contact_type' => 'Individual',
+      'email' => 'man3@yahoo.com',
+      'api.CustomField.create' => array(
+        'custom_group_id' => $customGroup['id'],
+        'name' => 'test_datetime',
+        'label' => 'Demo Date',
+        'html_type' => 'Select Date',
+        'data_type' => 'Date',
+        'time_format' => 2,
+        'weight' => 4,
+        'is_required' => 1,
+        'is_searchable' => 0,
+        'is_active' => 1,
+      ),
+    );
+
+
+    $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__);
+    $customFldId = $result['values'][$result['id']]['api.CustomField.create']['id'];
+    $this->assertNotNull($result['id'], 'in line ' . __LINE__);
+    $this->assertNotNull($customFldId, 'in line ' . __LINE__);
+
+    $params = array(
+      'id' => $result['id'],
+      "custom_{$customFldId}" => $dateTime,
+      'api.CustomValue.get' => 1,
+    );
+
+    $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__);
+    $this->assertNotNull($result['id'], 'in line ' . __LINE__);
+    $customFldDate = date("YmdHis", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
+    $this->assertNotNull($customFldDate, 'in line ' . __LINE__);
+    $this->assertEquals($dateTime, $customFldDate);
+    $customValueId = $result['values'][$result['id']]['api.CustomValue.get']['values'][0]['id'];
+    $dateTime = date('Ymd');
+    //date custom field should not contain time part when time_format is null
+    $params = array(
+      'id' => $result['id'],
+      'api.CustomField.create' => array(
+        'id' => $customValueId,
+        'html_type' => 'Select Date',
+        'data_type' => 'Date',
+        'time_format' => '',
+      ),
+      'api.CustomValue.create' => array(
+        'id' => $customValueId,
+        'entity_id' => $result['id'],
+        "custom_{$customFldId}" => $dateTime,
+      ),
+      'api.CustomValue.get' => 1,
+    );
+    $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__);
+    $this->assertNotNull($result['id'], 'in line ' . __LINE__);
+    $customFldDate = date("Ymd", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
+    $customFldTime = date("His", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
+    $this->assertNotNull($customFldDate, 'in line ' . __LINE__);
+    $this->assertEquals($dateTime, $customFldDate);
+    $this->assertEquals(000000, $customFldTime);
+    $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__);
+  }
+
 
   /**
    * Test creating a current employer through API.