'). */ define('KEYWORD',1); define('CC',2); define('ESCAPE',3); define('INDEX',4); if (!class_exists('AmazonLinkSearch')) { class AmazonLinkSearch { var $data = array(); function __construct() { $this->URLRoot = plugins_url("", __FILE__); $this->base_name = plugin_basename( __FILE__ ); $this->plugin_dir = dirname( $this->base_name ); } /* * Must be called by the client in its init function. */ function init($parent) { // AJAX callbacks need to be registered early during init. $script = plugins_url("amazon-link-search.js", __FILE__); wp_register_script('amazon-link-search', $script, array('jquery'), '1.0.0'); add_action('wp_ajax_amazon-link-search', array($this, 'performSearch')); // Handle ajax search requests add_action('wp_ajax_amazon-link-get-image', array($this, 'grabImage')); // Handle ajax image download add_action('wp_ajax_amazon-link-remove-image', array($this, 'removeImage')); // Handle ajax image removal $settings = $parent->getSettings(); if (!empty($settings['media_library'])) { // Standard Image Filter add_filter('amazon_link_template_get_image', array($this, 'get_images_filter'), 12, 6); add_filter('amazon_link_template_get_thumb', array($this, 'get_images_filter'), 12, 6); } // Standard Link Filter add_filter('amazon_link_template_get_link_open', array($this, 'get_links_filter'), 12, 6); add_filter('amazon_link_template_get_rlink_open', array($this, 'get_links_filter'), 12, 6); add_filter('amazon_link_template_get_slink_open', array($this, 'get_links_filter'), 12, 6); add_filter('amazon_link_template_get_url', array($this, 'get_urls_filter'), 12, 6); add_filter('amazon_link_template_get_rurl', array($this, 'get_urls_filter'), 12, 6); add_filter('amazon_link_template_get_surl', array($this, 'get_urls_filter'), 12, 6); add_filter('amazon_link_template_get_tag', array($this, 'get_tags_filter'), 12, 6); add_filter('amazon_link_template_get_chan', array($this, 'get_channel_filter'), 12, 6); $this->alink = $parent; } /*****************************************************************************************/ /// AJAX Call Handlers /*****************************************************************************************/ function performSearch($Opts='') { if (!is_array($Opts)) $Opts = $_POST; $Opts['multi_cc'] = '0'; $Opts['localise'] = 0; $Opts['live'] = 1; $Opts['skip_slow'] = 1; $Settings = array_merge($this->alink->getSettings(), $Opts); if ( empty($Settings['s_title']) && empty($Settings['s_author']) ) { $Items = $this->alink->cached_query($Settings['asin'], $Settings); } else { $Settings['found'] = 1; if (!empty($Settings['translate']) && !empty($Opts['s_title_trans'])) $Opts['s_title'] = $Opts['s_title_trans']; $Items = $this->do_search($Settings); } $results['message'] = 'No Error '; $results['success'] = 0; if (isset($Items['Error'])) { $results['message'] = 'Error: ' . (isset($Items['Error']['Message']) ? $Items['Error']['Message'] : 'No Error Message'); } else if (is_array($Items) && (count($Items) >0)) { foreach($Items as $item) { $item = array_merge($Settings,$item); $results['items'][]['template'] = $this->parse_template($item); } $results['success'] = 1; } print json_encode($results); exit(); } function removeImage() { $Opts = $_POST; /* Do we have this image? */ $media_ids = $this->find_attachments( $Opts['asin'] ); if (is_wp_error($media_ids)) { $results = array('in_library' => false, 'asin' => $Opts['asin'], 'error' => __('No matching image found', 'amazon-link')); } else { $results = array('in_library' => false, 'asin' => $Opts['asin'], 'error' => __('Images deleted','amazon-link')); /* Only remove images attached to this post */ foreach ($media_ids as $id => $media_id) { if ($media_id->post_parent == $Opts['post']) { /* Remove attachment */ wp_delete_attachment($media_id->ID); } else { $results['in_library'] = true; $results['id'] = $media_id->ID; } } } print json_encode($results); exit(); } function grabImage() { $Opts = $_POST; /* Do not upload if we already have this image */ $media_ids = $this->find_attachments( $Opts['asin'] ); if (!is_wp_error($media_ids)) { $results = array('in_library' => true, 'asin' => $Opts['asin'], 'id' => $media_ids[0]->ID); } else { /* Attempt to download the image */ $result = $this->grab_image($Opts['asin'], $Opts['post']); if (is_wp_error($result)) { $results = array('in_library' => false, 'asin' => $Opts['asin'], 'error' => $result->get_error_code()); } else { $results = array('in_library' => true, 'asin' => $Opts['asin'], 'id' => $result); } } print json_encode($results); exit(); } /*****************************************************************************************/ /// Helper Functions /*****************************************************************************************/ function get_aws_info() { $search_index_by_locale = array( 'ca' => array('All', 'Blended', 'Books', 'Classical', 'DVD', 'Electronics', 'ForeignBooks', 'Kitchen', 'Music', 'Software', 'SoftwareVideoGames', 'VHS', 'Video', 'VideoGames'), 'us' => array('All', 'Apparel', 'Appliances', 'ArtsAndCrafts', 'Automotive', 'Baby', 'Beauty', 'Blended', 'Books', 'Classical', 'Collectibles', 'DigitalMusic', 'Grocery', 'MP3Downloads', 'DVD', 'Electronics', 'HealthPersonalCare', 'HomeGarden', 'Industrial', 'Jewelry', 'KindleStore', 'Kitchen', 'LawnAndGarden', 'Magazines', 'Merchants', 'Miscellaneous', 'MobileApps', 'Music', 'MusicalInstruments', 'MusicTracks', 'OfficeProducts', 'OutdoorLiving', 'PCHardware', 'PetSupplies', 'Photo', 'Shoes', 'Software', 'SportingGoods', 'Tools', 'Toys', 'UnboxVideo', 'VHS', 'Video', 'VideoGames', 'Watches', 'Wireless', 'WirelessAccessories'), 'cn' => array('All', 'Apparel', 'Appliances', 'Automotive', 'Baby', 'Beauty', 'Books', 'Electronics', 'Grocery', 'HealthPersonalCare', 'Home', 'HomeImprovement', 'Jewelry', 'Misc', 'Music', 'OfficeProducts', 'Photo', 'Shoes', 'Software', 'SportingGoods', 'Toys', 'Video', 'VideoGames', 'Watches'), 'de' => array('All', 'Apparel', 'Automotive', 'Baby', 'Blended', 'Beauty', 'Books', 'Classical', 'DVD', 'Electronics', 'ForeignBooks', 'Grocery', 'HealthPersonalCare', 'HomeGarden', 'Jewelry', 'KindleStore', 'Kitchen', 'Lighting', 'Magazines', 'MP3Downloads', 'Music', 'MusicalInstruments', 'MusicTracks', 'OfficeProducts', 'OutdoorLiving', 'Outlet', 'PCHardware', 'Photo', 'Software', 'SoftwareVideoGames', 'SportingGoods', 'Tools', 'Toys', 'VHS', 'Video', 'VideoGames', 'Watches'), 'es' => array('All', 'Books', 'DVD', 'Electronics', 'ForeignBooks', 'Kitchen', 'Music', 'Software', 'Toys', 'VideoGames', 'Watches'), 'fr' => array('All', 'Apparel', 'Baby', 'Beauty', 'Blended', 'Books', 'Classical', 'DVD', 'Electronics', 'ForeignBooks', 'HealthPersonalCare', 'HomeImprovement', 'Jewelry', 'Kitchen', 'Lighting', 'MP3Downloads', 'Music', 'MusicalInstruments', 'MusicTracks', 'OfficeProducts', 'Outlet', 'Shoes', 'Software', 'SoftwareVideoGames', 'VHS', 'Video', 'VideoGames', 'Watches'), 'it' => array('All', 'Books', 'DVD', 'Electronics', 'ForeignBooksSearchIndex:Garden', 'KindleStore', 'Kitchen', 'Music', 'Shoes', 'Software', 'Toys', 'VideoGames', 'Watches'), 'in' => array('All', 'Books', 'DVD', 'Electronics', 'Marketplace'), 'jp' => array('All', 'Apparel', 'Appliances', 'Automotive', 'Baby', 'Beauty', 'Blended', 'Books', 'Classical', 'DVD', 'Electronics', 'ForeignBooks', 'Grocery', 'HealthPersonalCare', 'Hobbies', 'HomeImprovement', 'Jewelry', 'Kitchen', 'MP3Downloads', 'Music', 'MusicalInstruments', 'MusicTracks', 'OfficeProducts', 'Shoes', 'Software', 'SportingGoods', 'Toys', 'VHS', 'Video', 'VideoGames', 'Watches'), 'uk' => array('All', 'Apparel', 'Automotive', 'Baby', 'Beauty', 'Blended', 'Books', 'Classical', 'DVD', 'Electronics', 'Grocery', 'HealthPersonalCare', 'HomeGarden', 'Jewelry', 'KindleStore', 'Kitchen', 'Lighting', 'MP3Downloads', 'Music', 'MusicalInstruments', 'MusicTracks', 'OfficeProducts', 'OutdoorLiving', 'Outlet', 'Shoes', 'Software', 'SoftwareVideoGames', 'Toys', 'VHS', 'Video', 'VideoGames', 'Watches'), 'us' => array('All', 'Apparel', 'Appliances', 'ArtsAndCrafts', 'Automotive', 'Baby', 'Beauty', 'Blended', 'Books', 'Classical', 'DigitalMusic', 'Grocery', 'MP3Downloads', 'DVD', 'Electronics', 'HealthPersonalCare', 'HomeGarden', 'Industrial', 'Jewelry', 'KindleStore', 'Kitchen', 'Magazines', 'Merchants', 'Miscellaneous', 'MobileApps', 'Music', 'MusicalInstruments', 'MusicTracks', 'OfficeProducts', 'OutdoorLiving', 'PCHardware', 'PetSupplies', 'Photo', 'Shoes', 'Software', 'SportingGoods', 'Tools', 'Toys', 'UnboxVideo', 'VHS', 'Video', 'VideoGames', 'Watches', 'Wireless', 'WirelessAccessories')); return array('SearchIndexByLocale' => $search_index_by_locale); } function do_search($Settings) { // Not working: Baby, MusicalInstruments $Creator = array( 'Author' => array( 'Books', 'ForeignBooks', 'MobileApps', 'MP3Downloads'), 'Actor' => array( 'DigitalMusic' ), 'Artist' => array('Music'), 'Director' => array('DVD', 'UnboxVideo', 'VHS', 'Video'), 'Publisher' => array('Magazines'), 'Brand' => array('Apparel', 'ArtsAndCrafts', 'Baby', 'Beauty', 'Grocery', 'Lighting', 'OfficeProducts', 'Miscellaneous', 'PetSupplies', 'Shoes', 'MusicalInstruments', 'VideoGames'), 'Manufacturer' => array('Appliances', 'Automotive', 'Electronics', 'Garden', 'HealthPersonalCare', 'Hobbies', 'Home', 'HomeGarden', 'HomeImprovement', 'Industrial', 'Kitchen', 'OutdoorLiving', 'Photo', 'Software', 'SoftwareVideoGames'), 'Composer' => array('Classical')); $Keywords = array('Blended', 'All', 'DigitalMusic', 'MusicTracks', 'Outlet'); $Sort['uk'] = array('salesrank' => array('Books', 'Classical', 'DVD', 'Electronics', 'HealthPersonalCare', 'HomeGarden', 'HomeImprovement', 'Kitchen', 'MarketPlace', 'Music', 'OutdoorLiving', 'PCHardware', 'Software', 'SoftwareVideoGames', 'Toys', 'VHS', 'Video', 'VideoGames'), 'relevancerank' => array('Apparel', 'Automotive', 'Baby', 'Beauty', 'Grocery', 'Jewelry', 'KindleStore', 'MP3Downloads', 'MusicalInstruments', 'OfficeProducts', 'Shoes', 'Watches'), 'xsrelevancerank' => array('Shoes')); $Sort['us'] = array('salesrank' => array('Books', 'Classical', 'DVD', 'Electronics', 'HealthPersonalCare', 'HomeGarden', 'HomeImprovement', 'Kitchen', 'MarketPlace', 'Music', 'OutdoorLiving', 'PCHardware', 'Software', 'SoftwareVideoGames', 'Toys', 'VHS', 'Video', 'VideoGames'), 'relevancerank' => array('Apparel', 'Automotive', 'Baby', 'Beauty', 'Grocery', 'Jewelry', 'KindleStore', 'MP3Downloads', 'MusicalInstruments', 'OfficeProducts', 'Shoes', 'Watches'), 'xsrelevancerank' => array('Shoes')); // Create query to retrieve the first 10 matching items $request = array('Operation' => 'ItemSearch', 'ResponseGroup' => 'Offers,ItemAttributes,Small,EditorialReview,Images,SalesRank', 'SearchIndex'=>$Settings['s_index'], 'ItemPage'=>$Settings['s_page']); foreach ($Sort['uk'] as $Term => $Indices) { if (in_array($Settings['s_index'], $Indices)) { $request['Sort'] = $Term; continue; } } foreach ($Creator as $Term => $Indices) { if (in_array($Settings['s_index'], $Indices)) { $request[$Term] = $Settings['s_author']; continue; } } if (in_array($Settings['s_index'], $Keywords)) { $request['Keywords'] = $Settings['s_title']; } else { $request['Title'] = $Settings['s_title']; } $items = $this->alink->cached_query($request, $Settings); return $items; } /*****************************************************************************************/ function find_attachments ($asin) { // Do we already have a local image ? $args = array( 'post_type' => 'attachment', 'numberposts' => -1, 'post_status' => 'all', 'suppress_filters' => true, 'meta_query' => array(array('key' => 'amazon-link-ASIN', 'value' => $asin))); $query = new WP_Query( $args ); $media_ids = $query->posts; if ($media_ids) { return $media_ids; } else { return new WP_Error(__('No images found','amazon-link')); } } function grab_image ($ASIN, $post_id = 0) { $ASIN = strtoupper($ASIN); $settings = $this->alink->getSettings(); $data = $this->alink->cached_query($ASIN,NULL,True); if ( ! ( ( $uploads = wp_upload_dir() ) && false === $uploads['error'] ) ) return new WP_Error($uploads['error']); $filename = $ASIN. '.JPG'; $filename = '/' . wp_unique_filename( $uploads['path'], basename($filename)); $filename_full = $uploads['path'] . $filename; $data['template_content'] = '%IMAGE%'; $data = array_merge($settings,$data); $image_url = $this->parse_template($data); if (empty($image_url)) return new WP_Error(__('No Images Found for this ASIN', 'amazon-link')); $result = wp_remote_get($image_url); if (is_wp_error($result)) return $result; //new WP_Error(__('Could not retrieve remote image file','amazon-link')); // Save file to media library $content = $result['body']; $size = file_put_contents ($filename_full, $content); if (is_readable($filename_full)) { // Grabbed Image successfully now add it to the media library $wp_filetype = wp_check_filetype(basename($filename_full), null ); $attachment = array( 'guid' => $filename, 'post_mime_type' => $wp_filetype['type'], 'post_title' => $data['artist'] . ' - ' . $data['title'], // Title 'post_excerpt' => $data['title'], // Caption 'post_content' => '', // Description 'post_status' => 'inherit'); $attach_id = wp_insert_attachment( $attachment, $filename_full, $post_id); // you must first include the image.php file // for the function wp_generate_attachment_metadata() to work update_post_meta($attach_id , 'amazon-link-ASIN', $ASIN); require_once(ABSPATH . "wp-admin" . '/includes/image.php'); $attach_data = wp_generate_attachment_metadata( $attach_id, $filename_full ); wp_update_attachment_metadata( $attach_id, $attach_data ); } else { return new WP_Error(__('Could not read downloaded image','amazon-link')); } return $attach_id; } /*****************************************************************************************/ function get_channel_filter ($channel, $keyword, $country, $data, $settings, $al) { if (!empty($channel)) return $channel; $channel = $al->get_channel(array_merge($settings, $data[$country])); return $channel['ID']; } function get_tags_filter ($tag, $keyword, $country, $data, $settings, $al) { if (!empty($tag)) return $tag; $channel = $al->get_channel(array_merge($settings, $data[$country])); return $channel['tag_'.$country]; } function get_urls_filter ($url, $keyword, $country, $data, $settings, $al) { if (!empty($url)) return $url; $map = array( 'url' => 'A', 'rurl' => 'R', 'surl' => 'S'); $type = $map[$keyword]; $url = apply_filters('amazon_link_url', '', $type, $settings['asin'], $data[$settings['local_cc']]['search_text'], $data[$country], $settings, $al); return $url; } function get_links_filter ($link, $keyword, $country, $data, $settings, $al) { if (empty($al->search->settings['multi_cc']) && !empty($link)) return $link; $map = array( 'link_open' => 'A', 'rlink_open' => 'R', 'slink_open' => 'S'); $type = $map[$keyword]; return $al->make_link($settings, $data[$country], $type, array($data[$settings['local_cc']]['search_text'],$data[$settings['local_cc']]['search_text_s'])); } function get_images_filter ($images, $keyword, $country, $l_data, $settings, $al) { $data = &$al->search->data; if (isset($data['get_images_run'][$country][$keyword])) return $images; $data['get_images_run'][$country][$keyword] = 1; /* * Check for image in uploads */ if (empty($data[$country]['media_id'])) { $asin = isset($data[$country]['asin']) ? $data[$country]['asin'] : $data[$settings['home_cc']]['asin']; $media_ids = $this->find_attachments( $asin ); if (!is_wp_error($media_ids)) { // Only do one country, as other countries may have a different ASIN specified. $data[$country]['media_id'] = $media_ids[0]->ID; $data[$country]['downloaded'] = '1'; } else { $data[$country]['media_id'] = -1; $data[$country]['downloaded'] = '0'; return $images; } } if ($data[$country]['downloaded']) { if ($keyword == 'image') { $image = wp_get_attachment_url($data[$country]['media_id']); } else if ($keyword == 'thumb') { $image = wp_get_attachment_thumb_url($data[$country]['media_id']); } if (!empty($image)) return (array)$image; } return $images; } function remap_data ($data, $indexes, &$output) { foreach ($data as $key => $info) { if (is_array($info) && !array_key_exists(0, $info)) { /* Transpose data */ foreach ($info as $cc => $item) $output[$cc][$key] = $item; } else { /* Apply to all 'indexes' */ foreach($indexes as $cc) $output[$cc][$key] = $info; } } } /* * This will perform differently to the usual parser as it does the keywords in the order * found in the template - e.g. 'FOUND' will be done first! * We need to run the regex twice to catch new template tags replacing old ones (LINK_OPEN) */ function parse_template ($item) { $start_time = microtime(true); // Just get the country data, no local info yet $data = $this->alink->get_country_data(); $countries_a = array_keys($data); $keywords_data = $this->alink->get_keywords(); $sep = $sepc = $keywords = $keywords_c = ''; foreach ($keywords_data as $keyword => $key_data) { if (empty($key_data['Calculated'])) { $keywords .= $sep.$keyword; $sep = '|'; } else { $keywords_c .= $sepc.$keyword; $sepc= '|'; } } $local_country = $this->alink->get_country($item); $default_country = $item['default_cc']; $item['home_cc'] = $default_country; $item['local_cc'] = $local_country; if (empty($item['asin']) || !is_array($item['asin'])) $item['asin'] = array($default_country => !empty($item['asin']) ? $item['asin'] : ''); if ($item['global_over']) { $this->remap_data($item, $countries_a, $data); } else { $this->remap_data($item, array($local_country), $data); } $input = htmlspecialchars_decode (stripslashes($item['template_content'])); $this->settings = $item; $this->data = $data; $countries = implode('|',$countries_a); do { $input = preg_replace_callback( "!(?>%($keywords)%)(?:(?>($countries))?(?>(S))?([0-9]+)?#)?!i", array($this, 'parse_template_callback'), $input, -1, $count); } while ($count); $input = preg_replace_callback( "!(?>%($keywords_c)%)(?:(?>($countries))?(?>(S))?([0-9]+)?#)?!i", array($this, 'parse_template_callback'), $input); $this->alink->Settings['default_cc'] = $item['default_cc']; $this->alink->Settings['multi_cc'] = $item['multi_cc']; $this->alink->Settings['localise'] = $item['localise']; $time = microtime(true) - $start_time; if (!empty($item['debug'])) $input .=""; // Clear out local settings and data, no longer needed unset($this->settings, $this->data); return $input; } function parse_template_callback ($args) { $keyword = strtolower($args[KEYWORD]); $keywords = $this->alink->get_keywords(); $settings = $this->settings; $default_country = $settings['home_cc']; $key_data = $keywords[$keyword]; /* * Process Modifiers */ if (empty($args[CC])) { $country = $settings['local_cc']; } else { // Manually set country, hard code to not localised $country = strtolower($args[CC]); $settings['multi_cc'] = 0; $settings['localise'] = 0; $settings['default_cc'] = $country; } $escaped = !empty($args[ESCAPE]); $keyword_index = (!empty($args[INDEX]) ? $args[INDEX] : 0); $local_info = $this->data[$country]; /* * Select the most appropriate ASIN for the locale */ if (empty($this->data[$country]['asin'])) { $this->data[$country]['asin'] = $this->data[$default_country]['asin']; } $asin = $this->data[$country]['asin']; /* * Prefetch product data if not already fetched and prefetch is enabled */ if ($settings['live'] && $settings['prefetch'] && empty($this->data[$country]['prefetched'])) { $item_data = $this->alink->cached_query($asin, $settings, True); if ($item_data['found'] && empty($settings['asin'][$country])) { $settings['asin'][$country] = $asin; $this->settings['asin'][$country] = $asin; } else if (!empty($settings['localise']) && ($country != $default_country)) { $settings['default_cc'] = $default_country; $settings['localise'] = 0; $item_data = $this->alink->cached_query($asin, $settings, True); $item_data['not_found'] = 1; } $this->data[$country] = array_merge($item_data, (array)$this->data[$country]); $this->data[$country]['prefetched'] = 1; } /* * Apply any template_get filters for this keyword */ $phrase = apply_filters( 'amazon_link_template_get_'. $keyword, isset($this->data[$country][$keyword])?$this->data[$country][$keyword]:NULL, $keyword, $country, $this->data, $settings, $this->alink); if ($phrase !== NULL) $this->data[$country][$keyword] = $phrase; /* * If the keyword is not yet set then we need to populate it */ if (!isset($this->data[$country][$keyword])) { /* * If we can get it from Amazon then try and get it */ if (!empty($key_data['Live']) && ($settings['live'])) { $item_data = $this->alink->cached_query($asin, $settings, True); if ($item_data['found'] && empty($settings['asin'][$country])) { $settings['asin'][$country] = $asin; $this->settings['asin'][$country] = $asin; } else if (!$item_data['found'] && $settings['localise'] && ($country != $settings['default_cc'])) { $settings['localise'] = 0; $item_data = $this->alink->cached_query($asin, $settings, True); $item_data['not_found'] = 1; } if ($settings['debug'] && isset($item_data['Error'])) { echo ""; } $this->data[$country] = array_merge($item_data, (array)$this->data[$country]); } else { /* * We can't retreive it, so just use the default if set */ $this->data[$country][$keyword] = isset($key_data['Default']) ? ( is_array($key_data['Default']) ? $key_data['Default'][$country] : $key_data['Default'] ) : '-'; } } /* * Run the 'process' filters to post process the keyword */ $this->data[$country][$keyword] = apply_filters( 'amazon_link_template_process_'. $keyword, isset($this->data[$country][$keyword])?$this->data[$country][$keyword]:NULL, $keyword, $country, $this->data, $settings, $this->alink); /* * If multiple results returned then select the one requested in the template */ $phrase = $this->data[$country][$keyword]; if (is_array($phrase)) { $phrase = $phrase[$keyword_index]; } /* * This just needs to get the data through to the javascript, typical HTML looks like: * * Need to ensure there are no unescaped ' or " characters or new lines * * It is up to the receiving javascript to ensure that the data is present correctly for the next stage * - in postedit -> strip out > and " and & and [ to ensure the shortcode is parsed correctly * - in popup (do nothing?). */ if ($escaped) $phrase = str_ireplace(array( "'", '&'), array("\'", '%26'), $phrase); if (!empty($key_data['Live']) && empty($key_data['Link'])) $phrase = str_ireplace(array( '"', "'", "\r", "\n"), array('"', ''',' ',' '), $phrase); /* * Update unused_args to remove used keyword. */ if (!empty($this->data[$default_country]['unused_args'])) $this->data[$default_country]['unused_args'] = preg_replace('!(&?)'.$keyword.'=[^&]*(\1?)&?!','\2', $this->data[$default_country]['unused_args']); return $phrase; } } } ?>