<?php
/*
   Plugin Name: Preview Image Picker Plugin
   Plugin URI: http://spectacu.la/
   Description: Errrr..
   Author: James R Whitehead
   Version: 1.0.0
   Author URI: http://interconnectit.com
*/
define (PPPMETA_NAME,'_PIPPimage');
//define (CLEAN_UP_POST_META,true);
//delete_post_meta_by_key(PPPMETA_NAME);
//delete_post_meta_by_key('excerptthumb-image-url');
//delete_post_meta_by_key('image-id');
//delete_post_meta_by_key('medium-image-url');
//delete_post_meta_by_key('spectaculahighlight-image-url');
//delete_post_meta_by_key('thumbnail-image-url');

if (!class_exists('PIPPClass',false)) {
	class PIPPClass {
		var $defaultSizes = array('medium','thumbnail','large');

		function PIPPClass() {
			add_action('admin_menu',array($this,'addPostPageOptions'));
			add_action('save_post',array($this,'processPostOptions'),10,2);
			add_filter('intermediate_image_sizes',array($this,'intermediateImageSizes'));

			// Load up the defaults that come with WP.
			foreach($this->defaultSizes as $size){
				$this->size[$size] = array('width' => get_option("{$size}_size_w"),'height' => get_option("{$size}_size_h"), 'crop' => get_option("{$size}_crop"));
			}
		}

		function addPostPageOptions(){
			if( function_exists("add_meta_box")) {
				add_meta_box("PPPthemePostOptions","Preview Image Picker Plugin",array($this,"singlePostOptions"),"post");
				add_meta_box("PPPthemePostOptions","Preview Image Picker Plugin",array($this,"singlePostOptions"),"page");
			}
		}

		function processPostOptions($postID,$postContent) {

			if ( !wp_verify_nonce( $_POST['icitPIPPNonce'], plugin_basename(__FILE__) )) {
				return $postID;
			}
			if (!current_user_can('upload_files')){
				return $postID;
			}

			if ((strtolower($postContent->post_type) != 'post') && (strtolower($postContent->post_type) != 'page') && (strtolower($postContent->post_type) != 'revision')) {
				return $postID;
			}

			if ($postContent->post_type == "revision") {
				$postID = $postContent->post_parent;
	//			$postContent = get_post($postID);
			}

			// Set the new ID.
			$id = intval( $_POST['previewimage']);
			$postMeta = array('id' => $id);

			if ($id != -1) {
				if ($this->generateImages($id) !== false);
					$postMeta = $this->generatePostMeta($id);
			}

			// Save settings
			if (!update_post_meta($postID,PPPMETA_NAME,$postMeta))
				add_post_meta($postID,PPPMETA_NAME,$postMeta);
		}

		function singlePostOptions() {
			global $post;
			echo '<p>'.__('Choose an image to represent this post',THEMENAME).'</p>';

			if ($post->ID) {
				$attachments = get_children("post_parent={$post->ID}&post_type=attachment&orderby=menu_order ASC,ID&order=DESC");
				$PIPPImage = get_post_meta($post->ID ,PPPMETA_NAME,true);
				$currentAttachmentID = $PIPPImage['id'];
			}
			if ($attachments) {
				// TODO: Ajax load any changes to the attachment list.

				echo '<select name="previewimage" id="previewimage" style="width:350px">';
				echo '<option value="-1"'.((int)$currentAttachmentID == 0 || $currentAttachmentID == -1 ? ' selected="selected"' : '').'>(None)</option> ';
				foreach ($attachments as $attachment) {
					echo '<option value="'.$attachment->ID.'"'.((int)$currentAttachmentID == (int)$attachment->ID ? ' selected="selected"' : '').'>'.$attachment->post_title.'</option>';
				}

				echo '</select>';
				echo '<input type="hidden" name="icitPIPPNonce" id="icitPIPPNonce" value="'.wp_create_nonce(plugin_basename(__FILE__)).'" />';

			} else {
				echo '<p>'.	__("There are no images attached to this post or you'll need to save the post for any new attachments to be seen.").'</p>';
			}
		}

		function intermediateImageSizes($passed) {
			if (is_array($passed) && is_array($this->size)) {
				$sizes = array_keys($this->size);
				$newSizes = array_diff($sizes,$passed);
				$passed = array_merge($passed,$newSizes);

				foreach ($newSizes as $size) {
					update_option("{$size}_size_w",$this->size[$size]['width']);
					update_option("{$size}_size_h",$this->size[$size]['height']);
					update_option("{$size}_crop",$this->size[$size]['crop']);
				}
			}

			return $passed;
		}

		// Run through each
		function generateImages($attachmentID) {
			$attachmentID = intval($attachmentID);
			$file = get_attached_file($attachmentID);
			$uploads = wp_upload_dir();

			if(!file_exists($file) && file_exists($uploads['basedir'].$file))
				$file = $uploads['basedir'].$file;

			if (file_exists($file)) {
				if(!function_exists('wp_generate_attachment_metadata'))
					include_once (ABSPATH .'wp-admin/includes/image.php');
				wp_update_attachment_metadata($attachmentID,wp_generate_attachment_metadata($attachmentID,$file));
			}

			return;
		}

		function generatePostMeta($attachmentID) {
			$attachmentID = intval($attachmentID);

			$output = array('id' => $attachmentID);
			$attachmentMeta = wp_get_attachment_metadata($attachmentID,true);
			if (!is_array($attachmentMeta) || empty($attachmentMeta)){
				$file = get_attached_file($attachmentID);
				if (file_exists($file)) {
					if(!function_exists('wp_generate_attachment_metadata'))
						include_once (ABSPATH .'wp-admin/includes/image.php');
					wp_update_attachment_metadata($attachmentID,wp_generate_attachment_metadata($attachmentID,$file));
				}
				return;
			}

			foreach(array_keys($this->size) as $size) {
				if ($attachmentMeta['sizes'][$size]['width'] != $this->size[$size]['width'] && $attachmentMeta['sizes'][$size]['height'] != $this->size[$size]['height']) {
					list($url,$width,$height) = wp_get_attachment_image_src($attachmentID,$size);
				} else {
					$url = path_join(dirname(wp_get_attachment_url($attachmentID)), $attachmentMeta['sizes'][$size]['file'] );
					$width = $attachmentMeta['sizes'][$size]['width'];
					$height = $attachmentMeta['sizes'][$size]['height'];
				}
				$srcW = $attachmentMeta['width'];
				$srcH = $attachmentMeta['height'];
				$destW = $this->size[$size]['width'];
				$destH = $this->size[$size]['height'];

				if($srcW < $destW && $srcH < $destH && ($destH > 0 && $destW > 0 && $srcH > 0 && $srcW > 0)) {
					// Set the sizes for times when the desired x & y are bigger than the image.
					// This needs to be sorted out for cropped images. Because we're scaling the
					// image up with the browser and image width height attributes we can't easily
					// crop the image. So the image will maintain its source aspect.
					if ($srcW * ($destH/$srcH) > $destW) {
						$height = ceil($srcH * ($destW/$srcW));
						$width = $destW;
					} else {
						$width = ceil($srcW * ($destH/$srcH));
						$height = $destH;
					}
	//				trace("Source Smaller than Desired \n W = $width H = $height Sw = $srcW  Sh = $srcH Dw = $destW Dh = $destH \n $size");
				}

				$output[$size]['url'] = $url;
				$output[$size]['width'] = $width;
				$output[$size]['height'] = $height;
			}
	//		die;
			return $output;
		}
	}
}

