diff options
Diffstat (limited to 'mod/lightpics/lib')
| -rw-r--r-- | mod/lightpics/lib/exif.php | 110 | ||||
| -rw-r--r-- | mod/lightpics/lib/migrate.php | 301 | ||||
| -rw-r--r-- | mod/lightpics/lib/resize.php | 522 | ||||
| -rw-r--r-- | mod/lightpics/lib/tidypics.php | 365 | ||||
| -rw-r--r-- | mod/lightpics/lib/upload.php | 119 | 
5 files changed, 1417 insertions, 0 deletions
diff --git a/mod/lightpics/lib/exif.php b/mod/lightpics/lib/exif.php new file mode 100644 index 000000000..46a73e920 --- /dev/null +++ b/mod/lightpics/lib/exif.php @@ -0,0 +1,110 @@ +<?php +/** + * Exif Processing Library + * + * @package TidypicsExif + */ + +/** + * Pull EXIF data from image file + *  + * @param TidypicsImage $image + */ +function td_get_exif($image) { + +	// catch for those who don't have exif module loaded +	if (!is_callable('exif_read_data')) { +		return; +	} + +	$mime = $image->mimetype; +	if ($mime != 'image/jpeg' && $mime != 'image/pjpeg') { +		return; +	} + +	$filename = $image->getFilenameOnFilestore(); +	$exif = exif_read_data($filename, 'IFD0,EXIF', true); +	if (is_array($exif) && isset($exif['EXIF'])) { +		$data = array_merge($exif['IFD0'], $exif['EXIF']); +		foreach ($data as $key => $value) { +			if (is_string($value)) { +				// there are sometimes unicode characters that cause problems with serialize +				$data[$key] = preg_replace( '/[^[:print:]]/', '', $value); +			} +		} +		$image->tp_exif = serialize($data); +	} +} + +/** + * Grab array of EXIF data for display + *  + * @param TidypicsImage $image + * @return array|false + */ +function tp_exif_formatted($image) { + +	$exif = $image->tp_exif; +	if (!$exif) { +		return false; +	} + +	$exif = unserialize($exif); + +	$model = $exif['Model']; +	if (!$model) { +		$model = "N/A"; +	} +	$exif_data['Model'] = $model; + +	$exposure = $exif['ExposureTime']; +	if (!$exposure) { +		$exposure = "N/A"; +	} +	$exif_data['Shutter'] = $exposure; + +	//got the code snippet below from http://www.zenphoto.org/support/topic.php?id=17 +	//convert the raw values to understandible values +	$Fnumber = explode("/", $exif['FNumber']); +	if ($Fnumber[1] != 0) { +		$Fnumber = $Fnumber[0] / $Fnumber[1]; +	} else { +		$Fnumber = 0; +	} +	if (!$Fnumber) { +		$Fnumber = "N/A"; +	} else { +		$Fnumber = "f/$Fnumber"; +	} +	$exif_data['Aperture'] = $Fnumber; + +	$iso = $exif['ISOSpeedRatings']; +	if (!$iso) { +		$iso = "N/A"; +	} +	$exif_data['ISO Speed'] = $iso; + +	$Focal = explode("/", $exif['FocalLength']); +	if ($Focal[1] != 0) { +		$Focal = $Focal[0] / $Focal[1]; +	} else { +		$Focal = 0; +	} +	if (!$Focal || round($Focal) == "0") { +		$Focal = 0; +	} +	if (round($Focal) == 0) { +		$Focal = "N/A"; +	} else { +		$Focal = round($Focal) . "mm"; +	} +	$exif_data['Focal Length'] = $Focal; + +	$captured = $exif['DateTime']; +	if (!$captured) { +		$captured = "N/A"; +	} +	$exif_data['Captured'] = $captured; + +	return $exif_data; +} diff --git a/mod/lightpics/lib/migrate.php b/mod/lightpics/lib/migrate.php new file mode 100644 index 000000000..8c62126f0 --- /dev/null +++ b/mod/lightpics/lib/migrate.php @@ -0,0 +1,301 @@ +<?php +/** + * Tidypics file plugin migration + * + * Supports moving photos from the files plugin to Tidypics. All of a users + * photos end up in a single album. + * + * Not supported + */ + +// need access to ElggDiskFilestore::make_file_matrix(), which is protected. +// this is a PITA. +class tempFilestore extends ElggDiskFilestore { +	public function make_file_matrix($filename) { +		return parent::make_file_matrix($filename); +	} + +} +$filestore = new tempFilestore(); + + + +/** + * Migrates all pics from files to tidypics. + * + */ +function tidypics_migrate_pics() { +	$limit = 100; +	$r = true; + +	// migrate +	// @todo: should this return false since there was no error? +	if (!$users = tidypics_get_user_guids_with_pics_in_files(0, $limit)) { +		return $r; +	} + +	//echo "Grabbed " . count($users) . " users\n"; +	while (is_array($users) AND count($users) > 0) { +		foreach ($users as $user_guid) { +			// reset the query cache. +			$DB_QUERY_CACHE = array(); +			if (!$user = get_entity($user_guid)) { +				continue; +			} + +			$r = tidypics_migrate_user_pics($user); +		} + +		//echo "Trying to grab $limit more users...\n"; +		$offset = $offset + $limit; +		$users = tidypics_get_user_guids_with_pics_in_files($offset, $limit); +	} + +	return $r; +} + + +/** + * Migrates all pictures owned by a user regardless of + * if they're group or user files. + *  + * @param ElggUser $user User to migrate. + * @return bool on success + */ +function tidypics_migrate_user_pics(ElggUser $user) { +	global $CONFIG, $filestore; + +	$user_guid = $user->getGUID(); + +	// update all entity subtypes in a single go at the end. +	$updated_guids = array(); + +	if (!$pics = tidypics_get_user_pics_from_files($user_guid) OR count($pics) < 1) { +		return false; +	} + +	//echo "{$user->name} ({$user->getGUID()}) has " . count($pics) . " pics.\n"; +	 +	// get an album to migrate into if it already exists. +	// will create later on if it doesn't. +	$user_album_entities = get_entities_from_metadata('migrated_from_files', true, 'object', 'album', $user->getGUID(), 1); +	$user_album_guid = isset($album_entities[0]) ? $album_entities[0]->getGUID() : false; + +	// a list of albums to randomly select a cover for on newly created albums. +	$new_album_guids = array(); + +	foreach ($pics as $pic) { +		// check that it's not already in tidy pics +		if (false !== strpos($pic->filename, 'image/')) { +			//echo "{$pic->filename} ({$pic->getGUID()}) looks like it's already in tidy pics. Ignoring.\n"; +			continue; +		} +	 +		// blank some vars +		$group_pic = $group_album_guid = $group_guid = false; +		 +		// see if we're doing a group file migration. +		if ($pic->container_guid != $user->getGUID()  +			AND $group = get_entity($pic->container_guid) +			AND $group instanceof ElggGroup +		) { +			//echo "{$pic->getGUID()} is in a group!\n"; +			$group_pic = true; +			$group_guid = $group->getGUID(); +			 +			// yes, this is how you get entities by container_guid. +			// yes, it's wrong, wrong, wrong for this function to work this way. +			$group_album_entities = get_entities('object', 'album', $group_guid); +			 +			// get_entities_from_metadata doesn't support container_guid (or owner_guid meaning container_guid) +			// do it the hard way. +			if (is_array($group_album_entities)) { +				foreach ($group_album_entities as $group_album) { +					if ($group_album->migrated_from_files == true) { +						$group_album_guid = $group_album->getGUID(); +						break; +					} +				} +			} +			$album_guid = $group_album_guid; +			$group_album_guids[] = $group_album_guid; +		} else { +			$album_guid = $user_album_guid; +		} +		 +		//echo "album_guid is $album_guid and group_pic is: $group_pic\n"; +		 +		// create an album if we need to. +		if (!$album_guid) { +			//echo "Creating new album...\n"; +			$album = new ElggObject(); +			$album->subtype = 'album'; +			$album->new_album = TP_NEW_ALBUM; +			 +			if ($group_pic) { +				$album->container_guid = $group_guid; +				$album->owner_guid = $group->owner_guid; +				$album->access_id = $group->group_acl; +				$album->title = $group->name; +			} else { +				$album->container_guid = $user_guid; +				$album->owner_guid = $user->getGUID(); +				$album->access_id = ACCESS_DEFAULT; +				$album->title = $user->name; +			} + +			if (!$album->save()) { +				//echo "Couldn't migrate pics for {$user->name} ($user_guid)!\n"; +				return false; +			} +			$album->migrated_from_files = true; +			$album_guid = $album->getGUID(); +			$new_album_guids[] = $album_guid; +			 +			// save the album guid as the users +			if (!$group_pic) { +				$user_album_guid = $album_guid; +			} +		} +		 +		if (!tidypics_migrate_pic_from_files($pic, $album_guid)) { +			//echo "{$pic->filename} ({$pic->getGUID()}) Couldn't be migrated. Ignoring.\n"; +			continue; +		} +	} + +	// randomly pic an image to be the cover for the user gallery +	//$album->cover = $pic_guids[array_rand($pic_guids)]; +	foreach ($new_album_guids as $guid) { +		tidypics_set_random_cover_pic($guid); +	} +	 +	return true; +} + + +/** + * Randomly pics an image from an album to be the cover. + * @return bool on success + */ +function tidypics_set_random_cover_pic($album_guid) { +	global $CONFIG; +	 +	if ($album = get_entity($album_guid) AND $album instanceof TidypicsAlbum) { +		$q = "SELECT guid FROM {$CONFIG->dbprefix}entities WHERE container_guid = $album_guid ORDER BY RAND() limit 1"; +		$pic = get_data($q); +		 +		return $album->cover = $pic[0]->guid; +	} +	 +	return false; +} + +/** + * Migrates a single pic from the file repo. + * @return bool on succes. + */ +function tidypics_migrate_pic_from_files($pic, $album_guid) { +	global $CONFIG, $filestore; + +	// get the subtype id. +	$image_subtype_id = get_subtype_id('object', 'image'); + +	// hold which metadata on the files need to be changes +	// also holds the images we need to move +	$file_md_fields = array('filename', 'thumbnail', 'smallthumb', 'largethumb'); + +	if (!$user = get_entity($pic->owner_guid)) { +		return false; +	} + +	// figure out where to move the files. +	$matrix = $filestore->make_file_matrix($user->username); +	$user_fs_path = $CONFIG->dataroot . $matrix; +	$album_fs_path = $CONFIG->dataroot . $matrix . "image/$album_guid/"; +	if (!is_dir($album_fs_path)) { +		if (!mkdir($album_fs_path, 0700, true)) { +			return false; +		} +	} + +	// change all the 'file/'s to 'image/'s in certain metadata +	// these are also the files we need to move. +	foreach ($file_md_fields as $md_name) { +		// $pic->$md_name = str_replace('file/', 'image/', $pic->$md_name); +		$old_file = $pic->$md_name; +		$new_file = str_replace('file/', "image/$album_guid", $old_file); + +		if (!($old_fp = fopen($user_fs_path . $old_file, 'r')  +		AND $new_fp = fopen($user_fs_path . $new_file, 'w'))) { +			//echo "Could not move {$user_fs_path}{$old_file} to {$user_fs_path}{$new_file}\n"; +			continue; +		} + +		while (!feof($old_fp)) { +			if (!fputs($new_fp, fread($old_fp, 8192))) { +				//echo "Could not move {$user_fs_path}{$old_file} to {$user_fs_path}{$new_file} (Error writing.)\n"; +				break; +			} +		} + +		$pic->$md_name = $new_file; +	} +	// update container. +	// this doesn't work...? +	//$pic->container_guid = $album_guid; + +	// delete old one. +	unlink($user_fs_path . $old_file); + +	$q = "UPDATE {$CONFIG->dbprefix}entities SET subtype = $image_subtype_id, container_guid = $album_guid WHERE guid = {$pic->getGUID()}"; +	//echo "Finished moving {$user_fs_path}{$old_file} to {$user_fs_path}{$new_file}\n"; + +	return update_data($q); +} + + +/** + * Grabs all user IDs with images in the files repo. + * return mixed. False on fail, array of GUIDs on success. + */ +function tidypics_get_user_guids_with_pics_in_files($offset, $limit) { +	global $CONFIG; +	 +	//$simpletype_ms_id = add_metastring('simple_type'); +	//$image_ms_id = add_metastring('image'); +	 +	$q = "SELECT DISTINCT e.owner_guid  +		FROM  +			{$CONFIG->dbprefix}entities as e,  +			{$CONFIG->dbprefix}entity_subtypes as st +			 +		WHERE st.subtype = 'file' +		AND e.subtype = st.id +		LIMIT $offset, $limit"; + +	if (!$data = get_data($q)) { +		return false; +	} +	 +	// return an array of IDs +	$r = array(); +	foreach ($data as $row) { +		$r[] = $row->owner_guid; +	} + +	return $r; +} + +/** + * Gets a list of images for a single user. + * @return array of GUIDs, false on fail. + */ +function tidypics_get_user_pics_from_files($user_guid) { +	if (!$user = get_entity($user_guid) AND $user instanceof ElggUser) { +		return false; +	} + +	// @todo Might have to cycle this through with standard while + foreach. +	return get_entities_from_metadata('simpletype', 'image', 'object', 'file', $user_guid, 5000); +} diff --git a/mod/lightpics/lib/resize.php b/mod/lightpics/lib/resize.php new file mode 100644 index 000000000..aa2eabea1 --- /dev/null +++ b/mod/lightpics/lib/resize.php @@ -0,0 +1,522 @@ +<?php +/** + * Elgg tidypics library of resizing functions + * + * @package TidypicsImageResize + */ + + +/** + * Create thumbnails using PHP GD Library + * + * @param ElggFile holds the image that was uploaded + * @param string   folder to store thumbnail in + * @param string   name of the thumbnail + * @return bool    TRUE on success + */ +function tp_create_gd_thumbnails($file, $prefix, $filestorename) { +	global $CONFIG; + +	$image_sizes = elgg_get_plugin_setting('image_sizes', 'lightpics'); +	if (!$image_sizes) { +		// move this out of library +		register_error(elgg_echo('tidypics:nosettings')); +		forward(REFERER); +		return FALSE; +	} +	$image_sizes = unserialize($image_sizes); + +	$thumb = new ElggFile(); +	$thumb->owner_guid = $file->owner_guid; +	$thumb->container_guid = $file->container_guid; + +	// tiny thumbail +	$thumb->setFilename($prefix."thumb".$filestorename); +	$thumbname = $thumb->getFilenameOnFilestore(); +	$rtn_code = tp_gd_resize(	$file->getFilenameOnFilestore(), +								$thumbname, +								$image_sizes['tiny_image_width'], +								$image_sizes['tiny_image_height'], +								TRUE); +	if (!$rtn_code) { +		return FALSE; +	} +	$file->thumbnail = $prefix."thumb".$filestorename; + +	// album thumbnail +	global $CONFIG; +	$CONFIG->debug = 'WARNING'; +	$thumb->setFilename($prefix."smallthumb".$filestorename); +	$thumbname = $thumb->getFilenameOnFilestore(); +	$rtn_code = tp_gd_resize(	$file->getFilenameOnFilestore(), +								$thumbname, +								$image_sizes['small_image_width'], +								$image_sizes['small_image_height'], +								TRUE); +	if (!$rtn_code) { +		return FALSE; +	} +	$file->smallthumb = $prefix."smallthumb".$filestorename; +	unset($CONFIG->debug); + +	// main image +	$thumb->setFilename($prefix."largethumb".$filestorename); +	$thumbname = $thumb->getFilenameOnFilestore(); +	$rtn_code = tp_gd_resize(	$file->getFilenameOnFilestore(), +								$thumbname, +								$image_sizes['large_image_width'], +								$image_sizes['large_image_height'], +								FALSE); +	if (!$rtn_code) { +		return FALSE; +	} +	$file->largethumb = $prefix."largethumb".$filestorename; + + +	unset($thumb); + +	return TRUE; +} + +/** + * Writes resized version of an already uploaded image - original from Elgg filestore.php + * Saves it in the same format as uploaded + * + * @param string $input_name The name of the file on the disk + * @param string $output_name The name of the file to be written + * @param int $maxwidth The maximum width of the resized image + * @param int $maxheight The maximum height of the resized image + * @param TRUE|FALSE $square If set to TRUE, will take the smallest of maxwidth and maxheight and use it to set the dimensions on all size; the image will be cropped. + * @return bool TRUE on success or FALSE on failure + */ +function tp_gd_resize($input_name, $output_name, $maxwidth, $maxheight, $square = FALSE, $x1 = 0, $y1 = 0, $x2 = 0, $y2 = 0) { + +	// Get the size information from the image +	$imgsizearray = getimagesize($input_name); +	if (!$imgsizearray) { +		return FALSE; +	} + +	// Get width and height of image +	$width = $imgsizearray[0]; +	$height = $imgsizearray[1]; + +	$params = tp_im_calc_resize_params($width, $height, $maxwidth, $maxheight, $square, $x1, $y1, $x2, $y2); +	if (!$params) { +		return FALSE; +	} +	 +	$new_width = $params['new_width']; +	$new_height = $params['new_height']; +	$region_width = $params['region_width']; +	$region_height = $params['region_height']; +	$widthoffset = $params['width_offset']; +	$heightoffset = $params['height_offset']; + +	$accepted_formats = array( +			'image/jpeg' => 'jpeg', +			'image/pjpeg' => 'jpeg', +			'image/png' => 'png', +			'image/x-png' => 'png', +			'image/gif' => 'gif' +	); + +	// make sure the function is available +	$function = "imagecreatefrom" . $accepted_formats[$imgsizearray['mime']]; +	if (!is_callable($function)) { +		return FALSE; +	} + +	// load old image +	$oldimage = $function($input_name); +	if (!$oldimage) { +		return FALSE; +	} + +	// allocate the new image +	$newimage = imagecreatetruecolor($new_width, $new_height); +	if (!$newimage) { +		return FALSE; +	} + +	$rtn_code = imagecopyresampled(	$newimage, +									$oldimage, +									0, +									0, +									$widthoffset, +									$heightoffset, +									$new_width, +									$new_height, +									$region_width, +									$region_height); +	if (!$rtn_code) { +		return $rtn_code; +	} + +	switch ($imgsizearray['mime']) { +		case 'image/jpeg': +		case 'image/pjpeg': +			$rtn_code = imagejpeg($newimage, $output_name, 85); +			break; +		case 'image/png': +		case 'image/x-png': +			$rtn_code = imagepng($newimage, $output_name); +			break; +		case 'image/gif': +			$rtn_code = imagegif($newimage, $output_name); +			break; +	} + +	imagedestroy($newimage); +	imagedestroy($oldimage); + +	return $rtn_code; +} + + +/** + * Create thumbnails using PHP imagick extension + * + * @param ElggFile holds the image that was uploaded + * @param string   folder to store thumbnail in + * @param string   name of the thumbnail + * @return bool    TRUE on success + */ +function tp_create_imagick_thumbnails($file, $prefix, $filestorename) { +	$image_sizes = elgg_get_plugin_setting('image_sizes', 'tidypics'); +	if (!$image_sizes) { +		register_error(elgg_echo('tidypics:nosettings')); +		return FALSE; +	} +	$image_sizes = unserialize($image_sizes); + +	$thumb = new ElggFile(); +	$thumb->owner_guid = $file->owner_guid; +	$thumb->container_guid = $file->container_guid; + +	// tiny thumbnail +	$thumb->setFilename($prefix."thumb".$filestorename); +	$thumbname = $thumb->getFilenameOnFilestore(); +	$rtn_code = tp_imagick_resize(	$file->getFilenameOnFilestore(), +									$thumbname, +									$image_sizes['tiny_image_width'], +									$image_sizes['tiny_image_height'], +									TRUE); +	if (!$rtn_code) { +		return FALSE; +	} +	$file->thumbnail = $prefix."thumb".$filestorename; + +	// album thumbnail +	$thumb->setFilename($prefix."smallthumb".$filestorename); +	$thumbname = $thumb->getFilenameOnFilestore(); +	$rtn_code = tp_imagick_resize(	$file->getFilenameOnFilestore(), +									$thumbname, +									$image_sizes['small_image_width'], +									$image_sizes['small_image_height'], +									TRUE); +	if (!$rtn_code) { +		return FALSE; +	} +	$file->smallthumb = $prefix."smallthumb".$filestorename; + +	// main image +	$thumb->setFilename($prefix."largethumb".$filestorename); +	$thumbname = $thumb->getFilenameOnFilestore(); +	$rtn_code = tp_imagick_resize(	$file->getFilenameOnFilestore(), +									$thumbname, +									$image_sizes['large_image_width'], +									$image_sizes['large_image_height'], +									FALSE); +	if (!$rtn_code) { +		return FALSE; +	} +	$file->largethumb = $prefix."largethumb".$filestorename; + +	unset($thumb); + +	return TRUE; +} + + +/** + * Resize using PHP imagick extension + * + * Writes resized version of an already uploaded image + * + * + * @param string $input_name The name of the file input field on the submission form + * @param string $output_name The name of the file to be written + * @param int $maxwidth The maximum width of the resized image + * @param int $maxheight The maximum height of the resized image + * @param TRUE|FALSE $square If set to TRUE, will take the smallest of maxwidth and maxheight and use it to set the dimensions on all size; the image will be cropped. + * @return bool TRUE on success + */ +function tp_imagick_resize($input_name, $output_name, $maxwidth, $maxheight, $square = FALSE, $x1 = 0, $y1 = 0, $x2 = 0, $y2 = 0) { + +	// Get the size information from the image +	$imgsizearray = getimagesize($input_name); +	if (!$imgsizearray) { +		return FALSE; +	} + +	// Get width and height +	$width = $imgsizearray[0]; +	$height = $imgsizearray[1]; +	 +	$params = tp_im_calc_resize_params($width, $height, $maxwidth, $maxheight, $square, $x1, $y1, $x2, $y2); +	if (!$params) { +		return FALSE; +	} +	 +	$new_width = $params['new_width']; +	$new_height = $params['new_height']; +	$region_width = $params['region_width']; +	$region_height = $params['region_height']; +	$widthoffset = $params['width_offset']; +	$heightoffset = $params['height_offset']; + +	try { +		$img = new Imagick($input_name); +	} catch (ImagickException $e) { +		return FALSE; +	} + +	$img->cropImage($region_width, $region_height, $widthoffset, $heightoffset); + +	// use the default IM filter (windowing filter), I think 1 means default blurring or number of lobes +	$img->resizeImage($new_width, $new_height, imagick::FILTER_LANCZOS, 1); +	$img->setImagePage($new_width, $new_height, 0, 0); + +	if ($img->writeImage($output_name) != TRUE) { +		$img->destroy(); +		return FALSE; +	} + +	$img->destroy(); + +	return TRUE; +} + +/** + * Create thumbnails using ImageMagick executables + * + * @param ElggFile holds the image that was uploaded + * @param string   folder to store thumbnail in + * @param string   name of the thumbnail + * @return bool    TRUE on success + */ +function tp_create_im_cmdline_thumbnails($file, $prefix, $filestorename) { +	$image_sizes = elgg_get_plugin_setting('image_sizes', 'tidypics'); +	if (!$image_sizes) { +		register_error(elgg_echo('tidypics:nosettings')); +		return FALSE; +	} +	$image_sizes = unserialize($image_sizes); + +	$thumb = new ElggFile(); +	$thumb->owner_guid = $file->owner_guid; +	$thumb->container_guid = $file->container_guid; + +	// tiny thumbnail +	$thumb->setFilename($prefix."thumb".$filestorename); +	$thumbname = $thumb->getFilenameOnFilestore(); +	$rtn_code = tp_im_cmdline_resize(	$file->getFilenameOnFilestore(), +										$thumbname, +										$image_sizes['tiny_image_width'], +										$image_sizes['tiny_image_height'], +										TRUE); +	if (!$rtn_code) { +		return FALSE; +	} +	$file->thumbnail = $prefix."thumb".$filestorename; + + +	// album thumbnail +	$thumb->setFilename($prefix."smallthumb".$filestorename); +	$thumbname = $thumb->getFilenameOnFilestore(); +	$rtn_code = tp_im_cmdline_resize(	$file->getFilenameOnFilestore(), +										$thumbname, +										$image_sizes['small_image_width'], +										$image_sizes['small_image_height'], +										TRUE); +	if (!$rtn_code) { +		return FALSE; +	} +	$file->smallthumb = $prefix."smallthumb".$filestorename; + +	// main image +	$thumb->setFilename($prefix."largethumb".$filestorename); +	$thumbname = $thumb->getFilenameOnFilestore(); +	$rtn_code = tp_im_cmdline_resize(	$file->getFilenameOnFilestore(), +										$thumbname, +										$image_sizes['large_image_width'], +										$image_sizes['large_image_height'], +										FALSE); +	if (!$rtn_code) { +		return FALSE; +	} +	$file->largethumb = $prefix."largethumb".$filestorename; + +	unset($thumb); + +	return TRUE; +} + +/** + * Gets the jpeg contents of the resized version of an already uploaded image + * (Returns FALSE if the uploaded file was not an image) + * + * @param string $input_name The name of the file input field on the submission form + * @param string $output_name The name of the file to be written + * @param int $maxwidth The maximum width of the resized image + * @param int $maxheight The maximum height of the resized image + * @param TRUE|FALSE $square If set to TRUE, will take the smallest of maxwidth and maxheight and use it to set the dimensions on all size; the image will be cropped. + * @return bool + */ +function tp_im_cmdline_resize($input_name, $output_name, $maxwidth, $maxheight, $square = FALSE, $x1 = 0, $y1 = 0, $x2 = 0, $y2 = 0) { + + +	// Get the size information from the image +	$imgsizearray = getimagesize($input_name); +	if (!$imgsizearray) { +		return FALSE; +	} + +	// Get width and height +	$orig_width = $imgsizearray[0]; +	$orig_height = $imgsizearray[1]; + +	$params = tp_im_calc_resize_params($orig_width, $orig_height, $maxwidth, $maxheight, $square, $x1, $y1, $x2, $y2); +	if (!$params) { +		return FALSE; +	} + +	$newwidth = $params['new_width']; +	$newheight = $params['new_height']; +	 +	$accepted_formats = array( +			'image/jpeg' => 'jpeg', +			'image/pjpeg' => 'jpeg', +			'image/png' => 'png', +			'image/x-png' => 'png', +			'image/gif' => 'gif' +	); + +	// If it's a file we can manipulate ... +	if (!array_key_exists($imgsizearray['mime'],$accepted_formats)) { +		return FALSE; +	} + +	$im_path = elgg_get_plugin_setting('im_path', 'tidypics'); +	if (!$im_path) { +		$im_path = "/usr/bin/"; +	} +	if (substr($im_path, strlen($im_path)-1, 1) != "/") { +		$im_path .= "/"; +	} + +	// see imagemagick web site for explanation of these parameters +	// the ^ in the resize means those are minimum width and height values +	$command = $im_path . "convert \"$input_name\" -resize ".$newwidth."x".$newheight."^ -gravity center -extent ".$newwidth."x".$newheight." \"$output_name\""; +	$output = array(); +	$ret = 0; +	exec($command, $output, $ret); +	if ($ret == 127) { +		trigger_error('Tidypics warning: Image Magick convert is not found', E_USER_WARNING); +		return FALSE; +	} else if ($ret > 0) { +		trigger_error('Tidypics warning: Image Magick convert failed', E_USER_WARNING); +		return FALSE; +	} +	 +	return TRUE; +} + +/** + * Calculate the resizing/cropping parameters + * + * @param int $orig_width + * @param int $orig_height + * @param int $new_width + * @param int $new_height + * @param bool $square + * @param int $x1 + * @param int $y1 + * @param int $x2 + * @param int $y2 + * @return array|FALSE + */ +function tp_im_calc_resize_params($orig_width, $orig_height, $new_width, $new_height, $square = FALSE, $x1 = 0, $y1 = 0, $x2 = 0, $y2 = 0) { +	// crop image first? +	$crop = TRUE; +	if ($x1 == 0 && $y1 == 0 && $x2 == 0 && $y2 == 0) { +		$crop = FALSE; +	} + +	// how large a section of the image has been selected +	if ($crop) { +		$region_width = $x2 - $x1; +		$region_height = $y2 - $y1; +	} else { +		// everything selected if no crop parameters +		$region_width = $orig_width; +		$region_height = $orig_height; +	} + +	// determine cropping offsets +	if ($square) { +		// asking for a square image back + +		// detect case where someone is passing crop parameters that are not for a square +		if ($crop == TRUE && $region_width != $region_height) { +			return FALSE; +		} + +		// size of the new square image +		$new_width = $new_height = min($new_width, $new_height); + +		// find largest square that fits within the selected region +		$region_width = $region_height = min($region_width, $region_height); + +		// set offsets for crop +		if ($crop) { +			$widthoffset = $x1; +			$heightoffset = $y1; +			$orig_width = $x2 - $x1; +			$orig_height = $orig_width; +		} else { +			// place square region in the center +			$widthoffset = floor(($orig_width - $region_width) / 2); +			$heightoffset = floor(($orig_height - $region_height) / 2); +		} +	} else { +		// non-square new image + +		// maintain aspect ratio of original image/crop +		if (($region_height / (float)$new_height) > ($region_width / (float)$new_width)) { +			$new_width = floor($new_height * $region_width / (float)$region_height); +		} else { +			$new_height = floor($new_width * $region_height / (float)$region_width); +		} + +		// by default, use entire image +		$widthoffset = 0; +		$heightoffset = 0; + +		if ($crop) { +			$widthoffset = $x1; +			$heightoffset = $y1; +		} +	} + +	$resize_params = array(); +	$resize_params['new_width'] = $new_width; +	$resize_params['new_height'] = $new_height; +	$resize_params['region_width'] = $region_width; +	$resize_params['region_height'] = $region_height; +	$resize_params['width_offset'] = $widthoffset; +	$resize_params['height_offset'] = $heightoffset; + +	return $resize_params; +}
\ No newline at end of file diff --git a/mod/lightpics/lib/tidypics.php b/mod/lightpics/lib/tidypics.php new file mode 100644 index 000000000..1419a260a --- /dev/null +++ b/mod/lightpics/lib/tidypics.php @@ -0,0 +1,365 @@ +<?php +/** + * Elgg tidypics library of common functions + * + * @package TidypicsCommon + */ + +/** + * Get images for display on front page + * + * @param int number of images + * @param int (optional) guid of owner + * @return string of html for display + * + * To use with the custom index plugin, use something like this: +	 + if (is_plugin_enabled('tidypics')) { + ?> + <!-- display latest photos --> + <div class="index_box"> +	<h2><a href="<?php echo $vars['url']; ?>pg/photos/world/"><?php echo elgg_echo("tidypics:mostrecent"); ?></a></h2> +	<div class="contentWrapper"> + <?php + echo tp_get_latest_photos(5); + ?> +	</div> + </div> + <?php + } + ?> + + * Good luck + */ +function tp_get_latest_photos($num_images, $owner_guid = 0, $context = 'front') { +	$prev_context = get_context(); +	set_context($context); +	$image_html = elgg_list_entities(array( +		'type' => 'object', +		'subtype' => 'image', +		'owner_guid' => $owner_guid, +		'limit' => $num_images, +		'full_view' => false, +		'pagination' => false, +	)); +	set_context($prev_context); +	return $image_html; +} + + +/** + * Get image directory path + * + * Each album gets a subdirectory based on its container id + * + * @return string	path to image directory + */ +function tp_get_img_dir() { +	$file = new ElggFile(); +    $file->setFilename('image/'); +	return $file->getFilenameOnFilestore(); +} + +/** + * Prepare vars for a form, pulling from an entity or sticky forms. + *  + * @param type $entity + * @return type + */ +function tidypics_prepare_form_vars($entity = null) { +	// input names => defaults +	$values = array( +		'title' => '', +		'description' => '', +		'access_id' => ACCESS_DEFAULT, +		'tags' => '', +		'container_guid' => elgg_get_page_owner_guid(), +		'guid' => null, +		'entity' => $entity, +	); + +	if ($entity) { +		foreach (array_keys($values) as $field) { +			if (isset($entity->$field)) { +				$values[$field] = $entity->$field; +			} +		} +	} + +	if (elgg_is_sticky_form('tidypics')) { +		$sticky_values = elgg_get_sticky_values('tidypics'); +		foreach ($sticky_values as $key => $value) { +			$values[$key] = $value; +		} +	} + +	elgg_clear_sticky_form('tidypics'); + +	return $values; +} + +/** + * Returns available image libraries. + *  + * @return string + */ +function tidypics_get_image_libraries() { +	$options = array(); +	if (extension_loaded('gd')) { +		$options['GD'] = 'GD'; +	} + +	if (extension_loaded('imagick')) { +		$options['ImageMagickPHP'] = 'imagick PHP extension'; +	} + +	$disablefunc = explode(',', ini_get('disable_functions')); +	if (is_callable('exec') && !in_array('exec', $disablefunc)) { +		$options['ImageMagick'] = 'ImageMagick executable'; +	} + +	return $options; +} + +/** + * Are there upgrade scripts to be run? + * + * @return bool  + */ +function tidypics_is_upgrade_available() { +	// sets $version based on code +	require_once elgg_get_plugins_path() . "lightpics/version.php"; +	return true; + +	$local_version = elgg_get_plugin_setting('version', 'tidypics'); +	if ($local_version === false) { +		// no version set so either new install or really old one +		if (!get_subtype_class('object', 'image') || !get_subtype_class('object', 'album')) { +			$local_version = 0; +		} else { +			// set initial version for new install +			elgg_set_plugin_setting('version', $version, 'tidypics'); +			$local_version = $version; +		} +	} elseif ($local_version === '1.62') { +		// special work around to handle old upgrade system +		$local_version = 2010010101; +		elgg_set_plugin_setting('version', $local_version, 'tidypics'); +	} + +	if ($local_version == $version) { +		return false; +	} else { +		return true; +	} +} + +/** + * This lists the photos in an album as sorted by metadata + * + * @todo this only supports a single album. The only case for use a + * procedural function like this instead of TidypicsAlbum::viewImgaes() is to + * fetch images across albums as a helper to elgg_get_entities(). + * This should function be deprecated or fixed to work across albums. + * + * @param array $options + * @return string + */ +function tidypics_list_photos(array $options = array()) { +	global $autofeed; +	$autofeed = true; + +	$defaults = array( +		'offset' => (int) max(get_input('offset', 0), 0), +		'limit' => (int) max(get_input('limit', 10), 0), +		'full_view' => true, +		'list_type_toggle' => false, +		'pagination' => true, +	); + +	$options = array_merge($defaults, $options); + +	$options['count'] = true; +	$count = elgg_get_entities($options); + +	$album = get_entity($options['container_guid']); +	if ($album) { +		$guids = $album->getImageList(); +		// need to pass all the guids and handle the limit / offset in sql +		// to avoid problems with the navigation +		//$guids = array_slice($guids, $options['offset'], $options['limit']); +		$options['guids'] = $guids; +		unset($options['container_guid']); +	} +	$options['count'] = false; +	$entities = elgg_get_entities($options); + +	$keys = array(); +	foreach ($entities as $entity) { +		$keys[] = $entity->guid; +	} +	 +	$entities = array_combine($keys, $entities); + +	$sorted_entities = array(); +	foreach ($guids as $guid) { +		if (isset($entities[$guid])) { +			$sorted_entities[] = $entities[$guid]; +		} +	} + +	// for this function count means the total number of entities +	// and is required for pagination +	$options['count'] = $count; + +	return elgg_view_entity_list($sorted_entities, $options); +} + +/** + * Returns just a guid from a database $row. Used in elgg_get_entities()'s callback. + * + * @param stdClass $row + * @return type + */ +function tp_guid_callback($row) { +	return ($row->guid) ? $row->guid : false; +} + + +/********************************************************************* + * the functions below replace broken core functions or add functions  + * that could/should exist in the core + */ + +function tp_view_entity_list($entities, $count, $offset, $limit, $fullview = true, $viewtypetoggle = false, $pagination = true) { +	$context = get_context(); + +	$html = elgg_view('tidypics/gallery',array( +			'entities' => $entities, +			'count' => $count, +			'offset' => $offset, +			'limit' => $limit, +			'baseurl' => $_SERVER['REQUEST_URI'], +			'fullview' => $fullview, +			'context' => $context, +			'viewtypetoggle' => $viewtypetoggle, +			'viewtype' => get_input('search_viewtype','list'), +			'pagination' => $pagination +	)); + +	return $html; +} + +function tp_get_entities_from_annotations_calculate_x($sum = "sum", $entity_type = "", $entity_subtype = "", $name = "", $mdname = '', $mdvalue = '', $owner_guid = 0, $limit = 10, $offset = 0, $orderdir = 'desc', $count = false) { +	global $CONFIG; + +	$sum = sanitise_string($sum); +	$entity_type = sanitise_string($entity_type); +	$entity_subtype = get_subtype_id($entity_type, $entity_subtype); +	$name = get_metastring_id($name); +	$limit = (int) $limit; +	$offset = (int) $offset; +	$owner_guid = (int) $owner_guid; +	if (!empty($mdname) && !empty($mdvalue)) { +		$meta_n = get_metastring_id($mdname); +		$meta_v = get_metastring_id($mdvalue); +	} + +	if (empty($name)) return 0; + +	$where = array(); + +	if ($entity_type!="") +		$where[] = "e.type='$entity_type'"; +	if ($owner_guid > 0) +		$where[] = "e.owner_guid = $owner_guid"; +	if ($entity_subtype) +		$where[] = "e.subtype=$entity_subtype"; +	if ($name!="") +		$where[] = "a.name_id='$name'"; + +	if (!empty($mdname) && !empty($mdvalue)) { +		if ($mdname!="") +			$where[] = "m.name_id='$meta_n'"; +		if ($mdvalue!="") +			$where[] = "m.value_id='$meta_v'"; +	} + +	if ($sum != "count") +		$where[] = "a.value_type='integer'"; // Limit on integer types + +	if (!$count) { +		$query = "SELECT distinct e.*, $sum(ms.string) as sum "; +	} else { +		$query = "SELECT count(distinct e.guid) as num, $sum(ms.string) as sum "; +	} +	$query .= " from {$CONFIG->dbprefix}entities e JOIN {$CONFIG->dbprefix}annotations a on a.entity_guid = e.guid JOIN {$CONFIG->dbprefix}metastrings ms on a.value_id=ms.id "; + +	if (!empty($mdname) && !empty($mdvalue)) { +		$query .= " JOIN {$CONFIG->dbprefix}metadata m on m.entity_guid = e.guid "; +	} + +	$query .= " WHERE "; +	foreach ($where as $w) +		$query .= " $w and "; +	$query .= get_access_sql_suffix("a"); // now add access +	$query .= ' and ' . get_access_sql_suffix("e"); // now add access +	if (!$count) $query .= ' group by e.guid'; + +	if (!$count) { +		$query .= ' order by sum ' . $orderdir; +		$query .= ' limit ' . $offset . ' , ' . $limit; +		return get_data($query, "entity_row_to_elggstar"); +	} else { +		if ($row = get_data_row($query)) { +			return $row->num; +		} +	} +	return false; +} + +/** + * Is page owner a group - convenience function + * + * @return true/false + */ +function tp_is_group_page() { + +	if ($group = page_owner_entity()) { +		if ($group instanceof ElggGroup) +			return true; +	} + +	return false; +} + + +/** + * Is the request from a known browser + * + * @return true/false + */ +function tp_is_person() { +	$known = array('msie', 'mozilla', 'firefox', 'safari', 'webkit', 'opera', 'netscape', 'konqueror', 'gecko'); + +	$agent = strtolower($_SERVER['HTTP_USER_AGENT']); + +	foreach ($known as $browser) { +		if (strpos($agent, $browser) !== false) { +			return true; +		} +	} + +	return false; +} + +/** + * Convenience function for listing recent images + * + * @param int $max + * @param bool $pagination + * @return string + */ +function tp_mostrecentimages($max = 8, $pagination = true) { +	return list_entities("object", "image", 0, $max, false, false, $pagination); +} diff --git a/mod/lightpics/lib/upload.php b/mod/lightpics/lib/upload.php new file mode 100644 index 000000000..a83323f16 --- /dev/null +++ b/mod/lightpics/lib/upload.php @@ -0,0 +1,119 @@ +<?php +/** + * Helper library for working with uploads + */ + +/** + * Guess on the mimetype based on file extension + * + * @param string $originalName + * @return string + */ +function tp_upload_get_mimetype($originalName) { +	$extension = substr(strrchr($originalName, '.'), 1); +	switch (strtolower($extension)) { +		case 'png': +			return 'image/png'; +			break; +		case 'gif': +			return 'image/gif'; +			break; +		case 'jpg': +		case 'jpeg': +			return 'image/jpeg'; +			break; +		default: +			return 'unknown'; +			break; +	} +} + +/** + * Check if this is an image + *  + * @param string $mime + * @return bool false = not image + */ +function tp_upload_check_format($mime) { +	$accepted_formats = array( +		'image/jpeg', +		'image/png', +		'image/gif', +		'image/pjpeg', +		'image/x-png', +	); + +	if (!in_array($mime, $accepted_formats)) { +		return false; +	} +	return true; +} + +/** + * Check if there is enough memory to process this image + *  + * @param string $image_lib + * @param int $num_pixels + * @return bool false = not enough memory + */ +function tp_upload_memory_check($image_lib, $num_pixels) { +	if ($image_lib !== 'GD') { +		return true; +	} + +	$mem_avail = ini_get('memory_limit'); +	$mem_avail = rtrim($mem_avail, 'M'); +	$mem_avail = $mem_avail * 1024 * 1024; +	$mem_used = memory_get_usage(); +	$mem_required = ceil(5.35 * $num_pixels); + +	$mem_avail = $mem_avail - $mem_used - 2097152; // 2 MB buffer +	if ($mem_required > $mem_avail) { +		return false; +	} + +	return true; +} + +/** + * Check if image is within limits + * + * @param int $image_size + * @return bool false = too large + */ +function tp_upload_check_max_size($image_size) { +	$max_file_size = (float) elgg_get_plugin_setting('maxfilesize', 'tidypics'); +	if (!$max_file_size) { +		// default to 5 MB if not set +		$max_file_size = 5; +	} +	// convert to bytes from MBs +	$max_file_size = 1024 * 1024 * $max_file_size; +	return $image_size <= $max_file_size; +} + +/** + * Check if this image pushes user over quota + * + * @param int $image_size + * @param int $owner_guid + * @return bool false = exceed quota + */ +function tp_upload_check_quota($image_size, $owner_guid) { +	static $quota; +	 +	if (!isset($quota)) { +		$quota = elgg_get_plugin_setting('quota', 'tidypics'); +		$quota = 1024 * 1024 * $quota; +	} + +	if ($quota == 0) { +		// no quota +		return true; +	} + +	$owner = get_entity($owner_guid); +	$image_repo_size_md = (int)$owner->image_repo_size; +	 +	return ($image_repo_size + $image_size) < $quota; +}
\ No newline at end of file  | 
