CiviCRM Community Forums (archive)

*

News:

Have a question about CiviCRM?
Get it answered quickly at the new
CiviCRM Stack Exchange Q+A site

This forum was archived on 25 November 2017. Learn more.
How to get involved.
What to do if you think you've found a bug.



  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion »
  • APIs and Hooks (Moderator: Donald Lobo) »
  • Updating via CREATE
Pages: [1] 2

Author Topic: Updating via CREATE  (Read 2700 times)

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Updating via CREATE
January 29, 2011, 11:11:07 am
Hi,

I realised on doing the membership_type_create that if 'id' is passed in it makes sense to fetch any existing values BEFORE checking if all the params are present - that way just an id is sufficient for an update request & our creates are 'update-friendly'

Code: [Select]
/**
 * API to Create or update a Membership Type
 * 
 * @param   array  $params  an associative array of name/value property values of civicrm_membership_type
 * @return array $result newly created or updated membership type property values.
 * @access public
 */
function civicrm_membership_type_create(&$params)
{
  _civicrm_initialize();
  try{
    $values = $params;
    if(!empty($params['id'])){
     $getparams = array('id' => $params['id'],'version' => 3);
     $result = civicrm_membership_type_get($getparams);
     $values = array_merge($result['values'][$params['id']],$params); 
    }
    civicrm_verify_mandatory($values,'CRM_Member_DAO_MembershipType' ,array('name',  'duration_unit','duration_interval'));
     
    $ids['membershipType']   = CRM_Utils_Array::value( 'id', $params );
    $ids['memberOfContact']  = CRM_Utils_Array::value( 'member_of_contact_id', $params );
    $ids['contributionType'] = CRM_Utils_Array::value( 'contribution_type_id', $params );

    require_once 'CRM/Member/BAO/MembershipType.php';
    $membershipTypeBAO = CRM_Member_BAO_MembershipType::add($values, $ids);
    $membershipType = array();   
    _civicrm_object_to_array( $membershipTypeBAO, $membershipType[$membershipTypeBAO->id] );
    $membershipTypeBAO->free;
    return civicrm_create_success($membershipType,$params);

  } catch (PEAR_Exception $e) {
    return civicrm_create_error( $e->getMessage() );
  } catch (Exception $e) {
    return civicrm_create_error( $e->getMessage() );
  }
}
 
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Updating via CREATE
January 29, 2011, 11:15:45 am
NB - I suppose we could move into a helper function to turn it into a one-liner

Code: [Select]
    $values = $params;
    if(!empty($params['id'])){
     $getparams = array('id' => $params['id'],'version' => 3);
     $result = civicrm_membership_type_get($getparams);
     $values = array_merge($result['values'][$params['id']],$params); 
    }

Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Re: Updating via CREATE
January 30, 2011, 03:47:59 am
Like it nice move,

Have you tested what happen if the id is invalid ? I *think* I had an option so the api would throw an error instead of returning an is_error, I'll dig it if doesn't work straight out of the box.

X+

Quote from: Eileen on January 29, 2011, 11:15:45 am
NB - I suppose we could move into a helper function to turn it into a one-liner

Code: [Select]
    $values = $params;
    if(!empty($params['id'])){
     $getparams = array('id' => $params['id'],'version' => 3);
     $result = civicrm_membership_type_get($getparams);
     $values = array_merge($result['values'][$params['id']],$params); 
    }
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Updating via CREATE
February 05, 2011, 01:58:00 pm
Hi,

Just looking at how this function would look in the utils - just wondering what the latest is on what it should call. Also, does our existing stuff work with the UFGroup pattern - ie. two caps that don't represent U_F_Group


Code: [Select]
/*
 * Function to get existing values when an 'id' is passed into a Create api
 *
 * @params array $params input params
 * @return array $valuse params with existing values from contact
 */

function  civicrm_update_get_existing($params,$function, $filename){
    $values = $params;
// figure out here how to determine the function call we need from function or filename - nb make sure it copes with UFField etc anomolies
    if(!empty($params['id'])){
     $getparams = array('id' => $params['id'],'version' => 3);
     $result = civicrm_membership_type_get($getparams);
     $values = array_merge($result['values'][$params['id']],$params);
    }
    return $values;
}
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Re: Updating via CREATE
February 05, 2011, 11:30:39 pm
Isn't the param entity_id not id ?

As for the function to get the entity from the function of file name (what I'm doing on Entity.php)

This starts lookging weird: every call of the api is supposed to have action and entity separated (eg. civicrm_api (entity,action), ajax/rest?action=&entity= ...)

Then we mungle and put them as civicrm_entity_action, then we need to split them again ;)

Wondering if the call of that shouldn't be done before the civicrm_entity_action, and that we add the result of the get as params['previous']

     $values = array_merge($result['values'][$params['id']],$params);
Still would prefer the sequential by default and
     $values = array_merge($result['values'][0],$params);

;)



Quote from: Eileen on February 05, 2011, 01:58:00 pm
Hi,

Just looking at how this function would look in the utils - just wondering what the latest is on what it should call. Also, does our existing stuff work with the UFGroup pattern - ie. two caps that don't represent U_F_Group


Code: [Select]
/*
 * Function to get existing values when an 'id' is passed into a Create api
 *
 * @params array $params input params
 * @return array $valuse params with existing values from contact
 */

function  civicrm_update_get_existing($params,$function, $filename){
    $values = $params;
// figure out here how to determine the function call we need from function or filename - nb make sure it copes with UFField etc anomolies
    if(!empty($params['id'])){
     $getparams = array('id' => $params['id'],'version' => 3);
     $result = civicrm_membership_type_get($getparams);
     $values = array_merge($result['values'][$params['id']],$params);
    }
    return $values;
}
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Updating via CREATE
February 06, 2011, 01:25:06 am
The top level of any call is giving

