diff options
Diffstat (limited to 'mod/lightpics/classes')
-rw-r--r-- | mod/lightpics/classes/TidypicsAlbum.php | 375 | ||||
-rw-r--r-- | mod/lightpics/classes/TidypicsImage.php | 406 |
2 files changed, 781 insertions, 0 deletions
diff --git a/mod/lightpics/classes/TidypicsAlbum.php b/mod/lightpics/classes/TidypicsAlbum.php new file mode 100644 index 000000000..0cb8bd84e --- /dev/null +++ b/mod/lightpics/classes/TidypicsAlbum.php @@ -0,0 +1,375 @@ +<?php +/** + * Tidypics Album class + * + * @package TidypicsAlbum + * @author Cash Costello + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License v2 + */ + + +class TidypicsAlbum extends ElggObject { + /** + * Sets the internal attributes + */ + protected function initializeAttributes() { + parent::initializeAttributes(); + + $this->attributes['subtype'] = "album"; + } + + /** + * Constructor + * @param mixed $guid + */ + public function __construct($guid = null) { + parent::__construct($guid); + } + + /** + * Save an album + * + * @return bool + */ + public function save() { + + if (!isset($this->new_album)) { + $this->new_album = true; + } + + if (!isset($this->last_notified)) { + $this->last_notified = 0; + } + + if (!parent::save()) { + return false; + } + + mkdir(tp_get_img_dir() . $this->guid, 0755, true); + + elgg_trigger_event('create', 'album', $this); + + return true; + } + + /** + * Delete album + * + * @return bool + */ + public function delete() { + + $this->deleteImages(); + $this->deleteAlbumDir(); + + return parent::delete(); + } + + /** + * Get the title of the photo album + * + * @return string + */ + public function getTitle() { + return $this->title; + } + + /** + * Get the URL for this album + * + * @return string + */ + public function getURL() { + $title = elgg_get_friendly_title($this->getTitle()); + $url = "photos/album/$this->guid/$title"; + return elgg_normalize_url($url); + } + + /** + * Get an array of image objects + * + * @param int $limit + * @param int $offset + * @return array + */ + public function getImages($limit, $offset = 0) { + $imageList = $this->getImageList(); + if ($offset > count($imageList)) { + return array(); + } + + $imageList = array_slice($imageList, $offset, $limit); + + $images = array(); + foreach ($imageList as $guid) { + $images[] = get_entity($guid); + } + return $images; + } + + /** + * View a list of images + * + * @param array $options Options to pass to elgg_view_entity_list() + * @return string + */ + public function viewImages(array $options = array()) { + $count = $this->getSize(); + + if ($count == 0) { + return ''; + } + + $defaults = array( + 'count' => $count, + 'limit' => 16, + 'offset' => max(get_input('offset'), 0), + 'full_view' => false, + 'list_type' => 'gallery', + 'list_type_toggle' => false, + 'pagination' => true, + 'gallery_class' => 'tidypics-gallery elgg-lightbox-gallery', + ); + + $options = array_merge($defaults, (array) $options); + $images = $this->getImages($options['limit'], $options['offset']); + + if (count($images) == 0) { + return ''; + } + + return elgg_view_entity_list($images, $options); + } + + /** + * Returns the cover image entity + * @return TidypicsImage + */ + public function getCoverImage() { + return get_entity($this->getCoverImageGuid()); + } + + /** + * Get the GUID of the album cover + * + * @return int + */ + public function getCoverImageGuid() { + if ($this->getSize() == 0) { + return 0; + } + + $guid = $this->cover; + $imageList = $this->getImageList(); + if (!in_array($guid, $imageList)) { + // select random photo to be cover + $index = array_rand($imageList, 1); + $guid = $imageList[$index]; + $this->cover = $guid; + } + return $guid; + } + + /** + * Set the GUID for the album cover + * + * @param int $guid + * @return bool + */ + public function setCoverImageGuid($guid) { + $imageList = $this->getImageList(); + if (!in_array($guid, $imageList)) { + return false; + } + $this->cover = $guid; + return true; + } + + /** + * Get the number of photos in the album + * + * @return int + */ + public function getSize() { + return count($this->getImageList()); + } + + /** + * Returns an order list of image guids + * + * @return array + */ + public function getImageList() { + $listString = $this->orderedImages; + if (!$listString) { + return array(); + } + $list = unserialize($listString); + + // if empty don't need to check the permissions. + if (!$list) { + return array(); + } + + // check access levels + $guidsString = implode(',', $list); + + $options = array( + 'wheres' => array("e.guid IN ($guidsString)"), + 'order_by' => "FIELD(e.guid, $guidsString)", + 'callback' => 'tp_guid_callback', + 'limit' => ELGG_ENTITIES_NO_VALUE + ); + + $list = elgg_get_entities($options); + return $list; + } + + /** + * Sets the album image order + * + * @param array $list An indexed array of image guids + * @return bool + */ + public function setImageList($list) { + // validate data + foreach ($list as $guid) { + if (!filter_var($guid, FILTER_VALIDATE_INT)) { + return false; + } + } + + $listString = serialize($list); + $this->orderedImages = $listString; + return true; + } + + /** + * Add new images to the front of the image list + * + * @param array $list An indexed array of image guids + * @return bool + */ + public function prependImageList($list) { + $currentList = $this->getImageList(); + $list = array_merge($list, $currentList); + return $this->setImageList($list); + } + + /** + * Get the previous image in the album. Wraps around to the last image if given the first. + * + * @param int $guid GUID of the current image + * @return TidypicsImage + */ + public function getPreviousImage($guid) { + $imageList = $this->getImageList(); + $key = array_search($guid, $imageList); + if ($key === FALSE) { + return null; + } + $key--; + if ($key < 0) { + return get_entity(end($imageList)); + } + return get_entity($imageList[$key]); + } + + /** + * Get the next image in the album. Wraps around to the first image if given the last. + * + * @param int $guid GUID of the current image + * @return TidypicsImage + */ + public function getNextImage($guid) { + $imageList = $this->getImageList(); + $key = array_search($guid, $imageList); + if ($key === FALSE) { + return null; + } + $key++; + if ($key >= count($imageList)) { + return get_entity($imageList[0]); + } + return get_entity($imageList[$key]); + } + + /** + * Get the index into the album for a particular image + * + * @param int $guid GUID of the image + * @return int + */ + public function getIndex($guid) { + return array_search($guid, $this->getImageList()) + 1; + } + + /** + * Remove an image from the album list + * + * @param int $imageGuid + * @return bool + */ + public function removeImage($imageGuid) { + $imageList = $this->getImageList(); + $key = array_search($imageGuid, $imageList); + if ($key === false) { + return false; + } + + unset($imageList[$key]); + $this->setImageList($imageList); + + return true; + } + + /** + * Has enough time elapsed between the last_notified and notify_interval setting? + * + * @return bool + */ + public function shouldNotify() { + return time() - $this->last_notified > elgg_get_plugin_setting('notify_interval', 'tidypics'); + } + + /** + * Delete all the images in this album + * + * @todo ElggBatch? + */ + protected function deleteImages() { + $images = elgg_get_entities(array( + "type=" => "object", + "subtype" => "image", + "container_guid" => $this->guid, + "limit" => ELGG_ENTITIES_NO_VALUE, + )); + if ($images) { + foreach ($images as $image) { + if ($image) { + $image->delete(); + } + } + } + } + + /** + * Delete the album directory on disk + */ + protected function deleteAlbumDir() { + $tmpfile = new ElggFile(); + $tmpfile->setFilename('image/' . $this->guid . '/._tmp_del_tidypics_album_'); + $tmpfile->subtype = 'image'; + $tmpfile->owner_guid = $this->owner_guid; + $tmpfile->container_guid = $this->guid; + $tmpfile->open("write"); + $tmpfile->write(''); + $tmpfile->close(); + $tmpfile->save(); + $albumdir = eregi_replace('/._tmp_del_tidypics_album_', '', $tmpfile->getFilenameOnFilestore()); + $tmpfile->delete(); + if (is_dir($albumdir)) { + rmdir($albumdir); + } + } +} diff --git a/mod/lightpics/classes/TidypicsImage.php b/mod/lightpics/classes/TidypicsImage.php new file mode 100644 index 000000000..5a8d42ccc --- /dev/null +++ b/mod/lightpics/classes/TidypicsImage.php @@ -0,0 +1,406 @@ +<?php +/** + * Tidypics Image class + * + * @package TidypicsImage + * @author Cash Costello + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License v2 + */ + + +class TidypicsImage extends ElggFile { + protected function initializeAttributes() { + parent::initializeAttributes(); + + $this->attributes['subtype'] = "image"; + } + + public function __construct($guid = null) { + parent::__construct($guid); + } + + /** + * Save the image + * + * @warning container_guid must be set first + * + * @param array $data + * @return bool + */ + public function save($data = null) { + + if (!parent::save()) { + return false; + } + + if ($data) { + // new image + $this->simpletype = "image"; + $this->saveImageFile($data); + $this->saveThumbnails(); + $this->extractExifData(); + } + + return true; + } + + /** + * Delete image + * + * @return bool + */ + public function delete() { + + // check if batch should be deleted + $batch = elgg_get_entities_from_relationship(array( + 'relationship' => 'belongs_to_batch', + 'relationship_guid' => $this->guid, + 'inverse_relationship' => false, + )); + if ($batch) { + $batch = $batch[0]; + $count = elgg_get_entities_from_relationship(array( + 'relationship' => 'belongs_to_batch', + 'relationship_guid' => $batch->guid, + 'inverse_relationship' => true, + 'count' => true, + )); + if ($count == 1) { + // last image so delete batch + $batch->delete(); + } + } + + $album = get_entity($this->container_guid); + if ($album) { + $album->removeImage($this->guid); + } + + $this->removeThumbnails(); + + // update quota + $owner = $this->getOwnerEntity(); + $owner->image_repo_size = (int)$owner->image_repo_size - $this->size(); + + return parent::delete(); + } + + /** + * Get the title of the image + * + * @return string + */ + public function getTitle() { + if ($this->title) { + return $this->title; + } else { + return $this->originalfilename; + } + } + + /** + * Get the URL for the web page of this image + * + * @return string + */ + public function getURL() { + $title = elgg_get_friendly_title($this->getTitle()); + $url = "photos/image/$this->guid/$title"; + return elgg_normalize_url($url); + } + + /** + * Get the src URL for the image + * + * @return string + */ + public function getIconURL($size = 'small') { + if ($size == 'tiny') { + $size = 'thumb'; + } + return elgg_normalize_url("photos/thumbnail/$this->guid/$size/"); + } + + /** + * Get the view information for this image + * + * @param $viewer_guid The guid of the viewer + * @return array with number of views, number of unique viewers, and number of views for this viewer + */ + public function getViewInfo($viewer_guid = 0) { + if ($viewer_guid == 0) { + $viewer_guid = elgg_get_logged_in_user_guid(); + } + + $views = elgg_get_annotations(array( + 'guid' => $this->getGUID(), + 'annotation_name' => 'tp_view', + 'limit' => 0, + )); + if ($views) { + $total_views = count($views); + + if ($this->getOwnerGUID() == $viewer_guid) { + // get unique number of viewers + $diff_viewers = array(); + foreach ($views as $view) { + $diff_viewers[$view->owner_guid] = 1; + } + $unique_viewers = count($diff_viewers); + } else if ($viewer_guid) { + // get the number of times this user has viewed the photo + $my_views = 0; + foreach ($views as $view) { + if ($view->owner_guid == $viewer_guid) { + $my_views++; + } + } + } + + $view_info = array("total" => $total_views, "unique" => $unique_viewers, "mine" => $my_views); + } + else { + $view_info = array("total" => 0, "unique" => 0, "mine" => 0); + } + + return $view_info; + } + + /** + * Add a view to this image + * + * @param $viewer_guid + * @return void + */ + public function addView($viewer_guid = 0) { + if ($viewer_guid == 0) { + $viewer_guid = elgg_get_logged_in_user_guid(); + } + + if ($viewer_guid != $this->owner_guid && tp_is_person()) { + create_annotation($this->getGUID(), "tp_view", "1", "integer", $viewer_guid, ACCESS_PUBLIC); + } + } + + + /** + * Set the internal filenames + */ + protected function setOriginalFilename($originalName) { + $prefix = "image/" . $this->container_guid . "/"; + $filestorename = elgg_strtolower(time() . $originalName); + $this->setFilename($prefix . $filestorename); + $this->originalfilename = $originalName; + } + + /** + * Save the uploaded image + * + * @param array $data + */ + protected function saveImageFile($data) { + $this->checkUploadErrors($data); + + // we need to make sure the directory for the album exists + // @note for group albums, the photos are distributed among the users + $dir = tp_get_img_dir() . $this->getContainerGUID(); + if (!file_exists($dir)) { + mkdir($dir, 0755, true); + } + + // move the uploaded file into album directory + $this->setOriginalFilename($data['name']); + $filename = $this->getFilenameOnFilestore(); + $result = move_uploaded_file($data['tmp_name'], $filename); + if (!$result) { + return false; + } + + $owner = $this->getOwnerEntity(); + $owner->image_repo_size = (int)$owner->image_repo_size + $this->size(); + + return true; + } + + /** + * Need to restore sanity to this function + * @param type $data + */ + protected function checkUploadErrors($data) { + // check for upload errors + if ($data['error']) { + if ($data['error'] == 1) { + trigger_error('Tidypics warning: image exceeded server php upload limit', E_USER_WARNING); + throw new Exception(elgg_echo('tidypics:image_mem')); + } else { + throw new Exception(elgg_echo('tidypics:unk_error')); + } + } + + // must be an image + if (!tp_upload_check_format($data['type'])) { + throw new Exception(elgg_echo('tidypics:not_image')); + } + + // make sure file does not exceed memory limit + if (!tp_upload_check_max_size($data['size'])) { + throw new Exception(elgg_echo('tidypics:image_mem')); + } + + // make sure the in memory image size does not exceed memory available + $imginfo = getimagesize($data['tmp_name']); + if (!tp_upload_memory_check($image_lib, $imginfo[0] * $imginfo[1])) { + trigger_error('Tidypics warning: image memory size too large for resizing so rejecting', E_USER_WARNING); + throw new Exception(elgg_echo('tidypics:image_pixels')); + } + + // make sure file fits quota + if (!tp_upload_check_quota($data['size'], elgg_get_logged_in_user_guid())) { + throw new Exception(elgg_echo('tidypics:cannot_upload_exceeds_quota')); + } + } + + /** + * Save the image thumbnails + */ + protected function saveThumbnails() { + elgg_load_library('tidypics:resize'); + + $imageLib = elgg_get_plugin_setting('image_lib', 'tidypics'); + + $prefix = "image/" . $this->container_guid . "/"; + $filename = $this->getFilename(); + $filename = substr($filename, strrpos($filename, '/') + 1); + + if ($imageLib == 'ImageMagick') { + // ImageMagick command line + if (tp_create_im_cmdline_thumbnails($this, $prefix, $filename) != true) { + trigger_error('Tidypics warning: failed to create thumbnails - ImageMagick command line', E_USER_WARNING); + } + } else if ($imageLib == 'ImageMagickPHP') { + // imagick php extension + if (tp_create_imagick_thumbnails($this, $prefix, $filename) != true) { + trigger_error('Tidypics warning: failed to create thumbnails - ImageMagick PHP', E_USER_WARNING); + } + } else { + if (tp_create_gd_thumbnails($this, $prefix, $filename) != true) { + trigger_error('Tidypics warning: failed to create thumbnails - GD', E_USER_WARNING); + } + } + } + + /** + * Get the image data of a thumbnail + * + * @param string $size + * @return string + */ + public function getThumbnail($size) { + switch ($size) { + case 'thumb': + $thumb = $this->thumbnail; + break; + case 'small': + $thumb = $this->smallthumb; + break; + case 'large': + $thumb = $this->largethumb; + break; + default: + return ''; + break; + } + + if (!$thumb) { + return ''; + } + + $file = new ElggFile(); + $file->owner_guid = $this->getOwnerGUID(); + $file->setFilename($thumb); + return $file->grabFile(); + } + + public function getImage() { + return $this->grabFile(); + } + + /** + * Extract EXIF Data from image + * + * @warning image file must be saved first + */ + public function extractExifData() { + elgg_load_library('tidypics:exif'); + td_get_exif($this); + } + + /** + * Has the photo been tagged with "in this photo" tags + * + * @return true/false + */ + public function isPhotoTagged() { + $num_tags = count_annotations($this->getGUID(), 'object', 'image', 'phototag'); + if ($num_tags > 0) { + return true; + } else { + return false; + } + } + + /** + * Get an array of photo tag information + * + * @return array + */ + public function getPhotoTags() { + + $tags = array(); + $annotations = elgg_get_annotations(array( + 'guid' => $this->getGUID(), + 'annotation_name' => 'phototag', + )); + foreach ($annotations as $annotation) { + $tag = unserialize($annotation->value); + $tag->annotation_id = $annotation->id; + $tags[] = $tag; + } + + return $tags; + } + + /** + * Remove thumbnails - usually in preparation for deletion + * + * The thumbnails are not actually ElggObjects so we create + * temporary objects to delete them. + */ + protected function removeThumbnails() { + $thumbnail = $this->thumbnail; + $smallthumb = $this->smallthumb; + $largethumb = $this->largethumb; + + //delete standard thumbnail image + if ($thumbnail) { + $delfile = new ElggFile(); + $delfile->owner_guid = $this->getOwnerGUID(); + $delfile->setFilename($thumbnail); + $delfile->delete(); + } + //delete small thumbnail image + if ($smallthumb) { + $delfile = new ElggFile(); + $delfile->owner_guid = $this->getOwnerGUID(); + $delfile->setFilename($smallthumb); + $delfile->delete(); + } + //delete large thumbnail image + if ($largethumb) { + $delfile = new ElggFile(); + $delfile->owner_guid = $this->getOwnerGUID(); + $delfile->setFilename($largethumb); + $delfile->delete(); + } + } +} |