$value) { $fieldname = strtolower($key); $node->$fieldname = $value; } if ($node->type == 'amazon_node') $node->title = $amazondata->title; } return $amazondata; } /** * array of product data from Amazon.com for all products associated with. */ function _amazon_product_data_array($node) { global $_amazon_search_amazon_shop_URI; $_amazon_locale_index = variable_get('amazon_locale', '0'); $_amazon_locale_list = array_keys($_amazon_search_amazon_shop_URI); $_amazon_locale = $_amazon_locale_list[$_amazon_locale_index]; $asinlist = explode(',', $node->asin); foreach ($asinlist as $key => $value) $asinlist[$key] = trim($value); $asins = implode(',', $asinlist); $REST_params = array('AmazonShop'=>$_amazon_locale, 'Operation' => 'ItemLookup', 'ItemId' => $asins, 'AssociateTag'=> variable_get('amazon_associate_id', ''), 'ResponseGroup' => 'Medium,Offers', 'MerchantId' => 'Featured'); return amazon_get_items($REST_params); } /** * product data from database for a single product (amazon_node). */ function _amazon_product_db_data($asin_data) { if (is_string($asin_data)) { $ASIN_query_string = "SELECT a.* FROM {amazonitem} a WHERE asin = '$asin_data'"; } else if (is_object($asin_data)) { $ASIN_query_string = "SELECT a.* FROM {amazonitem} a WHERE asin = '$asin_data->asin'"; } $ASIN_query = db_query($ASIN_query_string); if (db_num_rows($ASIN_query)) { $ASIN_query_record = db_fetch_object($ASIN_query); $amazondata = db_fetch_object(db_query("SELECT * FROM {amazonitem} WHERE asin = '$ASIN_query_record->asin'")); $amazondata->author = unserialize($amazondata->author); } if (isset($amazondata)) { return $amazondata; } else { return NULL; } } /** * array of product data from database for all products in a comma-delimited list of ASINs. */ function _amazon_product_db_data_by_ASIN($ASINList) { if (is_string($ASINList)) { $out_ASINs = explode(',', $ASINList); } elseif (is_array($ASINList)) { $out_ASINs = $ASINList; } else { return null; } foreach ($out_ASINs as $asin) { $out_asin_array[] = "'".$asin."'"; } if (count($out_asin_array) > 0) { $ASIN_query = db_query('SELECT a.* FROM {amazonitem} a WHERE asin IN ('. implode(',', $out_asin_array) . ')'); while ($ASIN_query_record = db_fetch_object($ASIN_query)) { $ASIN_query_record->author = unserialize($ASIN_query_record->author); $amazondata_array[] = $ASIN_query_record; } return $amazondata_array; } } /** * array of product data from Amazon.com for all products in a comma-delimited list of ASINs. */ function _amazon_product_data_from_Amazon($ASINList){ global $_amazon_search_amazon_shop_URI; $_amazon_locale_index = variable_get('amazon_locale', '0'); $_amazon_locale_list = array_keys($_amazon_search_amazon_shop_URI); $_amazon_locale = $_amazon_locale_list[$_amazon_locale_index]; $REST_params = array('AmazonShop'=>$_amazon_locale, 'AssociateTag'=>variable_get('amazon_associate_id', ''), 'Operation' => 'ItemLookup', 'ItemId' => $ASINList, 'ResponseGroup' => 'Medium,Offers', 'MerchantId' => 'Featured'); return amazon_get_items($REST_params); } /** * create a new amazon_node item from amazon item data. */ function _to_amazonnode($amazon) { global $user; $exists_query = db_query('SELECT n.nid FROM {node} n JOIN {amazonnode} a ON n.nid = a.nid ' ."WHERE n.type = 'amazon_node' AND a.asin = '$amazon->asin'"); $exists = db_num_rows($exists_query); if (!$exists) { $node = array('type' => 'amazon_node'); $amazon_node = array( 'op' => t('Submit'), 'asin' => $amazon->asin, 'name' => $user->name, 'taxonomy' => $amazon->taxonomy, 'log' => '', ); drupal_execute('amazon_node_node_form', $amazon_node, $node); } } function _refresh_amazonitem_data($Amazonitem) { db_query("update {amazonitem} set detailpageurl = '%s', " . "smallimageurl = '%s', smallimageheight = %d, smallimagewidth = %d, ". "mediumimageurl = '%s', mediumimageheight = %d, mediumimagewidth = %d, ". "largeimageurl = '%s', largeimageheight = %d, largeimagewidth = %d, ". "author = '%s', editorialreview = '%s', binding = '%s', listamount = %d, listcurrencycode = '%s', " . "listformattedprice = '%s', amount = %d, currencycode = '%s', " . "formattedprice = '%s', pricedate = now()" . "where asin = '%s'", $Amazonitem->detailpageurl, $Amazonitem->smallimageurl, $Amazonitem->smallimageheight, $Amazonitem->smallimagewidth, $Amazonitem->mediumimageurl, $Amazonitem->mediumimageheight, $Amazonitem->mediumimagewidth, $Amazonitem->largeimageurl, $Amazonitem->largeimageheight, $Amazonitem->largeimagewidth, serialize($Amazonitem->author), db_escape_string($Amazonitem->editorialreview), $Amazonitem->binding, $Amazonitem->listamount, $Amazonitem->listcurrencycode, $Amazonitem->listformattedprice, $Amazonitem->amount ? $Amazonitem->amount: $Amazonitem->listamount, $Amazonitem->currencycode, $Amazonitem->formattedprice ? $Amazonitem->formattedprice: $Amazonitem->listformattedprice, /* time(),*/ $Amazonitem->asin); } /** * block hook */ function amazon_block($op = 'list', $delta = 0, $edit = array()) { switch ($op) { case 'configure': { $form = array(); switch ($delta) { case 0: break; case 1: break; case 2: $options = array(t('')); $options = array_merge($options, explode(',', variable_get('amazon_ratings_labels', 'Poor, Below average, Average, Above average, Excellent'))); $form['amazon_recommended_minimum_rating'] = array( '#type' =>'select', '#title' => t('Minimum rating'), '#description' => 'The minimum score a review must have to be displayed.', '#options' => $options, '#default_value' => variable_get('amazon_recommended_minimum_rating', 3), ); break; } return $form; } case 'save': { switch ($delta) { case 0: break; case 1: break; case 2: variable_set('amazon_recommended_minimum_rating', $edit['amazon_recommended_minimum_rating']); break; } break; } case 'list': { $block[0]['info'] = 'Amazon: Random book'; $block[1]['info'] = 'Amazon: Random review'; $block[2]['info'] = 'Amazon: We recommend'; return $block; } case 'view': { switch ($delta) { case 0: // get the number of amazonitem records $amazon_counter = db_fetch_object(db_query('SELECT COUNT(asin) AS count FROM {amazonitem}')); break; case 1: // get the number of amazonitem records $amazon_counter = db_fetch_object(db_query(" SELECT COUNT(DISTINCT asin) AS count FROM {amazonnode} WHERE ntype='amazon'")); break; case 2: // get the number of amazonitem records $amazon_block_minimum_score = variable_get('amazon_block_minimum_score', 3); $amazon_counter = db_fetch_object(db_query(" SELECT COUNT(DISTINCT asin) AS count FROM {amazonnode} WHERE rating >= $amazon_block_minimum_score" )); break; } $max_record = $amazon_counter->count; if ($max_record){ // generate a random number between 1 and the count $random = rand(0, $max_record - 1); switch ($delta) { case 0: $selected_book = db_fetch_object(db_query("SELECT * from {amazonitem} LIMIT 1 OFFSET $random")); $blocksubject = t('We read'); break; case 1: $selected_book = db_fetch_object(db_query(" SELECT n.nid, n.rating, a.* FROM {amazonnode} n JOIN {amazonitem} a ON a.asin = n.asin WHERE ntype = 'amazon' LIMIT 1 OFFSET $random")); $blocksubject = t('We reviewed'); break; case 2: $selected_book = db_fetch_object(db_query(" SELECT n.nid, n.rating, a.* FROM {amazonnode} n JOIN {amazonitem} a ON a.asin = n.asin WHERE n.rating >= $amazon_block_minimum_score LIMIT 1 OFFSET $random" )); $blocksubject = t('We recommend'); break; } } if ($selected_book){ $block['subject'] = $blocksubject; $block['content'] = theme('amazon_block', $selected_book); return $block; } } } } /** * node hooks */ function amazon_access($op, $node) { global $user; switch (is_string($node)? $node : $node->type) { case 'amazon': if ($op == 'create') { return user_access('create amazon'); } if ($op == 'update' || $op == 'delete') { if (user_access('edit amazon') && ($user->uid == $node->uid)) { return TRUE; } } break; case 'amazon_node': if ($op == 'create') { return user_access('create amazon_node'); } if ($op == 'update' || $op == 'delete') { if (user_access('edit amazon_node')) { return TRUE; } } break; } } function amazon_delete($node) { $rows = db_num_rows(db_query("SELECT asin FROM {amazonnode} WHERE asin = '$node->asin'")); if ($rows == 1) { db_query("DELETE FROM {amazonitem} WHERE asin = '$node->asin'"); } db_query("DELETE FROM {amazonnode} WHERE nid = $node->nid AND ntype = '$node->type'"); } function amazon_form($node) { $type = node_get_types('type', $node); $form = array(); if (is_null($node->nid)) { $form['asin'] = array( '#type' => 'textfield', '#title' => t('ASIN'), '#default_value' => $node->asin, '#size' => 20, '#maxlength' => 20, '#description' => t('Enter the ASIN of the item with no spaces or punctuation.'), '#required' => TRUE, ); } else { $form['asin'] = array( '#type' => 'value', '#value' => $node->asin, ); } $form['rating'] = array( '#type' => 'select', '#title' => 'Rating', '#options' => explode(',', 'Unrated,' . variable_get('amazon_ratings_labels', 'Poor, Below average, Average, Above average, Excellent')), '#default_value' => $node->rating, ); if ($node->type == 'amazon') { $form['title'] = array( '#type' => 'textfield', '#title' => check_plain($type->title_label), '#default_value' => $node->title, '#size' => 20, '#required' => TRUE, ); $form['body'] = array( '#type' => 'textarea', '#title' => check_plain($type->body_label), '#default_value' => $node->body, '#cols' => 60, '#rows' => 20, ); } $form['format'] = filter_form($node->format); return $form; } function amazon_form_alter($form_id, &$form_values) { if ($form_id == 'node_type_form') { $node_type = $form_values['old_type']['#value']; if (strpos($node_type, 'amazon') === FALSE) { $form_values['workflow']['amazon_related_link'] = array( '#type' => 'radios', '#title' => t('Allow Amazon.com related product link'), '#default_value' => variable_get('amazon_related_link_'.$node_type, 0), '#options' => array(t('Disabled'), t('Enabled')), ); } } elseif (($form_id == $form_values['type']['#value'] .'_node_form')) { $node = $form_values['#node']; if (variable_get('amazon_related_link_'.$form_values['type']['#value'], 0) > 0) { $form_values['asin_field'] = array( '#type' => 'fieldset', '#title' => t('Related Amazon.com product id'), '#collapsible' => TRUE, '#collapsed' => empty($node->asin), ); $form_values['asin_field']['asin'] = array( '#type' => 'textfield', '#title' => t('Related product(s)'), '#size' => 20, '#maxlength' => 110, '#default_value' => $node->asin, '#description' => t('Enter a comma delimited list of up to 10 ASINs for the related books.'), '#weight' => 10, '#valid' => 'asin', ); } } } function valid_asin() { global $form_values; if ($form_values['asin']) $ASINList = explode(',', $form_values['asin']); if (count($ASINList) > 0) { unset($form_values['amazonnode_data']); $ASINS_as_keys = array_flip($ASINList); $ASINs_at_Amazon = _amazon_product_data_array((object) $form_values); if (count($ASINs_at_Amazon)) { foreach($ASINs_at_Amazon as $ASIN) { $form_values['amazonnode_data'][] = $ASIN; unset($ASINS_as_keys[$ASIN->asin]); $out_ASIN_list[] = $ASIN->asin; } if (count($ASINS_as_keys) > 0) { $ASINS_as_keys = array_flip($ASINS_as_keys); form_set_error('asin', t('No data is available for ') . implode(',', $ASINS_as_keys)); } $form_values['amazonnode_data'] = implode(',',$out_ASIN_list); } } } function amazon_node_form_validate($form_id, &$form_values) { $asin = $form_values['asin']; $amazondata = _amazon_product_data_from_Amazon($asin); if (count($amazondata) == 0) { form_set_error('asin', t("No product: %asin exists at Amazon.com"), array('%asin' => $asin)); } } function amazon_node_node_form_validate($form_id, &$form_values) { $asin = $form_values['asin']; $amazondata = _amazon_product_db_data($asin); if (isset($amazondata) && (is_null($form_values['nid']))) { form_set_error('asin', t("%title is already registered", array('%title' => $amazondata->title))); return; } amazon_node_form_validate($form_id, $form_values); } function amazon_node_node_form_submit($form_id, &$form_values) { $asin = $form_values['asin']; $amazon_result = _amazon_product_data_from_Amazon($asin); $form_values['title'] = $form_values['title'] ? $form_values['title'] : truncate_utf8($amazon_result[0]->title, 128, TRUE); $form_values['body'] = $form_values['body'] ? $form_values['body'] : $amazon_result[0]->editorialreview; $form_values['log'] = $form_values['log'] ? $form_values['log'] : ''; if ($form_values['op'] == t('Submit')) { return node_form_submit($form_id, $form_values); } } function amazon_node_form_submit($form_id, &$form_values) { $asin = $form_values['asin']; $amazon_result = _amazon_product_data_from_Amazon($asin); $form_values['title'] = $form_values['title'] ? $form_values['title'] : truncate_utf8($amazon_result[0]->title, 128, TRUE); $form_values['body'] = $form_values['body'] ? $form_values['body'] : $amazon_result[0]->editorialreview; $form_values['log'] = $form_values['log'] ? $form_values['log'] : ''; if ($form_values['op'] == t('Submit')) { return node_form_submit($form_id, $form_values); } } function amazon_help($section) { switch ($section) { case 'node/add#amazon': return t("Review an item available at Amazon.com."); case 'node/add#amazon_node': return t("Manually add an item from Amazon.com."); case 'admin/help#amazon': return t("

amazon.module creates two new node types:

  1. The node type 'amazon' is for stories about a book sold by Amazon.com. I picture it being used for reviews. One can have as many 'amazon' nodes connected to a single product as you wish.
  2. The node type 'amazon_node' is pure product information. They can be created individually or automatically for each review or related product link entered. This lets your users build your database of products. The administrative interface has an Amazon.com search facility that lets you look up books by keyword or list of ASINs and import them into 'amazon_node' nodes in bulk. Only one 'amazon_node' is created per ASIN.

A field for related products is added to all node types. A comma delimited list of ASINs will produce Amazon links for each ASIN at the bottom of the post.

Because the 'amazon_node' nodes are standard nodes they can have categories attached and taxinomy based pages are automatically available.

The module also has a block that displays a random item linked to the Amazon detail page for the item.

The module includes a drop-in search engine for Amazon.com's book store. The search returns a minimally formatted list of books, including the image Amazon.com provides, the list and Amazon.com prices, a purchase link and each author's name links to an Amazon search for more books by that same author.

"); break; case 'admin/modules#description': return t('Creates associate links to Amazon.com books.'); break; } } function amazon_insert($node) { $amazon_data = _amazon_product_db_data($node->asin); if (is_null($amazon_data)) { $amazon_data_array = _amazon_product_data_from_Amazon($node->asin); $amazon_data = $amazon_data_array[0]; db_query("INSERT INTO {amazonitem} (asin, detailpageurl, smallimageurl, smallimageheight, smallimagewidth, mediumimageurl, mediumimageheight, mediumimagewidth, largeimageurl, largeimageheight, largeimagewidth, author, editorialreview, binding, listamount, listcurrencycode, listformattedprice, title, amount, currencycode, formattedprice, pricedate, availability) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, %d, '%s', %d, %d, '%s', '%s', '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s')", $amazon_data->asin, $amazon_data->detailpageurl, db_escape_string($amazon_data->smallimageurl), $amazon_data->smallimageheight, $amazon_data->smallimagewidth, db_escape_string($amazon_data->mediumimageurl), $amazon_data->mediumimageheight, $amazon_data->mediumimagewidth, db_escape_string($amazon_data->largeimageurl), $amazon_data->largeimageheight, $amazon_data->largeimagewidth, serialize($amazon_data->author), db_escape_string($amazon_data->editorialreview), $amazon_data->binding, $amazon_data->listamount, $amazon_data->listcurrencycode, $amazon_data->listformattedprice, $amazon_data->title, $amazon_data->amount ? $amazon_data->amount: $amazon_data->listamount, $amazon_data->currencycode, $amazon_data->formattedprice ? $amazon_data->formattedprice: $amazon_data->listformattedprice, date('Y-m-d H:i:s'), $amazon_data->availability); } $rating = $node->rating ? $node->rating : 0; db_query("INSERT INTO {amazonnode} (nid, asin, ntype, rating) VALUES (%d, '%s', '%s', %d)", $node->nid, $node->asin, $node->type, $rating); } function amazon_load(&$node) { $ASINRec = db_fetch_object(db_query("SELECT * FROM {amazonnode} WHERE nid = %d", $node->nid)); $additions = db_fetch_object(db_query("SELECT * FROM {amazonitem} WHERE asin = '%s'", $ASINRec->asin)); $additions->author = unserialize($additions->author); $additions->rating = $ASINRec->rating; $additions->product_title = $additions->title; unset($additions->title); return $additions; } function amazon_manage() { return drupal_get_form('amazon_item_manage'); } function amazon_item_manage() { // get total number of amazon item and number of stale dated items $stale_price_date = date('Y-m-d', time() - 604800); //604800 is a week of seconds $cq = "SELECT 'total' as counttype, count(asin) AS count from {amazonitem} UNION SELECT 'stale' as counttype, count(asin) FROM {amazonitem} WHERE pricedate <= '$stale_price_date'"; $counterquery = db_query($cq); while ($counter_record = db_fetch_object($counterquery)) { switch ($counter_record->counttype) { case 'stale': $stale_count = $counter_record->count; break; default: $total_count = $counter_record->count; break; } } $max_passes = ceil($total_count / 10); $totallabel = t('Total registered items'); $stalelabel = t('Total stale prices'); $banner = "

$totallabel: $total_count
$stalelabel: $stale_count

"; $form = array(); $form['max_passes'] = array( '#type' => 'value', '#value' => $max_passes, ); $form['stale'] = array( '#type' => 'fieldset', ); $form['stale']['make_stale'] = array( '#prefix' => $banner, '#type' => 'submit', '#value' => t('Mark all prices stale'), ); $form['refresh'] = array( '#type' => 'fieldset', ); $form['refresh']['pass_count'] = array( '#type' => 'select', '#options' => array(0 => 'all', 1, 2, 3, 4, 5), '#description' => t('Select the passes to make. Ten records are refreshed per pass.'), '#title' => t('Pass count') ); $form['refresh']['refresh_stale'] = array( '#type' => 'submit', '#value' => t('Refresh prices'), ); return $form; } function amazon_menu($may_cache) { global $_amazon_search_browse_fields; $tab_weight = 0; $items = array(); // if ($may_cache) { $items[] = array('path' => 'node/add/amazon', 'title' => t('Amazon'), 'access' => user_access('create amazon')); $items[] = array('path' => 'admin/content/amazon_import', 'title' => t('Amazon item import'), 'callback' => 'amazon_import_page', 'weight' => 0, 'description' => t('Search for products on Amazon.com and import into nodes.')); $items[] = array('path' => 'admin/content/amazon_import/import', 'title' => t('Import'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'callback' => 'amazon_import_page'); foreach ($_amazon_search_browse_fields as $product_type => $data) { $items[] = array('path' => 'admin/content/amazon_import/import/' . $product_type, 'title' => $product_type, 'access' => TRUE, 'type' => MENU_LOCAL_TASK, 'callback' => 'amazon_import_page', 'weight' => $tab_weight++,); } $items[] = array('path' => 'admin/content/amazon_import/manage', 'title' => t('Manage'), 'type' => MENU_LOCAL_TASK, 'callback' => 'amazon_manage'); $items[] = array('path' => 'search/amazon', 'title' => ('Amazon.com'), 'access' => user_access('search amazon.com'), 'type' => MENU_LOCAL_TASK, 'callback' => 'amazon_search_page'); $tab_weight = 0; foreach ($_amazon_search_browse_fields as $product_type => $data) { $items[] = array('path' => 'search/amazon/' . $product_type, 'title' => ($product_type), 'access' => user_access('search amazon.com'), 'type' => MENU_LOCAL_TASK, 'callback' => 'amazon_search_page', 'weight' => $tab_weight++,); } $items[] = array('path' => 'admin/settings/amazon', 'title' => t('Amazon'), 'description' => t('Set the Amazon store and Associate ID.'), 'callback' => 'drupal_get_form', 'callback arguments' => 'amazon_settings', 'access' => user_access('administer site configuration')); return $items; } function amazon_node_info() { return array( 'amazon' => array( 'name' => t('amazon'), 'module' => 'amazon', 'description' => t('Review an item at Amazon.com.') ), 'amazon_node' => array( 'name' => t('amazon node'), 'module' => 'amazon', 'description' => t('Amazon.com data for "related product" links.') ) ); } function amazon_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { global $form_values; if (variable_get('amazon_related_link_'.$node->type, 0) == 1) { switch ($op) { case 'update': case 'insert': if ($node->nid) { db_query('DELETE FROM {amazonnode} WHERE nid = %d', $node->nid); } if ($form_values['asin']) { $amazondata = _amazon_product_data_from_Amazon($form_values['asin']); foreach($amazondata as $amazon_data) { _to_amazonnode($amazon_data); db_query("INSERT INTO {amazonnode} (nid, asin, ntype) VALUES (%d, '%s', '%s')", $node->nid, $amazon_data->asin, $node->type); } } break; case 'delete': db_query('DELETE FROM {amazonnode} where nid = %s', $node->nid); break; case 'load': if ($node->nid) { $ASINQuery = db_query("SELECT asin FROM {amazonnode} WHERE nid = %d", $node->nid); while ($ASINRec = db_fetch_object($ASINQuery)) { $ASINList[] = $ASINRec->asin; } if (count($ASINList) > 0) { $node->asin = implode(',', $ASINList); $form_values['asin']['#value'] = $node->asin; $node->amazonnode_data = _amazon_product_db_data_by_ASIN($node->asin); } } break; case 'view': { if ($node->in_preview == 1) { $amazondata = _amazon_product_data_from_Amazon($form_values['asin']); } else { $amazondata = $node->amazonnode_data; } if ($amazondata) { foreach($amazondata as $amazon_data) { $related_links .= theme('amazon_related_link', $amazon_data); } $node->content['related_links'] = array( '#value' => $related_links ); } } break; } } } function amazon_perm() { return array('create amazon', 'edit amazon', 'create amazon_node', 'edit amazon_node', 'search amazon.com',); } function amazon_settings() { global $_amazon_search_amazon_shop_URI; $form = array(); $form['amazon_locale'] = array( '#type' => 'select', '#title' => t('Locale'), '#default_value' => variable_get('amazon_locale', 0), '#options' => array_keys($_amazon_search_amazon_shop_URI), '#description' => t('Select the Amazon.com locale you are affiliated with.'), ); $form['amazon_associate_id'] = array( '#type' => 'textfield', '#title' => t('Amazon Associate ID'), '#size' => 30, '#maxlength' => 30, '#default_value' => variable_get('amazon_associate_id', ''), '#description' => t('Lets Amazon.com know which associate to credit with the referral. If you do not fill in this field you will not earn commissions.'), ); $form['amazon_ratings_labels'] = array( '#title' => t('Ratings labels'), '#type' => 'textarea', '#default_value' => variable_get('amazon_ratings_labels', 'Poor, Below average, Average, Above average, Excellent'), '#description' => t('Enter a comma delimited list of rating lables, from lowest to highest.'), '#width' => 60, '#height' => 5, ); $form['amazon_link_functionality'] = array( '#title' => t('Link Functionality'), '#type' => 'radios', '#options' => array(t('Images link back to Amazon'),t('Disable image links'),t('Images link to product node')), '#default_value' => variable_get('amazon_link_functionality', 0), ); return system_settings_form($form); } function amazon_update($node) { db_query('UPDATE {amazonnode} SET rating=\'%d\' WHERE nid = %d', $node->rating, $node->nid); } function amazon_view($node, $teaser, $page) { $node = node_prepare($node, $teaser); $node->content['amazon_data'] = array( '#value' => theme('amazon_node', $node), ); return $node; } function amazon_cron() { // get 10 ASINs whose prices haven't been updated for a week $stale_price_date = date('Y-m-d', time() - 604800); //604800 is a week of seconds $stale_records = db_query_range("SELECT asin FROM {amazonitem} WHERE pricedate <= '%s' ORDER BY pricedate", $stale_price_date, 0, 10); if (db_num_rows($stale_records) > 0) { // get the Amazon records for each of them while ($stale_ASIN = db_fetch_object($stale_records)) { $ASIN_to_refresh[] = $stale_ASIN->asin; } $ASINList = implode(',', $ASIN_to_refresh); $ASIN_update = _amazon_product_data_from_Amazon($ASINList); // update their amazonitem records if (count($ASIN_update) > 0) { foreach($ASIN_update as $ASIN_data) { _refresh_amazonitem_data($ASIN_data); } } } } function _amazon_bulk_import(&$_search_form_values, $_amazon_locale) { if ($_search_form_values[items]) { foreach ($_search_form_values[items] as $asinkey => $amazon_item) { if (isset($amazon_item['add'])) $ASIN_array[] = $asinkey; } $ASIN_query_params = array('AssociateTag'=>variable_get('amazon_associate_id', ''), 'AmazonShop'=>$_amazon_locale, 'Operation' => 'ItemLookup', 'ItemId' => implode(',', $ASIN_array), 'ResponseGroup' => 'Medium,Offers', 'MerchantId' => 'Featured'); // do an Amazon ASIN query, returned as an array of amazon item objects $books_to_save = amazon_get_items($ASIN_query_params); // save them nodes! foreach ($books_to_save as $amazon_node) { if (isset($_search_form_values['items']["$amazon_node->asin"]['taxonomy'])) { $amazon_node->taxonomy = $_search_form_values['items']["$amazon_node->asin"]['taxonomy']; } $amazon_node->rating = 0; //drupal_set_message(print_r($amazon_node, 1)); _to_amazonnode($amazon_node); } } else { drupal_set_message(t('Select the checkbox next to the book record(s) you want to import.')); } } function _amazon_search_form($_amazon_operation_request, $_search_form_values, $_amazon_locale) { global $_amazon_search_browse_fields; global $_amazon_search_browse_nodes; $search_form['#token'] = FALSE; $search_form['Operation'] = array( '#type' => 'hidden', '#value' => 'ItemSearch' ); $search_form['ResponseGroup'] = array( '#type' => 'hidden', '#value' => 'Medium' ); $search_form['MerchantId'] = array( '#type' => 'hidden', '#value' => 'Featured' ); $search_form['ItemPage'] = array( '#type' => 'hidden', '#value' => '1' ); $search_form['TotalPages'] = array( '#type' => 'hidden', '#value' => $_amazon_operation_request['stats']['TotalPages'] ); $search_form['SearchIndex'] = array( '#type' => 'hidden', '#value' => $_search_form_values['SearchIndex'], ); $search_form['SearchField'] = array( '#type' => 'select', '#title' => t('Search'), '#default_value' => ($_search_form_values['SearchField'])?$_search_form_values['SearchField']:array('Keywords'=>'Keywords'), '#options' => $_amazon_search_browse_fields[$_search_form_values['SearchIndex']], '#attributes' => 'size="4"' ); $search_form['BrowseField'] = array( '#type' => 'select', '#title' => t('Search Category'), '#default_value' => ($_search_form_values['BrowseField'])?$_search_form_values['BrowseField']:array('0'=>'All'), '#options' => $_amazon_search_browse_nodes[$_search_form_values['SearchIndex']], '#attributes' => 'size="4"' ); $search_form['SearchFor'] = array( '#type' => 'textfield', '#title' => t('Search for'), '#default_value' => ($_search_form_values['SearchFor'])?urldecode($_search_form_values['SearchFor']):'', '#size' => 60, '#maxlength' => 127 ); $search_form['Search'] = array('#type' => 'button', '#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#value' => 'Search', '#execute' => TRUE); $search_form['AmazonCredit'] = array( '#type' => 'markup', '#value' => '
in association with Amazon.com
' ); // execute the search ant output the result return $search_form; } function _amazon_search_params($_search_form_values, $_amazon_locale) { if ($_search_form_values['SearchFor']) { $_amazon_search_params = array(); // get the search parameters $_amazon_search_params['AssociateTag'] = variable_get('amazon_associate_id', ''); $_amazon_search_params['Operation'] = $_search_form_values['Operation']; $_amazon_search_params['SearchIndex'] = $_search_form_values['SearchIndex']; $_amazon_search_params['ResponseGroup'] = $_search_form_values['ResponseGroup']; $_amazon_search_params['MerchantId'] = $_search_form_values['MerchantId']; $_amazon_search_params['AmazonShop'] = $_amazon_locale; if ($_search_form_values['BrowseField']) { $_amazon_search_params['BrowseNode'] = $_search_form_values['BrowseField']; } $search_for = $_search_form_values['SearchFor']; if (function_exists('iconv')) { $search_for = iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $search_for); } $_amazon_search_params[$_search_form_values['SearchField']] = $search_for; switch ($_search_form_values['op']) { CASE 'Search': CASE 'First page': { $_amazon_search_params['ItemPage'] = 1; break; } case 'Import and continue': case 'Next page': { $_amazon_search_params['ItemPage'] = $_search_form_values['ItemPage'] + 1; break; } case 'Previous page': { $_amazon_search_params['ItemPage'] = $_search_form_values['ItemPage'] - 1; break; } case 'Last page': { $_amazon_search_params['ItemPage'] = $_search_form_values['TotalPages']; break; } case 'Go to page': { $_amazon_search_params['ItemPage'] = $_search_form_values['GotoPage']; break; } } return $_amazon_search_params; } } function _amazon_seach_search($_amazon_search_params) { global $_amazon_search_amazonDOM; // do the query $_amazon_search_amazonDOM = amazon_get_DOM($_amazon_search_params); // return the array of items return _amazon_items_array_from_DOM($_amazon_search_amazonDOM); } function _amazon_search_output(&$_amazon_search_params, $_search_form_values) { global $_amazon_operation_request; global $_amazon_search_amazonDOM; if ($_amazon_search_params) { // return the array of items $_amazon_items = _amazon_seach_search($_amazon_search_params); $_amazon_operation_request = _amazon_operation_request($_amazon_search_amazonDOM); // render the array $output = '
'; if (count($_amazon_items) > 0) { foreach ($_amazon_items as $_amazon_item) { $output .= _amazon_search_format_item($_amazon_item, $_amazon_operation_request['Arguments']); } $_amazon_search_params['TotalPages'] = $_amazon_operation_request['stats']['TotalPages']; $_amazon_search_params['SearchField'] = $_search_form_values['SearchField']; $_amazon_search_params['SearchFor'] = $_search_form_values['SearchFor']; } else { $output = t('No items were found that match your query.'); } } return $output; } function _amazon_search_pager($_amazon_search_params) { // [[First][Previous] Page X of XXX <-combo/page [Next][Last]] $_TotalPages = $_amazon_search_params['TotalPages']; $_current_page = $_amazon_search_params['ItemPage']; if ($_current_page > 1) { $output['leftfloat'] = array( '#type' => 'markup', '#value' => '
' ); $output[]['op'] = array( '#type' => 'button', '#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#value' => 'First page', '#execute' => TRUE ); $output[]['op'] = array( '#type' => 'button', '#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#value' => 'Previous page', '#execute' => TRUE ); $output['closeleft']= array( '#type' => 'markup', '#value' => '
' ); } if ($_current_page < $_TotalPages) { $output['rightfloat']= array( '#type' => 'markup', '#value' => '
' ); $output[]['op'] = array( '#type' => 'button', '#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#value' => 'Next page', '#execute' => TRUE ); $output[]['op'] = array( '#type' => 'button', '#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#value' => 'Last page', '#execute' => TRUE ); $output['closeright']= array( '#type' => 'markup', '#value' => '
' ); } if (isset($_amazon_search_params)) { foreach ($_amazon_search_params as $key => $value) { if ($key == 'BrowseNode') { $output['BrowseField'] = array( '#type' => 'hidden', '#value' => $value ); } else { $output[$key] = array( '#type' => 'hidden', '#value' => $value ); } } $_current_page = $_current_page ? $_current_page : 1; $output['centerfloatstart']= array( '#type' => 'markup', '#value' => '
', ); $output[]['op'] = array( '#type' => 'button', '#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#value' => 'Go to page', '#execute' => TRUE ); $output['GotoPage']= array( '#type' => 'textfield', '#default_value' => $_current_page, '#size' => 4, '#maxlength' => 4, ); $output['centerfloatend']= array( '#type' => 'markup', '#value' => " of $_TotalPages
", ); } return $output; } function _amazon_search_linkto($AmazonItem, $linkText) { $link_title = t('Purchase this item at Amazon.com'); return "detailpageurl\" title=\"$link_title\">$linkText"; } function _amazon_search_format_item($amazonitem, $qparams) { $output = '
'; if ($amazonitem->mediumimageurl) { // the image (and alignment) should be optional via admin page $output .= '
'; $output .= _amazon_search_linkto($amazonitem, "mediumimageurl\" height=\"$amazonitem->mediumimageheight\" width=\"$amazonitem->mediumimagewidth\" alt=\"cover of $amazonitem->title\" hspace=\"5\" />"); $output .= '
'; } $output .= 'title:  '._amazon_search_linkto($amazonitem, $amazonitem->title).'
'; /** * amazon.com may return multiple instances of these, and we want to be able to search on the returned * values so they get special handling * */ $qparams['def']['SearchIndex'] = 'Books'; // $qparams['def']['SearchIndex'] = $qparams['var']['SearchIndex']; foreach ($qparams['def'] as $key =>$value) { if ($key!='q') $qstr[] = "$key=$value"; } $qstr[] = 'Operation=ItemSearch'; $qstr[] = 'SearchField=Author'; $qstr[] = 'ResponseGroup=Medium'; if (is_array($amazonitem->author)) { foreach($amazonitem->author as $key => $value) { $output .= 'author:    $amazonitem->asin
"; if ($amazonitem->binding) { $output .= '' . t('binding') . ": $amazonitem->binding
"; } if ($amazonitem->listformattedprice) { $output .= '' . t('list price') . ": $amazonitem->listformattedprice $amazonitem->listcurrencycode
"; } if ($amazonitem->formattedprice) { $output .= '' . t('amazon price') . ": $amazonitem->formattedprice $amazonitem->currencycode

"; } $output .= '

'; $output .= '
'; return $output; } function _amazon_import_format_item($node) { $module_dir = drupal_get_path('module', 'amazon'); $output = array(); $output['#tree'] = 1; $output['startrow']= array( '#type' => 'markup', '#value' => '' ); $exists_query = db_query('SELECT a.nid FROM {amazonnode} a WHERE a.ntype = \'amazon_node\' AND a.asin = \'%s\'', $node->asin); $exists = db_num_rows($exists_query); if (!$exists) { $output['add'] = array( '#type' => 'checkbox', '#default_value' => 0, '#prefix' => '', '#suffix' => '' ); } else { $output['add'] = array( '#type' => 'markup', '#value' => '' ); } $datacell .= ""; if ($node->smallimageurl) { $datacell .= "smallimageurl\" height=\"$node->smallimageheight\" width=\"$node->smallimagewidth\" alt=\"cover of $node->title\" />"; } else { $datacell .= "\"no"; } $datacell .= ''; $datacell .= ""; if ($node->detailpageurl) { $datacell .= amazon_paint_link($node); } if ($node->author) { $datacell .= 'author: ' . implode(",",$node->author) . '
'; } if ($node->asin) { $datacell .= 'asin: ' . $node->asin . '
'; } if ($node->binding) { $datacell .= "binding: $node->binding
"; } if ($node->listformattedprice) { $datacell .= "list price: $node->listformattedprice $node->listcurrencycode
"; } if ($node->formattedprice) { $datacell .= "amazon price: $node->formattedprice $node->currencycode

"; } $datacell .= ''; $output['datacell']= array( '#type' => 'markup', '#value' => $datacell, ); // taxonomy form goes in this cell! $output['taxonomy'] = _amazon_taxonomy_term_control(); $output['endrow']= array( '#type' => 'markup', '#value' => '', ); return $output; } function _amazon_import_search_output(&$_amazon_search_params, $_search_form_values){ global $_amazon_operation_request; global $_amazon_search_amazonDOM; if ($_amazon_search_params) { $search_for = $_search_form_values['SearchFor']; if (function_exists('iconv')) { $search_for = iconv('UTF-8', 'ISO-8859-1', $search_for); } $_amazon_search_params[$_search_form_values['SearchField']] = $search_for; // return the array of items return _amazon_seach_search($_amazon_search_params); } } function _amazon_taxonomy_term_control() { global $amazon_vid; // get the vocabulary id for the first vocabulary assigned to the node type $vocab_query = db_query("SELECT v.* FROM {vocabulary_node_types} vnt JOIN {vocabulary} v ON v.vid = vnt.vid WHERE vnt.type = 'amazon_node' ORDER BY weight, vid LIMIT 1"); if ($vocab = db_fetch_object($vocab_query)) { switch ($vocab->tags) { case 0: $vtree = taxonomy_get_tree($vocab->vid); $options[0] = t(''); foreach ($vtree as $vterm) { $options[$vterm->tid] = $vterm->name; } $control[$vocab->vid] = array( '#type' => 'select', '#multiple' => $vocab->multiple, '#prefix' => '', '#suffix' => '', '#options' => $options, ); break; case 1: $control['tags'][$vocab->vid] = array( '#title' => t('tags'), '#type' => 'textfield', '#size' => 20, '#prefix' => '', '#suffix' => '', ); break; } return $control; } else { return array(); } } function amazon_search_page() { global $_amazon_search_amazon_shop_URI; global $_amazon_operation_request; global $_amazon_search_browse_fields; $_amazon_locale_index = variable_get('amazon_locale', '0'); $_amazon_locale_list = array_keys($_amazon_search_amazon_shop_URI); $_amazon_locale = $_amazon_locale_list[$_amazon_locale_index]; $_search_form_values = $_POST; if (count($_search_form_values) == 0) { $_search_form_values = $_GET; } if (count($_search_form_values) > 0) { $_search_form_values['op'] = $_POST['op'] ? $_POST['op'] : 'Search'; if (!isset($_search_form_values['SearchIndex'])) { if (arg(2)) { $_search_form_values['SearchIndex'] = arg(2); } else { $search_index = array_keys($_amazon_search_browse_fields); $_search_form_values['SearchIndex'] = $search_index[0]; } } } $_amazon_search_params = _amazon_search_params($_search_form_values, $_amazon_locale); $output = _amazon_search_output($_amazon_search_params, $_search_form_values); $output .= drupal_get_form('_amazon_search_pager', $_amazon_search_params); // the search form itself $search_form = drupal_get_form('_amazon_search_form', $_amazon_operation_request, $_search_form_values, $_amazon_locale); drupal_set_title(t('Amazon.com book search')); return $search_form . $output; } function amazon_item_manage_submit($form_id, &$form_values) { $command = $_POST['op']; switch ($command) { case t('Mark all prices stale'): db_query("UPDATE {amazonitem} SET pricedate = '2001-01-01'"); break; case t('Refresh prices'): set_time_limit(600); $max_pass = $form_values['pass_count'] ? $form_values['pass_count'] : $form_values['max_passes']; for ($pass = 0; $pass < $max_pass; $pass++ ) { amazon_cron(); } break; } } function amazon_import_result_form($_amazon_search_params, $_search_form_values) { global $_amazon_search_amazon_shop_URI; global $_amazon_search_amazonDOM; global $_amazon_taxonomy_term_select; if ($_amazon_search_params) { $_amazon_items = _amazon_import_search_output($_amazon_search_params, $_search_form_values); // render the array // $output = '
'; if (count($_amazon_items) > 0) { $_amazon_operation_request = _amazon_operation_request($_amazon_search_amazonDOM); $output['#token'] = FALSE; $output['starttable'] = array( '#type' => 'markup', '#value' => '' ); $output['Operation'] = array( '#type' => 'hidden', '#value' => 'ItemSearch' ); $output['ResponseGroup'] = array( '#type' => 'hidden', '#value' => 'Medium' ); $output['MerchantId'] = array( '#type' => 'hidden', '#value' => $_search_form_values['MerchantId'] ); $output['ItemPage'] = array( '#type' => 'hidden', '#value' => $_amazon_search_params['ItemPage'] ); $output['TotalPages'] = array( '#type' => 'hidden', '#value' => $_amazon_operation_request['Arguments']['stats']['TotalPages'] ); $output['SearchIndex'] = array( '#type' => 'hidden', '#value' => $_search_form_values['SearchIndex'] ); $output['SearchField'] = array( '#type' => 'hidden', '#value' => $_search_form_values['SearchField'] ); $output['BrowseField'] = array( '#type' => 'hidden', '#value' => $_search_form_values['BrowseField'] ); $output['SearchFor'] = array( '#type' => 'hidden', '#value' => $_search_form_values['SearchFor'] ); $output['items'] = array( '#tree' => 1 ); foreach ($_amazon_items as $_amazon_item) { $output['items'][$_amazon_item->asin] = _amazon_import_format_item($_amazon_item); } $_amazon_search_params['TotalPages'] = $_amazon_operation_request['stats']['TotalPages']; $_amazon_search_params['SearchField'] = $_search_form_values['SearchField']; $_amazon_search_params['SearchFor'] = $_search_form_values['SearchFor']; $output[]['op'] = array( '#type' => 'button', '#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#value' => 'Import', '#execute' => TRUE, '#prefix' => '' ); } $output['pager'] = array( '#type' => 'markup', '#value' => '' ); $output['endtable'] = array( '#type' => 'markup', '#value' => '
' ); if($_amazon_search_params['ItemPage'] < $_amazon_search_params['TotalPages']){ $output[]['op'] = array( '#type' => 'button', '#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#value' => 'Import and continue', '#execute' => TRUE, '#suffix' => '
' . drupal_get_form('_amazon_search_pager', $_amazon_search_params) . '
' ); } else { if ($_POST['op']) { $output[] = array( '#type' => 'markup', '#value' => t('No items were found that match your query.'), ); } } } return $output; } function amazon_import_page() { global $_amazon_search_amazon_shop_URI; global $_amazon_search_amazonDOM; global $_amazon_search_params; global $_amazon_taxonomy_term_select; global $_amazon_search_browse_fields; $_amazon_locale_index = variable_get('amazon_locale', '0'); $_amazon_locale_list = array_keys($_amazon_search_amazon_shop_URI); $_amazon_locale = $_amazon_locale_list[$_amazon_locale_index]; $search_indexes = array_keys($_amazon_search_browse_fields); $_search_form_values = $_POST; $_search_form_values['op'] = $_POST['op']; $_search_form_values['SearchIndex'] = arg(4) ? arg(4) : $search_indexes[0]; $_amazon_search_params = _amazon_search_params($_search_form_values,$_amazon_locale); if (($_search_form_values['op'] == 'Import') or ($_search_form_values['op'] == 'Import and continue')) { _amazon_bulk_import($_search_form_values, $_amazon_locale); } // the search form itself $search_form = drupal_get_form('_amazon_search_form', $_amazon_operation_request, $_search_form_values, $_amazon_locale); $output = drupal_get_form('amazon_import_result_form', $_amazon_search_params, $_search_form_values); return $search_form . $output; } function theme_amazon_block($selected_book) { if (isset($selected_book->nid)) { $is_review = TRUE; $review_url = url("node/$selected_book->nid"); } $module_dir = drupal_get_path('module', 'amazon'); $book_image = $selected_book->mediumimageurl ? $selected_book->mediumimageurl : "$module_dir/images/missingm.gif"; $blockcontent = '
'; if ($is_review) { $blockcontent .= "review "; $blockcontent .= "mediumimageheight\" width=\"$selected_book->mediumimagewidth\" alt=\"cover of $selected_book->title\" />
"; $blockcontent .= '
'; $blockcontent .= "".amazon_paint_link($node); $blockcontent .= ''; $blockcontent .= ""; $blockcontent .= t('Read the review'); $blockcontent .= ''; } else { $blockcontent .= amazon_paint_image($node,$book_image,$selected_book); $blockcontent .= amazon_paint_link($selected_book); } if ($selected_book->rating) { $output .= "rating: rating.gif\" alt=\"$selected_book->rating\" />
"; } $blockcontent .= '
'; return $blockcontent; } function theme_amazon_node($node) { $module_dir = drupal_get_path('module', 'amazon'); $output = ''; $output .= ''; $output .= ''; $output .= "'; $output .= ''; $output .= '
"; $output .= amazon_paint_image($node); $output .= ""; if ($node->type == 'amazon') { if ($node->detailpageurl) { $output .= "detailpageurl\" target=\"_blank\">"; } $output .= $node->product_title . '

'; if ($node->detailpageurl) { $output .= '
'; } } else { if ($node->detailpageurl) { $output .= "detailpageurl\" target=\"_blank\">"; } $output .= 'See ' . $node->product_title . ' at Amazon

'; if ($node->detailpageurl) { $output .= '
'; } } if ($node->author) { $output .= 'author: ' . implode('
', $node->author) . '
'; } if ($node->rating) { $output .= "rating: rating.gif\" alt=\"\" />
"; } if ($node->asin) { $output .= 'asin: ' . $node->asin . '
'; } if ($node->binding) { $output .= "binding: $node->binding
"; } if ($node->listformattedprice) { $output .= "list price: $node->listformattedprice $node->listcurrencycode
"; } if ($node->formattedprice) { $output .= "amazon price: $node->formattedprice $node->currencycode

"; } $output .= '

'; return $output; } function theme_amazon_related_link($node) { $output = ''; $output .= "'; $output .= "'; $output .= '
"; $output .= amazon_paint_link($node); $module_dir = drupal_get_path('module', 'amazon'); if ($node->smallimageurl) { $output .= "smallimageurl\" height=\"$node->smallimageheight\" width=\"$node->smallimagewidth\" alt=\"cover of $node->title\" />"; } else { $output .= "\"no"; } $output .= '"; if ($node->detailpageurl) { $output .= amazon_paint_link($node); } if ($node->author) { $output .= 'author: ' . implode(",",$node->author) . '
'; } if ($node->asin) { $output .= 'asin: ' . $node->asin . '
'; } $output .= '
'; return $output; } function amazon_paint_image($node,$book_image=null,$selected_book=null) { $src = $book_image; $height = $selected_book->mediumimageheight; $width = $selected_book->mediumimagewidth; if(!$src) { $src = $node->mediumimageurl; $height = $node->mediumimageheight; $width = $node->width; } if ($src) { $image .= "\"covertitle\" />"; } else { $image .= "\"no"; } switch(variable_get('amazon_link_functionality',0)) { case 0: $output .= l($image,$node->detailpageurl,array('target'=>'_blank'),null,null,false,true); break; case 1: $output .= $image; break; case 2: if(!$node->nid) { $node = db_fetch_object(db_query("SELECT nid,asin from {amazonnode} where asin = '%s'",$selected_book->asin)); } $output .= l($image,'node/'.$node->nid,null,null,null,false,true); break; } return $output; } function amazon_paint_link($selected_book) { $href = $selected_book->detailpageurl; $title = $selected_book->title; switch(variable_get('amazon_link_functionality',0)) { case 0: $output .= "

".l($title,$href,array('target'=>'_blank'),null,null,false,false)."

"; break; case 1: $output .= "

$title

"; break; case 2: $node = db_fetch_object(db_query("SELECT nid,asin from {amazonnode} where asin = '%s'",$selected_book->asin)); $output .= "

".l($title,'node/'.$node->nid,null,null,null,false,false)."

"; break; } return $output; }