$result['id'] & entity_id or whatever is in the values array - I'm actually quite liking this while modding the tests.

I set it so that any call with a single entity returned sets the top level 'id' as well - which means it happens on 'get' too.

I think sequential should be the default in the REST calls
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Updating via CREATE
February 06, 2011, 01:41:03 am
So, you're suggesting we do the getting before it even gets to the _create function.

Makes sense but it takes a bit of getting my head around the idea of the functions not being self-contained. I'd been thinking of the api.php as a handy extra rather than a necessary .... good.
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Re: Updating via CREATE
February 06, 2011, 02:07:55 am
Yeap,

didn't realise that slowly but surely, we are reaching a point where the instructions should be

call civicrm_api ('entity','action',$params), get an array in return.

If you want to test the options on what any entity+action can have as input/output and some quick testing, go to /civicrm/ajax/doc on your install.

The big con is that you cant' really easily find what code is using what api. This has been a pita for me to debug/upgrade codes that were (ab)using require_once ($tringthatisgenerated).

The big pro is that when we require_once(api/api.php) in CRM/Core.php the api is available everywhere without any extra require

Up to debate what should be the instuction.

X+

How is the civicrm_entity_action done below is none of your business unless you plan to add a new api or help us migrate to v3
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Updating via CREATE
February 06, 2011, 02:40:15 am
So, something like

/*
 * Function to get existing values when an 'id' is passed into a Create api
 *
 * @params array $params input params
 * @return array $valuse params with existing values from contact
 */

function  civicrm_update_get_existing($params, $filename){
    $entity = substr ( basename($filename) ,0, strlen(basename($filename))-8 );
    if (strstr($entity,'UF')){// a cleverer person than me would do it in a single regex
       $fnPrefix = strtolower(preg_replace('/(?<! )(?<!^)(?<=UF)[A-Z]/','_$0', $entity));         
    }else{
        $fnPrefix = strtolower(preg_replace('/(?<! )(?<!^)[A-Z]/','_$0', $entity));
     }   
    $function = "civicrm_" . $fnPrefix . "_get";
    $values = $params;
    if(!empty($params['id'])){
     $getparams = array('id' => $params['id'],'version' => 3);
     $result = $$function($getparams);
     $values = array_merge($result['values'][$params['id']],$params);
    }
    return $values;
}   
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Re: Updating via CREATE
February 06, 2011, 03:00:36 am
as the param use the __FUNCTION__ instead of the __FILE__ and that's a str replace (_create, _get), no ?

X+

Quote from: Eileen on February 06, 2011, 02:40:15 am
So, something like

/*
 * Function to get existing values when an 'id' is passed into a Create api
 *
 * @params array $params input params
 * @return array $valuse params with existing values from contact
 */

function  civicrm_update_get_existing($params, $filename){
    $entity = substr ( basename($filename) ,0, strlen(basename($filename))-8 );
    if (strstr($entity,'UF')){// a cleverer person than me would do it in a single regex
       $fnPrefix = strtolower(preg_replace('/(?<! )(?<!^)(?<=UF)[A-Z]/','_$0', $entity));         
    }else{
        $fnPrefix = strtolower(preg_replace('/(?<! )(?<!^)[A-Z]/','_$0', $entity));
     }   
    $function = "civicrm_" . $fnPrefix . "_get";
    $values = $params;
    if(!empty($params['id'])){
     $getparams = array('id' => $params['id'],'version' => 3);
     $result = $$function($getparams);
     $values = array_merge($result['values'][$params['id']],$params);
    }
    return $values;
}
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Updating via CREATE
February 06, 2011, 03:01:46 am
yeah - good point - that's even simpler - I copied it from somewhere where I couldn't do a simple replace
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Updating via CREATE
February 06, 2011, 03:38:08 am
OK

Added update helper     $values = civicrm_update_get_existing($params, __FUNCTION__); - this is tested for & works in membershipType

note that my dreams of copying & pasting into every function are hampered by the fact that we receive &$params

& if we put

$params = civicrm_update_get_existing($params, __FUNCTION__);

into the functions it will change the $params array passed in by the user (we did say on another discussion thread we wouldn't do that).

changing to something other than $params will mean a bit more per function editing
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Re: Updating via CREATE
February 06, 2011, 07:11:46 am
This one is a serious bummer.

What do we do when reality and theory don't match ?

I'd personally be tempted to modify and say that it isn't &$params that you pass as a param to the civicrm_entity_create but $params.

while we are a it could do it as well for the others, cause it's not going to be long arrays anyway.

But really not sure, beside it's a problem.

X+
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Updating via CREATE
February 06, 2011, 11:10:16 am
yes, I think either we change the standard to be that we DO alter the $params array on updates or we remove the & in &params on update
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Got an idea/solution
February 06, 2011, 02:29:46 pm
Plan B:

We don't touch the _create (ie. if you don't put the existing fields, they are erased).

We create a new action in civicrm_api/crmAPI/ajax: modify

if (modify)
  current = civicrm_api (entity, 'get', param)
  tmp = array merge (param,current);
  civicrm_api (entity, 'create')


What do you think ?

And the modify api is only available if you use the civicrm_api & friends. If you want to call directly the civicrm_entity_create, fine, but you have to deal yourself with copying the current fields.

X+
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Pages: [1] 2
  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion »
  • APIs and Hooks (Moderator: Donald Lobo) »
  • Updating via CREATE

This forum was archived on 2017-11-26.