global $wp_version;
if (version_compare($wp_version,'2.7','ge')) {
	if (class_exists('PIPPClass',false))
		$PIPPObject = new PIPPClass();
}

/**
 * Add an image size to the list with dimensions of your choosing.
 * You can also specify a fail over image which can be show when no
 * image is available in the post.
 *
 * @param string $name A unique name for the image type.
 * @param int $width The width of the output image.
 * @param int $height The height of the output image.
 * @param int $crop Optional. Whether you'd like to crop the image or maintain its aspect.
 * @param string $alternateImage Optional. The image to show if no image is part of the post.
 */
if (!function_exists('PIPPAddImage')){
	function PIPPAddImage($name,$width,$height,$crop = false,$alternateImage = false) {
		global $PIPPObject;
		if (!is_object($PIPPObject))
			return false;

		if (intval($width) > 0 && intval($height) > 0 && !empty($name) && empty($PIPPObject->size[strtolower($name)])) {
			$PIPPObject->size[strtolower($name)] = array('width'=>intval($width),'height' => intval($height),'crop' => (bool)$crop);
			if ($alternateImage !== false) {
				$PIPPObject->size[strtolower($name)]['alt'] = clean_url($alternateImage,array('http','https'));
			}
		} else {
			echo "<pre>There was a problem with your ".__FUNCTION__." call.
	You could have specified an image name twice or entered something other than an integer for the width and height.
	</pre>";
		}
	}
}

