How to create new post with photo attached in WordPress using XMLRPC?

P.C. picture P.C. · Sep 30, 2011 · Viewed 13k times · Source

Anyone knows how to create new post with photo attached in WordPress using XMLRPC?

I am able to create new post and upload new picture separately, but looks like there is no way to attach the uploaded photo to the created post?

Below is the codes I'm currently using.

<?php
DEFINE('WP_XMLRPC_URL', 'http://www.blog.com/xmlrpc.php');
DEFINE('WP_USERNAME', 'username');
DEFINE('WP_PASSWORD', 'password');

require_once("./IXR_Library.php");
$rpc = new IXR_Client(WP_XMLRPC_URL);
$status = $rpc->query("system.listMethods"); // method name
if(!$status){
    print "Error (".$rpc->getErrorCode().") : ";
    print $rpc->getErrorMessage()."\n";
    exit;
}

$content['post_type'] = 'post'; // post title
$content['title'] = 'Post Title '.date("F j, Y, g:i a"); // post title
$content['categories'] = array($response[1]['categoryName']); // psot categories
$content['description'] = '<p>Hello World!</p>'; // post body
$content['mt_keywords'] = 'tag keyword 1, tag keyword 2, tag keyword 3'; // post tags
$content['mt_allow_comments'] = 1; // allow comments
$content['mt_allow_pings'] = 1; // allow pings
$content['custom_fields'] = array(array('key'=>'Key Name', 'value'=>'Value One')); // custom fields
$publishBool = true;

if(!$rpc->query('metaWeblog.newPost', '', WP_USERNAME, WP_PASSWORD, $content, $publishBool)){
    die('An error occurred - '.$rpc->getErrorCode().":".$rpc->getErrorMessage());
}
$postID = $rpc->getResponse();
echo 'POST ID: '.$postID.'<br/>';

if($postID){ // if post has successfully created

    $fs = filesize(dirname(__FILE__).'/image.jpg');
    $file = fopen(dirname(__FILE__).'/image.jpg', 'rb');
    $filedata = fread($file, $fs);
    fclose($file);

    $data = array(
        'name'  => 'image.jpg',
        'type'  => 'image/jpg',
        'bits'  => new IXR_Base64($filedata),
        false // overwrite
    );

    $status = $rpc->query(
        'metaWeblog.newMediaObject',
        $postID,
        WP_USERNAME,
        WP_PASSWORD,
        $data
    );
    echo print_r($rpc->getResponse()); // Array ( [file] => image.jpg [url] => http://www.blog.com/wp-content/uploads/2011/09/image.jpg [type] => image/jpg )
}
?>

Answer

O_H picture O_H · Dec 31, 2011

I've been involved in WordPress sites (my current employer uses 3 of these) and posting stuff daily and by the bulk has forced me to use what I do best-- scripts!

They're PHP-based and are quick and easy to use and deploy. And security? Just use .htaccess to secure it.

As per research, XMLRPC when it comes to files is one thing wordpress really sucks at. Once you upload a file, you can't associate that attachment to a particular post! I know, it's annoying.

So I decided to figure it out for myself. It took me a week to sort it out. You will need 100% control over your publishing client that is XMLRPC compliant or this won't mean anything to you!

You will need, from your WordPress installation:

  • class-IXR.php, located in /wp-admin/includes
  • class-wp-xmlrpc-server.php, located in /wp-includes

class-IXR.php will be needed if you craft your own posting tool, like me. They have the correctly-working base64 encoder. Don't trust the one that comes with PHP.

You also need to be somewhat experienced in programming to be able to relate to this. I will try to be clearer.

  1. Modify class-wp-xmlrpc-server.php

    • Download this to your computer, through ftp. Backup a copy, just in case.
    • Open the file in a text editor. If it doesn't come formatted, (typically it should, else, it's unix-type carriage breaks they are using) open it elsewhere or use something like ultraedit.
    • Pay attention to the mw_newMediaObject function. This is our target. A little note here; WordPress borrows functionality from blogger and movabletype. Although WordPress also has a unique class sets for xmlrpc, they choose to keep functionality common so that they work no matter what platform is in use.
    • Look for the function mw_newMediaObject($args). Typically, this should be in line 2948. Pay attention to your text editor's status bar to find what line number you are in. If you can't find it still, look for it using the search/find function of your text editor.
    • Scroll down a little and you should have something that looks like this:

       $name = sanitize_file_name( $data['name'] );
       $type = $data['type'];
       $bits = $data['bits'];
      
    • After the $name variable, we will add something. See below.

       $name = sanitize_file_name( $data['name'] );
       $post = $data['post']; //the post ID to attach to.
       $type = $data['type'];
       $bits = $data['bits'];
      

      Note the new $post variable. This means whenever you will make a new file upload request, a 'post' argument will now be available for you to attach.

      How to find your post number depends on how you add posts with an xmlrpc-compliant client. Typically, you should obtain this as a result from posting. It is a numeric value.

      Once you've edited the above, it's time to move on to line 3000.

      // Construct the attachment array
      // attach to post_id 0
      $post_id = 0;
      $attachment = array(
          'post_title' => $name,
          'post_content' => '',
          'post_type' => 'attachment',
          'post_parent' => $post_id,
          'post_mime_type' => $type,
          'guid' => $upload[ 'url' ]
      );
      
    • So here's why no image is associated to any post! It is always defaulted to 0 for the post_parent argument! That's not gonna be the case anymore.

      // Construct the attachment array
      // attach to post_id 0
      $post_id = $post;
      $attachment = array(
          'post_title' => $name,
          'post_content' => '',
          'post_type' => 'attachment',
          'post_parent' => $post_id,
          'post_mime_type' => $type,
          'guid' => $upload[ 'url' ]
      );
      

      $post_id now takes up the value of $post, which comes from the xmlrpc request. Once this is committed to the attachment, it will be associated to whatever post you desire!

      This can be improved. A default value can be assigned so things don't get broken if no value is entered. Although in my side, I put the default value on my client, and no one else is accessing the XMLRPC interface but me.

    • With the changes done, save your file and re-upload it in the same path where you found it. Again, make sure to make backups.

      Be wary of WordPress updates that affects this module. If that happens, you need to reapply this edit again!

  2. Include class-IXR.php in your PHP-type editor. If you're using something else, well, I can't help you there. :(

Hope this helps some people.