Hi there,

need some help with updating a user... I can't figure out, how to dial with the update array.. I have this.. this is not working (of cause Iogged in..) What I have to do, to update a user?
)

// -> login....
$base_url = 'http://xx/rest';
$headers = array(
    'Cookie' => $data->session_name . '=' . $data->sessid
          );
$account = array(
      'data' => array(
      'profile_ls_id' => array(array('value' => '111111')),
      'name' => 'test_userd1xxxxxx12',
      'pass' => 'xyzzy1',
      'mail' => 'xxxxxxxxxxxx@gf.de'
    )
  );
update_user($base_url, $account, $headers);

function update_user($base_url, $account, $headers){
  $query = http_build_query($account, '', '&');

  $response = drupal_http_request(
          $base_url.'/user/272',  // uid of update user
          $headers, 
          'PUT', 
          $query
          );
}

Comments

Apfel007’s picture

Title: Update a user with REST » user.update with REST - need some help to update profile field

This is my code for now - the update function send me an error "The name test_userd1xxxxxx12 is already taken." Is this a bug? Why the update function try to use insert a username?


<?php
/**

 * arg (0) = SID ?? mal sehen
 * arg (1) = email
 * http://www.example.com/my_rec/12?bookisdn=ISDN
 * profile fields.. 
 * profile_ls_id tauschen
 * 
 */

include_once 'includes/common.inc';
include_once 'includes/bootstrap.inc';
// This is the base URL for our installation
$base_url = 'http://dcf-panel/rest';

include 'ChromePhp.php';
ChromePhp::log('DCF Servci');


// necessary or the response is empty:
$headers = array('Content-Type' => 'application/x-www-form-urlencoded');

// Login
$data = array(
  'username' => 'webservice',
  'password' => 'webservice',
);

//$headers =  array('Accept' => 'application/json');

$data = http_build_query($data, '', '&');
$response = drupal_http_request($base_url . '/user/login', $headers, 'POST', $data);

$cookie = $response->headers['Set-Cookie'];
$headers = array('Cookie' => $cookie);
$data = json_decode($response->data);

// Check if login was successful
if ($response->code == 200) {
  // Now recycle the login cookie we recieved in the first request  

  $headers = array(
    'Cookie' => $data->session_name . '=' . $data->sessid
          );
  
  $account = array(
      'profile_ls_id' => array(array('value' => '111111')),
      'name' => 'test_userd1xxxxxx12',
      'pass' => 'xyzzy1',
      'mail' => 'xxxxxxxxxxxx@gf.de' 
  );  
  update_user($base_url, $account, $headers);  
  
}
else{
    die ('Failed to login');
    
  }


/*
 * 
 * no $op in service module yet for user roles!! in order to that use update_user
 * 
 * @param $base_url
 * @param $headers
 * @param $account 
 */

function create_user($base_url, $headers){
  $account = array(
      'name' => 'test_userd1xxxxxx13',
      'pass' => 'xyzzy1',
      'mail' => 'test_usder1xxxxxx13@gf.de'
    );

  $query = http_build_query($account=array('account'=>$account), '', '&');
    //if we got code 200, the login was a succes, we can procede to create a user account
  $response = drupal_http_request(
          $base_url.'/user',
          $headers, 
          'POST', 
          $query
          );
  if ($response->code == 200) {
    $user_data = json_decode($response->data);
    ChromePhp::log('create user');
    return $user_data->uid;

    }
    else{
      ChromePhp::log('ERROR create user');
    }

//return json_decode($response->data[uid]);
}

/* update user 
 * @account field for user
 */

function update_user($base_url, $account, $headers){
  ChromePhp::log ($query);
    
  $response = drupal_http_request(
          $base_url.'/user/272',  // path with user uid
          $headers, 
          'PUT', 
          $query
          );
  ChromePhp::log( json_decode($response->data));
//return $response->data[uid];
}
ygerasimov’s picture

Indeed it looks strange that you can't update user. I would recommend to use curl instead of drupal_http_request. At least our tests use curl for building requests and they succeed with PUT type.

Please take a look at test that updates user: http://drupalcode.org/project/services.git/blob/refs/heads/6.x-3.x:/test...

Let me know if you still have any questions.

Apfel007’s picture

Hi ygerasimov,
thanks for that hint...

Could you explain me, whats the difference or advantage between curl and http-request..

ygerasimov’s picture

Just different type of connection. drupal_http_request uses sockets connection but curl is different. Anyhow I don't think this matters much for your use case. I am just not sure whether you get proper PUT request with sockets. With curl you will definitively would be able to do that and there are examples available.

