Amazon Wish List Synchronizer

Submitted by Howard on Tue, 10/21/2008 - 05:41


According to department stores, Christmas is fast approaching. This got me thinking about the fact that every year I scramble to assemble a list of things to put on my Christmas list. Last year, I vowed to start an Amazon wish-list to keep track of things I liked or wanted as the year progressed. I kept to my word but I also found a number of things throughout the year that weren't available on Amazon and I started thinking about how I could add them to my list (most notably this sweatshirt). This is how I built a simple module to solve my problem.

The Problem

Display an Amazon wish-list along-side items from other online stores throughout the web.

The Solution

After playing around with Jeff Eaton's fantastic Amazon Module I realized that wish list functionality was something that wouldn't be terribly difficult to do give Amazon's API. My answer is to create a content type that has an amazon field (provided by the Amazon Module and to then create a module that could be triggered by a cron job that would fetch the list from Amazon, check to see which products had already been imported, import any that had not been and finally check to see which had previously been imported that were no longer on this wishlist (allowing for automatic removal). It came together pretty cleanly easily as described below:

The Code

This is the code for amazon_wishlist_synchronizer.module. It was written for Drupal 6 but none of the functions are D6 specific so I it should work perfectly in D5 as well. It does use a SimpleXML function, however, so it will only work with PHP5. The module is also attached at the bottom of the page (though the attached module has fewer comments).
Warning: There is a now a known issue with this code. It worked perfectly for several days before it started reporting an error. I have disabled the module on this site and will update this post when I have the time to figure out what the heck is wrong.

Building a request

The hardest part of this section was actually finding the appropriate documentation. Amazon has some great docs but their web services site is a real pain to navigate. Finding this document really made things easier. Here is the function for building the web services request url:

Get and convert the XML data

If you've never used PHP 5's SimpleXML before you're in for a treat! I hadn't and expected to have to jump through some hoops in order to perform the necessary DOM traversal but it wasn't necessary! using simlexml_load_string() you can convert a string of xml directly into a PHP object. At that point it couldn't be any easier to work with! Here's the function that fetches the xml, parses it and returns a PHP object: 'Error loading Amazon XML data.'); } // Use SimpleXML to convert the string into a native php object $parsed_xml = simplexml_load_string($response); // Return the php object return $parsed_xml; } ?>

Synchronizing the Data

Next we need to take that data and synchronize it with the server. This is hard coded for my setup which includes; a content type called "product" (which would cause problems if I ever installed an e-commerce solution) which has a taxonomy term that specifies "wish list" and an Amazon field (provided by the Amazon module) called "field_amazon_asin". $existing_entry['nid'], 'asin' => $existing_entry['field_amazon_asin']); } // call our other two functions to get the parsed xml $parsed_xml = _amazon_wishlist_synchronizer_get_xml(_amazon_wishlist_synchronizer_build_request($subscription_id, $wishlist_id)); // find out how many pages we need to get the whole list $total_pages = (int) $parsed_xml->Lists->List->TotalPages; // setup a new object to collect the data so that it can be processed at once // (this is crucial if we are going to remove nodes that are no longer on the wish list) $product_list = new stdClass; // for each page get the page and process it while($page Lists->List->ListItem as $item){ // it's important to specify "(string)" or you get a SimpleXML object $asin = (string) $item->Item->ASIN; // create a new object containing objects keyed with the asin so that it can be // compared to the array of existing nodes $product_list->$asin = new stdClass; $product_list->$asin->asin = $asin; $product_list->$asin->title = (string) $item->Item->ItemAttributes->Title; $created = (string) $item->DateAdded; // reformat the date added into a unix timestamp $created =explode("-",$created); $created = mktime(0, 0, 0, $created[1], $created[2], $created[0]); $product_list->$asin->created = $created; $processed += 1; } $page += 1; } // Now that we have a complete list, look though each product foreach($product_list as $product) { // Check to see if there is an existing node with that asin if(!isset($existing_amazon_nodes[$product->asin])){ $node = new stdClass; $node->type = 'product'; $node->uid = 1; $node->promote = 0; $node->moderate; $node->field_amazon = array(array('asin' => $product->asin)); $node->title = $product->title; $node->taxonomy = array('tid' => 2); $node->created = $product->created; node_save($node); } //if there is an existing product that was unpublished with that asin //publish it elseif(!$existing_amazon_nodes[$product->asin]['status']) { $node = node_load($existing_amazon_nodes[$product->asin]['nid']); $node->status = 1; $node->created = $product->created; node_save($node); } } // Check for existing nodes that have been removed from the wish list foreach($existing_amazon_nodes as $existing_amazon_node) { if(!isset($product_list->$existing_amazon_node['asin'])) { // If an asin is found that is no longer on the wish list then unpublish the node $node = node_load($existing_amazon_node['nid']); $node->status = 0; node_save($node); } } } ?>

Run a cron job

In order to keep the site updated automagically behind the scenes, we will add a cron job that calls the function that above. If you have cron running often and have a long wish list you may want to add some logic the prevents it from running quite so frequently. If you would like to play around with the module, it is attached.
Warning: This module is provided as is for reference only and comes with no warranty expressed or implied!
AttachmentSize
amazon_wishlist_synchronizer_2.zip0 bytes
Add new comment

Filtered HTML

  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. The supported tag styles are: <foo>, [foo]. PHP source code can also be enclosed in <?php ... ?> or <% ... %>.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd> <table> <tr> <td>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Type the characters you see in this picture. (verify using audio)
Type the characters you see in the picture above; if you can't read them, submit the form and a new image will be generated. Not case sensitive.