/**
  * @dataProvider entities_updatesingle
  *
  * limitations include the problem with avoiding loops when creating test objects -
  * hence FKs only set by createTestObject when required. e.g parent_id on campaign is not being followed through
  * Currency - only seems to support US
  */
 public function testCreateSingleValueAlter($entityName)
 {
     if (in_array($entityName, $this->toBeImplemented['create'])) {
         // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
         return;
     }
     $baoString = _civicrm_api3_get_DAO($entityName);
     $this->assertNotEmpty($baoString, $entityName);
     $this->assertNotEmpty($entityName, $entityName);
     $fieldsget = $fields = $this->callAPISuccess($entityName, 'getfields', array('action' => 'get'));
     if ($entityName != 'Pledge') {
         $fields = $this->callAPISuccess($entityName, 'getfields', array('action' => 'create'));
     }
     $fields = $fields['values'];
     $return = array_keys($fieldsget['values']);
     $valuesNotToReturn = $this->getKnownUnworkablesUpdateSingle($entityName, 'break_return');
     // these can't be requested as return values
     $entityValuesThatDontWork = array_merge($this->getKnownUnworkablesUpdateSingle($entityName, 'cant_update'), $this->getKnownUnworkablesUpdateSingle($entityName, 'cant_return'), $valuesNotToReturn);
     $return = array_diff($return, $valuesNotToReturn);
     $baoObj = new CRM_Core_DAO();
     $baoObj->createTestObject($baoString, array('currency' => 'USD'), 2, 0);
     $getentities = $this->callAPISuccess($entityName, 'get', array('sequential' => 1, 'return' => $return, 'options' => array('sort' => 'id DESC', 'limit' => 2)));
     // lets use first rather than assume only one exists
     $entity = $getentities['values'][0];
     $entity2 = $getentities['values'][1];
     foreach ($fields as $field => $specs) {
         $fieldName = $field;
         if (!empty($specs['uniquename'])) {
             $fieldName = $specs['uniquename'];
         }
         if ($field == 'currency' || $field == 'id' || $field == strtolower($entityName) . '_id' || in_array($field, $entityValuesThatDontWork)) {
             //@todo id & entity_id are correct but we should fix currency & frequency_day
             continue;
         }
         switch ($specs['type']) {
             case CRM_Utils_Type::T_DATE:
             case CRM_Utils_Type::T_TIMESTAMP:
                 $entity[$fieldName] = '2012-05-20';
                 break;
                 //case CRM_Utils_Type::T_DATETIME:
             //case CRM_Utils_Type::T_DATETIME:
             case 12:
                 $entity[$fieldName] = '2012-05-20 03:05:20';
                 break;
             case CRM_Utils_Type::T_STRING:
             case CRM_Utils_Type::T_BLOB:
             case CRM_Utils_Type::T_MEDIUMBLOB:
             case CRM_Utils_Type::T_TEXT:
             case CRM_Utils_Type::T_LONGTEXT:
             case CRM_Utils_Type::T_EMAIL:
                 $entity[$fieldName] = substr('New String', 0, CRM_Utils_Array::Value('maxlength', $specs, 100));
                 break;
             case CRM_Utils_Type::T_INT:
                 // probably created with a 1
                 $entity[$fieldName] = '6';
                 if (!empty($specs['FKClassName'])) {
                     if ($specs['FKClassName'] == $baoString) {
                         $entity[$fieldName] = (string) $entity2['id'];
                     } else {
                         $uniqueName = CRM_Utils_Array::value('uniqueName', $specs);
                         $entity[$fieldName] = (string) empty($entity2[$field]) ? CRM_Utils_Array::value($uniqueName, $entity2) : $entity2[$field];
                         //todo - there isn't always something set here - & our checking on unset values is limited
                         if (empty($entity[$field])) {
                             unset($entity[$field]);
                         }
                     }
                 }
                 break;
             case CRM_Utils_Type::T_BOOLEAN:
                 // probably created with a 1
                 $entity[$fieldName] = '0';
                 break;
             case CRM_Utils_Type::T_FLOAT:
             case CRM_Utils_Type::T_MONEY:
                 $entity[$field] = '222';
                 break;
             case CRM_Utils_Type::T_URL:
                 $entity[$field] = 'warm.beer.com';
         }
         if (!empty($specs['pseudoconstant']) || !empty($specs['enumValues'])) {
             $options = $this->callAPISuccess($entityName, 'getoptions', array('context' => 'create', 'field' => $field));
             if (empty($options['values'])) {
             }
             $entity[$field] = array_rand($options['values']);
         }
         $updateParams = array('id' => $entity['id'], $field => isset($entity[$field]) ? $entity[$field] : NULL);
         $update = $this->callAPISuccess($entityName, 'create', $updateParams);
         $checkParams = array('id' => $entity['id'], 'sequential' => 1, 'return' => $return, 'options' => array('sort' => 'id DESC', 'limit' => 2));
         $checkEntity = $this->callAPISuccess($entityName, 'getsingle', $checkParams);
         $this->assertAPIArrayComparison($entity, $checkEntity, array(), "checking if {$fieldName} was correctly updaetd\n" . print_r(array('update-params' => $updateParams, 'update-result' => $update, 'getsingle-params' => $checkParams, 'getsingle-result' => $checkEntity, 'expected entity' => $entity), TRUE));
     }
     $baoObj->deleteTestObjects($baoString);
     $baoObj->free();
 }
 /**
  * @dataProvider entities_updatesingle
  *
  * limitations include the problem with avoiding loops when creating test objects -
  * hence FKs only set by createTestObject when required. e.g parent_id on campaign is not being followed through
  * Currency - only seems to support US
  * @param $entityName
  */
 public function testCreateSingleValueAlter($entityName)
 {
     if (in_array($entityName, $this->toBeImplemented['create'])) {
         // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
         return;
     }
     $baoString = _civicrm_api3_get_BAO($entityName);
     $this->assertNotEmpty($baoString, $entityName);
     $this->assertNotEmpty($entityName, $entityName);
     $fieldsGet = $fields = $this->callAPISuccess($entityName, 'getfields', array('action' => 'get', 'options' => array('get_options' => 'all')));
     if ($entityName != 'Pledge') {
         $fields = $this->callAPISuccess($entityName, 'getfields', array('action' => 'create', 'options' => array('get_options' => 'all')));
     }
     $fields = $fields['values'];
     $return = array_keys($fieldsGet['values']);
     $valuesNotToReturn = $this->getKnownUnworkablesUpdateSingle($entityName, 'break_return');
     // these can't be requested as return values
     $entityValuesThatDoNotWork = array_merge($this->getKnownUnworkablesUpdateSingle($entityName, 'cant_update'), $this->getKnownUnworkablesUpdateSingle($entityName, 'cant_return'), $valuesNotToReturn);
     $return = array_diff($return, $valuesNotToReturn);
     $baoObj = new CRM_Core_DAO();
     $baoObj->createTestObject($baoString, array('currency' => 'USD'), 2, 0);
     $getEntities = $this->callAPISuccess($entityName, 'get', array('sequential' => 1, 'return' => $return, 'options' => array('sort' => 'id DESC', 'limit' => 2)));
     // lets use first rather than assume only one exists
     $entity = $getEntities['values'][0];
     $entity2 = $getEntities['values'][1];
     $this->deletableTestObjects[$baoString][] = $entity['id'];
     $this->deletableTestObjects[$baoString][] = $entity2['id'];
     foreach ($fields as $field => $specs) {
         $resetFKTo = NULL;
         $fieldName = $field;
         if (!empty($specs['uniquename'])) {
             $fieldName = $specs['uniquename'];
         }
         if ($field == 'currency' || $field == 'id' || $field == strtolower($entityName) . '_id' || in_array($field, $entityValuesThatDoNotWork)) {
             //@todo id & entity_id are correct but we should fix currency & frequency_day
             continue;
         }
         $this->assertArrayHasKey('type', $specs, "the _spec function for {$entityName} field {$field} does not specify the type");
         switch ($specs['type']) {
             case CRM_Utils_Type::T_DATE:
                 $entity[$fieldName] = '2012-05-20';
                 break;
             case CRM_Utils_Type::T_TIMESTAMP:
             case 12:
                 $entity[$fieldName] = '2012-05-20 03:05:20';
                 break;
             case CRM_Utils_Type::T_STRING:
             case CRM_Utils_Type::T_BLOB:
             case CRM_Utils_Type::T_MEDIUMBLOB:
             case CRM_Utils_Type::T_TEXT:
             case CRM_Utils_Type::T_LONGTEXT:
             case CRM_Utils_Type::T_EMAIL:
                 if ($fieldName == 'form_values' && $entityName == 'SavedSearch') {
                     // This is a hack for the SavedSearch API.
                     // It expects form_values to be an array.
                     // If you want to fix this, you should definitely read this forum
                     // post.
                     // http://forum.civicrm.org/index.php/topic,33990.0.html
                     // See also my question on the CiviCRM Stack Exchange:
                     // https://civicrm.stackexchange.com/questions/3437
                     $entity[$fieldName] = array('sort_name' => "SortName2");
                 } else {
                     $entity[$fieldName] = substr('New String', 0, CRM_Utils_Array::Value('maxlength', $specs, 100));
                     // typecast with array to satisfy changes made in CRM-13160
                     if ($entityName == 'MembershipType' && in_array($fieldName, array('relationship_type_id', 'relationship_direction'))) {
                         $entity[$fieldName] = (array) $entity[$fieldName];
                     }
                 }
                 break;
             case CRM_Utils_Type::T_INT:
                 // probably created with a 1
                 if ($fieldName == 'weight') {
                     $entity[$fieldName] = 2;
                 } elseif (!empty($specs['FKClassName'])) {
                     if ($specs['FKClassName'] == $baoString) {
                         $entity[$fieldName] = (string) $entity2['id'];
                     } else {
                         $uniqueName = CRM_Utils_Array::value('uniqueName', $specs, $fieldName);
                         if (!empty($entity[$fieldName])) {
                             $resetFKTo = array($fieldName => $entity[$fieldName], $uniqueName => $entity[$fieldName]);
                         }
                         $entity[$fieldName] = (string) empty($entity2[$field]) ? CRM_Utils_Array::value($uniqueName, $entity2) : $entity2[$field];
                         //todo - there isn't always something set here - & our checking on unset values is limited
                         if (empty($entity[$field])) {
                             unset($entity[$field]);
                         }
                     }
                 } else {
                     $entity[$fieldName] = '6';
                 }
                 break;
             case CRM_Utils_Type::T_BOOLEAN:
                 // probably created with a 1
                 $entity[$fieldName] = '0';
                 break;
             case CRM_Utils_Type::T_FLOAT:
             case CRM_Utils_Type::T_MONEY:
                 $entity[$field] = '22.75';
                 break;
             case CRM_Utils_Type::T_URL:
                 $entity[$field] = 'warm.beer.com';
         }
         if (empty($specs['FKClassName']) && (!empty($specs['pseudoconstant']) || !empty($specs['options']))) {
             $options = CRM_Utils_Array::value('options', $specs, array());
             if (!$options) {
                 //eg. pdf_format id doesn't ship with any
                 if (isset($specs['pseudoconstant']['optionGroupName'])) {
                     $optionValue = $this->callAPISuccess('option_value', 'create', array('option_group_id' => $specs['pseudoconstant']['optionGroupName'], 'label' => 'new option value', 'sequential' => 1));
                     $optionValue = $optionValue['values'];
                     $keyColumn = CRM_Utils_Array::value('keyColumn', $specs['pseudoconstant'], 'value');
                     $options[$optionValue[0][$keyColumn]] = 'new option value';
                 }
             }
             $entity[$field] = array_rand($options);
         }
         if (!empty($specs['FKClassName']) && !empty($specs['pseudoconstant'])) {
             // in the weird situation where a field has both an fk and pseudoconstant defined,
             // e.g. campaign_id field, need to flush caches.
             // FIXME: Why doesn't creating a campaign clear caches?
             civicrm_api3($entityName, 'getfields', array('cache_clear' => 1));
         }
         $updateParams = array('id' => $entity['id'], $field => isset($entity[$field]) ? $entity[$field] : NULL);
         if (isset($updateParams['financial_type_id']) && in_array($entityName, array('Grant'))) {
             //api has special handling on these 2 fields for backward compatibility reasons
             $entity['contribution_type_id'] = $updateParams['financial_type_id'];
         }
         if (!empty($specs['uniqueName'])) {
             $entity[$specs['uniqueName']] = $entity[$specs['name']];
         }
         $update = $this->callAPISuccess($entityName, 'create', $updateParams);
         $checkParams = array('id' => $entity['id'], 'sequential' => 1, 'return' => $return, 'options' => array('sort' => 'id DESC', 'limit' => 2));
         $checkEntity = $this->callAPISuccess($entityName, 'getsingle', $checkParams);
         $this->assertAPIArrayComparison($entity, $checkEntity, array(), "checking if {$fieldName} was correctly updated\n" . print_r(array('update-params' => $updateParams, 'update-result' => $update, 'getsingle-params' => $checkParams, 'getsingle-result' => $checkEntity, 'expected entity' => $entity), TRUE));
         if ($resetFKTo) {
             //reset the foreign key fields because otherwise our cleanup routine fails & some other unexpected stuff can kick in
             $entity = array_merge($entity, $resetFKTo);
             $updateParams = array_merge($updateParams, $resetFKTo);
             $this->callAPISuccess($entityName, 'create', $updateParams);
             if (isset($updateParams['financial_type_id']) && in_array($entityName, array('Grant'))) {
                 //api has special handling on these 2 fields for backward compatibility reasons
                 $entity['contribution_type_id'] = $updateParams['financial_type_id'];
             }
         }
     }
     $baoObj->free();
 }
 /**
  * @param array $params
  * @param int $id
  * @param $entity
  * @param int $delete
  * @param string $errorText
  *
  * @throws Exception
  */
 public function getAndCheck($params, $id, $entity, $delete = 1, $errorText = '')
 {
     $result = $this->callAPISuccessGetSingle($entity, array('id' => $id));
     if ($delete) {
         $this->callAPISuccess($entity, 'Delete', array('id' => $id));
     }
     $dateFields = $keys = $dateTimeFields = array();
     $fields = $this->callAPISuccess($entity, 'getfields', array('version' => 3, 'action' => 'get'));
     foreach ($fields['values'] as $field => $settings) {
         if (array_key_exists($field, $result)) {
             $keys[CRM_Utils_Array::Value('name', $settings, $field)] = $field;
         } else {
             $keys[CRM_Utils_Array::Value('name', $settings, $field)] = CRM_Utils_Array::value('name', $settings, $field);
         }
         $type = CRM_Utils_Array::value('type', $settings);
         if ($type == CRM_Utils_Type::T_DATE) {
             $dateFields[] = $settings['name'];
             // we should identify both real names & unique names as dates
             if ($field != $settings['name']) {
                 $dateFields[] = $field;
             }
         }
         if ($type == CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME) {
             $dateTimeFields[] = $settings['name'];
             // we should identify both real names & unique names as dates
             if ($field != $settings['name']) {
                 $dateTimeFields[] = $field;
             }
         }
     }
     if (strtolower($entity) == 'contribution') {
         $params['receive_date'] = date('Y-m-d', strtotime($params['receive_date']));
         // this is not returned in id format
         unset($params['payment_instrument_id']);
         $params['contribution_source'] = $params['source'];
         unset($params['source']);
     }
     foreach ($params as $key => $value) {
         if ($key == 'version' || substr($key, 0, 3) == 'api' || !array_key_exists($keys[$key], $result)) {
             continue;
         }
         if (in_array($key, $dateFields)) {
             $value = date('Y-m-d', strtotime($value));
             $result[$key] = date('Y-m-d', strtotime($result[$key]));
         }
         if (in_array($key, $dateTimeFields)) {
             $value = date('Y-m-d H:i:s', strtotime($value));
             $result[$keys[$key]] = date('Y-m-d H:i:s', strtotime(CRM_Utils_Array::value($keys[$key], $result, CRM_Utils_Array::value($key, $result))));
         }
         $this->assertEquals($value, $result[$keys[$key]], $key . " GetandCheck function determines that for key {$key} value: {$value} doesn't match " . print_r($result[$keys[$key]], TRUE) . $errorText);
     }
 }
 /**
  * Set the report date range where the report dates are defined by an end date and
  * an offset
  * @param array $startParams
  *  - start_offset
  *  - start_offset_unit
  */
 function setReportingStartDate($startParams)
 {
     if (!empty($startParams['start_offset']) && !$this->_reportingStartDate) {
         $startOffset = CRM_Utils_Array::Value($startParams['start_offset'], $this->_params, $startParams['start_offset']);
         $startOffsetUnit = CRM_Utils_Array::Value($startParams['start_offset_unit'], $this->_params, $startParams['start_offset_unit']);
         $this->_reportingStartDate = date('Y-m-d', strtotime("-  {$startOffset}  {$startOffsetUnit} ", strtotime($this->_params['receive_date_value'])));
     }
 }