
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!
| Attachment | Size |
|---|---|
| 0 bytes |