Apfel007’s picture

OK I started with Curl.. but need some more help - this should update a user, but it doesn't! I get not error message.. "mysqli_real_escape_string() expects parameter 2 ..." What wrong with this code snippet? I think the problem ist the $account-data. Is this array build right? It seems that the object returns "http_code: 406"

$api = new DrupalREST($endpoint_url, $username, $password, FALSE);
...
$uid = 258;
$account_update = array(
  'mail' => 'updateDrupalREST_01@gmx.li',
  'name' => 'test_user',
      'pass' => 'xx',
);
$api->updateUser($uid, $account_update);

...
class DrupalREST { ...
function updateUser($uid, $account)
    {
        $post = http_build_query($account, '', '&');
        $ch = curl_init($this->endpoint . 'user/'.$uid);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_PUT, TRUE);  // PUT for update
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
        curl_setopt($ch, CURLOPT_HTTPHEADER,
                array (
                       "Accept: application/json",
                       "Content-type: application/x-www-form-urlencoded",
                       "Cookie: $this->session"
                ));
ChromePhp::log('update user');

       
$result = $this->_handleResponse($ch);

       curl_close($ch);

       return $result;
    }
ygerasimov’s picture

Please advise what you are trying to update? password?

First of all please enable debug mode on your rest server and check in logs what arguments you got passed.

Apfel007’s picture

Hi,

in the end I try to add something to a profile field, add a role and add user to a og-group (for that I need a custom action/recource..right?)

First I tried something easy - change the email-adress to understand how it works..

Passed arguments:
Array
(
[0] => 258
[1] => Array
(
)
)
The array is nearly empyt - it seems that'S someting wrong with my account-array..

$account = array(
        'profile_ls_id' => array(array('value' => '111111')),
      'name' => 'test_userd1xxxxxx12',
      'pass' => 'xyzzy1',
      'mail' => 'xxxxxxxxxxxx@gf.de'
      );
Apfel007’s picture

Title: user.update with REST - need some help to update profile field » user profile fields UPDATE with with REST

Hi, I try to use this class to update a user profile field..

 function updateUser($uid, $account)
    {
     // $post = $account;
       $post = http_build_query($account, '', '&');
        $ch = curl_init($this->endpoint . 'user/'.$uid);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, true);
       curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
      //  curl_setopt($ch, CURLOPT_PUT, TRUE);  // PUT for update
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
        curl_setopt($ch, CURLOPT_HTTPHEADER,
                array (
                       "Accept: application/json",
                       "Content-type: application/x-www-form-urlencoded",
                       "Cookie: $this->session"
                ));

and call it with

$account_update = array(
    'mail' => 'updateDrupal_02@gmx.li',
);
$account_update['name'] = $usernew['name']; // is mandatory for update!?
//$account_update['roles'] = array( 5 => 'Panel TN');
//$account_update['category'] = array( 0 => 'auth');
//$account_update['og_groups'] = array( 0 => 2);

//////////////////////////////
// how set a profile field ////////->       $account_update['field_user_id'] = array( 0 => 2);
//////////////////////////////
$api->updateUser($usernew['uid'],array('data' => $account_update));

Could someone give me a hint how to solve this? The update of the email-adress is working.. but not the field update. It seems something to do with the "update-array"

Thanks

Apfel007’s picture

$account_update['name'] = $usernew['name']; // is mandetory!
//$account_update['roles'] = array( 5 => 'Panel TN');

$account_update['category'] = 'auth';

$account_update['fields'] = array( 'profile_field_ls_id' => 'hallo');
//$account_update['og_groups'] = array( 0 => 2);

$userupdate = $api->updateUser($usernew['uid'],array('data' => $account_update));

now the category is transmitted, but the profile field is not saved... if it has a value before this value is deleted... now

devkinetic’s picture

subscribing. Currently I have not found a way to successfully update a user to add a role, change email, etc.

krem’s picture

Hi there,

I am also having a hard time updating users details in Drupal 7... Any more help or guidance on the topic would be highly appreciated ;)

kylebrowning’s picture

Have you guys looked at the tests? They are a great resource to see how it works and to prove that it does work.

krem’s picture

Version: 6.x-3.x-dev » 7.x-3.x-dev

I found my way around (Drupal 7), following is an example using Titanium appcelerator syntax but the code should easily be adaptable to other languages :

        var localise = 'POINT (' + longitude + ' ' + latitude + ')';
        xhrUpdate.open('PUT', 'http://www.myurl.com');
	xhrUpdate.setRequestHeader('Content-Type','application/json; charset=utf-8');
	var postUser = {
		data:{
		    name: username,
		    mail: email,
		    current_pass: 'currentpass',
		    pass: password,
		    field_localise: {und:[{wkt:localise}]}
	    }
	}
	xhrUpdate.send(JSON.stringify(postUser)); 

