_Amazon = new AMZSCAmazon();
}
/**
* Generates a new showcase and adds it to the list
*
* @return string Identifier of newly created showcase
*/
function AddNewShowcase() {
// Create new Showcase object
$showcase = new AMZSCShowcase();
$showcaseIdentifier = $showcase->GetIdentifier();
// Add it to the list of existing showcases
$this->_showcases[$showcaseIdentifier] = $showcase;
$this->Save();
return $showcaseIdentifier;
}
/**
* Creates a new showcase with default values and saves to the database.
* Outputs HTML to be appended to options panel
*/
function AjaxAddShowcase() {
$showcaseIdentifier = $this->AddNewShowcase();
die($this->_showcases[$showcaseIdentifier]->ShowcaseOptionsFormHtml());
}
/**
* Creates a new showcase item with default values and saves to the database.
* Outputs HTML to be appended to options panel
*
* @param string $showcaseIdentifier
*/
function AjaxAddShowcaseItem($showcaseIdentifier = null) {
if (!$showcaseIdentifier) { return 0; }
$itemIdentifier = $this->_showcases[$showcaseIdentifier]->AddItem();
$this->Save();
die($this->_showcases[$showcaseIdentifier]->ItemOptionsFormHtml($itemIdentifier));
}
/**
* Generates a preview of an Amazon Item and displays. Used for ajax calls
*
* @param mixed $asin
*/
function AjaxGenerateItemPreview($asin) {
// Do some minor cleanup on the asin
$asin = AMZSCShowcase::CleanAsin($asin);
$amazonData = $this->_Amazon->GetItems(array($asin));
if (isset($amazonData[$asin]['images']['thumbnail']['url'])) {
die(' ');
} else {
die('Thumbnail preview not available. Sorry!');
}
}
/**
* Removes a showcase completely.
*
* @param string $identifier
*/
function AjaxRemoveShowcase($identifier = null) {
if (!$identifier) { return 0; }
// Remove the showcase
unset($this->_showcases[$identifier]);
$this->Save();
}
/**
* Removes a showcase item completely.
*
* @param string $showcaseIdentifier
* @param string $itemIdentifier
*/
function AjaxRemoveShowcaseItem($showcaseIdentifier = null, $itemIdentifier= null) {
if (!$showcaseIdentifier || !$itemIdentifier) { return 0; }
// Remove the showcase item
$this->_showcases[$showcaseIdentifier]->RemoveItem($itemIdentifier);
$this->Save();
}
/**
* Displays the options page
*/
function DisplayOptionsPage() {
$this->Initiate();
if (!empty($_POST['amzshcs_form_action']) && $_POST['amzshcs_form_action'] == 'update') {
if (isset($_POST['amzshcs']['showcases'])) {
foreach ($_POST['amzshcs']['showcases'] as $identifier => $showcase) {
$this->_showcases[$identifier]->SetOptions($showcase);
$this->_showcases[$identifier]->UpdateShowcaseAmazonData();
}
$this->Save();
}
}
$postUrl = $this->GetPostUrl();
?>
_showcases[$showcaseIdentifier])) {
echo $this->_showcases[$showcaseIdentifier]->ShowcaseHTML();
}
}
/**
* Displays a showcase as a widget
*
*/
function DisplayWidget($args, $showcaseIdentifier) {
extract($args);
echo $before_widget;
if (!empty($this->_showcases[$showcaseIdentifier])) {
echo $before_title . $this->_showcases[$showcaseIdentifier]->GetName() . $after_title;
echo $this->_showcases[$showcaseIdentifier]->ShowcaseHTML();
}
echo $after_widget;
}
/**
* Enables Amazon Showcase and registers all appropriate WordPress hooks
*/
function Enable() {
if (!isset($GLOBALS['AmazonShowcase'])) {
$GLOBALS['AmazonShowcase'] = new AmazonShowcase();
$GLOBALS['AmazonShowcase']->Initiate();
// Hook for adding settings menus
add_action('admin_menu', array(&$GLOBALS['AmazonShowcase'], 'RegisterOptionsPage'));
// Filter for post content
add_filter('the_content', array(&$GLOBALS['AmazonShowcase'], 'ParseContent'));
// Register Widgets
$GLOBALS['AmazonShowcase']->RegisterShowcaseWidgets();
}
}
/*
Check the item's cache:
- If the cache is recent, use it
- If the cache is out dated, query Amazon and update cache with results
Forcing update
- Query amazon and update cache with fresh data
On preview - force cache update
On showcase save - update entire showcase
If missing data, attempt to query Amazon for fresh data
*/
/**
* Utility function for determining the URL for posting forms to
*
* @return string
*/
function GetPostUrl() {
$page = basename(__FILE__);
if (!empty($_GET['page'])) {
$page = preg_replace('[^a-zA-Z0-9\.\_\-]', '', $_GET['page']);
}
return $_SERVER['PHP_SELF'] . "?page=" . $page;
}
/**
* Initiates the plugin and loads options
*/
function Initiate() {
if (!$this->_initiated) {
// Load Amazon Showcase data from the database
$options = get_option('amzshcs');
if ($options && is_array($options)) {
foreach ($options['showcases'] as $showcaseIdentifier => $showcase) {
$this->_showcases[$showcaseIdentifier] = new AMZSCShowcase($showcaseIdentifier);
}
}
$this->_initiated = true;
}
}
/**
* Parses post content looking for showcase tags. Replaces found showcase tags
* with showcase HTML
*
* @param string $content
* @return string
*/
function ParseContent($content = null) {
$this->Initiate();
if (!empty($this->_showcases)) {
preg_match_all('/\[amazonshowcase_(.*?)\]/i', $content, $matches, PREG_PATTERN_ORDER);
foreach ($matches[1] as $showcaseIdentifier) {
if (isset($this->_showcases[$showcaseIdentifier])) {
$content = str_replace('[amazonshowcase_'.$showcaseIdentifier.']', $this->_showcases[$showcaseIdentifier]->ShowcaseHTML(), $content);
}
}
}
return $content;
}
/**
* Adds the options page in the admin menu
*/
function RegisterOptionsPage() {
if (function_exists('add_options_page')) {
add_options_page(__('Amazon Showcase', 'amazonshowcase'), __('Amazon Showcase', 'amazonshowcase'), 'administrator', basename(__FILE__), array(&$this, 'DisplayOptionsPage'));
}
}
/**
* Creates a widget for each showcase
*
*/
function RegisterShowcaseWidgets() {
if (function_exists('register_sidebar_widget')) {
foreach ($this->_showcases as $showcase) {
register_sidebar_widget($showcase->GetName(), array(&$GLOBALS['AmazonShowcase'], 'DisplayWidget'), $showcase->GetIdentifier());
}
}
}
/**
* Save Amazon Showcase data to the database
*
* @return bool
*/
function Save() {
$options = array();
foreach ($this->_showcases as $showcase) {
$options['showcases'][$showcase->GetIdentifier()] = $showcase->GetOptionsArray();
};
return update_option("amzshcs", $options);
}
}
class AMZSCAmazon {
var $_AWSAccessKeyId = '1YNZ339ZCHHAKYFSY702';
var $_AssociateId = 'amazonshowcase-20';
/**
* Sends http request to Amazon web service and parses response into tidy array
*
* @param array $asins
* @param string $associateId
* @param string $locale
* @return array Items
*/
function GetItems($asins = array(), $associateId = null, $locale = 'us') {
$items = array();
// We batch the items into groups of 10 because that is the maxiumum numbers of ASINs
// that can be queried at once.
$asinBatches = array_chunk($asins, 10);
foreach ($asinBatches as $asinBatch) {
if ($xml = $this->ItemSearch($asinBatch, $associateId, $locale)) {
$itemData = $this->ParseXml($xml);
foreach ($itemData as $asin => $data) { // Would use array_merge here, but numeric asins are reindexed
$items[$asin] = $data;
}
}
}
return $items;
}
/**
* Sends http request to Amazon web service
*
* @param array $asins
* @param string $associateId
* @param string $locale
* @return xml Amazon API Response
*/
function ItemSearch($asins = array(), $associateId = null, $locale = 'us') {
if (is_array($asins) && !empty($asins)) {
//Set the values for some of the parameters.
$operation = "ItemLookup";
$version = "2008-08-19";
$responseGroup = "Small,Images";
$associateId = empty($associateId) ? $this->_AssociateId : $associateId;
switch ($locale) {
case 'uk': $base = 'http://ecs.amazonaws.co.uk/onca/xml'; break;
case 'de': $base = 'http://ecs.amazonaws.de/onca/xml'; break;
case 'jp': $base = 'http://ecs.amazonaws.co.jp/onca/xml'; break;
case 'fr': $base = 'http://ecs.amazonaws.fr/onca/xml'; break;
case 'ca': $base = 'http://ecs.amazonaws.ca/onca/xml'; break;
default: $base = 'http://ecs.amazonaws.com/onca/xml'; break;
}
//Define the request
$request = $base
. "?Service=AWSECommerceService"
. "&AssociateTag=" . $associateId
. "&AWSAccessKeyId=" . $this->_AWSAccessKeyId
. "&Operation=" . $operation
. "&Version=" . $version
. "&ItemId=" . urlencode(implode(',', $asins))
. "&ResponseGroup=" . $responseGroup;
//Catch the response in the $response object
$response = getUrl($request);
return $response;
}
return false;
}
/**
* Parses Amazon API response XML into tidy array
*
* @param string $xml
* @return array Items
*/
function ParseXml($xml) {
$items = array();
preg_match_all("/- (.*?)<\/Item>/", $xml, $itemMatches, PREG_SET_ORDER);
foreach ($itemMatches as $itemMatch) {
// ASIN
preg_match("/
(.*?)<\/ASIN>/", $itemMatch[1], $matches);
$asin = $matches[1];
// URL
preg_match("/(.*?)<\/DetailPageURL>/", $itemMatch[1], $matches);
$url = $matches[1];
// Title
preg_match("/(.*?)<\/Title>/", $itemMatch[1], $matches);
$title = $matches[1];
// Authors
$authors = array();
$authorMatches = array();
preg_match_all("/<(Author|Creator Role=\"Editor\")>(.*?)<\/(Author|Creator)>/", $itemMatch[1], $authorMatches, PREG_SET_ORDER);
foreach ($authorMatches as $authorMatch) {
$authors[] = $authorMatch[2];
}
// Images
preg_match("/(.*?)<\/ImageSet>/", $itemMatch[1], $imageSetMatches, PREG_OFFSET_CAPTURE);
if (isset($imageSetMatches[1][0])) {
$images = array();
$imageMatches = array();
preg_match_all("/<(\w+)Image>(.*?)<\/(\w+)Image>/", $imageSetMatches[1][0], $imageMatches, PREG_SET_ORDER);
foreach ($imageMatches as $imageMatch) {
if (!isset($images[strtolower($imageMatch[1])])) {
// URL
preg_match("/(.*?)<\/URL>/", $imageMatch[2], $matches);
$imageUrl = $matches[1];
// Height
preg_match("/(.*?)<\/Height>/", $imageMatch[2], $matches);
$height = $matches[1];
// Width
preg_match("/(.*?)<\/Width>/", $imageMatch[2], $matches);
$width = $matches[1];
$images[strtolower($imageMatch[1])] = array(
'url' => $imageUrl,
'height' => $height,
'width' => $width
);
}
}
}
$items[strtolower($asin)] = array(
'title' => $title,
'author' => $authors,
'url' => $url,
'images' => $images
);
}
return $items;
}
}
class AMZSCShowcase {
var $_Amazon = null;
var $_identifier = '';
var $_name = 'New Showcase';
var $_locale = 'us';
var $_associateId = '';
var $_displayNum = 0;
var $_sortMethod = 'normal';
var $_items = array();
var $_defaultItemTemplate = '';
var $_defaultShowcaseTemplate = '[showcaseItems]
';
/**
* Generates a new item and adds it to the showcase
*
*/
function AddItem() {
$item = array(
'identifier' => $this->GenerateIdentifier(),
'asin' => '',
'imageSize' => 'small',
'template' => '',
);
$this->_items[$item['identifier']] = $item;
return $item['identifier'];
}
/**
* Initializes a Showcase object
*
* @param string $showcaseIdentifier Identifier of the Showcase to be loaded
*/
function AMZSCShowcase($showcaseIdentifier = null) {
$this->_Amazon = new AMZSCAmazon();
if (!$showcaseIdentifier) {
$this->_identifier = $this->GenerateIdentifier();
} else {
$this->_identifier = $showcaseIdentifier;
$this->LoadOptions();
}
}
/**
* Cleans up an ASIN in preparation for an API call
*
* @param string $asin ASIN to be cleaned
* @return string Cleaned ASIN
*/
function CleanAsin($asin) {
$asin = str_replace('-', '', $asin);
$asin = str_replace(' ', '', $asin);
$asin = strtolower($asin);
return $asin;
}
/**
* Generates a unique identifier
*
* @return string
*/
function GenerateIdentifier() {
return md5(uniqid(rand(), true));
}
/**
* Return associate id
*
* @return string
*/
function GetAssociateId() {
return $this->_associateId;
}
/**
* Return display num
*
* @return integer
*/
function GetDisplayNum() {
return $this->_displayNum;
}
/**
* Return identifier
*
* @return string
*/
function GetIdentifier() {
return $this->_identifier;
}
/**
* Return items
*
* @return array
*/
function GetItems() {
return $this->_items;
}
/**
* Return locale
*
* @return string
*/
function GetLocale() {
return $this->_locale;
}
/**
* Return name
*
* @return string
*/
function GetName() {
return $this->_name;
}
/**
* Creates an array of all showcase options
*
*/
function GetOptionsArray() {
$options = array(
'associateid' => $this->_associateId,
'displaynum' => $this->_displayNum,
'identifier' => $this->_identifier,
'items' => $this->_items,
'locale' => $this->_locale,
'name' => $this->_name,
'sortmethod' => $this->_sortMethod
);
return $options;
}
/**
* Utility function for determining the URL for posting forms to
*/
function GetPostUrl() {
$page = basename(__FILE__);
if (isset($_GET['page']) && !empty($_GET['page'])) {
$page = preg_replace('[^a-zA-Z0-9\.\_\-]', '', $_GET['page']);
}
return $_SERVER['PHP_SELF'] . "?page=" . $page;
}
/**
* Return sort method
*
* @return string
*/
function GetSortMethod() {
return $this->_sortMethod;
}
/**
* Generates options HTML for an individual showcase item
*
* @return string Generated HTML
*/
function ItemOptionsFormHtml($itemIdentifier = null) {
if (isset($this->_items[$itemIdentifier])) {
$item = $this->_items[$itemIdentifier];
$selectedImageSize = array('swatch'=>'', 'small'=>'', 'tiny'=>'', 'medium'=>'', 'large'=>'');
$selectedImageSize[$item['imageSize']] = 'selected';
$template = !empty($item['template']) ? stripslashes($item['template']) : $this->_defaultItemTemplate;
$preview = '';
if (isset($item['amazonCache']['data']['images']['thumbnail']['url']) && !empty($item['amazonCache']['data']['images']['thumbnail']['url'])) {
$preview = ' ';
}
$html = <<
Swatch (30px)
Small (75px)
Tiny (110px)
Medium (160px)
Large (450px+)
{$preview}
HTML;
return $html;
}
return '';
}
/**
* Removes a specific item from the showcase
*
* @param string $itemIdentifier Identifier of item to be removed
*/
function RemoveItem($itemIdentifier = null) {
if (isset($this->_items[$itemIdentifier])) {
unset($this->_items[$itemIdentifier]);
}
}
/**
* Assign all private variable values by load the showcase options from the DB
*
*/
function LoadOptions() {
$options = get_option('amzshcs');
if (isset($options['showcases'][$this->_identifier])) {
$showcaseOptions = $options['showcases'][$this->_identifier];
if (isset($showcaseOptions['associateid'])) {
$this->_associateId = $showcaseOptions['associateid'];
}
if (isset($showcaseOptions['displaynum'])) {
$this->_displayNum = $showcaseOptions['displaynum'];
}
if (isset($showcaseOptions['items'])) {
$this->_items = $showcaseOptions['items'];
}
if (isset($showcaseOptions['locale'])) {
$this->_locale = $showcaseOptions['locale'];
}
if (isset($showcaseOptions['name'])) {
$this->_name = $showcaseOptions['name'];
}
if (isset($showcaseOptions['sortmethod'])) {
$this->_sortMethod = $showcaseOptions['sortmethod'];
}
}
}
/**
* Set associate id
* @param string $associateId
* @return bool
*/
function SetAssociateId($associateId) {
return $this->_associateId = $associateId;
}
/**
* Set display num
* @param integer $displayNum
* @return bool
*/
function SetDisplayNum($displayNum) {
return $this->_displayNum = $displayNum;
}
/**
* Set identifier
* @param string $identifier
* @return bool
*/
function SetIdentifier($identifier) {
return $this->_identifier = $identifier;
}
/**
* Set items
* @param array $items
* @return bool
*/
function SetItems($items) {
return $this->_items = $items;
}
/**
* Set locale
* @param string $locale
* @return bool
*/
function SetLocale($locale) {
return $this->_locale = $locale;
}
/**
* Set name
* @param string $name
* @return bool
*/
function SetName($name) {
return $this->_name = $name;
}
/**
* Set multiple object options at once by passing an array of option values
*
* @param array $options
*/
function SetOptions($options = array()) {
foreach ($options as $option => $value) {
switch (strtolower($option)) {
case 'associateid':
$this->_associateId = $value;
break;
case 'displaynum':
$this->_displayNum = $value;
break;
case 'identifier':
$this->_identifier = $value;
break;
case 'items':
if (is_array($value)) {
foreach ($value as $identifier => $item) {
if (isset($item['asin'])) {
$value[$identifier]['asin'] = $this->CleanAsin($item['asin']);
}
}
$this->_items = $value;
} else {
$this->_items = array();
}
break;
case 'locale':
$this->_locale = $value;
break;
case 'name':
$this->_name = $value;
break;
case 'sortmethod':
$this->_sortMethod = $value;
break;
}
}
}
/**
* Set sort method
* @param string $sortMethod
* @return bool
*/
function SetSortMethod($sortMethod) {
return $this->_sortMethod = $sortMethod;
}
/**
* Returns the HTML for a showcase
*
* @param bool $encodeEntities If true, applies htmlspecialchars to data. Default false.
*/
function ShowcaseHtml($encodeEntities = false) {
$items = $this->_items;
if ($this->_displayNum > 0) {
shuffle($items);
$items = array_slice($items, 0, $this->_displayNum);
}
$itemHtml = '';
foreach ($items as $item) {
$itemIdentifier = $item['identifier'];
if (!empty($item['template'])) {
$itemHtml[$itemIdentifier] = stripslashes($item['template']);
} else {
$itemHtml[$itemIdentifier] = $this->_defaultItemTemplate;
}
if (is_array($item['amazonCache']['data']['author'])) {
$authors = implode(', ', $item['amazonCache']['data']['author']);
} else {
$authors = $item['amazonCache']['data']['author'];
}
if ($encodeEntities) {
$authors = htmlspecialchars($authors);
$item['amazonCache']['data']['title'] = htmlspecialchars($item['amazonCache']['data']['title']);
}
$itemHtml[$itemIdentifier] = str_replace('[itemIdentifier]', $itemIdentifier, $itemHtml[$itemIdentifier]);
$itemHtml[$itemIdentifier] = str_replace('[author]', $authors, $itemHtml[$itemIdentifier]);
$itemHtml[$itemIdentifier] = str_replace('[title]', $item['amazonCache']['data']['title'], $itemHtml[$itemIdentifier]);
$itemHtml[$itemIdentifier] = str_replace('[url]', $item['amazonCache']['data']['url'], $itemHtml[$itemIdentifier]);
$image = '';
$image_url = '';
$image_width = '';
$image_height = '';
if (!empty($item['amazonCache']['data']['images'][$item['imageSize']])) {
$image_url = $item['amazonCache']['data']['images'][$item['imageSize']]['url'];
$image_width = $item['amazonCache']['data']['images'][$item['imageSize']]['width'];
$image_height = $item['amazonCache']['data']['images'][$item['imageSize']]['height'];
$image = ' ';
}
$itemHtml[$itemIdentifier] = str_replace('[image]', $image, $itemHtml[$itemIdentifier]);
$itemHtml[$itemIdentifier] = str_replace('[image_url]', $image_url, $itemHtml[$itemIdentifier]);
$itemHtml[$itemIdentifier] = str_replace('[image_width]', $image_width, $itemHtml[$itemIdentifier]);
$itemHtml[$itemIdentifier] = str_replace('[image_height]', $image_height, $itemHtml[$itemIdentifier]);
}
$html = $this->_defaultShowcaseTemplate;
$html = str_replace('[showcaseIdentifier]', $this->_identifier, $html);
$html = str_replace('[showcaseItems]', implode('', $itemHtml), $html);
return $html;
}
/**
* Generates options HTML for the showcase
*
* @return string Generated HTML
*/
function ShowcaseOptionsFormHtml($postUrl = null) {
if (!$postUrl) {
$postUrl = $this->GetPostUrl();
}
$selectedLocale = array('us'=>'', 'uk'=>'', 'de'=>'', 'jp'=>'', 'fr'=>'', 'ca'=>'');
$selectedLocale[$this->_locale] = 'selected';
$selectedDisplayNum = array(0=>'', 1=>'', 2=>'', 3=>'', 4=>'', 5=>'', 6=>'', 7=>'', 8=>'', 9=>'', 10=>'');
$selectedDisplayNum[$this->_displayNum] = 'selected';
$selectedSortMethod = array('normal'=>'', 'random'=>'');
$selectedSortMethod[$this->_sortMethod] = 'selected';
$html = <<
{$this->_name} click to toggle options
HTML;
return $html;
}
/**
* Update Amazon data for all showcase items
*
*/
function UpdateShowcaseAmazonData() {
// Extact all of the ASINs from the items array
$asins = array();
foreach ($this->_items as $item) {
$asins[] = $item['asin'];
}
if (!empty($asins)) {
// Query Amazon for data
$amazonData = $this->_Amazon->GetItems($asins, $this->_associateId, $this->_locale);
foreach ($this->_items as $identifier => $item) {
if (!empty($amazonData[$item['asin']])) {
$this->_items[$identifier]['amazonCache'] = array(
'lastUpdated' => date('Y-m-d H:i:s'),
'data' => $amazonData[$item['asin']]
);
}
}
}
}
}
/**
* Display a showcase anywhere in a theme.
*
* @param string $showcaseIdentifier Showcase to display
*/
function amazonshowcase($showcaseIdentifier) {
$GLOBALS['AmazonShowcase']->DisplayShowcase($showcaseIdentifier);
}
if (!ini_get('allow_url_fopen') && !function_exists('curl_init')) {
echo 'Amazon Showcase is unable to function within your current server settings. Please either set "allow_url_fopen" to 1, or enable cURL.
';
} else {
// Handle all ajax requests
if (isset($_REQUEST["amzshcs_ajax_action"])) {
AmazonShowcase::Enable();
switch ($_REQUEST['amzshcs_ajax_action']) {
case 'ajax_preview':
$GLOBALS['AmazonShowcase']->AjaxGenerateItemPreview($_REQUEST["amzshcs_asin"]);
break;
case 'addshowcase':
$GLOBALS['AmazonShowcase']->AjaxAddShowcase();
break;
case 'removeshowcase':
$GLOBALS['AmazonShowcase']->AjaxRemoveShowcase($_REQUEST["amzshcs_identifier"]);
break;
case 'addshowcaseitem':
$GLOBALS['AmazonShowcase']->AjaxAddShowcaseItem($_REQUEST["amzshcs_showcase_identifier"]);
break;
case 'removeshowcaseitem':
$GLOBALS['AmazonShowcase']->AjaxRemoveShowcaseItem($_REQUEST["amzshcs_showcase_identifier"], $_REQUEST["amzshcs_item_identifier"]);
break;
}
} else {
// If Wordpress was initialized correctly, go ahead and enable the plugin
if (defined('ABSPATH') && defined('WPINC')) {
add_action('init', array('AmazonShowcase', 'Enable'), 1000, 0);
}
}
}
?>