aboutsummaryrefslogtreecommitdiff
path: root/mod/lightpics/lib
diff options
context:
space:
mode:
Diffstat (limited to 'mod/lightpics/lib')
-rw-r--r--mod/lightpics/lib/exif.php110
-rw-r--r--mod/lightpics/lib/migrate.php301
-rw-r--r--mod/lightpics/lib/resize.php522
-rw-r--r--mod/lightpics/lib/tidypics.php365
-rw-r--r--mod/lightpics/lib/upload.php119
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