/**
 * Collects the image assigned to the post and outputs an img tag. If the post doesn't have
 * the _PIPPimage post_meta value set and the visitor is logged in with a upload_files access level
 * it will generate the images for the post and set the post_meta.
 *
 * If you define CLEAN_UP_POST_META true then it will wipe out all existing _PIPPimage
 * post values.
 *
 * @param string $name The name given to the image size. Defined by PIPPAddImage
 * @return Will return false on error other wise the output is via an echo.
 */
if (!function_exists('PIPPGetImage')){
	function PIPPGetImage($name = "medium", $post_id = -1, $echo = true, $srcOnly = false) {
		global $PIPPObject,$post;

		if (!is_object($PIPPObject))
			return false;

		if (($post_id == -1) && (!in_the_loop() || empty($post->ID))){
			echo '<pre>'.__FUNCTION__.' should only be run from within the loop.</pre>';
			return false;
		} elseif ($post_id != -1) {
			$postID = $post_id;
		}  else  {
			$postID = $post->ID;
		}

		$name = strtolower($name);

		if (!in_array($name,(array)array_keys($PIPPObject->size))) {
			return false;
		}

		if (CLEAN_UP_POST_META === true)
			delete_post_meta($postID,PPPMETA_NAME,null);

		$postMeta = get_post_meta($postID,PPPMETA_NAME,true);
		$attachmentID = intval($postMeta['id']);

		// Only if the person looking at the page is logged in with editor level will we do a scan for images.
		if ($attachmentID == 0 && current_user_can('upload_files')) {
			$attachments = get_children("post_parent=$postID&post_type=attachment&orderby=menu_order ASC,ID&order=DESC");

			if (is_array($attachments)) {
				// We have attachments and this post has not been looked at by this plugin before so lets see what we can find.

				$attachment = array_slice($attachments,0,1,false);
				$attachmentID = $attachment[0]->ID;

				if ($PIPPObject->generateImages($attachmentID) !== false);
					$postMeta = $PIPPObject->generatePostMeta($attachmentID);

			} else {
				// If there are no attachments then there isn't much point looking.
				$postMeta = array('id' => -1);
			}

			// Save settings
			if (!update_post_meta($postID,PPPMETA_NAME,$postMeta))
				add_post_meta($postID,PPPMETA_NAME,$postMeta);
		}

		if($attachmentID >= 1){
			if (is_array($postMeta[$name]) && !empty($postMeta[$name]['url'])) {
				$alt = attribute_escape($post->post_title);
				$src = attribute_escape($postMeta[$name]['url']);
				$hw = image_hwstring($postMeta[$name]['width'],$postMeta[$name]['height']);
				$output = "<img src=\"$src\" alt=\"$alt\" $hw />";
			}
		}

		if (empty($output) && !empty($PIPPObject->size[$name]['alt'])) {
			$alt = attribute_escape($post->post_title);
			$src = attribute_escape($PIPPObject->size[$name]['alt']);
			$hw = image_hwstring($PIPPObject->size[$name]['width'],$PIPPObject->size[$name]['height']);
			$output = "<img src=\"$src\" alt=\"$alt\" $hw />";
		}
		if ($echo){
			echo ($srcOnly ? $src : $output);
		} else {
			return ($srcOnly ? $src : $output);
		}
	}
}

if (!function_exists('trace')) {
	function trace($var, $do_not_echo = false) {
		// from php.net/print_r user contributed notes
		// I Liked this function from earlier version of WP as a debug tool so I copied it into here
		// also gave it a better name. :D
		ob_start();
		print_r($var);
		$code =  htmlentities(ob_get_contents());
		ob_clean();
		if (!$do_not_echo) {
			echo "<br/>"; // Force the sending of headers.
			echo "<pre>$code</pre>";
		}
		return $code;
	}
}

?>
