The mystery of node.save and how to save more of a complext node with cck fields

gateway69's picture

Over the last few days I have been trying to figure out how to properly use the services node.save function to save more than just a simple content type such as story which has just a title and a body. This I can do w/o any issues. The issues that im trying to figure out is when you have a content type lets just say only these fields right now

content type photo
* title
* body
* field_my_photo -- cck imagefield

--- fid i already had from file.save

Now, node.save gets a bit more complex to figure out how to save when you have imagefield in it, building my own test php script to call node.save and send a json formatted array across I was never able to get it to save a node.

Trying to pass this to node.save from my script

  $node = array (
        'type' => 'photo',
      'title' => 'Test111',
    'field_my_photo' => array (
          array (
                    'fid' => 60,
                  'title' => 'test',
                  'filename' => 'rubicon-ipa.jpg',
                    'filepath' => 'sites/default/files/rubicon-ipa.jpg',
                    'filesize' => '487002',
         ),
             ),
         'uid' => 3,
           'status' => 1,
            'active' => 1
);

didnt seem to help..

then I started to dig though node.save in 6.2.2 and found out that it uses drupal_execute api call, which is great with forms you can fill out but gets more complex when your trying to figure out values to send to node.save that it will accept.

I was under the assumption originally it was using node_save.

So im a bit stumped as to figure out a way to easily understand what a custom content type with various cck fields wants and how to send that to node.save

I'm unable to find any documentation on this and the few I have asked have told me they wrote their own service for situations like this.

I can easily write my own service that uses node_save, but trying to stay consistent with the services methods I wanted to use node.save

thoughts on how to solve this mystery?

Comments

Here's an example of what I

mishwick's picture

Here's an example of what I had to do to save a file to a CCK field. In my case, it was an xml document and for various reasons I needed the node name to reflect the name of the document I was importing from a feed. For an image file you would need to change the mime type to the appropriate type, otherwise I think it's the same. Devel and the Krumo bar are very helpful for identifying what these values need to be. Best of luck and I hope this helps.

// fyi string structure: $destination = 'sites/default/files/yourpath/document.xml';

$file = new StdClass();
$file->filename = basename($destination);
$file->filepath = $destination;
$file->filemime = 'application/xml';
$file->filesize = filesize($destination);
$file->uid = 1;
$file->status = FILE_STATUS_PERMANENT;
$file->timestamp = time();

drupal_write_record('files', $file);

$node = new StdClass();
$node->type = 'news';
$node->title = basename($file->filename);
$node->field_news_xml = array(
        array(
                'fid' => $file->fid,
                'title' => basename($file->filename),
                'filename' => $file->filename,
                'filepath' => $file->filepath,
                'mimetype' => $mime,
                'description' => basename($file->filename),
                'list' => 1
        ),
);

$node->uid = 1;
$node->status = 0;
node_save($node);  

I tried to find the original post that helped me figure this out, but was unable to dig it up. I owe that person a huge thank you.

hmm, yea thanks... I did see

gateway69's picture

hmm, yea thanks... I did see such an example before, however this gets a bit more complicated since im trying to send this via services from my mobile phone client to drupal services... as a test I use a php example to send data... like the following below..

<?php
 
// set the working directory to your Drupal root used for user_password();
 
chdir('/var/www/yourdir/');
 
 
// require the bootstrap include
 
require_once './includes/bootstrap.inc';
 
 
// Load Drupal
 
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

   
$node = array (
       
'type' => 'photo',
     
'title' => 'Test111',
   
'field_my_photo' => array (
          array (
                   
'fid' => 60,
                 
'title' => 'test',
                 
'filename' => 'test.jpg',
                  
'filepath' => 'sites/default/files/test.jpg',
                  
'filesize' => '487002',
         ),
             ),
        
'uid' => 3,
          
'status' => 1,
           
'active' => 1
);

   
  
print_r($node);
   
  
$json = json_encode($node);
   
  
print_r($json);
   
 
$method = 'node.save';
 
$api_key = 'yourkey'; // Your API key.
 
$sessid = 'yoursessid'; // Your session ID.
 
$domain = $_SERVER['HTTP_HOST'];
 
$timestamp = (string) time();
 
$nonce = user_password();
 
$hash = hash_hmac('sha256', $timestamp .';'.$domain .';'. $nonce .';'. $method, $api_key);

 
$ch = curl_init();
 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 
curl_setopt($ch, CURLOPT_POST, 1);
 
curl_setopt($ch, CURLOPT_URL, 'http://yourdomain.com/services/json');

 
//prepare the field values being posted to the JSON service (WITH key authentication)
 
$data = array(
   
'method' => '"'. $method .'"',
   
'hash' => '"'. $hash .'"',
   
'domain_name' => '"'. $domain .'"',
   
'domain_time_stamp' => '"'. $timestamp .'"',
   
'nonce' => '"'. $nonce .'"',
   
'sessid' => '"'. $sessid .'"',
   
'node' =>  $json,
  );
 
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
 
 
//make the request
 
$result = curl_exec($ch);
  echo
print_r($result,1); // debugging

 
echo "<pre>";
  
print_r($data);
  echo
"</pre>";
  
?>

this generates json data from the test array, and sends it via the method call node.save but so far anything I try with the array doesn't seem to work..

Have you considered writing your own service handler?

mishwick's picture

Ah, I see. It might be that you have to create your own service call rather than relying on node.save. That way you can specify the values you need to send and write a little code to do the node save.

Yea was my next step, just

gateway69's picture

Yea was my next step, just seems that then really node.save isn't really a viable solution for content types with various cck fields since its really hard to tell what data to send and how to form your array of data from the clients to the server. I was hoping someone knew :)

But thank you for taking the time to reply mishwick ++

Have you tried to set only the fid?

waldmanm's picture

Take a look here: http://groups.drupal.org/node/21245

I haven't played with a cck imagefield yet (on my plate for next week ...), but I think you only need to set the fid in the cck imagefield, not the other file info. That would be similar to a nodereference field for which node.save expects to get something like:
'field_noderef' => array (
array (
'nid' => 30,
),
)

PS. Ignore the mention of a patch to file.save in the link above - the patch has already been committed.

HTH,
Micah

I think i have tried every

gateway69's picture

I think i have tried every combination, originally i started with just the fid to pass, but be careful since drupal_execute goes though a security blanket of form submission, so ideally what you submit i a form you have to pass though node.save service..

Did you find a solution

Dhammika's picture

I have run into the same issue. Did you find a way to use node.save and save a CCK field of type file ? If you did can you please post your solution ?

Thanks

Services

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: