Working on adding a "Replace Image" feature.
This commit is contained in:
		
							parent
							
								
									684193848a
								
							
						
					
					
						commit
						f3b6fde7a5
					
				@ -98,6 +98,7 @@ abstract class SimpleExtension implements Extension {
 | 
			
		||||
 | 
			
		||||
	public function receive_event(Event $event) {
 | 
			
		||||
		$name = get_class($event);
 | 
			
		||||
		// this is rather clever..
 | 
			
		||||
		$name = "on".str_replace("Event", "", $name);
 | 
			
		||||
		if(method_exists($this->_child, $name)) {
 | 
			
		||||
			$this->_child->$name($event);
 | 
			
		||||
@ -139,9 +140,18 @@ abstract class DataHandlerExtension implements Extension {
 | 
			
		||||
			if(is_null($image)) {
 | 
			
		||||
				throw new UploadException("Data handler failed to create image object from data");
 | 
			
		||||
			}
 | 
			
		||||
			$iae = new ImageAdditionEvent($event->user, $image);
 | 
			
		||||
			send_event($iae);
 | 
			
		||||
			$event->image_id = $iae->image->id;
 | 
			
		||||
			/* Check if we are replacing an image */
 | 
			
		||||
			if ( isset($event->metadata['replace']))
 | 
			
		||||
			{
 | 
			
		||||
				$image_id = $event->metadata['replace'];
 | 
			
		||||
				$ire = new ImageReplaceEvent($image_id, $image);
 | 
			
		||||
				send_event($ire);
 | 
			
		||||
				$event->image_id = $image_id;
 | 
			
		||||
			} else {
 | 
			
		||||
				$iae = new ImageAdditionEvent($event->user, $image);
 | 
			
		||||
				send_event($iae);
 | 
			
		||||
				$event->image_id = $iae->image->id;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if(($event instanceof ThumbnailGenerationEvent) && $this->supported_ext($event->type)) {
 | 
			
		||||
 | 
			
		||||
@ -457,6 +457,16 @@ class Image {
 | 
			
		||||
		unlink($this->get_thumb_filename());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * This function removes an image (and thumbnail) from the DISK ONLY.
 | 
			
		||||
	 * It DOES NOT remove anything from the database.
 | 
			
		||||
	 */
 | 
			
		||||
	public function remove_image_only() {
 | 
			
		||||
		log_info("core-image", "Removed Image File ({$this->hash})");
 | 
			
		||||
		unlink($this->get_image_filename());
 | 
			
		||||
		unlink($this->get_thumb_filename());
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * Someone please explain this
 | 
			
		||||
	 *
 | 
			
		||||
 | 
			
		||||
@ -46,6 +46,30 @@ class ImageDeletionEvent extends Event {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ImageReplaceEvent:
 | 
			
		||||
 *   $image -- the new image to be used
 | 
			
		||||
 *
 | 
			
		||||
 * This function replaces an image. Effectively it only
 | 
			
		||||
 * replaces the image file contents and leaves the tags
 | 
			
		||||
 * and such the same.
 | 
			
		||||
 */
 | 
			
		||||
class ImageReplaceEvent extends Event {
 | 
			
		||||
	var $image;
 | 
			
		||||
 | 
			
		||||
	public function ImageReplaceEvent(Image $image) {
 | 
			
		||||
		$this->image = $image;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ImageReplaceException extends SCoreException {
 | 
			
		||||
	var $error;
 | 
			
		||||
 | 
			
		||||
	public function __construct($error) {
 | 
			
		||||
		$this->error = $error;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ThumbnailGenerationEvent:
 | 
			
		||||
@ -129,6 +153,19 @@ class ImageIO extends SimpleExtension {
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if($event->page_matches("image_admin/replace")) {
 | 
			
		||||
			global $page, $user;
 | 
			
		||||
			if($user->is_admin() && isset($_POST['image_id']) && $user->check_auth_token()) {
 | 
			
		||||
				$image = Image::by_id($_POST['image_id']);
 | 
			
		||||
				if($image) {
 | 
			
		||||
					$page->set_mode("redirect");
 | 
			
		||||
					$page->set_redirect(make_link('upload/replace/'.$image->id));
 | 
			
		||||
				} else {
 | 
			
		||||
					/* Invalid image ID */
 | 
			
		||||
					// fail silently?
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function onImageAdminBlockBuilding($event) {
 | 
			
		||||
@ -151,6 +188,15 @@ class ImageIO extends SimpleExtension {
 | 
			
		||||
		$event->image->delete();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function onImageReplace($event) {
 | 
			
		||||
		try {
 | 
			
		||||
			$this->replace_image($event->image_old, $event->image_new);
 | 
			
		||||
		}
 | 
			
		||||
		catch(ImageReplaceException $e) {
 | 
			
		||||
			throw new UploadException($e->error);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public function onUserPageBuilding($event) {
 | 
			
		||||
		$u_id = url_escape($event->display_user->id);
 | 
			
		||||
		$i_image_count = Image::count_images(array("user_id={$event->display_user->id}"));
 | 
			
		||||
@ -266,7 +312,8 @@ class ImageIO extends SimpleExtension {
 | 
			
		||||
		$image->tag_array = array();
 | 
			
		||||
		send_event(new TagSetEvent($image, $tags_to_set));
 | 
			
		||||
	}
 | 
			
		||||
// }}}
 | 
			
		||||
// }}}  end add
 | 
			
		||||
 | 
			
		||||
// fetch image {{{
 | 
			
		||||
	private function send_file($image_id, $type) {
 | 
			
		||||
		global $config;
 | 
			
		||||
@ -312,6 +359,65 @@ class ImageIO extends SimpleExtension {
 | 
			
		||||
					"The requested image was not found in the database"));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
// }}}
 | 
			
		||||
}
 | 
			
		||||
// }}} end fetch
 | 
			
		||||
 | 
			
		||||
// replace image {{{
 | 
			
		||||
	private function replace_image($id, $image) {
 | 
			
		||||
		global $page;
 | 
			
		||||
		global $user;
 | 
			
		||||
		global $database;
 | 
			
		||||
		global $config;
 | 
			
		||||
		
 | 
			
		||||
		/*
 | 
			
		||||
		 * Validate things
 | 
			
		||||
		 */
 | 
			
		||||
		
 | 
			
		||||
		/* Check to make sure the image exists. */		
 | 
			
		||||
		$existing = Image::by_id($id);
 | 
			
		||||
		
 | 
			
		||||
		if(is_null($existing)) {
 | 
			
		||||
			throw new ImageReplaceException("Image to replace does not exist!");
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if ($existing->hash === $image->hash) {
 | 
			
		||||
			throw new ImageReplaceException("The uploaded image is the same as the one to replace.");
 | 
			
		||||
		}
 | 
			
		||||
		if(strlen(trim($image->source)) == 0) {
 | 
			
		||||
			$image->source = null;
 | 
			
		||||
		}
 | 
			
		||||
		if(!empty($image->source)) {
 | 
			
		||||
			if(!preg_match("#^(https?|ftp)://#", $image->source)) {
 | 
			
		||||
				throw new ImageReplaceException("Image's source isn't a valid URL");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		/*
 | 
			
		||||
			This step could be optional, ie: perhaps move the image somewhere
 | 
			
		||||
			and have it stored in a 'replaced images' list that could be 
 | 
			
		||||
			inspected later by an admin?
 | 
			
		||||
		*/	   
 | 
			
		||||
		$existing->remove_image_only();	// Actually delete the old image file from disk
 | 
			
		||||
		
 | 
			
		||||
		
 | 
			
		||||
		// Update the data in the database.
 | 
			
		||||
		$database->Execute(
 | 
			
		||||
				"UPDATE images SET 
 | 
			
		||||
					filename = :filename, filesize = :filesize,	hash = :hash,
 | 
			
		||||
					ext = :ext, width = :width, height = :height, source = :source
 | 
			
		||||
				WHERE 
 | 
			
		||||
					id = :id
 | 
			
		||||
				",
 | 
			
		||||
				array(
 | 
			
		||||
					"filename"=>$image_new->filename, "filesize"=>$image->filesize, "hash"=>$image->hash,
 | 
			
		||||
					"ext"=>$image->ext, "width"=>$image->width, "height"=>$image->height, "source"=>$image->source,
 | 
			
		||||
					"id"=>$existing->id
 | 
			
		||||
				)
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		log_info("image", "Replaced Image #{$existing->id} with ({$image->hash})");
 | 
			
		||||
	}
 | 
			
		||||
// }}} end replace
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
} // end of class ImageIO
 | 
			
		||||
?>
 | 
			
		||||
 | 
			
		||||
@ -54,6 +54,7 @@ class Upload implements Extension {
 | 
			
		||||
			$config->set_default_int('upload_count', 3);
 | 
			
		||||
			$config->set_default_int('upload_size', '1MB');
 | 
			
		||||
			$config->set_default_bool('upload_anon', false);
 | 
			
		||||
			$config->set_default_bool('upload_replace', true);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if($event instanceof PostListBuildingEvent) {
 | 
			
		||||
@ -67,44 +68,99 @@ class Upload implements Extension {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if(($event instanceof PageRequestEvent) && $event->page_matches("upload")) {
 | 
			
		||||
			if(count($_FILES) + count($_POST) > 0) {
 | 
			
		||||
				$tags = Tag::explode($_POST['tags']);
 | 
			
		||||
				$source = isset($_POST['source']) ? $_POST['source'] : null;
 | 
			
		||||
				if($this->can_upload($user)) {
 | 
			
		||||
					$ok = true;
 | 
			
		||||
					foreach($_FILES as $file) {
 | 
			
		||||
						$ok = $ok & $this->try_upload($file, $tags, $source);
 | 
			
		||||
					}
 | 
			
		||||
					foreach($_POST as $name => $value) {
 | 
			
		||||
						if(substr($name, 0, 3) == "url" && strlen($value) > 0) {
 | 
			
		||||
							$ok = $ok & $this->try_transload($value, $tags, $source);
 | 
			
		||||
						}
 | 
			
		||||
		if($event instanceof PageRequestEvent) {
 | 
			
		||||
			/* Upload and Replace Image */
 | 
			
		||||
			if ($event->page_matches("upload/replace"))
 | 
			
		||||
			{
 | 
			
		||||
				if($is_full) {
 | 
			
		||||
					throw new UploadException("Can not replace Image: disk nearly full");
 | 
			
		||||
				}
 | 
			
		||||
				$image_id = int_escape($event->get_arg(0));
 | 
			
		||||
				$image_old = Image::by_id($image_id);
 | 
			
		||||
 | 
			
		||||
				if(is_null($image_old)) {
 | 
			
		||||
					$this->theme->display_error($page, "Image not found", "No image in the database has the ID #$image_id");
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				if(count($_FILES) + count($_POST) > 0)
 | 
			
		||||
				{
 | 
			
		||||
					if (count($_FILES) + count($_POST) > 1) {
 | 
			
		||||
						throw new UploadException("Can not upload more than one image for replacing.");
 | 
			
		||||
					}
 | 
			
		||||
					
 | 
			
		||||
					$this->theme->display_upload_status($page, $ok);
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					$this->theme->display_permission_denied($page);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if(!empty($_GET['url'])) {
 | 
			
		||||
				if($this->can_upload($user)) {
 | 
			
		||||
					$url = $_GET['url'];
 | 
			
		||||
					$tags = array('tagme');
 | 
			
		||||
					if(!empty($_GET['tags']) && $_GET['tags'] != "null") {
 | 
			
		||||
						$tags = Tag::explode($_GET['tags']);
 | 
			
		||||
					if($this->can_upload($user)) {
 | 
			
		||||
						/* This could be changed so that it doesn't use foreach loops.. */
 | 
			
		||||
						foreach($_FILES as $file) {
 | 
			
		||||
							$ok = $ok & $this->try_upload($_FILES, $tags, $source, $image_id);
 | 
			
		||||
						}
 | 
			
		||||
						foreach($_POST as $name => $value) {
 | 
			
		||||
							if(substr($name, 0, 3) == "url" && strlen($value) > 0) {
 | 
			
		||||
								$ok = $ok & $this->try_transload($value, $tags, $source, $image_id);
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						/* Could replace with a page saying the image replace was successful? */
 | 
			
		||||
						$this->theme->display_upload_status($page, $ok);
 | 
			
		||||
					} else {
 | 
			
		||||
						$this->theme->display_permission_denied($page);
 | 
			
		||||
					}
 | 
			
		||||
					$ok = $this->try_transload($url, $tags, $url);
 | 
			
		||||
					$this->theme->display_upload_status($page, $ok);
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					$this->theme->display_permission_denied($page);
 | 
			
		||||
				else if(!empty($_GET['url']))
 | 
			
		||||
				{
 | 
			
		||||
					if($this->can_upload($user)) {
 | 
			
		||||
						$url = $_GET['url'];
 | 
			
		||||
						$ok = $this->try_transload($url, $tags, $url, $image_id);
 | 
			
		||||
						/* Replace with a page saying the image replace was successful */
 | 
			
		||||
						$this->theme->display_upload_status($page, $ok);
 | 
			
		||||
					}
 | 
			
		||||
					else {
 | 
			
		||||
						$this->theme->display_permission_denied($page);
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					$this->theme->display_replace_page($page);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				if(!$is_full) {
 | 
			
		||||
					$this->theme->display_page($page);
 | 
			
		||||
			/* Upload Image */
 | 
			
		||||
			else if ($event->page_matches("upload"))
 | 
			
		||||
			{
 | 
			
		||||
				if(count($_FILES) + count($_POST) > 0) {
 | 
			
		||||
					$tags = Tag::explode($_POST['tags']);
 | 
			
		||||
					$source = isset($_POST['source']) ? $_POST['source'] : null;
 | 
			
		||||
					if($this->can_upload($user)) {
 | 
			
		||||
						$ok = true;
 | 
			
		||||
						foreach($_FILES as $file) {
 | 
			
		||||
							$ok = $ok & $this->try_upload($file, $tags, $source);
 | 
			
		||||
						}
 | 
			
		||||
						foreach($_POST as $name => $value) {
 | 
			
		||||
							if(substr($name, 0, 3) == "url" && strlen($value) > 0) {
 | 
			
		||||
								$ok = $ok & $this->try_transload($value, $tags, $source);
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						$this->theme->display_upload_status($page, $ok);
 | 
			
		||||
					}
 | 
			
		||||
					else {
 | 
			
		||||
						$this->theme->display_permission_denied($page);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				else if(!empty($_GET['url']))
 | 
			
		||||
				{
 | 
			
		||||
					if($this->can_upload($user)) {
 | 
			
		||||
						$url = $_GET['url'];
 | 
			
		||||
						$tags = array('tagme');
 | 
			
		||||
						if(!empty($_GET['tags']) && $_GET['tags'] != "null") {
 | 
			
		||||
							$tags = Tag::explode($_GET['tags']);
 | 
			
		||||
						}
 | 
			
		||||
						$ok = $this->try_transload($url, $tags, $url);
 | 
			
		||||
						$this->theme->display_upload_status($page, $ok);
 | 
			
		||||
					}
 | 
			
		||||
					else {
 | 
			
		||||
						$this->theme->display_permission_denied($page);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					if(!$is_full) {
 | 
			
		||||
						$this->theme->display_page($page);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@ -126,6 +182,7 @@ class Upload implements Extension {
 | 
			
		||||
			$sb->add_label("<br/><i>PHP's Max Size Upload = ".ini_get('upload_max_filesize')."</i><br/>");
 | 
			
		||||
			$sb->add_shorthand_int_option("upload_size", "<br/>Max size per file: ");
 | 
			
		||||
			$sb->add_bool_option("upload_anon", "<br/>Allow anonymous uploads: ");
 | 
			
		||||
			$sb->add_bool_option("upload_replace", "<br/>Allow replacing images: ");
 | 
			
		||||
			$sb->add_choice_option("transload_engine", $tes, "<br/>Transload: ");
 | 
			
		||||
			$event->panel->add_block($sb);
 | 
			
		||||
		}
 | 
			
		||||
@ -172,7 +229,7 @@ class Upload implements Extension {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private function try_upload($file, $tags, $source) {
 | 
			
		||||
	private function try_upload($file, $tags, $source, $replace='') {
 | 
			
		||||
		global $page;
 | 
			
		||||
		global $config;
 | 
			
		||||
		global $user;
 | 
			
		||||
@ -195,6 +252,11 @@ class Upload implements Extension {
 | 
			
		||||
				$metadata['tags'] = $tags;
 | 
			
		||||
				$metadata['source'] = $source;
 | 
			
		||||
				
 | 
			
		||||
				/* check if we have been given an image ID to replace */
 | 
			
		||||
				if (!empty($replace)) {
 | 
			
		||||
					$metadata['replace'] = $replace;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				$event = new DataUploadEvent($user, $file['tmp_name'], $metadata);
 | 
			
		||||
 | 
			
		||||
				send_event($event);
 | 
			
		||||
@ -213,7 +275,7 @@ class Upload implements Extension {
 | 
			
		||||
		return $ok;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private function try_transload($url, $tags, $source) {
 | 
			
		||||
	private function try_transload($url, $tags, $source, $replace='') {
 | 
			
		||||
		global $page;
 | 
			
		||||
		global $config;
 | 
			
		||||
 | 
			
		||||
@ -279,6 +341,12 @@ class Upload implements Extension {
 | 
			
		||||
			$metadata['extension'] = $pathinfo['extension'];
 | 
			
		||||
			$metadata['tags'] = $tags;
 | 
			
		||||
			$metadata['source'] = $source;
 | 
			
		||||
			
 | 
			
		||||
			/* check if we have been given an image ID to replace */
 | 
			
		||||
			if (!empty($replace)) {
 | 
			
		||||
				$metadata['replace'] = $replace;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			$event = new DataUploadEvent($user, $tmp_filename, $metadata);
 | 
			
		||||
			try {
 | 
			
		||||
				send_event($event);
 | 
			
		||||
 | 
			
		||||
@ -75,6 +75,54 @@ class UploadTheme extends Themelet {
 | 
			
		||||
		$page->add_block(new Block("Upload", $html, "main", 20));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* only allows 1 file to be uploaded - for replacing another image file */
 | 
			
		||||
	public function display_replace_page(Page $page) {
 | 
			
		||||
		global $config;
 | 
			
		||||
		$tl_enabled = ($config->get_string("transload_engine", "none") != "none");
 | 
			
		||||
 | 
			
		||||
		$upload_list = '';
 | 
			
		||||
		$width = $tl_enabled ? "35%" : "80%";
 | 
			
		||||
		$upload_list .= "
 | 
			
		||||
			<tr>
 | 
			
		||||
				<td width='50'>File</td>
 | 
			
		||||
				<td width='250'><input id='data0' name='data0' type='file'></td>
 | 
			
		||||
		";
 | 
			
		||||
		if($tl_enabled) {
 | 
			
		||||
			$upload_list .= "
 | 
			
		||||
				<td width='50'>URL</td>
 | 
			
		||||
				<td width='250'><input id='url0' name='url0' type='text'></td>
 | 
			
		||||
			";
 | 
			
		||||
		}
 | 
			
		||||
		$upload_list .= "
 | 
			
		||||
			</tr>
 | 
			
		||||
		";
 | 
			
		||||
 | 
			
		||||
		$max_size = $config->get_int('upload_size');
 | 
			
		||||
		$max_kb = to_shorthand_int($max_size);
 | 
			
		||||
		$html = make_form(make_link("upload/replace"), "POST", $multipart=True)."
 | 
			
		||||
				<table id='large_upload_form'>
 | 
			
		||||
					$upload_list
 | 
			
		||||
					<tr><td>Source</td><td colspan='3'><input name='source' type='text'></td></tr>
 | 
			
		||||
					<tr><td colspan='4'><input id='uploadbutton' type='submit' value='Post'></td></tr>
 | 
			
		||||
				</table>
 | 
			
		||||
			</form>
 | 
			
		||||
			<small>(Max file size is $max_kb)</small>
 | 
			
		||||
		";
 | 
			
		||||
/*
 | 
			
		||||
		if($tl_enabled) {
 | 
			
		||||
			$link = make_http(make_link("upload"));
 | 
			
		||||
			$title = "Upload to " . $config->get_string('title');
 | 
			
		||||
			$html .= '<p><a href="javascript:location.href="' .
 | 
			
		||||
				$link . '?url="+location.href+"&tags="+prompt("enter tags")">' .
 | 
			
		||||
				$title . '</a> (Drag & drop onto your bookmarks toolbar, then click when looking at an image)';
 | 
			
		||||
		}
 | 
			
		||||
*/
 | 
			
		||||
		$page->set_title("Replace Image Upload");
 | 
			
		||||
		$page->set_heading("Replace Image Upload");
 | 
			
		||||
		$page->add_block(new NavBlock());
 | 
			
		||||
		$page->add_block(new Block("Replace Image Upload", $html, "main", 20));
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public function display_upload_status(Page $page, $ok) {
 | 
			
		||||
		if($ok) {
 | 
			
		||||
			$page->set_mode("redirect");
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user