Created
April 14, 2011 21:19
-
-
Save rfay/920580 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Amazon.module API Documentation | |
| =============================== | |
| Please read the handbook documentation at http://drupal.org/node/595464. | |
| The Amazon package gives Drupal based web sites access to the core features of | |
| the Amazon Product Marketing API. The package provides several components: | |
| 1) A core API module that communicates with Amazon's web services and adds | |
| support for retrieving, displaying, and storing basic product information | |
| in Drupal as well as associating Amazon products with content nodes. | |
| 2) A field type (and an accompanying set of formatters) for CCK that allows | |
| Amazon products to be explicitly added to any node type. | |
| 3) An 'Amazon Media' module that adds support for Amazon's extended product | |
| information for several common product types (Books, Music, DVDs, and | |
| Software). | |
| 4) An 'Amazon Search' module that allows developers to conduct API-driven | |
| searches of the Amazon product database. This module also allows users to | |
| search Amazon's product database from Drupal's Advanced Search page. | |
| Most users and site builders will want to enable the basic Amazon API module, | |
| as well as the Amazon Field and Amazon Media modules. These provide the | |
| functionality that the majority of simple sites need. | |
| For more information, visit the project page at http://drupal.org/project/amazon | |
| and the project documentation at http://drupal.org/node/595464. | |
| Amazon API conventions | |
| ====================== | |
| - All element keys are lowercased for consistency | |
| - The Amazon ItemAttributes collection is merged into the top level of the | |
| Drupal entity for simplicity. | |
| - Information outside the 'common' ItemAttributes, Product Images, and | |
| Artist/Author/Etc. data must be handled by external third-party modules. | |
| - Authors, Directors, and other creator information is stored in the generic | |
| $item['participants'] array. It's a crummy name, but until I come up with | |
| something better it'll have to do. A separate array for each participant type | |
| is also created. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Outputs a single piece of data as provided in $$detail. | |
| * | |
| * This is used primarily for amazon_filter, where any arbitrary piece of data | |
| * from the $item can be accessed. | |
| */ | |
| if (!empty($detail) && !empty($$detail)) { | |
| print $$detail; | |
| } else { | |
| print t('%detail not found for %asin', array('%detail' => $detail, '%asin' => $asin)); | |
| } | |
| ?> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Theme the 'amazon_inline_item' type. | |
| * Available variables: | |
| * - $item: The cleaned amazon_item with all data. | |
| */ | |
| ?> | |
| <span class="<?php print _amazon_item_classes($item) ?> amazon-item-inline"> | |
| <?php print l($item['title'], $item['detailpageurl'], array('html' => TRUE, 'attributes' => array('rel' => 'nofollow'))); ?> | |
| </span> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Theme the 'amazon-item' 'book' 'details' style. | |
| * Many, many available variables. See template_preprocess_amazon_item(). | |
| * Everything that gets put into $variables there is available. | |
| */ | |
| ?> | |
| <div class="<?php print $classes; ?>"> | |
| <?php if (!empty($smallimage)) { print $smallimage; } ?> | |
| <div><strong><?php print l($title, $detailpageurl, array('html' => TRUE, 'attributes' => array('rel' => 'nofollow'))); ?></strong></div> | |
| <div><strong><?php print t('Author'); ?>:</strong> <?php print $author; ?></div> | |
| <div><strong><?php print t('Publisher'); ?>:</strong> <?php print $publisher; ?> (<?php print $publicationyear; ?>)</div> | |
| <div><strong><?php print t('Binding'); ?>:</strong> <?php print t('@binding, @pages pages', array('@binding' => $binding, '@pages' => !empty($numberofpages) ? $numberofpages : "")); ?></div> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Theme the 'amazon-item' 'detail' style. | |
| * Many, many available variables. See template_preprocess_amazon_item(). | |
| * Everything that gets put into $variables there is available. | |
| */ | |
| ?> | |
| <div class="<?php print $classes; ?>"> | |
| <?php if (!empty($invalid_asin)) { print "<div class='invalid_asin'>This item is no longer valid on Amazon.</div>"; } ?> | |
| <?php print $smallimage; ?> | |
| <div><strong><?php print l($title, $detailpageurl, array('html' => TRUE, 'attributes' => array('rel' => 'nofollow'))); ?></strong></div> | |
| <div><strong><?php print t('Manufacturer'); ?>:</strong> <?php if (!empty($manufacturer)) { print $manufacturer; } ?></div> | |
| <div><strong><?php print t('Part Number'); ?>:</strong> <?php if (!empty($mpn)) {print $mpn; }?></div> | |
| <div><strong><?php print t('Price'); ?>:</strong> <?php if (!empty($listpriceformattedprice)) { print $listpriceformattedprice; }?></div> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Theme the 'amazon-item' 'dvd' 'details' style. | |
| * Many, many available variables. See template_preprocess_amazon_item(). | |
| * Everything that gets put into $variables there is available. | |
| */ | |
| ?> | |
| <div class="<?php print $classes; ?>"> | |
| <?php if (!empty($smallimage)) { print $smallimage; } ?> | |
| <div><strong><?php print l($title, $detailpageurl, array('html' => TRUE, 'attributes' => array('rel' => 'nofollow'))); ?></strong> (<?php print $theatricalreleaseyear; ?>)</div> | |
| <div><strong><?php print t('Director'); ?>:</strong> <?php print $director; ?></div> | |
| <div><strong><?php print t('Starring'); ?>:</strong> <?php print $actor; ?></div> | |
| <div><strong><?php print t('Rating'); ?>:</strong> <?php print $audiencerating; ?></div> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Theme the 'amazon-item' 'games' 'details' style. | |
| * Many, many available variables. See template_preprocess_amazon_item(). | |
| * Everything that gets put into $variables there is available. | |
| */ | |
| ?> | |
| <div class="<?php print $classes; ?>"> | |
| <?php if (!empty($smallimage)) { print $smallimage; } ?> | |
| <div><strong><?php print l($title, $detailpageurl, array('html' => TRUE, 'attributes' => array('rel' => 'nofollow'))); ?></strong> (<?php print $hardwareplatform; ?>)</div> | |
| <div><strong><?php print t('Genre'); ?>:</strong> <?php print $genre; ?></div> | |
| <div><strong><?php print t('Age rating'); ?>:</strong> <?php print $esrbagerating; ?></div> | |
| <div><strong><?php print t('Price'); ?>:</strong> <?php print $listpriceformattedprice; ?></div> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Theme the 'amazon-item' 'large' image style. | |
| * Many, many available variables. See template_preprocess_amazon_item(). | |
| * Everything that gets put into $variables there is available. | |
| */ | |
| ?> | |
| <div class="<?php print $classes; ?>"> | |
| <?php if (!empty($invalid_asin)) { print "<div class='invalid_asin'>This item is no longer valid on Amazon.</div>"; } ?> | |
| <?php if (!empty($largeimage)) { print $largeimage; } ?> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Theme the 'amazon-item' 'medium' image style. | |
| * Many, many available variables. See template_preprocess_amazon_item(). | |
| * Everything that gets put into $variables there is available. | |
| */ | |
| ?> | |
| <div class="<?php print $classes; ?>"> | |
| <?php if (!empty($invalid_asin)) { print "<div class='invalid_asin'>This item is no longer valid on Amazon.</div>"; } ?> | |
| <?php if (!empty($mediumimage)) { print $mediumimage; } ?> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Theme the 'amazon-item' 'software' 'details' style. | |
| * Many, many available variables. See template_preprocess_amazon_item(). | |
| * Everything that gets put into $variables there is available. | |
| */ | |
| ?> | |
| <div class="<?php print $classes; ?>"> | |
| <?php if (!empty($smallimage)) { print $smallimage; } ?> | |
| <div><strong><?php print l($title, $detailpageurl, array('html' => TRUE, 'attributes' => array('rel' => 'nofollow'))); ?></strong></div> | |
| <div><strong><?php print t('Publisher'); ?>:</strong> <?php print $publisher; ?></div> | |
| <?php if (!empty($operatingsystem)):?> | |
| <div><strong><?php print t('Operating System'); ?>:</strong> <?php print $operatingsystem; ?></div> | |
| <?php endif; ?> | |
| <?php if (!empty($listpriceformattedprice)): ?> | |
| <div><strong><?php print t('List Price'); ?>:</strong> <?php print $listpriceformattedprice; ?></div> | |
| <?php endif; ?> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Theme the 'amazon-item' 'thumbnail' image style. | |
| * Many, many available variables. See template_preprocess_amazon_item(). | |
| * Everything that gets put into $variables there is available. | |
| */ | |
| ?> | |
| <div class="<?php print $classes; ?>"> | |
| <?php if (!empty($invalid_asin)) { print "<div class='invalid_asin'>This item is no longer valid on Amazon.</div>"; } ?> | |
| <?php if (!empty($smallimage)) { print $smallimage; } ?> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Theme the 'amazon-item' style. | |
| * Many, many available variables. See template_preprocess_amazon_item(). | |
| * Everything that gets put into $variables there is available. | |
| */ | |
| ?> | |
| <div class="<?php print $classes; ?>"> | |
| <?php if (!empty($invalid_asin)) { print "<div class='invalid_asin'>This item is no longer valid on Amazon.</div>"; } ?> | |
| <?php if (!empty($smallimage)) { print $smallimage; } ?> | |
| <div><strong><?php print l($title, $detailpageurl, array('html' => TRUE, 'attributes' => array('rel' => 'nofollow'))); ?></strong></div> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file amazon-views-view-row-item.tpl.php | |
| * Default simple view template to display a single Amazon item. | |
| * | |
| * | |
| * @ingroup views_templates | |
| */ | |
| ?> | |
| <?php print $content; ?> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Amazon Admin pages. | |
| */ | |
| /** | |
| * Basic Amazon settings form. | |
| */ | |
| function amazon_settings_form($form, &$form_state) { | |
| $cache = amazon_data_cache(); | |
| $options = array(); | |
| foreach ($cache['locales'] as $locale => $data) { | |
| $options[$locale] = $data['name']; | |
| } | |
| $form['amazon_locale'] = array( | |
| '#type' => 'select', | |
| '#title' => t('Amazon locale'), | |
| '#default_value' => variable_get('amazon_locale', 'US'), | |
| '#options' => $options, | |
| '#description' => t('Amazon.com uses separate product databases and Ecommerce features in different locales; pricing and availability information, as well as product categorization, differs from one locale to the next. Be sure to select the locale your site will be running in.'), | |
| ); | |
| $form['associate_setting'] = array( | |
| '#type' => 'fieldset', | |
| '#title' => t('Amazon referral settings'), | |
| ); | |
| $form['associate_setting']['amazon_associate_setting'] = array( | |
| '#type' => 'select', | |
| '#title' => t('What Amazon associate ID do you want to use?'), | |
| '#default_value' => variable_get('amazon_associate_setting', 'association'), | |
| '#options' => array( | |
| 'association' => t('Use the Drupal Association\'s associate ID'), | |
| 'custom' => t('Use your own associate ID'), | |
| 'none' => t('Do not use any associate ID') | |
| ), | |
| '#description' => t('Outgoing links to Amazon.com can include an associate ID code. When shoppers purchase Amazon products via one of those links, the associate ID is used to determine who should receive a referral bonus from Amazon.com.'), | |
| ); | |
| $form['associate_setting']['amazon_custom_associate_id'] = array( | |
| '#type' => 'textfield', | |
| '#title' => t('Your associate ID'), | |
| '#description' => t('Enter your own associate ID to receive referral bonuses when shoppers purchase Amazon products via your site.'), | |
| '#default_value' => variable_get('amazon_custom_associate_id', ''), | |
| '#states' => array( | |
| 'visible' => array( | |
| "select[name=amazon_associate_setting]" => array('value' => 'custom'), | |
| ), | |
| ), | |
| ); | |
| $form['amazon_aws_access_key'] = array( | |
| '#type' => 'textfield', | |
| '#title' => t('Amazon AWS Access Key ID'), | |
| '#description' => t('You must sign up for an Amazon AWS account to use the Product Advertising Service. See !more_info for information and a registration form.', array('!more_info' => l(t('the AWS home page'), 'https://aws-portal.amazon.com/gp/aws/developer/account/index.html?ie=UTF8&action=access-key', array('html' => TRUE)))), | |
| '#default_value' => variable_get('amazon_aws_access_key', ''), | |
| '#required' => TRUE, | |
| ); | |
| $form['amazon_aws_secret_access_key'] = array( | |
| '#type' => 'textfield', | |
| '#title' => t('Amazon AWS Secret Access Key'), | |
| '#description' => t('You must sign up for an Amazon AWS account to use the Product Advertising Service. See !more_info for information and a registration form.', array('!more_info' => l(t('the AWS home page'), 'https://aws-portal.amazon.com/gp/aws/developer/account/index.html?ie=UTF8&action=access-key', array('html' => TRUE)))), | |
| '#default_value' => variable_get('amazon_aws_secret_access_key', ""), | |
| '#required' => TRUE, | |
| ); | |
| return system_settings_form($form); | |
| } | |
| /** | |
| * Form to determine how long things get cached. | |
| */ | |
| function amazon_storage_settings_form($form, &$form_state) { | |
| $period = drupal_map_assoc(array(3600, 7200, 14400, 21600, 43200, 86400), 'format_interval'); | |
| $form['details']['amazon_refresh_schedule'] = array( | |
| '#type' => 'select', | |
| '#title' => t('Amazon refresh schedule'), | |
| '#description' => t('Cached information on Amazon items must be refreshed regularly to keep pricing and stock information up to date. Cron must be enabled for this function to work properly.'), | |
| '#default_value' => variable_get('amazon_refresh_schedule', 86400), | |
| '#options' => $period | |
| ); | |
| $form['details']['amazon_core_data'] = array( | |
| '#type' => 'checkboxes', | |
| '#title' => t('Store extended product data'), | |
| '#default_value' => variable_get('amazon_core_data', array('creators', 'images', 'editorial_reviews')), | |
| '#options' => array( | |
| 'creators' => t('Book authors, film actors, etc.'), | |
| 'images' => t('Product image links'), | |
| 'editorial_reviews' => t('Editorial reviews'), | |
| ), | |
| ); | |
| return system_settings_form($form); | |
| } | |
| /** | |
| * Form for testing a single ASIN. | |
| * | |
| */ | |
| function amazon_test_form($form, &$form_state) { | |
| $form = array(); | |
| $form['asin'] = array( | |
| '#type' => 'textfield', | |
| '#title' => t('Amazon Product ID'), | |
| '#description' => t('The ASIN (ISBN-10) or EAN (ISBN-13) of a product listed on Amazon.'), | |
| '#required' => TRUE, | |
| ); | |
| $form['submit'] = array( | |
| '#type' => 'submit', | |
| '#value' => t('Look Up Product'), | |
| ); | |
| if (isset($form_state['amazon_item'])) { | |
| $form['item'] = array( | |
| '#type' => 'fieldset', | |
| '#title' => t('Result'), | |
| '#collapsible' => FALSE, | |
| ); | |
| $form['item']['display'] = array( | |
| '#markup' => theme('amazon_item', array('item' => $form_state['amazon_item'], 'style' => 'details')), | |
| '#weight' => 9, | |
| ); | |
| $form['item']['details'] = array( | |
| '#type' => 'fieldset', | |
| '#title' => t('Details'), | |
| '#collapsible' => TRUE, | |
| '#collapsed' => TRUE, | |
| '#weight' => 10, | |
| ); | |
| $form['item']['details']['data'] = array( | |
| '#markup' => '<pre><small>' . print_r($form_state['amazon_item'], TRUE) . '</small></pre>', | |
| ); | |
| } | |
| return $form; | |
| } | |
| function amazon_test_form_validate($form, &$form_state) { | |
| // Normalize input and look up | |
| $asin = amazon_convert_to_asin($form_state['values']['asin']); | |
| $items = amazon_item_lookup_from_web(array($asin)); | |
| if (!empty($items) && is_array($items)) { | |
| $form_state['amazon_item'] = array_pop($items); | |
| } | |
| else { | |
| form_set_error('asin', t("%input is no valid ASIN or EAN. Please check the !link for messages.", array('%input' => $form_state['values']['asin'], '!link' => l(t("error log"), 'admin/reports/dblog')))); | |
| } | |
| } | |
| function amazon_test_form_submit($form, &$form_state) { | |
| $item = $form_state['amazon_item']; | |
| amazon_item_delete($item['asin']); | |
| amazon_item_insert($item); | |
| $form_state['rebuild'] = TRUE; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Drupal.behaviors.amazon = { | |
| attach: { | |
| jQuery(document).ready(function(){ jQuery("#edit-amazon-associate-setting").bind("change", function() { | |
| if (this.value == 'custom') { | |
| $("#amazon-associate-id-wrapper").show('fast'); | |
| } | |
| else { | |
| $("#amazon-associate-id-wrapper").hide('fast'); | |
| } | |
| return false; | |
| }) | |
| }); | |
| jQuery(document).ready( | |
| function(){ jQuery("#edit-amazon-cache").bind("change", function() { | |
| if (this.checked == true) { | |
| $("#amazon-storage-details").show('fast'); | |
| } | |
| else { | |
| $("#amazon-storage-details").hide('fast'); | |
| } | |
| return false; | |
| }) | |
| }); | |
| } | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| div.field-type-asin { | |
| display: block; | |
| clear: both; | |
| border-top: 2px solid #DDD; | |
| padding-top: 3px; | |
| } | |
| div.amazon-item { | |
| clear: both; | |
| } | |
| div.amazon-item img { | |
| float: left; | |
| padding-left: 3px; | |
| margin-bottom: 1em; | |
| margin-right: 1em; | |
| } | |
| div.amazon-item div { | |
| padding-left: 1em; | |
| margin-left: 100px; | |
| height: 4em; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name = Amazon API | |
| description = Provides integration with the Amazon Product Advertising API. | |
| package = Amazon | |
| core = 7.x | |
| php = 5.2 | |
| configure = admin/config/amazon_settings/amazon | |
| ; views handler | |
| files[] = includes/views_handler_field_amazon_date.inc | |
| files[] = includes/views_handler_field_amazon_image.inc | |
| files[] = includes/views_handler_field_amazon_title.inc | |
| files[] = includes/views_handler_field_amazon_xss.inc | |
| files[] = includes/views_handler_filter_amazon_node_module.inc | |
| files[] = includes/views_handler_filter_string_compare.inc | |
| files[] = includes/amazon_views_plugin_row_amazon_view.inc |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Install, update and uninstall functions for the amazon module. | |
| */ | |
| /** | |
| * Implements hook_install. | |
| */ | |
| function amazon_install() { | |
| } | |
| /** | |
| * Implements hook_uninstall(). | |
| */ | |
| function amazon_uninstall() { | |
| $vars = array( | |
| 'amazon_media_data', | |
| 'amazon_locale', | |
| 'amazon_associate_setting', | |
| 'amazon_custom_associate_id', | |
| 'amazon_aws_access_key', | |
| 'amazon_aws_secret_access_key', | |
| 'amazon_refresh_schedule', | |
| 'amazon_core_data', | |
| ); | |
| foreach ($vars as $var) { | |
| variable_del($var); | |
| } | |
| } | |
| /** | |
| * implementation of hook_requirements to make sure we let them know about | |
| * the requirement for amazon_aws_secret_access_key | |
| * @param $phase | |
| * @return unknown_type | |
| */ | |
| function amazon_requirements($phase) { | |
| $secret_access_key = variable_get('amazon_aws_secret_access_key', ""); | |
| $api_key = variable_get('amazon_aws_access_key', ""); | |
| $requirement = array(); | |
| if (empty($secret_access_key) || empty($api_key)) { | |
| drupal_set_message(t("The Amazon API must be configured with an Access Key ID and an Amazon AWS Secret Access Key to function. Go to !settings.", array("!settings" => l(t("Amazon API Setttings"), 'admin/config/amazon_settings/amazon')))); | |
| $requirement['title'] = t("Amazon AWS Secret Access Key"); | |
| $requirement['severity'] = REQUIREMENT_WARNING; | |
| $requirement['value'] = t("Not Set"); | |
| $requirement['description'] = t("The Amazon API must be configured with an Access Key ID and an Amazon AWS Secret Access Key to function. Go to !settings.", array("!settings" => l(t("Amazon API Setttings"), 'admin/config/amazon_settings/amazon'))); | |
| return array('amazon_aws_secret_access_key', $requirement); | |
| } | |
| return NULL; | |
| } | |
| function amazon_schema() { | |
| $schema['amazon_item'] = array( | |
| 'fields' => array( | |
| 'asin' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE), | |
| 'title' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE), | |
| 'detailpageurl' => array('type' => 'text'), | |
| 'salesrank' => array('type' => 'int', 'unsigned' => TRUE), | |
| 'brand' => array('type' => 'varchar', 'length' => 64), | |
| 'publisher' => array('type' => 'varchar', 'length' => 64), | |
| 'manufacturer' => array('type' => 'varchar', 'length' => 64), | |
| 'mpn' => array('type' => 'varchar', 'length' => 128), | |
| 'studio' => array('type' => 'varchar', 'length' => 64), | |
| 'label' => array('type' => 'varchar', 'length' => 64), | |
| 'binding' => array('type' => 'varchar', 'length' => 64), | |
| 'releasedate' => array('type' => 'varchar', 'length' => 64), | |
| 'listpriceamount' => array('type' => 'numeric'), | |
| 'listpricecurrencycode' => array('type' => 'varchar', 'length' => 32), | |
| 'listpriceformattedprice' => array('type' => 'varchar', 'length' => 32), | |
| 'lowestpriceamount' => array('type' => 'numeric'), | |
| 'lowestpricecurrencycode' => array('type' => 'varchar', 'length' => 32), | |
| 'lowestpriceformattedprice' => array('type' => 'varchar', 'length' => 32), | |
| 'amazonpriceamount' => array('type' => 'numeric'), | |
| 'amazonpricecurrencycode' => array('type' => 'varchar', 'length' => 32), | |
| 'amazonpriceformattedprice' => array('type' => 'varchar', 'length' => 32), | |
| 'productgroup' => array('type' => 'varchar', 'length' => 255), | |
| 'producttypename' => array('type' => 'varchar', 'length' => 255), | |
| 'customerreviews_iframe' => array('type' => 'varchar', 'length' => 255), | |
| 'invalid_asin' => array('type' => 'int', 'default' => 0), | |
| 'timestamp' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0), | |
| ), | |
| 'primary key' => array('asin'), | |
| ); | |
| $schema['amazon_item_participant'] = array( | |
| 'fields' => array( | |
| 'asin' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE), | |
| 'type' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE), | |
| 'participant' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE), | |
| ), | |
| 'indexes' => array( | |
| 'asin' => array('asin'), | |
| ), | |
| ); | |
| $schema['amazon_item_image'] = array( | |
| 'fields' => array( | |
| 'asin' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE), | |
| 'size' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE), | |
| 'url' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE), | |
| 'height' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE), | |
| 'width' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE), | |
| ), | |
| 'primary key' => array('asin', 'size'), | |
| 'indexes' => array( | |
| 'asin' => array('asin'), | |
| ), | |
| ); | |
| $schema['amazon_item_editorial_review'] = array( | |
| 'fields' => array( | |
| 'asin' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE), | |
| 'source' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE), | |
| 'content' => array('type' => 'text'), | |
| ), | |
| 'indexes' => array('asin' => array('asin')), | |
| ); | |
| $schema['amazon_item_node'] = array( | |
| 'fields' => array( | |
| 'nid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE), | |
| 'vid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE), | |
| 'asin' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE), | |
| 'notes' => array('type' => 'text', 'not null' => FALSE), | |
| 'module' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => 'amazon'), | |
| 'delta' => array('type' => 'int', 'default' => 0), | |
| ), | |
| 'primary key' => array('nid', 'asin', 'module'), | |
| 'indexes' => array( | |
| 'nid' => array('nid'), | |
| 'vid' => array('vid'), | |
| 'vid_module' => array('vid', 'module'), | |
| 'asin' => array('asin'), | |
| ), | |
| ); | |
| return $schema; | |
| } | |
| /** | |
| * Fix messed up type for currency code in update 6012. | |
| */ | |
| function amazon_update_7100() { | |
| db_change_field('amazon_item', 'lowestpricecurrencycode', 'lowestpricecurrencycode', | |
| array('type' => 'varchar', 'length' => 32)); | |
| db_change_field('amazon_item', 'amazonpricecurrencycode', 'amazonpricecurrencycode', | |
| array('type' => 'varchar', 'length' => 32)); | |
| return(t("Updated currency code column types")); | |
| } | |
| /** | |
| * Amazon has stopped providing customer review data; now we only get an | |
| * iframe link where Amazon will provide the data, so we need to drop the table | |
| * that was used for customer reviews and add the new iframe link. | |
| */ | |
| function amazon_update_7102() { | |
| if (!db_field_exists('amazon_item', 'customerreviews_iframe')) { | |
| db_add_field('amazon_item', 'customerreviews_iframe', array('type' => 'varchar', 'length' => 255)); | |
| } | |
| if (db_table_exists('amazon_item_customer_review')) { | |
| db_drop_table('amazon_item_customer_review'); | |
| } | |
| // Expire all the existing amazon items so the next cron will update them. | |
| db_update('amazon_item') | |
| ->fields(array('timestamp' => 0)) | |
| ->execute(); | |
| return(t("Updated support for customer reviews")); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Amazon Integration | |
| * | |
| * Provides a Drupal wrapper and caching mechanism for the Amazon | |
| * Ecommerce APIs. This module provides no user-visible functionality | |
| * save configuration and setup. | |
| */ | |
| define('AMAZON_ECS_SCHEMA', '2010-09-01'); | |
| define('AMAZON_PARTICIPANT_TYPES', 'Author,Artist,Actor,Director,Creator'); | |
| // Other common sizes include SwatchImage, TinyImage, and ThumbnailImage. | |
| define('AMAZON_IMAGE_SIZES', 'SmallImage,MediumImage,LargeImage'); | |
| /** | |
| * Implementation of hook_menu. Adds the url path for the Amazon | |
| * settings page. | |
| */ | |
| function amazon_menu() { | |
| $items = array(); | |
| $items['admin/config/amazon_settings'] = array( | |
| 'title' => 'Amazon Settings', | |
| 'description' => 'Amazon-related module settings', | |
| 'page callback' => 'system_admin_menu_block_page', | |
| 'file' => 'system.admin.inc', | |
| 'file path' => drupal_get_path('module', 'system'), | |
| 'access callback' => 'user_access', | |
| 'access arguments' => array('access administration pages'), | |
| 'type' => MENU_NORMAL_ITEM, | |
| ); | |
| $items['admin/config/amazon_settings/amazon'] = array( | |
| 'title' => 'Amazon API', | |
| 'description' => 'Global settings for the Amazon Ecommerce API.', | |
| 'page callback' => 'drupal_get_form', | |
| 'page arguments' => array('amazon_settings_form'), | |
| 'file' => 'amazon.admin.inc', | |
| 'access callback' => 'user_access', | |
| 'access arguments' => array('administer amazon'), | |
| 'type' => MENU_NORMAL_ITEM | |
| ); | |
| $items['admin/config/amazon_settings/amazon/storage'] = array( | |
| 'title' => 'Storage', | |
| 'description' => 'Local data storage settings for Amazon products.', | |
| 'page callback' => 'drupal_get_form', | |
| 'page arguments' => array('amazon_storage_settings_form'), | |
| 'file' => 'amazon.admin.inc', | |
| 'access callback' => 'user_access', | |
| 'access arguments' => array('administer amazon'), | |
| 'type' => MENU_LOCAL_TASK | |
| ); | |
| $items['admin/config/amazon_settings/amazon/test'] = array( | |
| 'title' => 'Test', | |
| 'page callback' => 'drupal_get_form', | |
| 'page arguments' => array('amazon_test_form'), | |
| 'file' => 'amazon.admin.inc', | |
| 'access callback' => 'user_access', | |
| 'access arguments' => array('administer amazon'), | |
| 'type' => MENU_LOCAL_TASK | |
| ); | |
| $items['admin/config/amazon_settings/amazon/api'] = array( | |
| 'title' => 'Settings', | |
| 'weight' => -10, | |
| 'type' => MENU_DEFAULT_LOCAL_TASK | |
| ); | |
| return $items; | |
| } | |
| /** | |
| * Implementation of hook_permission | |
| */ | |
| function amazon_permission() { | |
| return array( | |
| 'administer amazon' => array( | |
| 'title' => t('Administer Amazon module'), | |
| 'description' => t('Configure and test Amazon module.'), | |
| ), | |
| ); | |
| } | |
| /** | |
| * Implementation of hook_theme(). | |
| */ | |
| function amazon_theme() { | |
| $templates = array( | |
| 'amazon_item' => array( | |
| 'variables' => array('item' => array(), 'style' => NULL), | |
| 'template' => 'amazon-item', | |
| ), | |
| 'amazon_inline_item' => array( | |
| 'variables' => array('item' => array()), | |
| 'template' => 'amazon-inline-item', | |
| 'preprocess functions' => array('template_preprocess_amazon_item'), | |
| ), | |
| 'amazon_detail' => array( | |
| 'variables' => array('item' => array(), 'detail' => NULL), | |
| 'template' => 'amazon-detail', | |
| 'preprocess functions' => array('template_preprocess_amazon_item'), | |
| ), | |
| // All templates provided at the module level have to be explicitly listed. | |
| 'amazon_item_detail' => array( | |
| 'variables' => array('item' => array()), | |
| 'template' => 'amazon-item-detail', | |
| 'preprocess functions' => array('template_preprocess_amazon_item'), | |
| ), | |
| 'amazon_item__details' => array( | |
| 'variables' => array('item' => array()), | |
| 'template' => 'amazon-item--details', | |
| 'preprocess functions' => array('template_preprocess_amazon_item'), | |
| ), | |
| 'amazon_item__default' => array( | |
| 'variables' => array('item' => array()), | |
| 'template' => 'amazon-item', | |
| 'preprocess functions' => array('template_preprocess_amazon_item'), | |
| ), | |
| 'amazon_item__thumbnail' => array( | |
| 'variables' => array('item' => array()), | |
| 'template' => 'amazon-item--thumbnail', | |
| 'preprocess functions' => array('template_preprocess_amazon_item'), | |
| ), | |
| 'amazon_item__medium' => array( | |
| 'variables' => array('item' => array()), | |
| 'template' => 'amazon-item--medium', | |
| 'preprocess functions' => array('template_preprocess_amazon_item'), | |
| ), | |
| 'amazon_item__large' => array( | |
| 'variables' => array('item' => array()), | |
| 'template' => 'amazon-item--large', | |
| 'preprocess functions' => array('template_preprocess_amazon_item'), | |
| ), | |
| ); | |
| return $templates; | |
| } | |
| /** | |
| * template_preprocess: amazon_item. | |
| */ | |
| function template_preprocess_amazon_item(&$variables, $theme_type) { | |
| $item = $variables['item']; | |
| // Do a quick cycle through the simple keys on the item, filter_xss() them, | |
| // and stick them in the variables collection. | |
| foreach ($item as $key => $value) { | |
| if (is_string($value)) { | |
| $variables[$key] = filter_xss($value); | |
| } | |
| } | |
| $variables['type'] = _amazon_clean_type($item['producttypename']); | |
| $variables['detailpageurl'] = check_url($item['detailpageurl']); | |
| $variables['editorialreview'] = !empty($item['editorialreviews']) ? filter_xss_admin($item['editorialreviews'][0]['content']) : ''; | |
| $variables['customerreviews_iframe'] = !empty($item['customerreviews_iframe']) ? check_url($item['customerreviews_iframe']) : ''; | |
| $variables['invalid_asin'] = !empty($item['invalid_asin']) ? 1 : 0; | |
| $variables['detailpageurl'] = check_url($variables['detailpageurl']); | |
| if (!empty($variables['customerreviews'])) { | |
| foreach($variables['customerreviews'] as $key => $review) { | |
| $variables['customerreviews'][$key] = filter_xss($variables['customerreviews'][$key]); | |
| } | |
| } | |
| $variables['invalid_asin'] = !empty($variables['invalid_asin']) ? 1 : 0; | |
| if (!empty($variables['theatricalreleasedate'])) { | |
| $date = explode('-', $variables['theatricalreleasedate']); | |
| $variables['releaseyear'] = $date[0]; | |
| } | |
| else { | |
| $variables['releaseyear'] = ''; | |
| } | |
| if (!empty($variables['publicationdate'])) { | |
| $date = explode('-', $variables['publicationdate']); | |
| $variables['publicationyear'] = $date[0]; | |
| } | |
| else { | |
| $variables['publicationyear'] = ''; | |
| } | |
| // Handle participants and types. | |
| if (isset($item['participants'])) { | |
| $variables['participants'] = filter_xss(filter_xss(implode(', ', $item['participants']))); | |
| $participant_types = preg_split('/,/', AMAZON_PARTICIPANT_TYPES); | |
| foreach ($participant_types as $participant_type) { | |
| $participant_type = strtolower($participant_type); | |
| if (!empty($item[$participant_type])) { | |
| if (is_string($item[$participant_type])) { | |
| $variables[$participant_type] = filter_xss($item[$participant_type]); | |
| } | |
| else { | |
| $variables[$participant_type] = filter_xss(implode(', ', $item[$participant_type])); | |
| } | |
| } | |
| } | |
| } | |
| $variables += array( | |
| 'participants' => '', | |
| 'director' => '', | |
| 'actor' => '', | |
| 'artist' => '', | |
| 'author' => '', | |
| ); | |
| // Handle supported image resolutions. | |
| if (isset($item['imagesets'])) { | |
| foreach ($item['imagesets'] as $key => $image) { | |
| $variables[$key] = theme('image', array('path' => $image['url'], 'alt' => t('Image of') . ' ' . strip_tags($item['title']), 'title' => strip_tags($item['title']), 'attributes' => array('height' => $image['height'], 'width' => $image['width']), 'getsize' => FALSE)); | |
| $variables["{$key}url"] = check_url($image['url']); | |
| $variables["{$key}height"] = check_plain($image['height']); | |
| $variables["{$key}width"] = check_plain($image['width']); | |
| } | |
| } | |
| $variables['image'] = !empty($variables['mediumimage']) ? $variables['mediumimage'] : ''; | |
| $variables['classes_array'] = array(); | |
| $variables['attributes_array'] = array(); | |
| $variables['title_attributes_array'] = array(); | |
| $variables['content_attributes_array'] = array(); | |
| if (!empty($variables['detail']) && $theme_type == 'amazon_detail') { | |
| $variables['classes_array'] = array("amazon-item", "amazon-item-detail-{$variables['detail']}"); | |
| } | |
| if (!empty($variables['style']) && $variables['style'] == 'inline' && !empty($variables['producttypename'])) { | |
| $variables['theme_hook_suggestions'][] = 'amazon_inline_item__' . _amazon_clean_type($item['producttypename']); | |
| } | |
| if (!empty($variables['style'])) { | |
| $variables['classes'] = _amazon_item_classes($item) . ' amazon-item-' . check_plain($variables['style']); | |
| // A set of more specific templates to use when displaying items. | |
| $variables['theme_hook_suggestions'][] = 'amazon_item__' . $variables['style']; | |
| $variables['theme_hook_suggestions'][] = 'amazon_item__' . strtolower($variables['type']); | |
| $variables['theme_hook_suggestions'][] = 'amazon_item__' . strtolower($variables['type']) . '__' . $variables['style']; | |
| if (!empty($item['view']) && !empty($item['view']->name)) { | |
| $variables['theme_hook_suggestions'][] = 'amazon_item_view__' . $item['view']->name; | |
| $variables['theme_hook_suggestions'][] = 'amazon_item__' . strtolower($variables['type']) . '__view__' . $item['view']->name; | |
| } | |
| } | |
| } | |
| /** | |
| * Convert a type like ABIS_whatever into just whatever. | |
| * @param unknown_type $type | |
| */ | |
| function _amazon_clean_type($type) { | |
| return check_plain(strtolower(str_replace(array('ABIS_', 'CONSOLE_', 'VIDEO_', ' '), array('', '', '', '_'), $type))); | |
| } | |
| /** | |
| * Create name of the extra css class for an item. | |
| * | |
| * @param $item | |
| * The amazon_item. | |
| */ | |
| function _amazon_item_classes($item) { | |
| return 'amazon-item amazon-item-' . str_replace('_', '-', _amazon_clean_type($item['producttypename'])); | |
| } | |
| /** | |
| * Create an issue an HTTP request to the Amazon API. | |
| * | |
| * Most of this is determined by the Amazon Product Advertising API. | |
| * @see http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?CHAP_response_elements.html | |
| * | |
| * | |
| * @param $operation | |
| * Must be 'AWSECommerceService' | |
| * @param $parameters | |
| * An associative array with the parameters for the API call. | |
| * @param $locale | |
| * The (optional) locale, a 2-character Amazon locale indicator. This has | |
| * nothing to do with an actual locale - it's really shorthand for what | |
| * Amazon site to use. | |
| */ | |
| function amazon_http_request($operation, $parameters = array(), $locale = NULL) { | |
| if (!isset($locale)) { | |
| $locale = variable_get('amazon_locale', 'US'); | |
| } | |
| $metadata = amazon_data_cache(); | |
| $locale_data = $metadata['locales'][$locale]; | |
| // Populate the params with default data. | |
| $parameters += array( | |
| 'Service' => 'AWSECommerceService', | |
| 'Version' => AMAZON_ECS_SCHEMA, | |
| 'AWSAccessKeyId' => variable_get('amazon_aws_access_key', ''), | |
| 'Operation' => $operation, | |
| ); | |
| if ($associate_id = amazon_get_associate_id()) { | |
| $parameters += array( | |
| 'AssociateTag' => $associate_id, | |
| ); | |
| } | |
| $parameters_after_hook = module_invoke_all('amazon_request', $parameters); | |
| if (!empty($parameters_after_hook)) { | |
| $parameters = $parameters_after_hook; | |
| } | |
| $parameters += array('Timestamp' => gmdate("Y-m-d\TH:i:s") . 'Z'); | |
| uksort($parameters, 'strnatcmp'); | |
| $params = array(); | |
| foreach ($parameters as $key => $value) { | |
| if (is_array($value)) { | |
| $value = implode(',', $value); | |
| } | |
| $param = str_replace("%7E", "~", rawurlencode($key)); | |
| $value = str_replace("%7E", "~", rawurlencode($value)); | |
| $params[] = $param . '=' . $value; | |
| } | |
| $secret_access_key = variable_get('amazon_aws_secret_access_key', ""); | |
| if ($secret_access_key == "") { | |
| watchdog('amazon', "No Secret Access Key configured. You must configure one at Admin->Settings->Amazon API", NULL, WATCHDOG_ERROR); | |
| drupal_set_message(t("Amazon Module: No Secret Access Key is configured. Please contact your site administrator")); | |
| return FALSE; | |
| } | |
| // Thanks for signature creation code from http://mierendo.com/software/aws_signed_query/ | |
| $query_string = implode('&', $params); | |
| $parsed_url = parse_url($locale_data['url']); | |
| $host = strtolower($parsed_url['host']); | |
| $string_to_sign = "GET\n$host\n{$parsed_url['path']}\n$query_string"; | |
| $signature = base64_encode(hash_hmac('sha256', $string_to_sign, $secret_access_key, TRUE)); | |
| $signature = str_replace("%7E", "~", rawurlencode($signature)); | |
| $query_string .= "&Signature=$signature"; | |
| $url = $locale_data['url'] . '?' . $query_string; | |
| // Make the request and return a SimpleXML object. | |
| $results = drupal_http_request($url, array('method' => 'GET')); | |
| if ($results->code == 200) { | |
| $xml = new SimpleXMLElement($results->data); | |
| return $xml; | |
| } | |
| if ($results->code >= 400 && $results->code < 500) { | |
| try { | |
| $xml = new SimpleXMLElement($results->data); | |
| } | |
| catch (Exception $e) { | |
| watchdog('amazon', "Error handling results: http_code=%http_code, data=%data.", array('%http_code' => $results->code, '%data' => (string) $results->data) ); | |
| return FALSE; | |
| } | |
| watchdog('amazon', "HTTP code %http_code accessing Amazon's AWS service: %code, %message", array('%http_code' => $results->code, '%code' => (string) $xml->Error->Code, '%message' => (string) $xml->Error->Message)); | |
| return FALSE; | |
| } | |
| watchdog('amazon', "Error accessing Amazon AWS web service. HTTP result code=%code, error=%error", array('%code' => $results->code, '%error' => $results->error)); | |
| return FALSE; | |
| } | |
| /** | |
| * Look up an item using database or web. | |
| * The default is to look in the database for existing data, and then to do the | |
| * web search if that fails. $force_lookup==TRUE forces going to Amazon's | |
| * API. | |
| * @param $item_ids | |
| * An array of ASIN strings or a single ASIN as a string. | |
| * @param $force_lookup | |
| * If TRUE, skip the database lookup and just go to the Amazon API lookup. | |
| * @return array | |
| * Array of "cleaned" XML item descriptions, keyed on ASIN. | |
| */ | |
| function amazon_item_lookup($item_ids = array(), $force_lookup = FALSE) { | |
| if (empty($item_ids)) { | |
| return array(); | |
| } | |
| if (is_string($item_ids)) { | |
| $item_ids = array($item_ids); | |
| } | |
| $items = array(); | |
| if (!$force_lookup) { | |
| $items = amazon_item_lookup_from_db($item_ids); | |
| } | |
| $items_to_fetch = array(); | |
| foreach ($item_ids as $item_id) { | |
| if (!isset($items[$item_id])) { | |
| $items_to_fetch[] = $item_id; | |
| } | |
| } | |
| $items_from_web = amazon_item_lookup_from_web($items_to_fetch); | |
| $full_set = $items + $items_from_web; | |
| return $full_set; | |
| } | |
| /** | |
| * Use Amazon API to look up an array of ASINs. | |
| * @param $item_ids | |
| * Array of ASIN strings to look up. | |
| * @return array | |
| * Array of cleaned XML structures keyed by ASIN. | |
| */ | |
| function amazon_item_lookup_from_web($item_ids = array()) { | |
| $amazon_limit = 10; // Amazon will accept no more than 10 items | |
| $asins = array(); | |
| $results = array(); | |
| $item_ids = array_filter($item_ids); // Remove any empty items. | |
| foreach ($item_ids as $asin) { | |
| if (!empty($asin)) { | |
| $asins[] = $asin; | |
| if (count($asins) >= $amazon_limit || count($asins) == count($item_ids)) { | |
| $results += _amazon_item_batch_lookup_from_web($asins); | |
| $asins = array(); | |
| } | |
| } | |
| } | |
| return $results; | |
| } | |
| /** | |
| * Get 10 or less items from the AWS web service. | |
| * AWS allows ONLY 10 items, | |
| * See http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?ItemLookup.html. | |
| * @param $item_ids | |
| * Array of ASINs to be looked up. | |
| * @return | |
| * Array of ASIN data structures keyed by ASIN. | |
| */ | |
| function _amazon_item_batch_lookup_from_web($item_ids = array()) { | |
| if (!empty($item_ids)) { | |
| $params = array( | |
| 'ItemId' => implode(',', $item_ids), | |
| 'ResponseGroup' => 'Large', | |
| ); | |
| $results = amazon_http_request('ItemLookup', $params); | |
| $errors = $results->Items->Request->Errors; | |
| if (!empty($errors)) { | |
| _amazon_item_batch_lookup_from_web_errors($errors); | |
| } | |
| $items = array(); | |
| if (!empty($results->Items->Item)) { | |
| foreach ($results->Items->Item as $xml) { | |
| $item = amazon_item_clean_xml($xml); | |
| amazon_item_insert($item); | |
| $items["{$item['asin']}"] = $item; | |
| } | |
| } | |
| return $items; | |
| } | |
| return array(); | |
| } | |
| function _amazon_item_batch_lookup_from_web_errors($errors) { | |
| foreach ($errors->Error as $error) { | |
| $code = (string) $error->Code; | |
| $message = (string) $error->Message; | |
| $matches = array(); | |
| // Find and extract the failing ASIN, so we can mark it in the db. | |
| if (preg_match('/^([^ ]+) is not a valid value for ItemId/', $message, $matches)) { | |
| $error_asin = $matches[1]; | |
| try { | |
| $result = db_update('amazon_item') | |
| ->fields(array('invalid_asin' => TRUE)) | |
| ->condition('asin', $error_asin) | |
| ->execute(); | |
| } | |
| catch(Exception $e) { | |
| amazon_db_error_watchdog('Failed to update invalid_asin=TRUE on amazon_item.', $e); | |
| } | |
| } | |
| watchdog('amazon', 'Error retrieving Amazon item %code, message: %message.', array('%code' => $code, '%message' => $message), WATCHDOG_WARNING); | |
| } | |
| } | |
| /** | |
| * Look up ASINs in database and return arrays of information keyed by ASIN. | |
| * @param $item_ids | |
| * An array of string ASINs. | |
| * @return array | |
| * Array of Amazon 'cleaned' data structures keyed by ASIN. | |
| */ | |
| function amazon_item_lookup_from_db($item_ids = array()) { | |
| if (!empty($item_ids)) { | |
| $timestamp = REQUEST_TIME - variable_get('amazon_refresh_schedule', 86400); | |
| $result = db_query('SELECT * from {amazon_item} WHERE asin IN (:asins) AND timestamp > :timestamp', | |
| array('asins' => $item_ids, 'timestamp' => $timestamp), | |
| array('fetch' => PDO::FETCH_ASSOC)); | |
| $items = array(); | |
| foreach ($result as $item) { | |
| _amazon_load_child_data($item); | |
| $item += module_invoke_all('amazon_item_load', $item); | |
| $items["{$item['asin']}"] = $item; | |
| } | |
| return $items; | |
| } | |
| return array(); | |
| } | |
| /** | |
| * Load participant, image, editorial_review data into database. | |
| * @param $item | |
| * Amazon data structure. | |
| */ | |
| function _amazon_load_child_data(&$item) { | |
| $result = db_query('SELECT type, participant FROM {amazon_item_participant} WHERE asin = :asin', | |
| array('asin' => $item['asin']), | |
| array('fetch' => PDO::FETCH_ASSOC)); | |
| foreach ($result as $participant) { | |
| // unset($participant['asin']); | |
| $item[$participant['type']][] = $participant['participant']; | |
| $item['participants'][] = $participant['participant']; | |
| } | |
| $result = db_query('SELECT * FROM {amazon_item_image} WHERE asin = :asin', | |
| array('asin' => $item['asin']), | |
| array('fetch' => PDO::FETCH_ASSOC)); | |
| foreach ($result as $image) { | |
| unset($image['asin']); | |
| $item['imagesets'][$image['size']] = $image; | |
| } | |
| $result = db_query('SELECT * FROM {amazon_item_editorial_review} WHERE asin = :asin', | |
| array('asin' => $item['asin']), | |
| array('fetch' => PDO::FETCH_ASSOC)); | |
| foreach ($result as $review) { | |
| unset($review['asin']); | |
| $item['editorialreviews'][] = $review; | |
| } | |
| } | |
| /** | |
| * Take the Amazon XML item and turn it into our own private 'cleaned' | |
| * data structure. | |
| * @param $xml | |
| * XML structure as returned from Amazon API call. | |
| * @return | |
| * 'Cleaned' XML structure for local use. | |
| */ | |
| function amazon_item_clean_xml($xml) { | |
| $metadata = amazon_data_cache(); | |
| $item = array(); | |
| // Pull the absolute basic information Amazon keeps at the top level | |
| // of the XML tree, cast to string, and move on. | |
| $item['asin'] = (string) $xml->ASIN; | |
| if (empty($xml->ItemAttributes->ISBN)) { | |
| $item['isbn'] = (string) $xml->ItemAttributes->ISBN; | |
| } | |
| if (empty($xml->ItemAttributes->EAN)) { | |
| $item['ean'] = (string) $xml->ItemAttributes->EAN; | |
| } | |
| $item['salesrank'] = (string) $xml->SalesRank; | |
| $item['detailpageurl'] = (string) $xml->DetailPageURL; | |
| if (!empty($xml->ItemAttributes->ListPrice)) { | |
| $item['listpriceamount'] = (string) $xml->ItemAttributes->ListPrice->Amount; | |
| $item['listpricecurrencycode'] = (string) $xml->ItemAttributes->ListPrice->CurrencyCode; | |
| $item['listpriceformattedprice'] = (string) $xml->ItemAttributes->ListPrice->FormattedPrice; | |
| } | |
| if (!empty($xml->OfferSummary->LowestNewPrice)) { | |
| $item['lowestpriceamount'] = (string) $xml->OfferSummary->LowestNewPrice->Amount; | |
| $item['lowestpricecurrencycode'] = (string) $xml->OfferSummary->LowestNewPrice->CurrencyCode; | |
| $item['lowestpriceformattedprice'] = (string) $xml->OfferSummary->LowestNewPrice->FormattedPrice; | |
| } | |
| // Note that this one assumes we've searched with Merchant = Amazon. | |
| // Otherwise we can do an xpath search looking for the actual amazon listing. | |
| if (!empty($xml->Offers->Offer[0]->OfferListing->Price)) { | |
| $amazon_merchant_ids = array( | |
| /* JP */ 'ATVPDKIKX0DER', | |
| /* UK */ 'A3P5ROKL5A1OLE', | |
| /* JP */ 'AN1VRQENFRJN5', | |
| /* FR */ 'A1X6FK5RDHNB96', | |
| /* DE */ 'A3JWKAKR8XB7XF', | |
| /* CA */ 'A3DWYIK6Y9EEQB', | |
| ); | |
| $merchant = (string)$xml->Offers->Offer[0]->Merchant->MerchantId; | |
| if (in_array($merchant, $amazon_merchant_ids)) { | |
| $item['amazonpriceamount'] = (string)$xml->Offers->Offer[0]->OfferListing->Price->Amount; | |
| $item['amazonpricecurrencycode'] = (string)$xml->Offers->Offer[0]->OfferListing->Price->CurrencyCode; | |
| $item['amazonpriceformattedprice'] = (string)$xml->Offers->Offer[0]->OfferListing->Price->FormattedPrice; | |
| } | |
| } | |
| $participant_types = preg_split('/,/', AMAZON_PARTICIPANT_TYPES); | |
| // Pull in the basics of the ItemAttributes collection. | |
| foreach ((array) ($xml->ItemAttributes) as $key => $value) { | |
| if (is_string($value) && !in_array($key, $participant_types)) { | |
| $key = strtolower($key); | |
| $item[$key] = $value; | |
| } | |
| } | |
| // Handle the Authors/Artists/Etc. | |
| foreach ($participant_types as $key) { | |
| if (isset($xml->ItemAttributes->$key)) { | |
| foreach ($xml->ItemAttributes->$key as $value) { | |
| $item[strtolower($key)][] = (string) $value; | |
| $item['participants'][] = (string) $value; | |
| } | |
| } | |
| } | |
| // Handle the product images. In theory, there could be a million different | |
| // product image types. We're only going to check for the most common ones | |
| // and ignore the rest for now. | |
| $supported_sizes = preg_split('/,/', AMAZON_IMAGE_SIZES); | |
| if (isset($xml->ImageSets->ImageSet)) { | |
| foreach ((array) $xml->ImageSets->ImageSet as $key => $data) { | |
| if (in_array($key, $supported_sizes)) { | |
| $item['imagesets'][strtolower($key)] = array( | |
| 'url' => (string) $data->URL, | |
| 'height' => (string) $data->Height, | |
| 'width' => (string) $data->Width, | |
| ); | |
| } | |
| } | |
| } | |
| // Handle the editorial reviews. | |
| if (isset($xml->EditorialReviews)) { | |
| foreach ($xml->EditorialReviews->EditorialReview as $data) { | |
| $item['editorialreviews'][] = array( | |
| 'source' => (string) $data->Source, | |
| 'content' => (string) $data->Content, | |
| ); | |
| } | |
| } | |
| // And the customer reviews. | |
| if (isset($xml->CustomerReviews)) { | |
| $item['customerreviews_iframe'] = (string)$xml->CustomerReviews->IFrameURL; | |
| } | |
| // Give other modules an opportunity to pull out other bits of Amazon data | |
| // that would otherwise be ignored. We can't use module_invoke_all, as it | |
| // would lose the reference. | |
| foreach (module_implements('amazon_item_clean_xml') as $module) { | |
| $function = $module . '_amazon_item_clean_xml'; | |
| $function($item, $xml); | |
| } | |
| return $item; | |
| } | |
| /** | |
| * Insert 'cleaned' amazon item into database. | |
| * @param $item | |
| * 'Cleaned' amazon structure. | |
| * @return | |
| * No return value. | |
| */ | |
| function amazon_item_insert($item) { | |
| static $item_keys = NULL; | |
| if (empty($item_keys)) { | |
| require_once('amazon.install'); | |
| $schema = amazon_schema(); | |
| $item_keys = $schema['amazon_item']['fields']; | |
| } | |
| // We have boatloads of data to insert in here, so we're going to | |
| // cheat and blow away the old entries first. | |
| amazon_item_delete($item['asin']); | |
| $metadata = amazon_data_cache(); | |
| $item['timestamp'] = REQUEST_TIME; | |
| // The db_insert needs fields that match exactly to the database, | |
| // so we'll intersect with what the actual schema says. | |
| $db_item = array_intersect_key($item, $item_keys); | |
| try { | |
| db_insert('amazon_item') | |
| ->fields($db_item) | |
| ->execute(); | |
| } | |
| catch (Exception $e) { | |
| amazon_db_error_watchdog("Failed to insert item into amazon_item table", $e); | |
| } | |
| // Handle the various credits for a product, including Artist, Author, | |
| // Actor, etc. We map these to a separate table. | |
| if (in_array('creators', variable_get('amazon_core_data', array('creators', 'images')))) { | |
| $participant_types = preg_split('/,/', AMAZON_PARTICIPANT_TYPES); | |
| foreach ($participant_types as $type) { | |
| if (isset($item[strtolower($type)])) { | |
| foreach ((array) $item[strtolower($type)] as $participant) { | |
| $item_participant = array('asin' => $item['asin'], 'type' => strtolower($type), 'participant' => $participant); | |
| try { | |
| db_insert('amazon_item_participant') | |
| ->fields($item_participant) | |
| ->execute(); | |
| } | |
| catch (Exception $e) { | |
| amazon_db_error_watchdog("Failed to insert item into amazon_item_participant table", $e); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| // Save the product images if they exist. | |
| if (in_array('images', variable_get('amazon_core_data', array('creators', 'images')))) { | |
| if (isset($item['imagesets'])) { | |
| foreach ($item['imagesets'] as $size => $data) { | |
| $image = array('asin' => $item['asin'], 'size' => $size, 'height' => $data['height'], 'width' => $data['width'], 'url' => $data['url']); | |
| try { | |
| db_insert('amazon_item_image') | |
| ->fields($image) | |
| ->execute(); | |
| } | |
| catch (Exception $e) { | |
| amazon_db_error_watchdog("Failed to insert item into amazon_item_image table", $e); | |
| } | |
| } | |
| } | |
| } | |
| // Save the editorial reviews if they exist. | |
| if (in_array('editorial_reviews', variable_get('amazon_core_data', array('creators', 'images')))) { | |
| if (isset($item['editorialreviews'])) { | |
| foreach ($item['editorialreviews'] as $data) { | |
| $review = array('asin' => $item['asin'], 'source' => $data['source'], 'content' => $data['content']); | |
| try { | |
| db_insert('amazon_item_editorial_review') | |
| ->fields($review) | |
| ->execute(); | |
| } | |
| catch (Exception $e) { | |
| amazon_db_error_watchdog("Failed to insert item into amazon_item_editorial_review table", $e); | |
| } | |
| } | |
| } | |
| } | |
| module_invoke_all('amazon_item_insert', $item); | |
| } | |
| /** | |
| * Delete all vestiges of Amazon item. | |
| * @param $asin | |
| * ASIN to be deleted. | |
| * @return No return. | |
| */ | |
| function amazon_item_delete($asin) { | |
| module_invoke_all('amazon_item_delete', $asin); | |
| db_delete('amazon_item') | |
| ->condition('asin', $asin) | |
| ->execute(); | |
| db_delete('amazon_item_participant') | |
| ->condition('asin', $asin) | |
| ->execute(); | |
| db_delete('amazon_item_image') | |
| ->condition('asin', $asin) | |
| ->execute(); | |
| db_delete('amazon_item_editorial_review') | |
| ->condition('asin', $asin) | |
| ->execute(); | |
| } | |
| /** | |
| * Try to turn a non-asin into an ASIN where possible. | |
| * | |
| * If the received input appears to be an EAN (ISBN-13) or an Amazon.com/de/uk | |
| * link, then this tries to convert it into an ASIN. | |
| * @param $input | |
| * @return | |
| * An ASIN if possible. Otherwise whatever was passed in, | |
| * after removing dashes. | |
| */ | |
| function amazon_convert_to_asin($input) { | |
| $input = preg_replace('/-/', '', $input); // Remove dashes. | |
| if (preg_match('/^https?:/', $input)) { | |
| $parts = preg_split('/\//', $input); | |
| $asin = $parts[5]; // 6th section of split, right after /dp/ | |
| return $asin; | |
| } | |
| // Attempt conversion of 13-digit ASIN by doing an Amazon lookup. | |
| if (strlen($input) == 13 && is_numeric($input)) { | |
| $asin = amazon_ean_to_asin($input); | |
| return $asin; | |
| } | |
| return $input; | |
| } | |
| /** | |
| * Given an EAN (ISBN-13), try to get Amazon to give it to us. | |
| * @param $ean | |
| * The EAN, ISBN-13 value | |
| * @return | |
| * The asin, or NULL if unsuccessful. | |
| * @see https://affiliate-program.amazon.com/gp/associates/help/t5/a16?ie=UTF8&pf_rd_t=501&pf_rd_m=ATVPDKIKX0DER&pf_rd_p=&pf_rd_s=assoc-center-2&pf_rd_r=&pf_rd_i=assoc_glossary | |
| */ | |
| function amazon_ean_to_asin($ean) { | |
| $asin = NULL; | |
| $params = array( | |
| 'ItemId' => $ean, | |
| 'IdType' => 'EAN', | |
| 'SearchIndex' => 'Books', | |
| ); | |
| $results = amazon_http_request('ItemLookup', $params); | |
| if (!empty($results->Items->Item->ASIN)) { | |
| $asin = (string) $results->Items->Item->ASIN; | |
| } | |
| return $asin; | |
| } | |
| /** | |
| * Utility functions for managing AmazonItem/Node relationships | |
| */ | |
| function amazon_item_node_save($asin, $node, $module = 'amazon', $weight = 0) { | |
| amazon_item_node_delete($asin, $nid, $module); | |
| try { | |
| $id = db_insert('amazon_item_node') | |
| ->fields(array( | |
| 'asin' => $asin, | |
| 'nid' => $nid, | |
| 'module' => $module, | |
| 'weight' => $weight, | |
| )) | |
| ->execute(); | |
| } catch(Exception $e) { | |
| amazon_db_error_watchdog('Failed to save amazon_item_node.', $e); | |
| } | |
| } | |
| function amazon_item_node_delete($asin = NULL, $nid = NULL, $module = NULL) { | |
| $delete = db_delete('amazon_item_node'); | |
| if (isset($asin)) { | |
| $delete = $delete->condition('asin', $asin); | |
| } | |
| if (isset($nid)) { | |
| $delete = $delete->condition('nid', $nid); | |
| } | |
| if (isset($module)) { | |
| $delete = $delete->condition('module', $module); | |
| } | |
| $delete->execute(); | |
| } | |
| /** | |
| * Misc. helper functions for managing the wide array of Amazon | |
| * data bitsies. | |
| */ | |
| function amazon_data_cache($reset = FALSE) { | |
| static $data; | |
| if (!isset($data) || $reset) { | |
| if (!$reset && ($cache = cache_get('amazon:metadata')) && !empty($cache->data)) { | |
| $data = $cache->data; | |
| } | |
| else { | |
| $data = array(); | |
| $data['locales'] = _amazon_default_locales(); | |
| drupal_alter('amazon_metadata', $data); | |
| cache_set('amazon:metadata', $data); | |
| } | |
| } | |
| return $data; | |
| } | |
| function _amazon_default_locales() { | |
| $locales = array(); | |
| $locales['US'] = array( | |
| 'url' => 'http://ecs.amazonaws.com/onca/xml', | |
| 'name' => t('United States'), | |
| ); | |
| $locales['UK'] = array( | |
| 'url' => 'http://ecs.amazonaws.co.uk/onca/xml', | |
| 'name' => t('United Kingdom'), | |
| ); | |
| $locales['JP'] = array( | |
| 'url' => 'http://ecs.amazonaws.jp/onca/xml', | |
| 'name' => t('Japan'), | |
| ); | |
| $locales['FR'] = array( | |
| 'url' => 'http://ecs.amazonaws.fr/onca/xml', | |
| 'name' => t('France'), | |
| ); | |
| $locales['DE'] = array( | |
| 'url' => 'http://ecs.amazonaws.de/onca/xml', | |
| 'name' => t('Germany'), | |
| ); | |
| $locales['CA'] = array( | |
| 'url' => 'http://ecs.amazonaws.ca/onca/xml', | |
| 'name' => t('Canada'), | |
| ); | |
| return $locales; | |
| } | |
| function amazon_get_associate_id() { | |
| switch (variable_get('amazon_associate_setting', 'association')) { | |
| case 'association': | |
| return 'drupal0a-20'; | |
| break; | |
| case 'custom': | |
| return variable_get('amazon_custom_associate_id', ''); | |
| break; | |
| default: | |
| return FALSE; | |
| } | |
| } | |
| function amazon_cron() { | |
| // Here, we're going to chug through all the existing ASINs and update them. | |
| // We'll grab 50 at a time to avoid thrashing things. | |
| $per_cron_limit = 50; | |
| $needs_update_time = REQUEST_TIME - variable_get('amazon_refresh_schedule', 86400); | |
| $result = db_select('amazon_item', NULL, array('fetch' => PDO::FETCH_ASSOC)) | |
| ->fields('amazon_item', array('asin')) | |
| ->condition('timestamp', $needs_update_time, '<') | |
| ->range(0, $per_cron_limit) | |
| ->execute(); | |
| $asins = $result->FetchCol(); | |
| if (!empty($asins)) { | |
| if ($items = amazon_item_lookup_from_web($asins)) { | |
| foreach ($items as $item) { | |
| amazon_item_insert($item); | |
| } | |
| watchdog('amazon', 'Amazon items were updated.'); | |
| } | |
| else { | |
| watchdog('amazon', 'Amazon items could not be updated.'); | |
| } | |
| } | |
| } | |
| /** | |
| * Implementation of hook_views_api. | |
| */ | |
| function amazon_views_api() { | |
| return array( | |
| 'api' => 2, | |
| 'path' => drupal_get_path('module', 'amazon') . '/includes', | |
| ); | |
| } | |
| /** | |
| * Template helper for theme_amazon_views_view_row_item | |
| */ | |
| function template_preprocess_amazon_views_view_row_item(&$vars) { | |
| $options = $vars['options']; | |
| $vars['amazon_item'] = ''; // make sure var is defined. | |
| $asin = $vars['row']->asin; | |
| $items = amazon_item_lookup($asin); | |
| if (empty($items[$asin])) { | |
| return; | |
| } | |
| else { | |
| $item = $items[$asin]; | |
| $item['view'] = $vars['view']; | |
| $vars['amazon_item'] = $item; | |
| if ($options['display_format'] == 'inline') { | |
| $vars['content'] = theme('amazon_item_inline', array('item' => $item, 'style' => $options['display_format'])); | |
| } | |
| else { | |
| $vars['content'] = theme('amazon_item', array('item' => $item, 'style' => $options['display_format'])); | |
| } | |
| } | |
| } | |
| function amazon_init() { | |
| drupal_add_css(drupal_get_path('module', 'amazon') . '/amazon.css'); | |
| } | |
| /** | |
| * Have watchdog emit complete errors about a database exception. | |
| * | |
| * @param $msg | |
| * The message explaining the error. | |
| * The message should not be localized, as it will be passed to watchdog(). | |
| * @param $e | |
| * The exception which was caught | |
| * | |
| */ | |
| function amazon_db_error_watchdog($msg, $e) { | |
| watchdog('amazon', "$msg: Message = %message, query= %query", | |
| array('%message' => $e->getMessage(), '%query' => $e->query_string)); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Provide views data and handlers for amazon.module | |
| */ | |
| /** | |
| * @defgroup views_amazon_module amazon.module handlers | |
| * | |
| * Includes the tables 'amazon_item', 'amazon_item_participant', | |
| * 'amazon_item_image', 'amazon_item_editorial_review', and 'amazon_item_node'. | |
| * @{ | |
| */ | |
| /** | |
| * Implementation of hook_views_plugins | |
| */ | |
| function amazon_views_plugins() { | |
| return array( | |
| 'module' => 'amazon', // This just tells our themes are elsewhere. | |
| 'row' => array( | |
| 'amazon_item' => array( | |
| 'title' => t('Amazon item'), | |
| 'help' => t('Display the item as a fully themed Amazon product.'), | |
| 'handler' => 'amazon_views_plugin_row_amazon_view', | |
| 'theme' => 'amazon_views_view_row_item', | |
| 'theme file' => 'amazon.theme.inc', | |
| 'theme path' => drupal_get_path('module', 'amazon'), | |
| 'base' => array('amazon_item'), | |
| 'uses options' => TRUE, | |
| 'type' => 'normal', | |
| 'parent' => 'views_plugin_row', | |
| ), | |
| ), | |
| ); | |
| } | |
| /** | |
| * Implementation of hook_views_handlers() | |
| */ | |
| function amazon_views_handlers() { | |
| return array( | |
| 'info' => array( | |
| 'path' => drupal_get_path('module', 'amazon') . '/includes', | |
| ), | |
| 'handlers' => array( | |
| 'views_handler_field_amazon_image' => array( | |
| 'parent' => 'views_handler_field', | |
| ), | |
| 'views_handler_field_amazon_participant' => array( | |
| 'parent' => 'views_handler_field_prerender_list', | |
| ), | |
| 'views_handler_field_amazon_title' => array( | |
| 'parent' => 'views_handler_field', | |
| ), | |
| 'views_handler_field_amazon_xss' => array( | |
| 'parent' => 'views_handler_field', | |
| ), | |
| 'views_handler_filter_amazon_image' => array( | |
| 'parent' => 'views_handler_filter_many_to_one', | |
| ), | |
| 'views_handler_filter_amazon_node_module' => array( | |
| 'parent' => 'views_handler_filter_in_operator', | |
| ), | |
| 'views_handler_field_amazon_date' => array( | |
| 'parent' => 'views_handler_field_date', | |
| ), | |
| 'views_handler_filter_string_compare' => array( | |
| 'parent' => 'views_handler_filter', | |
| ), | |
| ), | |
| ); | |
| } | |
| function amazon_views_data() { | |
| // Basic table information. | |
| // ---------------------------------------------------------------- | |
| // Core amazon_item table | |
| // Define the base group of this table. Fields that don't | |
| // have a group defined will go into this field by default. | |
| $data['amazon_item']['table']['group'] = t('Amazon'); | |
| // Advertise this table as a possible base table | |
| $data['amazon_item']['table']['base'] = array( | |
| 'field' => 'asin', | |
| 'title' => t('Amazon item'), | |
| 'help' => t('The Amazon item type allows views of Amazon products saved on your site.'), | |
| 'weight' => 10, | |
| ); | |
| // ---------------------------------------------------------------- | |
| // Fields | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'asin', 'ASIN', 'The product ID of the item.'); | |
| // title | |
| $data['amazon_item']['title'] = array( | |
| 'title' => t('Title'), // The item it appears as on the UI, | |
| 'help' => t('The name of the product.'), // The help that appears on the UI, | |
| // Information for displaying a title as a field | |
| 'field' => array( | |
| 'field' => 'title', // the real field | |
| 'handler' => 'views_handler_field_amazon_title', | |
| 'click sortable' => TRUE, | |
| ), | |
| 'sort' => array('handler' => 'views_handler_sort'), | |
| ); | |
| // detailpageurl | |
| $data['amazon_item']['detailpageurl'] = array( | |
| 'title' => t('Detail page URL'), // The item it appears as on the UI, | |
| 'help' => t("The URL of the product's page on Amazon.com."), // The help that appears on the UI, | |
| // Information for displaying a title as a field | |
| 'field' => array( | |
| 'field' => 'detailpageurl', // the real field | |
| 'handler' => 'views_handler_field', | |
| 'click sortable' => FALSE, | |
| ), | |
| ); | |
| _amazon_make_simple_number_field($data, 'amazon_item', 'salesrank', 'Sales rank', 'The current sales ranking of the product on Amazon.com.'); | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'publisher', 'Publisher', 'The publisher of the product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'manufacturer', 'Manufacturer', 'The manufacturer of the product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'mpn', "Part number", "The Manufacturer's own part number for the product."); | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'studio', 'Studio', 'The name of the studio that published the product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'label', 'Label', 'The name of the label that published the product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'binding', 'Binding', 'The style of binding used for the product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'productgroup', 'Product group', 'The Amazon grouping the product is categorized in.'); | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'producttypename', 'Product type name', 'The Amazon internal product-type code for the product.'); | |
| _amazon_make_simple_date_field($data, 'amazon_item', 'releasedate', 'Release date', 'The release date of the product.'); | |
| _amazon_make_simple_number_field($data, 'amazon_item', 'listpriceamount', 'List price (numeric)', 'The current sales ranking of the product on Amazon.com.'); | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'listpriceformattedprice', 'List price (formatted)', 'The current list price of the item.'); | |
| _amazon_make_simple_number_field($data, 'amazon_item', 'lowestpriceamount', 'Lowest price (numeric)', 'The current lowest price offered on Amazon.'); | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'lowestpriceformattedprice', 'Lowest price (formatted)', 'The lowest available price.'); | |
| _amazon_make_simple_number_field($data, 'amazon_item', 'amazonpriceamount', 'Amazon Price (numeric)', "Amazon's current price for the item"); | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'amazonpriceformattedprice', 'Amazon price (formatted)', "Amazon's current price for the item."); | |
| _amazon_make_simple_boolean_field($data, 'amazon_item', 'invalid_asin', 'Invalid ASIN', 'If nonzero, the ASIN is invalid or discontinued by Amazon'); | |
| unset($data['amazon_item']['listpriceformattedprice']['argument']); | |
| unset($data['amazon_item']['lowestformattedprice']['argument']); | |
| unset($data['amazon_item']['amazonpriceformattedprice']['argument']); | |
| // Define the base group of this table. Fields that don't | |
| // have a group defined will go into this field by default. | |
| $data['amazon_item_participant']['table']['group'] = t('Amazon'); | |
| $data['amazon_item_participant']['table']['join'] = array( | |
| // participant links to amazon_item directly via asin. | |
| 'amazon_item' => array( | |
| 'left_field' => 'asin', | |
| 'field' => 'asin', | |
| ), | |
| ); | |
| _amazon_make_simple_text_field($data, 'amazon_item_participant', 'participant', 'Participant name', 'The name of an individual who participated in the creation of a product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_item_participant', 'type', 'Participant role', 'The role the participant had in creating the product (author, artist, etc).'); | |
| //$data['amazon_item_participant']['participant']['argument']['handler'] = 'views_handler_argument_many_to_one'; | |
| unset($data['amazon_item_participant']['type']['argument']); | |
| // participants_all | |
| $data['amazon_item_participant']['participants_all'] = array( | |
| 'title' => t('All participants'), // The item it appears as on the UI, | |
| 'help' => t("The names of all individuals who participated in the creation of a product, grouped as a single field."), // The help that appears on the UI, | |
| // Information for displaying a title as a field | |
| 'field' => array( | |
| 'field' => 'participant', // the real field | |
| 'handler' => 'views_handler_field_amazon_participant', | |
| 'click sortable' => FALSE, | |
| ), | |
| ); | |
| // Define the base group of this table. Fields that don't | |
| // have a group defined will go into this field by default. | |
| $data['amazon_item_image']['table']['group'] = t('Amazon'); | |
| $data['amazon_item_image']['table']['join'] = array( | |
| // participant links to amazon_item directly via asin. | |
| 'amazon_item' => array( | |
| 'left_field' => 'asin', | |
| 'field' => 'asin', | |
| ), | |
| ); | |
| // image | |
| $data['amazon_item_image']['product_image'] = array( | |
| 'title' => t('Product image'), // The item it appears as on the UI, | |
| 'help' => t("An image of the Amazon product."), // The help that appears on the UI, | |
| // Information for displaying a title as a field | |
| 'field' => array( | |
| 'field' => 'url', // the real field | |
| 'handler' => 'views_handler_field_amazon_image', | |
| 'click sortable' => FALSE, | |
| ), | |
| 'filter' => array( | |
| 'field' => 'size', | |
| 'handler' => 'views_handler_filter_amazon_image', | |
| 'click sortable' => FALSE, | |
| ), | |
| ); | |
| // Editorial review | |
| $data['amazon_item_editorial_review']['table']['group'] = t('Amazon'); | |
| $data['amazon_item_editorial_review']['table']['join'] = array( | |
| // editorial review links to amazon_item directly via asin. | |
| 'amazon_item' => array( | |
| 'left_field' => 'asin', | |
| 'field' => 'asin', | |
| ), | |
| ); | |
| _amazon_make_simple_text_field($data, 'amazon_item_editorial_review', 'source', 'Editorial review source', 'The source of this editorial review. Since there may be more than one review for each product, your view will produce one row per review.'); | |
| _amazon_make_simple_markup_field($data, 'amazon_item_editorial_review', 'content', 'Editorial content', 'Content of an editorial review. Since there may be more than one review for each product, your view will produce one row per review.'); | |
| _amazon_make_simple_text_field($data, 'amazon_item', 'customerreviews_iframe', 'Customer reviews iframe', "A link to an customer reviews provided by Amazon which is suitable for placement in an iframe"); | |
| return $data; | |
| } | |
| function _amazon_make_simple_boolean_field(&$data, $table, $column, $title, $help = '') { | |
| $data[$table][$column] = array( | |
| 'title' => $title, // The item it appears as on the UI, | |
| 'help' => $help, // The help that appears on the UI, | |
| // Information for displaying a title as a field | |
| 'field' => array( | |
| 'field' => $column, // the real field | |
| 'handler' => 'views_handler_field_boolean', | |
| 'click sortable' => TRUE, | |
| ), | |
| 'argument' => array('handler' => 'views_handler_argument_numeric'), | |
| 'filter' => array('handler' => 'views_handler_filter_boolean_operator'), | |
| 'sort' => array('handler' => 'views_handler_sort'), | |
| ); | |
| } | |
| function _amazon_make_simple_text_field(&$data, $table, $column, $title, $help = '') { | |
| $data[$table][$column] = array( | |
| 'title' => $title, // The item it appears as on the UI, | |
| 'help' => $help, // The help that appears on the UI, | |
| // Information for displaying a title as a field | |
| 'field' => array( | |
| 'field' => $column, // the real field | |
| 'handler' => 'views_handler_field', | |
| 'click sortable' => TRUE, | |
| ), | |
| 'argument' => array('handler' => 'views_handler_argument_string'), | |
| 'filter' => array('handler' => 'views_handler_filter_string'), | |
| 'sort' => array('handler' => 'views_handler_sort'), | |
| ); | |
| } | |
| function _amazon_make_simple_markup_field(&$data, $table, $column, $title, $help = '') { | |
| $data[$table][$column] = array( | |
| 'title' => $title, // The item it appears as on the UI, | |
| 'help' => $help, // The help that appears on the UI, | |
| // Information for displaying a title as a field | |
| 'field' => array( | |
| 'handler' => 'views_handler_field_amazon_xss', | |
| ), | |
| ); | |
| } | |
| function _amazon_make_simple_date_field(&$data, $table, $column, $title, $help = '') { | |
| $data[$table][$column] = array( | |
| 'title' => $title, // The item it appears as on the UI, | |
| 'help' => $help, // The help that appears on the UI, | |
| // Information for displaying a title as a field | |
| 'field' => array( | |
| 'field' => $column, // the real field | |
| 'handler' => 'views_handler_field_amazon_date', | |
| 'click sortable' => TRUE, | |
| ), | |
| 'filter' => array('handler' => 'views_handler_filter_string_compare'), | |
| // Amazon date is sortable, so we can just use the standard handler. | |
| 'sort' => array('handler' => 'views_handler_sort'), | |
| ); | |
| } | |
| function _amazon_make_simple_number_field(&$data, $table, $column, $title, $help = '') { | |
| $data[$table][$column] = array( | |
| 'title' => $title, // The item it appears as on the UI, | |
| 'help' => $help, // The help that appears on the UI, | |
| // Information for displaying a title as a field | |
| 'field' => array( | |
| 'field' => $column, // the real field | |
| 'handler' => 'views_handler_field_numeric', | |
| 'click sortable' => TRUE, | |
| ), | |
| 'filter' => array('handler' => 'views_handler_filter_numeric'), | |
| 'sort' => array('handler' => 'views_handler_sort'), | |
| ); | |
| } | |
| /** | |
| * @} | |
| */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name = Amazon Filter | |
| description = Lets writers use the [amazon] tag to embed Amazon product information in text. | |
| package = Amazon | |
| dependencies[] = amazon | |
| core = 7.x | |
| php = 5.2 | |
| configure = admin/config/content/formats |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Implementation of hook_help(). | |
| */ | |
| /** | |
| * Implements of hook_filter_tips(). | |
| */ | |
| function _amazon_filter_tips($filter, $format, $long = FALSE) { | |
| if ($long) { | |
| return t('Get Amazon product data using [amazon ASIN selector], for example, [amazon 0399155341 thumbnail], | |
| [amazon 0399155341 full], or [amazon 0399155341 inline]. | |
| In addition, you can grab various data items from the item description using selectors like | |
| author, title, asin, isbn, ean, detailpageurl, salesrank, publisher, manufacturer, studio, | |
| label, binding, listpriceamount, listpricecurrencycode, listpriceformattedprice, | |
| lowestpriceamount, lowestpricecurrencycode, lowestpriceformattedprice, | |
| amazonpriceamount, amazonpricecurrencycode, amazonpriceformattedprice, | |
| productgroup, producttypename, invalid_asin, deweydecimalnumber, edition, numberofpages, | |
| publicationyear, type, releaseyear, publicationyear, smallimage, smallimageurl, smallimageheight, | |
| smallimagewidth, mediumimage, mediumimageurl, mediumimageheight, mediumimagewidth, | |
| largeimage, largeimageurl, largeimageheight, largeimagewidth. | |
| For example, [amazon 0596515804 title] will provide the title of the item, and | |
| [amazon 0596515804 largeimage] will be replaced with an img tag giving the large image. | |
| A complete description of filters is <a href="http://drupal.org/node/595464#filters">on the Amazon module handbook page</a>.'); | |
| } | |
| else { | |
| return t('Link to Amazon products with: [amazon product_id inline|full|thumbnail|datadescriptor]. Example: [amazon 1590597559 thumbnail] or [amazon 1590597559 author]. Details are <a href="http://drupal.org/node/595464#filters" target="_blank">on the Amazon module handbook page</a>.'); | |
| } | |
| } | |
| /** | |
| * Implements hook_filter_info(). | |
| */ | |
| function amazon_filter_info() { | |
| $filters['amazon'] = array( | |
| 'title' => t('Amazon filter'), | |
| 'description' => t('Provides access to many types of Amazon data. Simplest usage: [amazon ASIN inline], for example [amazon 0596515804 inline].'), | |
| 'process callback' => '_amazon_filter_process_text', | |
| 'tips callback' => '_amazon_filter_tips', | |
| ); | |
| return $filters; | |
| } | |
| /** | |
| * Actual filter processing function - changes [amazon <whatever>] in text. | |
| * @param $text | |
| * Text to be transformed. | |
| * @return | |
| * The transformed text. | |
| */ | |
| function _amazon_filter_process_text($text) { | |
| $pattern = "@\[amazon +(.*?)(?: +(.*?))?\]@"; | |
| $matches = array(); | |
| if (preg_match_all($pattern, $text, $matches)) { | |
| $search = $matches[0]; | |
| $replace = array(); | |
| foreach ($matches[0] as $key => $value) { | |
| $asin = $matches[1][$key]; | |
| $asin = amazon_convert_to_asin($asin); | |
| $action = $matches[2][$key]; | |
| $items = amazon_item_lookup($asin); | |
| $item = ""; | |
| if (!empty($items)) { | |
| $item = $items[$asin]; | |
| } | |
| if (!empty($item)) { | |
| switch ($action) { | |
| case "": | |
| case 'inline': | |
| $replace[] = theme('amazon_inline_item', array('item' =>$item)); | |
| break; | |
| // Full is a synonym of 'details'. | |
| case 'full': | |
| case 'details': | |
| $replace[] = theme('amazon_item', array('item' => $item, 'style' => 'details')); | |
| break; | |
| // Handle themeable cases, like thumbnail. | |
| case 'thumbnail': | |
| $replace[] = theme('amazon_item_thumbnail', array('item' => $item)); | |
| break; | |
| default: | |
| // Allow to use anything found in the item. | |
| $replace[] = theme('amazon_detail', array('item' => $item, 'detail' => $action)); | |
| break; | |
| } | |
| } | |
| else { | |
| // error case | |
| $replace[] = "<!-- The Amazon product '$asin' could not be found.-->"; | |
| } | |
| } | |
| $text = str_replace($search, $replace, $text); | |
| } | |
| return $text; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name = Amazon media | |
| description = Stores extended Amazon product information for books, music, DVDs, and software. | |
| package = Amazon | |
| dependencies[] = amazon | |
| core = 7.x | |
| php = 5.2 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Install, update and uninstall functions for the amazon_media module. | |
| * | |
| */ | |
| function amazon_media_install() { | |
| amazon_media_update_7002(); // Set system weight. | |
| } | |
| function amazon_media_uninstall() { | |
| } | |
| function amazon_media_schema() { | |
| $schema['amazon_book'] = array( | |
| 'fields' => array( | |
| 'asin' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE), | |
| 'ean' => array('type' => 'varchar', 'length' => 20, 'not null' => TRUE), | |
| 'isbn' => array('type' => 'varchar', 'length' => 20, 'not null' => TRUE), | |
| 'deweydecimalnumber' => array('type' => 'varchar', 'length' => 64), | |
| 'edition' => array('type' => 'varchar', 'length' => 128), | |
| 'numberofpages' => array('type' => 'int'), | |
| 'publicationdate' => array('type' => 'varchar', 'length' => 32), | |
| ), | |
| 'primary key' => array('asin'), | |
| ); | |
| $schema['amazon_dvd'] = array( | |
| 'fields' => array( | |
| 'asin' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE), | |
| 'regioncode' => array('type' => 'int'), | |
| 'runningtime' => array('type' => 'int'), | |
| 'audiencerating' => array('type' => 'varchar', 'length' => 64), | |
| 'aspectratio' => array('type' => 'varchar', 'length' => 16), | |
| 'theatricalreleasedate' => array('type' => 'varchar', 'length' => 32), | |
| ), | |
| 'primary key' => array('asin'), | |
| ); | |
| $schema['amazon_music'] = array( | |
| 'fields' => array( | |
| 'asin' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE), | |
| 'artist' => array('type' => 'varchar', 'length' => 128), | |
| 'label' => array('type' => 'varchar', 'length' => 128), | |
| 'studio' => array('type' => 'varchar', 'length' => 128), | |
| 'numberofdiscs' => array('type' => 'int', 'default' => 1), | |
| ), | |
| 'primary key' => array('asin'), | |
| ); | |
| $schema['amazon_software'] = array( | |
| 'fields' => array( | |
| 'asin' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE), | |
| 'esrbagerating' => array('type' => 'varchar', 'length' => 32), | |
| 'operatingsystem' => array('type' => 'varchar', 'length' => 64), | |
| 'hardwareplatform' => array('type' => 'varchar', 'length' => 64), | |
| 'platform' => array('type' => 'varchar', 'length' => 64), | |
| 'genre' => array('type' => 'varchar', 'length' => 128), | |
| ), | |
| 'primary key' => array('asin'), | |
| ); | |
| return $schema; | |
| } | |
| /** | |
| * Set the weight on amazon_media to be higher than amazon. | |
| * | |
| * This allows amazon_media to override theme settings that amazon has done. | |
| */ | |
| function amazon_media_update_7002() { | |
| db_query("UPDATE {system} SET weight = 10 WHERE name = 'amazon_media'"); | |
| } | |
| /** | |
| * Update the "edition" field to a varchar since it can be many things provided | |
| * by amazon. | |
| */ | |
| function amazon_media_update_7003() { | |
| db_change_field('amazon_book', 'edition', 'edition', array('type' => 'varchar', 'length' => 128)); | |
| return(t("Changed amazon_book 'edition' to a varchar")); | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Provides additional behaviors and data type for amazon items which are | |
| * DVDs, software, video games, music, etc. | |
| */ | |
| /** | |
| * Implements hook_theme(). | |
| */ | |
| function amazon_media_theme() { | |
| $templates = array( | |
| 'amazon_inline_item__dvd' => array( | |
| 'variables' => array('item' => array()), | |
| ), | |
| 'amazon_inline_item__software' => array( | |
| 'variables' => array('item' => array()), | |
| ), | |
| 'amazon_inline_item__games' => array( | |
| 'variables' => array('item' => array()), | |
| ), | |
| 'amazon_inline_item__console_video_games' => array( | |
| 'variables' => array('item' => array()), | |
| 'function' => 'theme_amazon_inline_item__games', | |
| ), | |
| 'amazon_item__book__details' => array( | |
| 'variables' => array('item' => array()), | |
| 'template' => 'amazon-item--book--details', | |
| ), | |
| 'amazon_item__dvd__details' => array( | |
| 'variables' => array('item' => array()), | |
| 'template' => 'amazon-item--dvd--details', | |
| ), | |
| 'amazon_item__software__details' => array( | |
| 'variables' => array('item' => array()), | |
| 'template' => 'amazon-item--software--details', | |
| ), | |
| 'amazon_item__games__details' => array( | |
| 'variables' => array('item' => array()), | |
| 'template' => 'amazon-item--games--details', | |
| ), | |
| ); | |
| return $templates; | |
| } | |
| /** | |
| * Implements hook_theme_registry_alter(). | |
| * | |
| * Because we aren't defining our own stuff here, just providing some | |
| * high-specificity templates for theme_amazon_item, we'll add this | |
| * module's directory to the list of paths to search for when finding | |
| * amazon_item tpl's. | |
| */ | |
| function amazon_media_theme_registry_alter(&$theme_registry) { | |
| $theme_registry['amazon_item']['theme path'] = drupal_get_path('module', 'amazon_media'); | |
| if (!empty($theme_registry['amazon_item'])) { | |
| // We'll try our best to avoid stepping on theme template files. | |
| if (!empty($theme_registry['amazon_item']['theme_paths']) && count($theme_registry['amazon_item']['theme paths']) > 1) { | |
| $theme = array_pop($theme_registry['amazon_item']['theme paths']); | |
| } | |
| $theme_registry['amazon_item']['theme paths'][] = drupal_get_path('module', 'amazon_media'); | |
| if (isset($theme)) { | |
| $theme_registry['amazon_item']['theme paths'][] = $theme; | |
| } | |
| } | |
| } | |
| /** | |
| * Implements hook_preprocess. | |
| * | |
| * @param $variables | |
| */ | |
| function amazon_media_preprocess_amazon_item(&$variables) { | |
| if (!empty($variables['theatricalreleasedate'])) { | |
| $date = explode('-', $variables['theatricalreleasedate']); | |
| $variables['theatricalreleaseyear'] = $date[0]; | |
| } | |
| else { | |
| $variables['theatricalreleaseyear'] = ''; | |
| } | |
| if (!empty($variables['publicationdate'])) { | |
| $date = explode('-', $variables['publicationdate']); | |
| $variables['publicationyear'] = $date[0]; | |
| } | |
| // Various bits we want to ensure have defaults. | |
| $variables += array( | |
| 'director' => '', | |
| 'actor' => '', | |
| 'audiencerating' => t('NR - Not Rated'), | |
| 'publicationyear' => '', | |
| 'runningtime' => '', | |
| 'theatricalreleaseyear' => '', | |
| ); | |
| } | |
| /** | |
| * Load and return additional information for an Amazon item. | |
| * @param $item | |
| * The item requiring additions. | |
| * @return | |
| * The added array elements, as an array. | |
| */ | |
| function amazon_media_amazon_item_load($item) { | |
| $table = amazon_media_get_table_name($item); | |
| if (!empty($table)) { | |
| $additions = db_select($table) | |
| ->condition('asin', $item['asin']) | |
| ->fields($table) | |
| ->execute() | |
| ->fetchAssoc(); | |
| return $additions; | |
| } | |
| } | |
| /** | |
| * Given an item, return the name of the table it's associated with. | |
| * @param $item | |
| * populated amazon_item with $item['producttypename'] populated. | |
| * @return | |
| * the name of the associated table. | |
| */ | |
| function amazon_media_get_table_name($item) { | |
| static $names = array('ABIS_BOOK' => 'amazon_book', | |
| 'BOOKS_1973_AND_LATER' => 'amazon_book', | |
| 'VIDEO_DVD' => 'amazon_dvd', | |
| 'ABIS_DVD' => 'amazon_dvd', | |
| 'ABIS_MUSIC' => 'amazon_music', | |
| 'CONSOLE_VIDEO_GAMES' => 'amazon_software', | |
| 'VIDEO_GAMES' => 'amazon_software', | |
| 'SOFTWARE' => 'amazon_software', | |
| ); | |
| if (!empty($names[$item['producttypename']])) { | |
| return $names[$item['producttypename']]; | |
| } | |
| } | |
| /** | |
| * Insert the associated information into the related table. | |
| * @param $item | |
| * Populated amazon item record. | |
| */ | |
| function amazon_media_amazon_item_insert($item) { | |
| static $item_keys = NULL; | |
| if (empty($item_keys)) { | |
| require_once('amazon_media.install'); | |
| $schema = amazon_media_schema(); | |
| $item_keys = $schema; | |
| } | |
| $table = amazon_media_get_table_name($item); | |
| if (!empty($table)) { | |
| // We need to present a record that only has the items in it used by | |
| // this table. | |
| $db_item = array_intersect_key($item, $item_keys[$table]['fields']); | |
| try { | |
| db_insert($table) | |
| ->fields($db_item) | |
| ->execute(); | |
| } | |
| catch (Exception $e) { | |
| amazon_db_error_watchdog("Failed to insert item into amazon table", $e); | |
| } | |
| } | |
| } | |
| /** | |
| * Delete a record using the asin as key. | |
| * @param $asin | |
| * the asin to delete. | |
| */ | |
| function amazon_media_amazon_item_delete($asin) { | |
| // This is pretty inefficient; we're going to thrash these tables | |
| // every time a product gets deleted or updated. We'll solve it later. | |
| db_delete('amazon_book') | |
| ->condition('asin', $asin) | |
| ->execute(); | |
| db_delete('amazon_dvd') | |
| ->condition('asin', $asin) | |
| ->execute(); | |
| db_delete('amazon_music') | |
| ->condition('asin', $asin) | |
| ->execute(); | |
| db_delete('amazon_software') | |
| ->condition('asin', $asin) | |
| ->execute(); | |
| } | |
| /** | |
| * Implements hook_views_api. | |
| */ | |
| function amazon_media_views_api() { | |
| return array('api' => 2); | |
| } | |
| /** | |
| * Implements theme_ with specialty dvd. | |
| * | |
| * @param $item | |
| * fully populated amazon item. | |
| * @param $style | |
| * 'full', 'thumbnail', or whatever. | |
| */ | |
| function theme_amazon_item__dvd($item, $style = 'default') { | |
| drupal_set_message('Theming with theme_amazon_item__dvd'); | |
| $output = ''; | |
| $type = $item['type']; | |
| switch ($style) { | |
| case 'full': | |
| $output .= '<div class="' . _amazon_item_classes($type) . ' amazon-item-full">'; | |
| $output .= theme('image', array('path' => $item['imagesets']['mediumimage']['url'], 'alt' => t('Cover image'), 'title' => check_markup($item['title']), 'attributes' => array(), 'getsize' => FALSE)); | |
| $output .= '<h3>' . l(check_plain($item['title']), $item['detailpageurl'], array('attributes' => array('rel' => 'nofollow'))) . '</h3>'; | |
| $output .= '</div>'; | |
| break; | |
| case 'thumbnail': | |
| $output .= '<div class="' . _amazon_item_classes($type) . ' amazon-item-thumbnail">'; | |
| $output .= theme('image', array('path' => $item['imagesets']['mediumimage']['url'], 'alt' => t('Cover image'), 'title' => check_markup($item['title']), 'attributes' => array(), 'getsize' => FALSE)); | |
| $output .= '</div>'; | |
| break; | |
| default: | |
| $output .= '<div class="' . _amazon_item_classes($type) . '">'; | |
| $output .= theme('image', array('path' => $item['imagesets']['smallimage']['url'], 'alt' => t('Cover image'), 'title' => check_markup($item['title']), 'attributes' => array(), 'getsize' => FALSE)); | |
| $date = preg_split('/-/', $item['theatricalreleasedate']); | |
| $output .= '<h3>' . l(check_markup($item['title']), $item['detailpageurl'], array('attributes' => array('rel' => 'nofollow'))) . ' (' . check_plain($date[0]) . ')</h3>'; | |
| $output .= '<div><strong>' . t('Director') . ':</strong> ' . implode(', ', $item['director']) . '</div>'; | |
| $output .= '<div><strong>' . t('Rating') . ':</strong> ' . $item['audiencerating'] . '</div>'; | |
| $output .= '<div><strong>' . t('Running time') . ':</strong> ' . $item['runningtime'] . ' ' . t('minutes') . '</div>'; | |
| $output .= '</div>'; | |
| break; | |
| } | |
| return $output; | |
| } | |
| /** | |
| * Theme with inline item dvd. | |
| * @param $item | |
| * @return | |
| * rendered output. | |
| */ | |
| function theme_amazon_inline_item__dvd($item) { | |
| $type = $item['type']; | |
| $date = preg_split('/-/', $item['theatricalreleasedate']); | |
| $output = ''; | |
| $output .= '<span class="' . _amazon_item_classes($type) . ' amazon-item-inline">'; | |
| $output .= l($item['title'] . ' (' . $date[0] . ')', $item['detailpageurl'], array('attributes' => array('rel' => 'nofollow'))); | |
| $output .= '</span>'; | |
| return $output; | |
| } | |
| function theme_amazon_inline_item__software($item) { | |
| $output = ''; | |
| $output .= '<span class="' . _amazon_item_classes($item) . ' amazon-item-inline">'; | |
| $output .= l($item['title'] . ' (' . $item['operatingsystem'] . ')', $item['detailpageurl'], array('attributes' => array('rel' => 'nofollow'))); | |
| $output .= '</span>'; | |
| return $output; | |
| } | |
| function theme_amazon_inline_item__games($item) { | |
| $output = ''; | |
| $output .= '<span class="' . _amazon_item_classes($item) . ' amazon-item-inline">'; | |
| $output .= l($item['title'] . ' (' . $item['hardwareplatform'] . ')', $item['detailpageurl'], array('attributes' => array('rel' => 'nofollow'))); | |
| $output .= '</span>'; | |
| return $output; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Provide views data and handlers for amazon.module | |
| */ | |
| /** | |
| * @defgroup views_amazon_module amazon.module handlers | |
| * | |
| * Includes the tables 'amazon_book', 'amazon_dvd', 'amazon_music', | |
| * and 'amazon_software'. | |
| * @{ | |
| */ | |
| /** | |
| * Implementation of hook_views_data() | |
| */ | |
| function amazon_media_views_data() { | |
| // Define the base group of this table. Fields that don't | |
| // have a group defined will go into this field by default. | |
| $data['amazon_book']['table']['group'] = t('Amazon'); | |
| $data['amazon_book']['table']['join'] = array( | |
| // participant links to amazon_item directly via asin. | |
| 'amazon_item' => array( | |
| 'left_field' => 'asin', | |
| 'field' => 'asin', | |
| ), | |
| ); | |
| _amazon_make_simple_text_field($data, 'amazon_book', 'deweydecimalnumber', 'Dewey decimal number', 'Dewey decimal number (used by libraries)'); | |
| _amazon_make_simple_text_field($data, 'amazon_book', 'isbn', 'ISBN number (10-digit)', 'Library of Congress ISBN number (10-digit)'); | |
| _amazon_make_simple_text_field($data, 'amazon_book', 'ean', 'EAN (13-digit ISBN number)', 'The newer, longer 13-digit EAN or 13-digit ISBN number'); | |
| _amazon_make_simple_text_field($data, 'amazon_book', 'edition', 'Edition', 'The edition of an Amazon book product.'); | |
| _amazon_make_simple_number_field($data, 'amazon_book', 'numberofpages', 'Pages', 'The number of pages in an Amazon book product.'); | |
| _amazon_make_simple_date_field($data, 'amazon_book', 'publicationdate', 'Publication date', 'The publication date of the item'); | |
| // Define the base group of this table. Fields that don't | |
| // have a group defined will go into this field by default. | |
| $data['amazon_dvd']['table']['group'] = t('Amazon'); | |
| $data['amazon_dvd']['table']['join'] = array( | |
| // participant links to amazon_item directly via asin. | |
| 'amazon_item' => array( | |
| 'left_field' => 'asin', | |
| 'field' => 'asin', | |
| ), | |
| ); | |
| _amazon_make_simple_date_field($data, 'amazon_dvd', 'theatricalreleasedate', 'Theatrical release date', 'The theatrical release date of an Amazon video product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_dvd', 'aspectratio', 'Aspect ratio', 'The aspect ratio of an Amazon video product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_dvd', 'audiencerating', 'Audience rating', 'The Audience rating of an Amazon video product (G, PG, etc).'); | |
| _amazon_make_simple_number_field($data, 'amazon_dvd', 'regioncode', 'Region code', 'The region code of an Amazon DVD product.'); | |
| _amazon_make_simple_number_field($data, 'amazon_dvd', 'runningtime', 'Running time', 'The length of an Amazon video product, in minutes.'); | |
| // Define the base group of this table. Fields that don't | |
| // have a group defined will go into this field by default. | |
| $data['amazon_music']['table']['group'] = t('Amazon'); | |
| $data['amazon_music']['table']['join'] = array( | |
| // participant links to amazon_item directly via asin. | |
| 'amazon_item' => array( | |
| 'left_field' => 'asin', | |
| 'field' => 'asin', | |
| ), | |
| ); | |
| // This appears to be a dupe of core data. We'll just ignore. | |
| // _amazon_make_simple_text_field($data, 'amazon_music', 'artist', 'Artist', 'The label that produced an Amazon music product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_music', 'label', 'Label', 'The label that published an Amazon music product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_music', 'studio', 'Studio', 'The studio that published an Amazon music product.'); | |
| _amazon_make_simple_number_field($data, 'amazon_music', 'numberofdiscs', 'Number of discs', 'The number of discs included in an Amazon music product.'); | |
| // Define the base group of this table. Fields that don't | |
| // have a group defined will go into this field by default. | |
| $data['amazon_software']['table']['group'] = t('Amazon'); | |
| $data['amazon_software']['table']['join'] = array( | |
| // participant links to amazon_item directly via asin. | |
| 'amazon_item' => array( | |
| 'left_field' => 'asin', | |
| 'field' => 'asin', | |
| ), | |
| ); | |
| _amazon_make_simple_text_field($data, 'amazon_software', 'esrbagerating', 'ESRB age rating', 'The age rating of an Amazon software product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_software', 'operatingsystem', 'Operating system', 'The operating systems required by an Amazon software product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_software', 'hardwareplatform', 'Hardware platform', 'The hardware platform required by an Amazon software product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_software', 'platform', 'Platform', 'The platform required by an Amazon software product.'); | |
| _amazon_make_simple_text_field($data, 'amazon_software', 'genre', 'Genre', 'The genre of an Amazon software product.'); | |
| return $data; | |
| } | |
| /** | |
| * @} | |
| */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name = Amazon search | |
| description = Provides an API for searching Amazon product information, and integration with the Drupal search system. | |
| package = Amazon | |
| dependencies[] = amazon | |
| dependencies[] = search | |
| core = 7.x | |
| php = 5.2 | |
| configure = admin/config/search/settings |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Sets up hook_search for Amazon items. | |
| * | |
| */ | |
| /** | |
| * Implements hook_permission. | |
| * @return unknown_type | |
| */ | |
| function amazon_search_permission() { | |
| return array( | |
| 'access amazon search' => array( | |
| 'title' => t('Access Amazon Search'), | |
| 'description' => t('Perform searches on Amazon.'), | |
| ), | |
| ); | |
| } | |
| /** | |
| * Implements hook_search_access(). | |
| */ | |
| function amazon_search_search_access() { | |
| return user_access('access amazon search'); | |
| } | |
| /** | |
| * Implements hook_search_info(). | |
| */ | |
| function amazon_search_search_info() { | |
| return array( | |
| 'title' => 'Amazon', | |
| 'path' => 'amazon_search', | |
| ); | |
| } | |
| /** | |
| * Implements hook_search_execute(). Implements remote Amazon searching. | |
| */ | |
| function amazon_search_search_execute($keys = NULL, $conditions = NULL) { | |
| $products = array(); | |
| $items = amazon_search_simple_search($keys); | |
| foreach ($items as $item) { | |
| $products[] = array( | |
| 'title' => filter_xss($item['title']), | |
| 'link' => check_url($item['detailpageurl']), | |
| 'type' => check_plain($item['productgroup']), | |
| 'user' => isset($item['participants']) ? implode(', ', $item['participants']) : '', | |
| 'snippet' => isset($item['editorialreviews']) ? filter_xss($item['editorialreviews'][0]['content']) : '', | |
| ); | |
| } | |
| return $products; | |
| } | |
| /** | |
| * Perform the search. | |
| * | |
| * @param $keywords | |
| * Keywords to be provided to Amazon. | |
| * @param $parameters | |
| * Optional extra parameters to be passed to the Amazon API. | |
| * @return | |
| * Array of Amazon items. | |
| */ | |
| function amazon_search_simple_search($keywords = '', $parameters = array()) { | |
| $parameters += array( | |
| 'ResponseGroup' => 'ItemAttributes,EditorialReview', | |
| 'SearchIndex' => 'Blended', | |
| ); | |
| $parameters['Keywords'] = urlencode($keywords); | |
| drupal_alter('amazon_search_parameters', $parameters); | |
| $items = array(); | |
| $results = amazon_http_request('ItemSearch', $parameters); | |
| foreach ($results->Items->Item as $xml) { | |
| $item = amazon_item_clean_xml($xml); | |
| $items[$item['asin']] = $item; | |
| } | |
| return $items; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Provide views handlers for amazon.module | |
| */ | |
| /** | |
| * Plugin which loads and themes an amazon item. | |
| * | |
| * @ingroup views_plugin_rows | |
| */ | |
| class amazon_views_plugin_row_amazon_view extends views_plugin_row { | |
| function option_definition() { | |
| $options = parent::option_definition(); | |
| $options['display_format'] = array('default' => 'default'); | |
| return $options; | |
| } | |
| function options_form(&$form, &$form_state) { | |
| $form['display_format'] = array( | |
| '#type' => 'select', | |
| '#title' => t('Display format'), | |
| '#options' => array( | |
| 'default' => t('Default'), | |
| 'details' => t('Details'), | |
| 'thumbnail' => t('Thumbnail'), | |
| 'inline' => t('Inline'), | |
| ), | |
| '#default_value' => $this->options['display_format'], | |
| ); | |
| } | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| p.asin-edit-title { | |
| font-size: 90%; | |
| font-style: italic; | |
| padding-bottom: 0px; | |
| margin-bottom: 0px; | |
| margin-top: 0px; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name = Amazon field | |
| description = Provides a field for Amazon products. | |
| package = Amazon | |
| dependencies[] = amazon | |
| core = 7.x | |
| php = 5.2 | |
| configure = admin/structure/types |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Install, update and uninstall functions for the asin module. | |
| * | |
| */ | |
| /** | |
| * Implements of hook_install(). | |
| */ | |
| function asin_install() { | |
| } | |
| /** | |
| * Implements of hook_uninstall(). | |
| */ | |
| function asin_uninstall() { | |
| } | |
| /** | |
| * Implements hook_field_schema(). | |
| */ | |
| function asin_field_schema($field) { | |
| $columns = array( | |
| 'asin' => array('type' => 'varchar', 'length' => 32, 'not null' => FALSE) | |
| ); | |
| return array( | |
| 'columns' => $columns, | |
| ); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Defines a field type for referencing an Amazon product. | |
| */ | |
| /** | |
| * Implementation of hook_menu(). | |
| */ | |
| function asin_menu() { | |
| $items = array(); | |
| $items['asin/autocomplete'] = array( | |
| 'page callback' => 'asin_autocomplete_callback', | |
| 'access arguments' => array('access content'), | |
| 'type' => MENU_CALLBACK | |
| ); | |
| return $items; | |
| } | |
| /** | |
| * Implementation of hook_field_info(). | |
| */ | |
| function asin_field_info() { | |
| return array( | |
| 'asin' => array( | |
| 'label' => t('Amazon item'), | |
| 'description' => t('Store the id of a product listed on Amazon.com.'), | |
| 'default_widget' => 'asin_text', | |
| 'default_formatter' => 'default', | |
| ), | |
| ); | |
| } | |
| ///** | |
| // * @todo: This is the leftover from D6 hook_field. Seems that there's some | |
| // * views stuff yet to be done? | |
| // */ | |
| //function asin_field_settings($op, $field) { | |
| //// TODO: Views data stuff | |
| // $data = content_views_field_views_data($field); | |
| // $db_info = content_database_info($field); | |
| // $table_alias = content_views_tablename($field); | |
| // | |
| // // Filter: Add a 'many to one' filter. | |
| // $copy = $data[$table_alias][$field['field_name'] . '_asin']; | |
| // $copy['title'] = t('@label (!name) - Allowed values', array('@label' => $field['widget']['label'], '!name' => $field['field_name'])); | |
| // $copy['filter']['handler'] = 'views_handler_filter_many_to_one'; | |
| // unset($copy['field'], $copy['argument'], $copy['sort']); | |
| // $data[$table_alias][$field['field_name'] . '_value_many_to_one'] = $copy; | |
| // // Argument : swap the handler to the 'many to one' operator. | |
| // $data[$table_alias][$field['field_name'] . '_value']['argument']['handler'] = 'views_handler_argument_many_to_one'; | |
| // | |
| // // Add a relationship for related node. | |
| // $data[$table_alias][$field['field_name'] . '_asin']['relationship'] = array( | |
| // 'base' => 'amazon_item', | |
| // 'field' => $db_info['columns']['asin']['column'], | |
| // 'handler' => 'views_handler_relationship', | |
| // ); | |
| // return $data; | |
| //} | |
| /** | |
| * Trim spaces from the front/back of each ASIN in an array. | |
| * | |
| * @param $items | |
| * Array of ASINS | |
| * @return | |
| * Same array of ASINs, trimmed | |
| */ | |
| function _asin_trim_items(&$items) { | |
| foreach ($items as $delta => &$item) { | |
| $item = trim($item); | |
| } | |
| } | |
| /** | |
| * Implements of hook_field_is_empty(). | |
| */ | |
| function asin_field_is_empty($item, $field) { | |
| if (empty($item['asin'])) { | |
| return TRUE; | |
| } | |
| return FALSE; | |
| } | |
| /** | |
| * Implementation of hook_field_formatter_info(). | |
| */ | |
| function asin_field_formatter_info() { | |
| return array( | |
| 'default' => array( | |
| 'label' => t('Thumbnail with title'), | |
| 'field types' => array('asin'), | |
| 'multiple values' => FIELD_BEHAVIOR_DEFAULT, | |
| ), | |
| 'details' => array( | |
| 'label' => t('Thumbnail with details'), | |
| 'field types' => array('asin'), | |
| 'multiple values' => FIELD_BEHAVIOR_DEFAULT, | |
| ), | |
| 'thumbnail' => array( | |
| 'label' => t('Thumbnail image'), | |
| 'field types' => array('asin'), | |
| 'multiple values' => FIELD_BEHAVIOR_DEFAULT, | |
| ), | |
| 'medium' => array( | |
| 'label' => t('Medium image'), | |
| 'field types' => array('asin'), | |
| 'multiple values' => FIELD_BEHAVIOR_DEFAULT, | |
| ), | |
| 'large' => array( | |
| 'label' => t('Large image'), | |
| 'field types' => array('asin'), | |
| 'multiple values' => FIELD_BEHAVIOR_DEFAULT, | |
| ), | |
| 'inline' => array( | |
| 'label' => t('Link to item'), | |
| 'field types' => array('asin'), | |
| 'multiple values' => FIELD_BEHAVIOR_DEFAULT, | |
| ), | |
| ); | |
| } | |
| /** | |
| * Implements hook_field_formatter_view(). | |
| */ | |
| function asin_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) { | |
| $element = array(); | |
| foreach ($items as $delta => $value) { | |
| $asin = trim($value['asin']); | |
| if (!empty($asin)) { | |
| $lookup = amazon_item_lookup($asin); | |
| if (!empty($lookup) && $item = $lookup[$asin]) { | |
| // TODO: kill off amazon_inline_item. There's no reason for it to clutter the earth. | |
| $theme_function = $display['type'] == 'inline' ? 'amazon_inline_item' : 'amazon_item'; | |
| $element[$delta] = array('#markup' => theme($theme_function, array('item' => $item, 'style' => $display['type']))); | |
| } | |
| } | |
| } | |
| return $element; | |
| } | |
| /** | |
| * Implementation of hook_field_widget_info(). | |
| * | |
| */ | |
| function asin_field_widget_info() { | |
| return array( | |
| 'asin_text' => array( | |
| 'label' => t('Amazon ASIN Text field'), | |
| 'field types' => array('asin'), | |
| ), | |
| 'asin_autocomplete' => array( | |
| 'label' => t('Product name autocomplete'), | |
| 'field types' => array('asin'), | |
| ), | |
| ); | |
| } | |
| /** | |
| * Implements hook_field_widget_form(). | |
| * | |
| */ | |
| function asin_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $base) { | |
| $element = $base; | |
| $element['asin'] = $base + array( | |
| '#type' => 'textfield', | |
| '#default_value' => !empty($items[$delta]['asin']) ? $items[$delta]['asin'] : '', | |
| ); | |
| switch ($instance['widget']['type']) { | |
| case 'asin_text': | |
| $element['asin']['#size'] = 25; | |
| $element['asin']['#element_validate'] = array('asin_field_widget_element_validate'); | |
| break; | |
| case 'asin_autocomplete': | |
| $element['asin']['#autocomplete_path'] = 'asin/autocomplete'; | |
| $element['asin']['#value_callback'] = 'asin_autocomplete_value'; | |
| $element['asin']['#maxlength'] = 256; | |
| $element['asin']['#element_validate'][] = 'asin_autocomplete_validate'; | |
| break; | |
| } | |
| $form_state['langcode'] = $langcode; | |
| return $element; | |
| } | |
| /** | |
| * Widget validation function. | |
| * | |
| * Checks to see if we can look up an ASIN, URL, or ISBN-13 using the | |
| * provided text. If we can, it's OK and we turn it into an ASIN. | |
| * Otherwise, flag as error. | |
| */ | |
| function asin_field_widget_element_validate($element, &$form_state) { | |
| $field_name = $element['#field_name']; | |
| $langcode = $form_state['langcode']; | |
| foreach ($form_state['values'][$field_name][$langcode] as $delta => &$item) { | |
| $asin = trim(amazon_convert_to_asin($item['asin'])); | |
| if (!empty($asin) && is_numeric($delta)) { | |
| $results = amazon_item_lookup(array($asin)); | |
| if (empty($results)) { | |
| form_set_error("{$field_name}][{$langcode}][{$delta}][asin", t('No Amazon product with the ASIN "%id" could be located.', array('%id' => $asin))); | |
| } | |
| else { | |
| $item['asin'] = (string)key($results); | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * Autocomplete callback for the asin_autocomplete widget. | |
| */ | |
| function asin_autocomplete_callback($string = '') { | |
| $items = $matches = array(); | |
| // Search Amazon. | |
| $parameters = array( | |
| 'ResponseGroup' => 'Small', | |
| 'SearchIndex' => 'Blended', | |
| 'Keywords' => urlencode($string) | |
| ); | |
| $results = amazon_http_request('ItemSearch', $parameters); | |
| // Process the results. | |
| foreach($results->Items->Item as $xml) { | |
| $items[(string) $xml->ASIN] = (string) $xml->ItemAttributes->Title; | |
| } | |
| // Create our response. | |
| foreach ($items as $asin => $title) { | |
| // Add a class wrapper for a few required CSS overrides. | |
| $matches[$title . ' [asin:' . $asin . ']'] = '<div class="reference-autocomplete">'. $title . '</div>'; | |
| } | |
| drupal_json_output($matches); | |
| } | |
| /** | |
| * Validate the autocomplete widget. | |
| * | |
| * This corrects the value (we want just the ASIN, not the whole title). | |
| */ | |
| function asin_autocomplete_validate($element, &$form_state) { | |
| $value = $element['#value']; | |
| $asin = NULL; | |
| if (preg_match('!.*\[asin\:([a-zA-Z0-9]*)\]!', $value, $matches)) { | |
| $asin = $matches[1]; | |
| } | |
| else { | |
| $asin = $value; | |
| } | |
| form_set_value($element, $asin, $form_state); | |
| } | |
| /** | |
| * Implements hook_field_views_data(). | |
| * | |
| * Through this hook we're given the chance to change the views schema | |
| * data for the asin field. The primary thing to be done is to add a join | |
| * on the ASIN type to the amazon_item views base stuff. | |
| */ | |
| function asin_field_views_data($field) { | |
| $data = field_views_field_default_views_data($field); | |
| foreach ($data as $table_name => $table_data) { | |
| foreach ($table_data as $field_name => $field_data) { | |
| if (!in_array($field_name, array('table', 'entity_id', 'revision_id'))) { | |
| $data[$table_name][$field_name]['relationship'] = array( | |
| 'handler' => 'views_handler_relationship', | |
| 'base' => 'amazon_item', | |
| 'base_field' => 'asin', | |
| 'label' => t('ASIN from !field_name', array('!field_name' => $field['field_name'])), | |
| ); | |
| } | |
| } | |
| } | |
| return $data; | |
| } | |
| /** | |
| * Implementation of hook_feeds_node_processor_targets_alter(). | |
| * | |
| * @see FeedsNodeProcessor::getMappingTargets(). | |
| */ | |
| function asin_feeds_node_processor_targets_alter(&$targets, $content_type) { | |
| $info = content_types($content_type); | |
| $fields = array(); | |
| if (isset($info['fields']) && count($info['fields'])) { | |
| foreach ($info['fields'] as $field_name => $field) { | |
| if ($field['type'] == 'asin') { | |
| $fields[$field_name] = isset($field['widget']['label']) ? $field['widget']['label'] : $field_name; | |
| } | |
| } | |
| } | |
| foreach ($fields as $k => $name) { | |
| $targets[$k] = array( | |
| 'name' => $name, | |
| 'callback' => 'asin_feeds_set_target', | |
| 'description' => t('The CCK !name field of the node.', array('!name' => $name)), | |
| ); | |
| } | |
| } | |
| /** | |
| * Callback for mapping. Here is where the actual mapping happens. | |
| * | |
| * When the callback is invoked, $target contains the name of the field the | |
| * user has decided to map to and $value contains the value of the feed item | |
| * element the user has picked as a source. | |
| */ | |
| function asin_feeds_set_target($node, $target, $value) { | |
| $field = isset($node->$target) ? $node->$target : array(); | |
| // Handle multiple value fields. | |
| if (is_array($value)) { | |
| $i = 0; | |
| foreach ($value as $v) { | |
| if (!is_array($v) && !is_object($v)) { | |
| $field[$i]['asin'] = $v; | |
| } | |
| $i++; | |
| } | |
| } | |
| else { | |
| $field[0]['asin'] = $value; | |
| } | |
| $node->$target = $field; | |
| } | |
| /** | |
| * Implements hook_devel_generate(). | |
| * Callback for populating ASIN fields with devel_generate module. | |
| * | |
| * Picks a random Drupal-related book. | |
| */ | |
| function asin_devel_generate($object, $field, $instance, $bundle) { | |
| if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_CUSTOM) { | |
| return devel_generate_multiple('_asin_devel_generate', $object, $field, $instance, $bundle); | |
| } | |
| else { | |
| return _asin_devel_generate($object, $field, $instance, $bundle); | |
| } | |
| } | |
| /** | |
| * Utility function that actually provides the values for asin_devel_generate(). | |
| */ | |
| function _asin_devel_generate($object, $field, $instance, $bundle) { | |
| $asins = &drupal_static(__FUNCTION__); | |
| if (!isset($asins) || $reset) { | |
| $actions = module_invoke_all('action_info'); | |
| } | |
| $parameters = array( | |
| 'ResponseGroup' => 'ItemAttributes,EditorialReview', | |
| 'SearchIndex' => 'Blended', | |
| 'Keywords' => 'drupal' | |
| ); | |
| $asins = array(); | |
| $results = amazon_http_request('ItemSearch', $parameters); | |
| foreach ($results->Items->Item as $xml) { | |
| $asin = amazon_item_clean_xml($xml); | |
| $asins[$asin['asin']] = $asin; | |
| } | |
| $field = array(); | |
| $field['asin'] = array_rand($asins, 1); | |
| return $field; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 7.x-1.0-beta6 | |
| ============= | |
| [#987986] by dereine: Improve views title handling. | |
| [#1071902] by rfay: Catch up with Views 3 API changes and fix broken handlers | |
| 7.x-1.0-beta5 | |
| =========== | |
| [#1014036] by Pancho: First take on token support: Remove non-working code | |
| [#1060704] by Pancho: Refactor admin test form: error handling, UX and codestyle | |
| [#1060694] by Pancho: Fix asin.module's error handling | |
| [#1053340] by Pancho: Cleanup: for variable_del walk thru array instead of preg_split | |
| [#1053110] by Pancho: Cleanup: add CVS $Ids where missing | |
| [#1052622] by Pancho: Cleanup *.info-files: remove file registry, add config links | |
| [#1015260] by rfay: Fix requirements message. | |
| [#1011280] by rfay: Fix the _field_sql_storage_etid() #fail | |
| [#1014128] by jdleonard, rfay: Fix invalid conditions in amazon_item_clean_xml() | |
| [#1037168] by rfay: Fix problem with amazon_media_software_template | |
| 7.x-1.0-beta4 | |
| ============= | |
| [#758630] by rfay: Views title should link to Amazon Store. | |
| [#879830] by rfay: Make amazon price work outside US | |
| [#801896] by rfay: Editorial content is double-escaped. | |
| [#944280] by rfay: Fix watchdog PDO fatal | |
| [#959810] by fragtom, rfay: Fix admin/config menu | |
| [#971820] by davidzz: Add BOOKS_1973_AND_LATER to types handled by amazon_media | |
| by rfay: Fixed problem with "all participants" field in views | |
| [#951070] by davidzz, rfay: Make editorialreview not get key tags stripped out. | |
| [#905198] by rfay: Update to new Amazon handling of customer reviews | |
| [#983598] by rfay: Make HTML in Amazon Editorial reviews work | |
| [#984894] by rfay: Change the type of the edition field | |
| [#959766] by dereine, rfay: Fix views support of images | |
| 7.x-1.0-beta3 | |
| ============ | |
| - [#761832] followup: Sorry, I messed up a bunch of tpl.php files. | |
| 7.x-1.0-beta2 | |
| =========== | |
| - [#761832] by rfay: D7 theming doesn't work right. | |
| - [#857616] by rfay: Amazon Media module fails with database prefix turned on. | |
| 6.x-1.x-RC4 release | |
| =================== | |
| - [#671686] by rfay: Fixed Amazon module localization errors. | |
| - [#609448] by rfay: Added rel="nofollow" to detailpageurl links | |
| - [#609448] by rfay: Added Feature: Add customer reviews and ratings to Amazon information retrieved. | |
| - [#556414] by rfay, stratosgear: Provide Amazon.com price or lowest price or both. | |
| - [#697138] by robertDouglass: Added Drupal alter $params before searching in amazon_search so that modules can customize search. | |
| - [#288577] by rfay, reprise: Add 13-digit ISBN/EAN support to the admin test | |
| 6.x-1.x-RC3 release | |
| =================== | |
| - [#288577] by rfay, tirsales, mleicester: Added 13 digit ISBNs / EAN support / converting to ASINs. | |
| With this patch, both EANs (ISBN-13) and Amazon.com/co.uk/de, etc. links can be used in | |
| either a CCK field or an Amazon filter. Also, hyphens are ignored in the input, so you can | |
| use a classically formatted ISBN-10 or ISBN-13. | |
| - [#679860] by rfay: User with 'administer amazon' permissions can not access ./admin/settings/amazon/test. | |
| - [#350320] by rfay: Fix Display of &amp; (and possibly other special chars) isn't handled correctly. (Again) | |
| - [#231612] by rfay: Fix upgrade path from D5 ASIN module. Also add upgrade path | |
| for AAT links and amazon nodes (which are the same thing) | |
| - [#608784] by rfay: Better filter tips in amazon_filter module. | |
| - [#590360] by rfay: Postgresql compatibility fix. | |
| 6.x-1.x-RC2 release | |
| ===================== | |
| - #661560 by rfay: PHP 5.3 compatibility fix | |
| - #660670 by rfay: Remove option of using author's Amazon associate ID. | |
| - #609388 by rfay: Make Amazon item title sortable in views, check other fields. | |
| - #622076 by rfay: invalid_asin filter should be a boolean filter or at least numeric. | |
| - #608782 by rfay: hook_update_6006() needs to use db_add_field() not db_add_column(). | |
| - #608780 by rfay: hook_uninstall() does not uninstall all schemas and variables. | |
| - #392576 by rfay: Partial data retrieved but with error mysqli_real_escape_string() expects parameter 2 to be string, array is SOME products. | |
| - #659728 by rfay: Move active development to HEAD | |
| - #608624 by rfay: Test should detect and report invalid credentials. Also now detects system time problems, etc. | |
| - #622418 by rfay: Remove the option of not storing amazon data locally. | |
| 18 October 2009: BETA-10 release | |
| ================================ | |
| - Minor changes to fix issues encountered during documentation and test of BETA-9 | |
| 18 October 2009: BETA-9 release (Beta-8 had a problem and had to be replaced) | |
| =============================== | |
| - #278034 by iva2k - Fix node-view CSS when there is more than one ASIN field | |
| - Add views handling for Amazon images, including linking. | |
| - #543990 by rfay - Fix bug where save didn't include Amazon database update | |
| - #353285 - Remove "NOT NULL" from database definition where Amazon might in fact not return information. | |
| - Added delete of amazon_item when related node is deleted. | |
| - #350320 - Allow HTML in title of Amazon item | |
| - #326963 by bangpound: Correct return values in hook_field() | |
| - #494648: Filtering by the contents of the ASIN field didn't work | |
| - #362884 by tomiyana: Change detailpageurl to TEXT because of long Japanes detailpageurls | |
| - amazon.module function documentation. | |
| - Improve consistency of data insert by always deleting item before insert. | |
| - #288119: Trim whitespace from ASIN in CCK field. | |
| - #437158: Date-related items are now supported in views as dates. | |
| - #510432: Make amazon_inline_item get preprocessed | |
| - #511008: Track and handle invalid ASINs. We now mark them as invalid_asin | |
| in the amazon_item table, and some of the tpl.php files make note | |
| of this. The invalid_asin is also available via views. | |
| - #598588: Many new filters are now available through [amazon ASIN detail]. | |
| Everything that is preprocessed in amazon_preprocess_amazon_item() | |
| is available for use. For example, [amazon 0596515804 detailpageurl] | |
| - #595980: Added a demonstration module (requires features module) that provides | |
| a CCK type and a view. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| There is a vast array of theming possibility with Amazon and the Amazon Media | |
| module. | |
| Most of the theming is done with .tpl.php files. You can copy these .tpl.php | |
| files into your theme and modify them: | |
| amazon-inline-item.tpl.php a simple text link | |
| amazon-item-details.tpl.php an item with detail info | |
| amazon-item-detail.tpl.php a single detail (for amazon_filter) | |
| amazon-item-thumbnail.tpl.php a thumbnail image | |
| amazon-item--large.tpl.php a large image | |
| amazon-item--medium.tpl.php a medium image | |
| amazon-item.tpl.php an item with less detail | |
| amazon-views-view-row-item.tpl.php a views row | |
| In addition, "theme hook suggestions" are provided for both amazon-item and | |
| amazon-inline-item. For an amazon-item, you can theme it with a template | |
| flle named amazon-item--<type>--<style>, so you could separately theme | |
| large DVD images with a template file amazon-item--dvd--large.tpl.php in your | |
| theme. | |
| The amazon_media module, if enabled, extends theming capabilities with a number | |
| of its own template files and a few template functions. You can override those | |
| as well. | |
| In most cases an overwhelming number of variables is available in the template | |
| file. See template_preprocess_amazon_item() in amazon.module for more | |
| information. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * A handler to provide proper displays for dates. | |
| * | |
| * @ingroup views_field_handlers | |
| */ | |
| class views_handler_field_amazon_date extends views_handler_field_date { | |
| function options_form(&$form, &$form_state) { | |
| parent::options_form($form, $form_state); | |
| $time = REQUEST_TIME; | |
| $form['date_format']['#options'] = array( | |
| 'default' => format_date($time, 'custom', 'Y-m-d'), | |
| 'custom' => t('Custom'), | |
| ); | |
| } | |
| function render($values) { | |
| $value = strtotime($this->get_value($values)); | |
| $format = $this->options['date_format']; | |
| $default_format = 'Y-m-d'; | |
| if (in_array($format, array('custom', 'raw time ago', 'time ago', 'raw time span', 'time span'))) { | |
| $custom_format = $this->options['custom_date_format']; | |
| } | |
| if (!$value) { | |
| return theme('views_nodate'); | |
| } | |
| else { | |
| $time_diff = REQUEST_TIME - $value; // will be positive for a datetime in the past (ago), and negative for a datetime in the future (hence) | |
| switch ($format) { | |
| case 'custom': | |
| return format_date($value, $format, $custom_format); | |
| default: | |
| return format_date($value, 'custom', $default_format); | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @file | |
| * Provide views handler so that Amazon Image can be displayed in the various | |
| * ways that are available. | |
| * | |
| * @author rfay | |
| * | |
| */ | |
| class views_handler_field_amazon_image extends views_handler_field { | |
| function option_definition() { | |
| $options = parent::option_definition(); | |
| $options['image_size'] = array('default' => 'smallimage'); | |
| $options['link_format'] = array('default' => 'amazon'); | |
| $options['presentation_format'] = array('default' => 'markup'); | |
| return $options; | |
| } | |
| /** | |
| * Override init function to provide generic option to link to node. | |
| */ | |
| function init(&$view, &$data) { | |
| parent::init($view, $data); | |
| if (!empty($data['image_size'])) { | |
| $this->additional_fields['height'] = 'height'; | |
| $this->additional_fields['width'] = 'width'; | |
| } | |
| if (!empty($data['link_format']) && $data['link_format'] == 'amazon') { | |
| $this->additional_fields['detailpageurl'] = array( | |
| 'table' => 'amazon_item', 'field' => 'detailpageurl', 'value' => 'amazon_item_detailpageurl' | |
| ); | |
| } | |
| $this->additional_fields['asin'] = 'asin'; | |
| $this->additional_fields['url'] = 'url'; | |
| } | |
| function ensure_my_table() { | |
| if (empty($this->table_alias)) { | |
| $join_extra = array(); | |
| if (!empty($this->options['image_size'])) { | |
| $join_extra[] = array('field' => 'size', 'value' => $this->options['image_size'], 'numeric' => FALSE); | |
| } | |
| $join = new views_join(); | |
| $join->construct($this->table, 'amazon_item', 'asin', 'asin', $join_extra); | |
| $this->table_alias = $this->query->ensure_table($this->table, $this->relationship, $join); | |
| } | |
| return $this->table_alias; | |
| } | |
| /** | |
| * Provide link to node option | |
| */ | |
| function options_form(&$form, &$form_state) { | |
| parent::options_form($form, $form_state); | |
| $form['image_size'] = array( | |
| '#title' => t('Image size'), | |
| '#type' => 'select', | |
| '#options' => array( | |
| 'smallimage' => t('Small'), | |
| 'mediumimage' => t("Medium"), | |
| 'largeimage' => t("Large"), | |
| ), | |
| '#default_value' => !empty($this->options['image_size']) ? $this->options['image_size'] : 'MedumImage', | |
| ); | |
| $form['link_format'] = array( | |
| '#title' => t('Link behavior'), | |
| '#type' => 'radios', | |
| '#options' => array( | |
| 'plain' => t('No link'), | |
| 'amazon' => t("A link to the product's Amazon page"), | |
| ), | |
| '#default_value' => !empty($this->options['link_format']) ? $this->options['link_format'] : 'plain', | |
| ); | |
| if (module_exists('amazon_store')) { | |
| $form['link_format']['#options']['amazon_store'] = t("A link to the product's Amazon Store page (Amazon Store Module)"); | |
| } | |
| $form['presentation_format'] = array( | |
| '#title' => t('Presentation format'), | |
| '#type' => 'select', | |
| '#options' => array( | |
| 'markup' => t('HTML img markup'), | |
| 'plain_url' => t('Plain URL to image'), | |
| ), | |
| '#default_value' => !empty($this->options['presentation_format']) ? $this->options['presentation_format'] : 'markup', | |
| ); | |
| } | |
| function render($values) { | |
| $url = $this->get_value($values, 'url'); | |
| $detailpageurl = $this->get_value($values, 'detailpageurl'); | |
| $asin = $this->get_value($values, 'asin'); | |
| // We may not have a URL. It's not guaranteed that Amazon will give us one. | |
| if (empty($url)) { | |
| return; | |
| } | |
| $attributes = array( | |
| 'height' => $this->get_value($values, 'height'), | |
| 'width' => $this->get_value($values, 'width'), | |
| ); | |
| // Choose presentation style | |
| if ($this->options['presentation_format'] == 'markup') { | |
| $image = theme('image', array('path' => $url, 'alt' => NULL, 'title' => NULL, 'attributes' => $attributes, 'getsize' => FALSE)); | |
| } | |
| else { | |
| $image = $url; | |
| } | |
| switch ($this->options['link_format']) { | |
| case 'plain': | |
| return $image; | |
| break; | |
| case 'amazon': | |
| if (!empty($detailpageurl)) { | |
| return l($image, $detailpageurl, array('html' => TRUE)); | |
| } | |
| else { | |
| return $image; | |
| } | |
| break; | |
| case 'amazon_store': | |
| return l($image, 'amazon_store/item/' . $asin, array('html' => TRUE)); | |
| break; | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| class views_handler_field_amazon_participant extends views_handler_field_prerender_list { | |
| function construct() { | |
| parent::construct(); | |
| $this->additional_fields['asin'] = array('table' => 'amazon_item', 'field' => 'asin'); | |
| } | |
| /** | |
| * Provide meaningful defaults | |
| */ | |
| function options(&$options) { | |
| parent::options($options); | |
| $options['participant_type'] = '**ALL**'; | |
| } | |
| /** | |
| * Provide "link to term" option. | |
| */ | |
| function options_form(&$form, &$form_state) { | |
| parent::options_form($form, $form_state); | |
| $form['participant_type'] = array( | |
| '#type' => 'select', | |
| '#title' => t('Participant restriction'), | |
| '#options' => array( | |
| '**ALL**' => t('Show all participants'), | |
| 'author' => t('Author'), | |
| 'artist' => t('Artist'), | |
| 'actor' => t('Actor'), | |
| 'director' => t('Director'), | |
| 'creator' => t('Creator'), | |
| ), | |
| '#default_value' => $this->options['participant_type'], | |
| ); | |
| } | |
| function query() { | |
| $this->add_additional_fields(); | |
| } | |
| function pre_render($values) { | |
| $this->field_alias = $this->aliases['asin']; | |
| $this->items = array(); | |
| $asins = array(); | |
| foreach ($values as $result) { | |
| $asin = $this->get_value($values, 'asin'); | |
| if (!empty($asin)) { | |
| $asins[] = $asin; | |
| } | |
| } | |
| $query = db_select('amazon_item_participant', 'aip') | |
| ->condition('asin', $asins, 'IN'); | |
| if ($this->options['participant_type'] != '**ALL**') { | |
| $query = $query->condition('type', $this->options['participant_type']); | |
| } | |
| $query->fields('aip', array('participant', 'asin')); | |
| $results = $query->execute(); | |
| while ($record = $results->fetchAssoc()) { | |
| $this->items[$record['asin']][] = check_plain($record['participant']); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| class views_handler_field_amazon_title extends views_handler_field { | |
| function option_definition() { | |
| $options = parent::option_definition(); | |
| $options['link_format'] = array('default' => 'amazon'); | |
| return $options; | |
| } | |
| /** | |
| * Override init function to provide generic option to link to node. | |
| */ | |
| function init(&$view, &$data) { | |
| parent::init($view, $data); | |
| if (!empty($data['link_format']) && $data['link_format'] == 'amazon') { | |
| $this->additional_fields['detailpageurl'] = 'detailpageurl'; | |
| } | |
| $this->additional_fields['asin'] = 'asin'; | |
| } | |
| /** | |
| * Provide link options. | |
| */ | |
| function options_form(&$form, &$form_state) { | |
| parent::options_form($form, $form_state); | |
| $form['link_format'] = array( | |
| '#title' => t('Link behavior'), | |
| '#type' => 'radios', | |
| '#options' => array( | |
| 'plain' => t('No link'), | |
| 'amazon' => t("A link to the product's Amazon page"), | |
| ), | |
| '#default_value' => !empty($this->options['link_format']) ? $this->options['link_format'] : 'plain', | |
| ); | |
| if (module_exists('amazon_store')) { | |
| $form['link_format']['#options']['amazon_store'] = t("A link to the product's Amazon Store page (Amazon Store Module)"); | |
| } | |
| } | |
| function render($values) { | |
| $value = $this->get_value($values); | |
| return $this->render_link($this->sanitize_value($value, 'xss'), $values); | |
| } | |
| function render_link($title, $values) { | |
| switch ($this->options['link_format']) { | |
| case 'plain': | |
| break; | |
| case 'amazon': | |
| $this->options['alter']['make_link'] = TRUE; | |
| $this->options['alter']['path'] = $this->sanitize_value($this->get_value($values, 'detailpageurl'), 'link'); | |
| $this->options['alter']['html'] = TRUE; | |
| break; | |
| case 'amazon_store': | |
| $this->options['alter']['make_link'] = TRUE; | |
| $this->options['alter']['html'] = TRUE; | |
| $asin = $this->get_value($values, 'asin'); | |
| $this->options['alter']['path'] = 'amazon_store/item/' . $asin; | |
| break; | |
| } | |
| return $title; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * @defgroup views_field_handlers Views' field handlers | |
| * @{ | |
| * Handlers to tell Views how to build and display fields. | |
| * | |
| */ | |
| /** | |
| * A handler to run a field through simple XSS filtering | |
| */ | |
| class views_handler_field_amazon_xss extends views_handler_field { | |
| function render($values) { | |
| $value = $this->get_value($values); | |
| return filter_xss_admin($value); | |
| } | |
| } | |
| /** | |
| * @} | |
| */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| Filter node-linked amazom products by source module | |
| */ | |
| class views_handler_filter_amazon_node_module extends views_handler_filter_in_operator { | |
| function construct() { | |
| parent::construct(); | |
| $this->value_title = t('Source module'); | |
| $options = array(); | |
| $result = db_query("SELECT DISTINCT ain.module FROM {amazon_item_node} ain"); | |
| while ($module = db_fetch_array($result)) { | |
| $options[$module['module']] = $module['module']; | |
| } | |
| $this->value_options = $options; | |
| } | |
| function options(&$options) { | |
| parent::options($options); | |
| $result = db_query("SELECT DISTINCT ain.module FROM {amazon_item_node} ain"); | |
| $module = db_fetch_array($result); | |
| $options['value'] = array($module['module']); | |
| } | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Basic textfield filter to handle string filtering commands | |
| * including equality, like, not like, etc. | |
| */ | |
| class views_handler_filter_string_compare extends views_handler_filter { | |
| // exposed filter options | |
| var $no_single = TRUE; | |
| function option_definition() { | |
| $options = parent::option_definition(); | |
| $options['case'] = array('default' => TRUE); | |
| return $options; | |
| } | |
| /** | |
| * This kind of construct makes it relatively easy for a child class | |
| * to add or remove functionality by overriding this function and | |
| * adding/removing items from this array. | |
| */ | |
| function operators() { | |
| $operators = array( | |
| '=' => array( | |
| 'title' => t('Is equal to'), | |
| 'short' => t('='), | |
| 'method' => 'op_equal', | |
| 'values' => 1, | |
| ), | |
| '!=' => array( | |
| 'title' => t('Is not equal to'), | |
| 'short' => t('!='), | |
| 'method' => 'op_equal', | |
| 'values' => 1, | |
| ), | |
| '<' => array( | |
| 'title' => t('Is less than'), | |
| 'short' => t('!='), | |
| 'method' => 'op_equal', | |
| 'values' => 1, | |
| ), | |
| '>' => array( | |
| 'title' => t('Is greater than'), | |
| 'short' => t('!='), | |
| 'method' => 'op_equal', | |
| 'values' => 1, | |
| ), | |
| 'contains' => array( | |
| 'title' => t('Contains'), | |
| 'short' => t('contains'), | |
| 'method' => 'op_contains', | |
| 'values' => 1, | |
| ), | |
| 'word' => array( | |
| 'title' => t('Contains any word'), | |
| 'short' => t('has word'), | |
| 'method' => 'op_word', | |
| 'values' => 1, | |
| ), | |
| 'allwords' => array( | |
| 'title' => t('Contains all words'), | |
| 'short' => t('has all'), | |
| 'method' => 'op_word', | |
| 'values' => 1, | |
| ), | |
| 'starts' => array( | |
| 'title' => t('Starts with'), | |
| 'short' => t('begins'), | |
| 'method' => 'op_starts', | |
| 'values' => 1, | |
| ), | |
| 'ends' => array( | |
| 'title' => t('Ends with'), | |
| 'short' => t('ends'), | |
| 'method' => 'op_ends', | |
| 'values' => 1, | |
| ), | |
| 'not' => array( | |
| 'title' => t('Does not contain'), | |
| 'short' => t('!has'), | |
| 'method' => 'op_not', | |
| 'values' => 1, | |
| ), | |
| ); | |
| // if the definition allows for the empty operator, add it. | |
| if (!empty($this->definition['allow empty'])) { | |
| $operators += array( | |
| 'empty' => array( | |
| 'title' => t('Is empty (NULL)'), | |
| 'method' => 'op_empty', | |
| 'short' => t('empty'), | |
| 'values' => 0, | |
| ), | |
| 'not empty' => array( | |
| 'title' => t('Is not empty (NULL)'), | |
| 'method' => 'op_empty', | |
| 'short' => t('not empty'), | |
| 'values' => 0, | |
| ), | |
| ); | |
| } | |
| return $operators; | |
| } | |
| /** | |
| * Build strings from the operators() for 'select' options | |
| */ | |
| function operator_options($which = 'title') { | |
| $options = array(); | |
| foreach ($this->operators() as $id => $info) { | |
| $options[$id] = $info[$which]; | |
| } | |
| return $options; | |
| } | |
| function admin_summary() { | |
| if (!empty($this->options['exposed'])) { | |
| return t('exposed'); | |
| } | |
| $options = $this->operator_options('short'); | |
| $output = check_plain($options[$this->operator]); | |
| if (in_array($this->operator, $this->operator_values(1))) { | |
| $output .= ' ' . check_plain($this->value); | |
| } | |
| return $output; | |
| } | |
| function options_form(&$form, &$form_state) { | |
| parent::options_form($form, $form_state); | |
| $form['case'] = array( | |
| '#type' => 'checkbox', | |
| '#title' => t('Case sensitive'), | |
| '#default_value' => $this->options['case'], | |
| '#description' => t('Case sensitive filters may be faster. MySQL might ignore case sensitivity.'), | |
| ); | |
| } | |
| function operator_values($values = 1) { | |
| $options = array(); | |
| foreach ($this->operators() as $id => $info) { | |
| if (isset($info['values']) && $info['values'] == $values) { | |
| $options[] = $id; | |
| } | |
| } | |
| return $options; | |
| } | |
| /** | |
| * Provide a simple textfield for equality | |
| */ | |
| function value_form(&$form, &$form_state) { | |
| // We have to make some choices when creating this as an exposed | |
| // filter form. For example, if the operator is locked and thus | |
| // not rendered, we can't render dependencies; instead we only | |
| // render the form items we need. | |
| $which = 'all'; | |
| if (!empty($form['operator'])) { | |
| $source = ($form['operator']['#type'] == 'radios') ? 'radio:options[operator]' : 'edit-options-operator'; | |
| } | |
| if (!empty($form_state['exposed'])) { | |
| $identifier = $this->options['expose']['identifier']; | |
| if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator'])) { | |
| // exposed and locked. | |
| $which = in_array($this->operator, $this->operator_values(1)) ? 'value' : 'none'; | |
| } | |
| else { | |
| $source = 'edit-' . form_clean_id($this->options['expose']['operator']); | |
| } | |
| } | |
| if ($which == 'all' || $which == 'value') { | |
| $form['value'] = array( | |
| '#type' => 'textfield', | |
| '#title' => t('Value'), | |
| '#size' => 30, | |
| '#default_value' => $this->value, | |
| ); | |
| if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier])) { | |
| $form_state['input'][$identifier] = $this->value; | |
| } | |
| if ($which == 'all') { | |
| $form['value'] += array( | |
| '#process' => array('views_process_dependency'), | |
| '#dependency' => array($source => $this->operator_values(1)), | |
| ); | |
| } | |
| } | |
| if (!isset($form['value'])) { | |
| // Ensure there is something in the 'value'. | |
| $form['value'] = array( | |
| '#type' => 'value', | |
| '#value' => NULL | |
| ); | |
| } | |
| } | |
| function case_transform() { | |
| return !empty($this->options['case']) ? '' : 'UPPER'; | |
| } | |
| /** | |
| * Add this filter to the query. | |
| * | |
| * Due to the nature of fapi, the value and the operator have an unintended | |
| * level of indirection. You will find them in $this->operator | |
| * and $this->value respectively. | |
| */ | |
| function query() { | |
| $this->ensure_my_table(); | |
| $field = "$this->table_alias.$this->real_field"; | |
| $upper = $this->case_transform(); | |
| $info = $this->operators(); | |
| if (!empty($info[$this->operator]['method'])) { | |
| $this->{$info[$this->operator]['method']}($field, $upper); | |
| } | |
| } | |
| function op_equal($field, $upper) { | |
| // operator is either = or != | |
| $this->query->add_where($this->options['group'], "$upper(%s) $this->operator $upper('%s')", $field, $this->value); | |
| } | |
| function op_contains($field, $upper) { | |
| $this->query->add_where($this->options['group'], "$upper(%s) LIKE $upper('%%%s%%')", $field, $this->value); | |
| } | |
| function op_word($field, $upper) { | |
| $where = array(); | |
| preg_match_all('/ (-?)("[^"]+"|[^" ]+)/i', ' ' . $this->value, $matches, PREG_SET_ORDER); | |
| foreach ($matches as $match) { | |
| $phrase = false; | |
| // Strip off phrase quotes | |
| if ($match[2][0] == '"') { | |
| $match[2] = substr($match[2], 1, -1); | |
| $phrase = true; | |
| } | |
| $words = trim($match[2], ',?!();:-'); | |
| $words = $phrase ? array($words) : preg_split('/ /', $words, -1, PREG_SPLIT_NO_EMPTY); | |
| foreach ($words as $word) { | |
| $where[] = "$upper(%s) LIKE $upper('%%%s%%')"; | |
| $values[] = $field; | |
| $values[] = trim($word, " ,!?"); | |
| } | |
| } | |
| if (!$where) { | |
| return; | |
| } | |
| if ($this->operator == 'word') { | |
| $where = '(' . implode(' OR ', $where) . ')'; | |
| } | |
| else { | |
| $where = implode(' AND ', $where); | |
| } | |
| // previously this was a call_user_func_array but that's unnecessary | |
| // as views will unpack an array that is a single arg. | |
| $this->query->add_where($this->options['group'], $where, $values); | |
| } | |
| function op_starts($field, $upper) { | |
| $this->query->add_where($this->options['group'], "$upper(%s) LIKE $upper('%s%%')", $field, $this->value); | |
| } | |
| function op_ends($field, $upper) { | |
| $this->query->add_where($this->options['group'], "$upper(%s) LIKE $upper('%%%s')", $field, $this->value); | |
| } | |
| function op_not($field, $upper) { | |
| $this->query->add_where($this->options['group'], "$upper(%s) NOT LIKE $upper('%%%s%%')", $field, $this->value); | |
| } | |
| function op_empty($field) { | |
| if ($this->operator == 'empty') { | |
| $operator = "IS NULL"; | |
| } | |
| else { | |
| $operator = "IS NOT NULL"; | |
| } | |
| $this->query->add_where($this->options['group'], "$field $operator"); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment