<?php
/*
 Plugin Name: Amazon Reloaded for WordPress
 Author: Nick Ohrn
 Author URI: http://nickohrn.com/
 Plugin URI: http://nickohrn.com/amazon-reloaded-for-wordpress
 Description: Allows WordPress users to quickly and easily insert Amazon product links into posts and pages.
 Version: 3.1.0
 */

// Ensures that no one has already named a class the same as the one to be loaded by this plugin
if( !class_exists( 'Amazon_Reloaded_For_WordPress' ) ) {

	// Unique class name to avoid naming collisions.
	class Amazon_Reloaded_For_WordPress {

		var $defaults = array( 'tld' => 'com', 'id' => '' );
		var $key = 'YOUR AMAZONWS KEY HERE';
		var $secret = 'YOUR AMAZONWS SECRET HERE';
		var $options;
		var $plugin_folder;
		var $version = '3.1.0';
		
		
		/**
		 * PHP4 backwards compatibility;
		 */
		function Amazon_Reloaded_For_WordPress( ) {
			$this->__construct();
		}

		/**
		 * Default constructor registers filter, action, and activation deactivation hooks.  It also
		 * loads the plugins options.
		 * 
		 * @return Amazon_Reloaded_For_WordPress a new instance of the ARFW class.
		 */
		function __construct() {
			// Activation/Deactivation
			register_activation_hook( __FILE__, array( &$this, 'on_activate' ) );
			register_deactivation_hook( __FILE__, array( &$this, 'on_deactivate' ) );
				
			// Add Actions
			add_action( 'admin_menu', array( &$this, 'on_admin_menu' ) );
			add_action( 'init', array( &$this, 'on_init' ) );
			add_action( 'wp_ajax_amazon_reloaded_for_wordpress', array( &$this, 'on_wp_ajax_amazon_reloaded_for_wordpress' ) );
				
			// Add Filters
			
			// Other Stuff
			$this->load_options();
			$this->plugin_folder = path_join( WP_PLUGIN_URL, basename( dirname( __FILE__ ) ) );
		}

		/**
		 * Hook for activate action.
		 *
		 * Adds the plugin's option to the database.
		 */
		function on_activate( ) {
			$this->load_options();
			$this->save_options();
		}

		/**
		 * Hook for deactivate action.
		 *
		 * Removes the plugin's option from the database.
		 */
		function on_deactivate( ) {
			$this->delete_options();
		}

		/**
		 * Hook for the admin_menu action.
		 *
		 * Enqueues proper javascript files for operation of the plugin.  Also adds the appropriate options page
		 * that lets the user manage their Amazon associate id and country.
		 */
		function on_admin_menu( ) {
				
			// If we're on the write post or write page interface, add the Amazon Reloaded javascript
			if( $this->is_write_page( ) ) {
				$css_file = path_join( $this->plugin_folder, 'css/amazon-reloaded.css' );
				$js_file = path_join( $this->plugin_folder, 'js/amazon-reloaded.js' );
				
				wp_enqueue_script( 'amazon-reloaded-for-wordpress', $js_file, array( 'jquery' ), $this->version );
				wp_enqueue_style( 'amazon-reloaded-for-wordpress', $css_file, array(), $this->version );
			}
				
			// Add the plugin option page
			add_options_page( 'Amazon Reloaded', 'Amazon Reloaded', 8, basename( __FILE__ ), array( &$this, 'options_page' ) );
				
			// Add the meta box to the post and page interfaces.  It is assigned a type of normal so it appears below the categories
			add_meta_box( __( 'Amazon Reloaded for WordPress' , 'amazon-reloaded-for-wordpress'), __( 'Amazon Reloaded for WordPress' , 'amazon-reloaded-for-wordpress'), array( &$this, 'meta_box_output' ), 'post', 'normal' );
			add_meta_box( __( 'Amazon Reloaded for WordPress' , 'amazon-reloaded-for-wordpress'), __( 'Amazon Reloaded for WordPress' , 'amazon-reloaded-for-wordpress'), array( &$this, 'meta_box_output' ), 'page', 'normal' );
		}

		/**
		 * Loads the plugin's text domain.
		 *
		 */
		function on_init() {
			load_plugin_textdomain( 'amazon-reloaded-for-wordpress', PLUGINDIR . '/' . dirname(plugin_basename(__FILE__) ) . '/i18n/' );
		}
		
		/**
		 * Hook for wp_ajax_amazon_reloaded_for_wordpress action.
		 *
		 * Request results from Amazon.com's web services and prints them to output.
		 */
		function on_wp_ajax_amazon_reloaded_for_wordpress( ) {
			$request_url = $this->get_web_service_request_url( );

			$request_url = $this->sign_url( $request_url );

			// We do a manual one-step redirect here
			if( function_exists( 'curl_init' ) ) {

				// Start the cURL session
				$session = curl_init( $request_url );

				// Set some cURL options
				curl_setopt( $session, CURLOPT_HEADER, false );
				curl_setopt( $session, CURLOPT_RETURNTRANSFER, true );
				curl_setopt( $session, CURLOPT_FOLLOWLOCATION, false );

				// Execute the cURL request
				$response = curl_exec( $session );

				// Closes the initial session
				curl_close( $session );

			} else if( ini_get( 'allow_url_fopen' ) ) {
				$response = file_get_contents( $request_url );
				
			} else {
				$response = '<p>' . __( 'Your server does not have the cURL extension or allow remote opening of files with the allow_url_fopen setting.  Amazon Reloaded for WordPress will not function in the current configuration.  If you still would like to use the plugin, please contact your server administrator.' , 'amazon-reloaded-for-wordpress') . '</p>';

			}
				
			echo $response;
				
			exit( );
		}

		/**
		 * Deletes the plugin's options from the database.
		 *
		 */
		function delete_options() { 
			return delete_option( 'Amazon Reloaded for WordPress Options' );
		}
		
		/**
		 * Retrieves the plugin's options from the database.
		 *
		 */
		function load_options() {
			if( false === ( $options = get_option( 'Amazon Reloaded for WordPress Options' ) ) ) {
				$this->options = $this->defaults;
			} else {
				$this->options = $options;
			}
			return $this->options;
		}

		/**
		 * Returns a boolean value indicating whether the currently requested page is a
		 * part of the write page or write post interface.
		 *
		 * @return boolean true if the currently requested page is a write interface for posts or pages.
		 */
		function is_write_page( ) {
			$is_new_post = ( false != strpos( $_SERVER[ 'REQUEST_URI' ], 'post-new.php' ) );
			$is_new_page = ( false != strpos( $_SERVER[ 'REQUEST_URI' ], 'page-new.php' ) );
			$is_post = ( false != strpos( $_SERVER[ 'REQUEST_URI' ], 'post.php' ) );
			$is_page = ( false != strpos( $_SERVER[ 'REQUEST_URI' ], 'page.php' ) );
			
			return $is_new_post || $is_new_page || $is_post || $is_page;
		}

		/**
		 * Returns the appropriate url for a web service request based on POST parameters.
		 *
		 * @return string the appropriate url to use in a web service request.
		 */
		function get_web_service_request_url( ) {
			$xslt_document_location = path_join( $this->plugin_folder, 'resources/amazon-reloaded.xslt' );	
			
			$request = "http://xml-us.amznxslt.";
			$request .= $this->options[ 'tld' ];
			$request .= "/onca/xml?";
			$request .= "AssociateTag=" . urlencode( $this->options[ 'id' ] );
			$request .= "&AWSAccessKeyId=" . urlencode( $this->key );
			$request .= "&ContentType=text%2Fhtml";
			$request .= "&Keywords=" . rawurlencode( $_POST[ 'keywords' ] );
			$request .= "&Operation=ItemSearch";
			$request .= "&ResponseGroup=Images%2CItemAttributes";
			$request .= "&SearchIndex=Blended";
			$request .= "&Service=AWSECommerceService";
			$request .= "&Style=" . urlencode( $xslt_document_location );
			$request .= "&Version=2008-04-07";

			return $request;
		}

		/**
		 * Displays the output for the plugin's meta box.
		 * 
		 */
		function meta_box_output( ) {
			require_once ( path_join( dirname( __FILE__ ), 'pages/meta_box.php' ) );
		}

		/**
		 * Processes submissions and displays the output for the plugin's option page.
		 * 
		 */
		function options_page( ) {
			// Processing
			if( isset( $_POST[ 'amazon-reloaded-associate-id' ] ) && check_admin_referer( 'amazon-reloaded-for-wordpress-save_options' ) ) {
				$amazon_reloaded_errors = array();
				if( !preg_match( '/^[a-zA-Z0-9\-]*$/', $_POST[ 'amazon-reloaded-associate-id' ] ) ) {
					$amazon_reloaded_errors[] = __( 'Invalid associate ID.  Please make sure you have entered the correct id.' , 'amazon-reloaded-for-wordpress');
					$associate_id = $this->options[ 'id' ];
				} else {
					$associate_id = $_POST[ 'amazon-reloaded-associate-id' ];
				}
				
				if( !in_array( $_POST[ 'amazon-reloaded-associate-country' ], array( 'ca', 'de', 'fr', 'jp', 'co.uk', 'com' ) ) ) {
					$amazon_reloaded_errors[] = __( 'Invalid country selection.  Please select your country again.' , 'amazon-reloaded-for-wordpress');
					$associate_country = $this->options[ 'tld' ];
				} else {
					$associate_country = $_POST[ 'amazon-reloaded-associate-country' ];
				}
				
				$this->options[ 'id' ] = $associate_id;
				$this->options[ 'tld' ] = $associate_country;
				$this->save_options();
				
				$amazon_reloaded_message = '';
				
				if( empty( $amazon_reloaded_errors ) ) {
					$amazon_reloaded_message = '<p>' . __( 'Your options have been saved.' , 'amazon-reloaded-for-wordpress') . '</p>';
				} else {
					$amazon_reloaded_message = '<ul>';
					foreach( $amazon_reloaded_errors as $error ) {
						$amazon_reloaded_message .= "<li>$error</li>";
					}
					$amazon_reloaded_message .= '</ul>';
				}
			}
			
			// Display
			require_once ( path_join( dirname( __FILE__ ), 'pages/options.php' ) );
		}

		/**
		 * Provides an easy mechanism to save the options value to the WordPress database
		 * for persistence.
		 *
		 * @return boolean true if the save was successful.
		 */
		function save_options( ) {
			return update_option( 'Amazon Reloaded for WordPress Options', $this->options );
		}

		/**
		 * Signes the URL per terms of Amazon API standards as of 2009-07-01
		 *
		 * @return text of signed URL.
		 */

		function sign_url( $url ){
			$host = parse_url($url,PHP_URL_HOST);
			$timestamp = gmstrftime("%Y-%m-%dT%H:%M:%S.000Z");
			$url = $url . "&Timestamp=" . $timestamp;

			$paramstart = strpos($url,"?");
			$workurl = substr($url,$paramstart+1);
			$workurl = str_replace(",","%2C",$workurl);
			$workurl = str_replace(":","%3A",$workurl);
  
			$params = explode("&",$workurl);
			sort($params);

			$signstr = "GET\n" . $host . "\n/onca/xml\n" . implode("&",$params);
			$signstr = base64_encode(hash_hmac('sha256', $signstr, $this->secret, true));
			$signstr = urlencode($signstr);
			$signedurl = $url . "&Signature=" . $signstr;

			return $signedurl;
		}

	}
}

if( class_exists( 'Amazon_Reloaded_For_WordPress' ) ) {
	$amazon_reloaded = new Amazon_Reloaded_For_WordPress( );
}

?>
