From c3d3e837a95ac3f453bfd75ab5ddf2b075e3443f Mon Sep 17 00:00:00 2001 From: Eileen Date: Fri, 13 Sep 2013 21:03:06 +1200 Subject: [PATCH] CRM-13234 fix profile to support lcase 'primary' & fix existing test failures --- api/v3/Profile.php | 111 ++++++++++++++++----------- api/v3/examples/ProfileApply.php | 8 +- api/v3/examples/ProfileGet.php | 19 ++--- api/v3/examples/ProfileGetFields.php | 58 +++++++++++--- api/v3/examples/ProfileSubmit.php | 13 ++-- tests/phpunit/api/v3/ProfileTest.php | 4 +- 6 files changed, 137 insertions(+), 76 deletions(-) diff --git a/api/v3/Profile.php b/api/v3/Profile.php index aefd89c317..d3c1d8faca 100644 --- a/api/v3/Profile.php +++ b/api/v3/Profile.php @@ -104,8 +104,11 @@ function civicrm_api3_profile_get($params) { } else { $contactFields[$fieldName] = $field; + // we should return 'Primary' with & without capitalisation. it is more consistent with api to not + // capitalise, but for form support we need it for now. Hopefully we can move away from it + $contactFields[strtolower($fieldName)] = $field; + } } - } $ufGroupBAO->setProfileDefaults($params['contact_id'], $contactFields, $values[$profileID], TRUE); @@ -115,10 +118,15 @@ function civicrm_api3_profile_get($params) { } elseif(!empty($params['contact_id'])) { $ufGroupBAO->setProfileDefaults($params['contact_id'], $profileFields, $values[$profileID], TRUE); - } - else{ - $values[$profileID] = array_fill_keys(array_keys($profileFields), ''); - } + foreach ($values[$profileID] as $fieldName => $field){ + // we should return 'Primary' with & without capitalisation. it is more consistent with api to not + // capitalise, but for form support we need it for now. Hopefully we can move away from it + $values[$profileID][strtolower($fieldName)] = $field; + } + } + else{ + $values[$profileID] = array_fill_keys(array_keys($profileFields), ''); + } } if($nonStandardLegacyBehaviour) { $result = civicrm_api3_create_success(); @@ -161,18 +169,8 @@ function civicrm_api3_profile_submit($params) { $contactParams = $activityParams = $missingParams = array(); - $profileFields = CRM_Core_BAO_UFGroup::getFields($profileID, - FALSE, - NULL, - NULL, - NULL, - FALSE, - NULL, - TRUE, - NULL, - CRM_Core_Permission::EDIT - ); - + $profileFields = civicrm_api3('profile', 'getfields', array('action' => 'submit', 'profile_id' => $profileID)); + $profileFields = $profileFields['values']; if ($isContactActivityProfile) { civicrm_api3_verify_mandatory($params, NULL, array('activity_id')); @@ -186,12 +184,6 @@ function civicrm_api3_profile_submit($params) { } foreach ($profileFields as $fieldName => $field) { - if (CRM_Utils_Array::value('is_required', $field)) { - if (!CRM_Utils_Array::value($fieldName, $params) || empty($params[$fieldName])) { - $missingParams[] = $fieldName; - } - } - if (!isset($params[$fieldName])) { continue; } @@ -200,27 +192,27 @@ function civicrm_api3_profile_submit($params) { if ($params[$fieldName] && isset($params[$fieldName . '_id'])) { $value = $params[$fieldName . '_id']; } - - if ($isContactActivityProfile && CRM_Utils_Array::value('field_type', $field) == 'Activity') { - $activityParams[$fieldName] = $value; + $contactEntities = array('contact', 'individual', 'organization', 'household'); + $locationEntities = array('email', 'address', 'phone', 'website', 'im'); + + $entity = strtolower(CRM_Utils_Array::value('entity', $field)); + if($entity && !in_array($entity, array_merge($contactEntities, $locationEntities))) { + $contactParams['api.' . $entity . '.create'][$fieldName] = $value; + if(isset($params[$entity . '_id'])) { + //todo possibly declare $entity_id in getfields ? + $contactParams['api.' . $entity . '.create']['id'] = $params[$entity . '_id']; + } } else { - $contactParams[$fieldName] = $value; + $contactParams[_civicrm_api3_profile_translate_fieldnames_for_bao($fieldName)] = $value; } } - if (!empty($missingParams)) { - throw new API_Exception("Missing required parameters for profile id {$params['profile_id']}: " . implode(', ', $missingParams)); - } - $contactParams['contact_id'] = CRM_Utils_Array::value('contact_id', $params); $contactParams['profile_id'] = $profileID; $contactParams['skip_custom'] = 1; $contactProfileParams = civicrm_api3_profile_apply($contactParams); - if (CRM_Utils_Array::value('is_error', $contactProfileParams)) { - return $contactProfileParams; - } // Contact profile fields $profileParams = $contactProfileParams['values']; @@ -273,6 +265,20 @@ function civicrm_api3_profile_submit($params) { return $result; } + +/** + * The api standards expect field names to be lower case but the BAO uses mixed case + * so we accept 'email-primary' but pass 'email-Primary' to the BAO + * we could make the BAO handle email-primary but this would alter the fieldname seen by hooks + * & we would need to consider that change + * @param string $fieldName API field name + * + * @return string BAO Field Name + */ +function _civicrm_api3_profile_translate_fieldnames_for_bao($fieldName){ + $fieldName = str_replace('url', 'URL', $fieldName); + return str_replace('primary', 'Primary', $fieldName); +} /** * metadata for submit action * @param array $params @@ -314,14 +320,14 @@ function civicrm_api3_profile_set($params) { * @deprecated - appears to be an internal function - should not be accessible via api * Provide formatted values for profile fields. * - * @param array $params Associative array of property name/value + * @param array $params Associative array of property name/value * pairs to profile field values * + * @throws API_Exception * @return formatted profile field values|CRM_Error * * @todo add example * @todo add test cases - * */ function civicrm_api3_profile_apply($params) { @@ -454,18 +460,23 @@ function _civicrm_api3_buildprofile_submitfields($profileID, $optionsBehaviour = } $fields = civicrm_api3('uf_field', 'get', array('uf_group_id' => $profileID)); $entities = array(); - foreach ($fields['values'] as $field) { if(!$field['is_active']) { continue; } list($entity, $fieldName) = _civicrm_api3_map_profile_fields_to_entity($field); - $profileFields[$profileID][$fieldName] = array( + $aliasArray = array(); + if(strtolower($fieldName) != $fieldName) { + $aliasArray['api.aliases'] = array($fieldName); + $fieldName = strtolower($fieldName); + } + $profileFields[$profileID][$fieldName] = array_merge(array( 'api.required' => $field['is_required'], 'title' => $field['label'], 'help_pre' => CRM_Utils_Array::value('help_pre', $field), 'help_post' => CRM_Utils_Array::value('help_post', $field), - ); + 'entity' => $entity, + ), $aliasArray); $realFieldName = $field['field_name']; //see function notes @@ -493,20 +504,28 @@ function _civicrm_api3_buildprofile_submitfields($profileID, $optionsBehaviour = $result = civicrm_api3($entity, 'getfields', array('action' => 'create')); $entityGetFieldsResult = _civicrm_api3_profile_appendaliases($result['values'], $entity); foreach ($entityFields as $entityfield => $realName) { - $profileFields[$profileID][$entityfield] = $entityGetFieldsResult[$realName]; + $profileFields[$profileID][strtolower($entityfield)] = array_merge($profileFields[$profileID][$entityfield], $entityGetFieldsResult[$realName]); if($optionsBehaviour && !empty($entityGetFieldsResult[$realName]['pseudoconstant'])) { if($optionsBehaviour > 1 || !in_array($realName, array('state_province_id', 'county_id', 'country_id'))) { $options = civicrm_api3($entity, 'getoptions', array('field' => $realName)); $profileFields[$profileID][$entityfield]['options'] = $options['values']; } } + + if($entityfield != strtolower($entityfield)) { + // we will make the mixed case version (e.g. of 'Primary') an aliase + if(!isset($profileFields[$profileID][strtolower($entityfield)])) { + $profileFields[$profileID][strtolower($entityfield)]['api.aliases'] = array(); + } + $profileFields[$profileID][strtolower($entityfield)]['api.aliases'][] = $entityfield; + } /** * putting this on hold -this would cause the api to set the default - but could have unexpected behaviour if(isset($result['values'][$realName]['default_value'])) { - //this would be the case for a custom field with a configured default - $profileFields[$profileID][$entityfield]['api.default'] = $result['values'][$realName]['default_value']; + //this would be the case for a custom field with a configured default + $profileFields[$profileID][$entityfield]['api.default'] = $result['values'][$realName]['default_value']; } - */ + */ } } return $profileFields[$profileID]; @@ -520,6 +539,7 @@ function _civicrm_api3_buildprofile_submitfields($profileID, $optionsBehaviour = function _civicrm_api3_map_profile_fields_to_entity(&$field) { $entity = $field['field_type']; $contactTypes = civicrm_api3('contact', 'getoptions', array('field' => 'contact_type')); + $locationFields = array('email' => 'Email'); if(in_array($entity, $contactTypes['values'])) { $entity = 'Contact'; } @@ -533,10 +553,15 @@ function _civicrm_api3_map_profile_fields_to_entity(&$field) { } $fieldName .= '-' . $field['location_type_id']; } + elseif(array_key_exists($fieldName, $locationFields)) { + $fieldName .= '-Primary'; + $entity = 'Email'; + } if(!empty($field['phone_type_id'])) { $fieldName .= '-' . $field['location_type_id']; $entity = 'Phone'; } + // @todo - sort this out! //here we do a hard-code list of known fields that don't map to where they are mapped to // not a great solution but probably if we looked in the BAO we'd find a scary switch statement diff --git a/api/v3/examples/ProfileApply.php b/api/v3/examples/ProfileApply.php index 24368a7dd5..55c2c59230 100644 --- a/api/v3/examples/ProfileApply.php +++ b/api/v3/examples/ProfileApply.php @@ -5,8 +5,8 @@ */ function profile_apply_example(){ $params = array( - 'profile_id' => 25, - 'contact_id' => 1, + 'profile_id' => 31, + 'contact_id' => 2, 'first_name' => 'abc2', 'last_name' => 'xyz2', 'email-Primary' => 'abc2.xyz2@gmail.com', @@ -41,10 +41,10 @@ function profile_apply_expectedresult(){ 'values' => array( 'contact_type' => 'Individual', 'contact_sub_type' => '', - 'contact_id' => 1, + 'contact_id' => 2, 'version' => 3, 'debug' => 1, - 'profile_id' => 25, + 'profile_id' => 31, 'first_name' => 'abc2', 'last_name' => 'xyz2', 'email' => array( diff --git a/api/v3/examples/ProfileGet.php b/api/v3/examples/ProfileGet.php index a390666000..ae90235bbb 100644 --- a/api/v3/examples/ProfileGet.php +++ b/api/v3/examples/ProfileGet.php @@ -6,11 +6,11 @@ function profile_get_example(){ $params = array( 'profile_id' => array( - '0' => 25, + '0' => 14, '1' => 1, '2' => 'Billing', ), - 'contact_id' => 1, + 'contact_id' => 2, ); try{ @@ -37,14 +37,15 @@ function profile_get_expectedresult(){ 'version' => 3, 'count' => 3, 'values' => array( - '25' => array( - 'first_name' => 'abc1', - 'last_name' => 'xyz1', - 'email-Primary' => 'abc1.xyz1@yahoo.com', - 'phone-1-1' => '021 512 755', - 'country-1' => '1228', - 'state_province-1' => '1021', + '14' => array( 'postal_code-1' => '90210', + 'state_province-1' => '1021', + 'country-1' => '1228', + 'phone-1-1' => '021 512 755', + 'email-Primary' => 'abc1.xyz1@yahoo.com', + 'last_name' => 'xyz1', + 'first_name' => 'abc1', + 'email-primary' => 'abc1.xyz1@yahoo.com', ), '1' => array( 'first_name' => 'abc1', diff --git a/api/v3/examples/ProfileGetFields.php b/api/v3/examples/ProfileGetFields.php index 4ec7519344..b7984ab8d3 100644 --- a/api/v3/examples/ProfileGetFields.php +++ b/api/v3/examples/ProfileGetFields.php @@ -6,7 +6,7 @@ function profile_getfields_example(){ $params = array( 'action' => 'submit', - 'profile_id' => 25, + 'profile_id' => 27, ); try{ @@ -34,9 +34,13 @@ function profile_getfields_expectedresult(){ 'count' => 9, 'values' => array( 'first_name' => array( + 'api.required' => '1', + 'title' => 'First Name', + 'help_pre' => '', + 'help_post' => '', + 'entity' => 'Contact', 'name' => 'first_name', 'type' => 2, - 'title' => 'First Name', 'maxlength' => 64, 'size' => 30, 'import' => true, @@ -46,9 +50,13 @@ function profile_getfields_expectedresult(){ 'export' => true, ), 'last_name' => array( + 'api.required' => '1', + 'title' => 'Last Name', + 'help_pre' => '', + 'help_post' => '', + 'entity' => 'Contact', 'name' => 'last_name', 'type' => 2, - 'title' => 'Last Name', 'maxlength' => 64, 'size' => 30, 'import' => true, @@ -57,11 +65,18 @@ function profile_getfields_expectedresult(){ 'dataPattern' => '/^\w+(\s\w+)?+$/', 'export' => true, ), - 'email' => array( + 'email-primary' => array( + 'api.required' => 1, + 'title' => 'Email', + 'help_pre' => '', + 'help_post' => '', + 'entity' => 'Email', + 'api.aliases' => array( + '0' => 'email-Primary', + ), 'name' => 'email', 'type' => 2, - 'title' => 'Email', - 'maxlength' => 64, + 'maxlength' => 254, 'size' => 20, 'import' => true, 'where' => 'civicrm_email.email', @@ -69,12 +84,15 @@ function profile_getfields_expectedresult(){ 'dataPattern' => '/^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/', 'export' => true, 'rule' => 'email', - 'api.required' => 1, ), 'phone-1-1' => array( + 'api.required' => 1, + 'title' => 'Phone', + 'help_pre' => '', + 'help_post' => '', + 'entity' => 'Phone', 'name' => 'phone', 'type' => 2, - 'title' => 'Phone', 'maxlength' => 32, 'size' => 20, 'import' => true, @@ -82,12 +100,15 @@ function profile_getfields_expectedresult(){ 'headerPattern' => '/phone/i', 'dataPattern' => '/^[\d\(\)\-\.\s]+$/', 'export' => true, - 'api.required' => 1, ), 'country-1' => array( + 'api.required' => '1', + 'title' => 'Country', + 'help_pre' => '', + 'help_post' => '', + 'entity' => 'Address', 'name' => 'country_id', 'type' => 1, - 'title' => 'Country', 'FKClassName' => 'CRM_Core_DAO_Country', 'pseudoconstant' => array( 'table' => 'civicrm_country', @@ -97,9 +118,13 @@ function profile_getfields_expectedresult(){ ), ), 'state_province-1' => array( + 'api.required' => '1', + 'title' => 'State', + 'help_pre' => '', + 'help_post' => '', + 'entity' => 'Address', 'name' => 'state_province_id', 'type' => 1, - 'title' => 'State', 'FKClassName' => 'CRM_Core_DAO_StateProvince', 'pseudoconstant' => array( 'table' => 'civicrm_state_province', @@ -108,9 +133,13 @@ function profile_getfields_expectedresult(){ ), ), 'postal_code-1' => array( + 'api.required' => 0, + 'title' => 'Postal Code', + 'help_pre' => '', + 'help_post' => '', + 'entity' => 'Address', 'name' => 'postal_code', 'type' => 2, - 'title' => 'Postal Code', 'maxlength' => 12, 'size' => 12, 'import' => true, @@ -120,6 +149,11 @@ function profile_getfields_expectedresult(){ 'export' => true, ), 'custom_1' => array( + 'api.required' => '1', + 'title' => 'first_name', + 'help_pre' => '', + 'help_post' => '', + 'entity' => 'Contact', 'label' => '_addCustomFieldToProfile', 'groupTitle' => '_addCustomFie', 'data_type' => 'String', diff --git a/api/v3/examples/ProfileSubmit.php b/api/v3/examples/ProfileSubmit.php index 0562485f37..156ac6552b 100644 --- a/api/v3/examples/ProfileSubmit.php +++ b/api/v3/examples/ProfileSubmit.php @@ -5,11 +5,11 @@ */ function profile_submit_example(){ $params = array( - 'profile_id' => 25, - 'contact_id' => 1, + 'profile_id' => 29, + 'contact_id' => 2, 'first_name' => 'abc2', 'last_name' => 'xyz2', - 'email-Primary' => 'abc2.xyz2@gmail.com', + 'email-primary' => 'abc2.xyz2@gmail.com', 'phone-1-1' => '022 321 826', 'country-1' => '1013', 'state_province-1' => '1000', @@ -38,10 +38,10 @@ function profile_submit_expectedresult(){ 'is_error' => 0, 'version' => 3, 'count' => 1, - 'id' => 1, + 'id' => 2, 'values' => array( - '1' => array( - 'id' => '1', + '2' => array( + 'id' => '2', 'contact_type' => 'Individual', 'contact_sub_type' => '', 'do_not_email' => 0, @@ -65,6 +65,7 @@ function profile_submit_expectedresult(){ 'first_name' => 'abc2', 'middle_name' => 'J.', 'last_name' => 'xyz2', + 'suffix_id' => '3', 'email_greeting_id' => '1', 'email_greeting_custom' => '', 'email_greeting_display' => 'Dear abc1', diff --git a/tests/phpunit/api/v3/ProfileTest.php b/tests/phpunit/api/v3/ProfileTest.php index a77247a29c..555dffd5a1 100644 --- a/tests/phpunit/api/v3/ProfileTest.php +++ b/tests/phpunit/api/v3/ProfileTest.php @@ -549,8 +549,8 @@ class api_v3_ProfileTest extends CiviUnitTestCase { 'activity_status_id' => '2', ); $profileParams = array_merge($params, $updateParams); - $profile = $this->callAPISuccess('profile', 'submit', $profileParams); - $result = $this->callAPISuccess('profile', 'get', $params); + $this->callAPISuccess('profile', 'submit', $profileParams); + $result = $this->callAPISuccess('profile', 'get', $params); foreach ($updateParams as $profileField => $value) { $this->assertEquals($value, CRM_Utils_Array::value($profileField, $result['values']), "In line " . __LINE__ . " error message: " . "missing/mismatching value for {$profileField}" -- 2.25.1