Using that code I am able to update an account details. I haven't done all tests to say which fields are mandatory but 'current_pass' was an important one to include in the call.

I hope it helps ;)
Clem

ygerasimov’s picture

Category: task » support
Status: Active » Fixed

Closing this issue. Please feel free to reopen if anyone still have problems with it.

Best source of all answers about how to update user are tests.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

hgneng’s picture

I have a hard time with service API and updating user info. I would like to share with you.

First, we can add "&XDEBUG_SESSION_START=netbeans-xdebug" at the end of service endpoint URL to activate debug. We may need to take a look at sites/all/modules/services/resources/user_resource.inc to get the API of user.update. But that's only a clue. We won't know the first argument "kid" is passed through URL service-endpoint/user/$uid and the second argument is passed through PUT. And I tried to access service-enpoint/user/update for many times until I found there are operations and actions for service types.

I only knew GET and POST method before. In RESTServer.inc, we have following code:

      $action_mapping = array(
        'GET' => 'retrieve',
        'POST' => 'create',
        'PUT' => 'update',
        'DELETE' => 'delete',
      );

And I know that I should use PUT instead of POST to invoke update method.

When using PUT, we don't specify data through CURLOPT_POSTFIELDS. Instead:

$serialize_args = json_encode($user_data);
    $putData = fopen('php://temp', 'rw+');
    fwrite($putData, $serialize_args);
    fseek($putData, 0);
curl_setopt($curl, CURLOPT_INFILE, $putData);
curl_setopt($curl, CURLOPT_INFILESIZE, drupal_strlen($serialize_args));

I got about info from tests code of services module after I understood what "tests" means in this thread.

When getting error of 401, 406 etc, we can search those numbers in RESTserver.inc and set breakpoint on them to see what's wrong.

Finally, here is the code I successfully run on Drupal 7:

// REST Server URL
$request_url = 'http://localhost:8888/?q=rest-test/user/login';

// User data
$user_data = array(
  'username' => 'student',
  'password' => 'xxx',
);

// cURL
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $request_url);
curl_setopt($curl, CURLOPT_POST, 1); // Do a regular HTTP POST
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($user_data)); // Set POST data
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);

$response = curl_exec($curl);

print $response;

$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
// Check if login was successful
if ($http_code == 200) {
  // Convert json response as array
  $logged_user = json_decode($response);
}
else {
  // Get error msg
  $http_message = curl_error($curl);
  die($http_message);
}

print_r($logged_user);

// REST Server URL
$request_url = 'http://localhost:8888/?q=rest-test/user/8&XDEBUG_SESSION_START=netbeans-xdebug';

$user_data = array('current_pass' => 'xxx', 'pass' => '123');

// Define cookie session
$cookie_session = $logged_user->session_name . '=' . $logged_user->sessid;

// cURL
$curl = curl_init($request_url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json',
    'Content-type: application/json')); // Accept JSON response
curl_setopt($curl, CURLOPT_PUT, TRUE);
curl_setopt($curl, CURLOPT_HEADER, TRUE); // FALSE);  // Ask to not return Header
curl_setopt($curl, CURLOPT_COOKIE, "$cookie_session"); // use the previously saved session
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);

// Emulate file.
$serialize_args = json_encode($user_data);
    $putData = fopen('php://temp', 'rw+');
    fwrite($putData, $serialize_args);
    fseek($putData, 0);
curl_setopt($curl, CURLOPT_INFILE, $putData);
curl_setopt($curl, CURLOPT_INFILESIZE, drupal_strlen($serialize_args));

$response = curl_exec($curl);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);

// Check if login was successful
$ret;
if ($http_code == 200) {
  // Convert json response as array
  $ret = json_decode($response);
}
else {
  // Get error msg
  $http_message = curl_error($curl);
  die($http_message);
}

print_r($ret);

curl_close($curl);

}

Hope my post can save someone's time.

Cameron

tanzeel’s picture

After searching all around the web i just figured out the issue i was facing to send update profile request. To send update request you need to take care of following curl properties:

curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-type: application/json"));
$serialize_args = json_encode($data);
curl_setopt($curl, CURLOPT_POSTFIELDS, $serialize_args);

Where $data is array of data to update.

I was missing CURLOPT_HTTPHEADER and not encoding the data in curl request.

Hope this can help someone.