2014-04-05 14:02:53 +00:00
< ? php
###
# @name Photo Module
# @author Tobias Reich
# @copyright 2014 by Tobias Reich
###
if ( ! defined ( 'LYCHEE' )) exit ( 'Error: Direct access is not allowed!' );
class Photo extends Module {
private $database = null ;
2014-04-11 22:30:26 +00:00
private $settings = null ;
2014-04-05 14:02:53 +00:00
private $photoIDs = null ;
2014-05-23 13:47:48 +00:00
private $allowedTypes = array (
2014-04-25 08:13:43 +00:00
IMAGETYPE_JPEG ,
IMAGETYPE_GIF ,
IMAGETYPE_PNG
2014-05-23 13:47:48 +00:00
);
private $validExtensions = array (
2014-04-25 08:13:43 +00:00
'.jpg' ,
'.jpeg' ,
'.png' ,
'.gif'
2014-05-23 13:47:48 +00:00
);
2014-04-25 08:13:43 +00:00
2014-04-11 22:30:26 +00:00
public function __construct ( $database , $plugins , $settings , $photoIDs ) {
2014-04-05 14:02:53 +00:00
# Init vars
$this -> database = $database ;
$this -> plugins = $plugins ;
2014-04-11 22:30:26 +00:00
$this -> settings = $settings ;
2014-04-05 14:02:53 +00:00
$this -> photoIDs = $photoIDs ;
return true ;
}
2014-04-11 22:30:26 +00:00
public function add ( $files , $albumID , $description = '' , $tags = '' ) {
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database ));
2014-04-11 22:30:26 +00:00
2014-05-16 21:24:11 +00:00
# Check permissions
2014-10-10 22:52:15 +00:00
if ( hasPermissions ( LYCHEE_UPLOADS_BIG ) === false ||
hasPermissions ( LYCHEE_UPLOADS_THUMB ) === false ||
hasPermissions ( LYCHEE_UPLOADS_MEDIUM ) === false ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , 'Wrong permissions in uploads/' );
exit ( 'Error: Wrong permissions in uploads-folder!' );
2014-05-16 21:24:11 +00:00
}
2014-04-11 22:30:26 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
switch ( $albumID ) {
case 's' :
# s for public (share)
$public = 1 ;
$star = 0 ;
$albumID = 0 ;
break ;
case 'f' :
# f for starred (fav)
$star = 1 ;
$public = 0 ;
$albumID = 0 ;
break ;
2014-06-29 13:40:06 +00:00
case 'r' :
# r for recent
$public = 0 ;
$star = 0 ;
$albumID = 0 ;
break ;
2014-04-11 22:30:26 +00:00
default :
$star = 0 ;
$public = 0 ;
break ;
}
foreach ( $files as $file ) {
2014-04-25 08:13:43 +00:00
# Verify extension
2014-05-20 10:44:08 +00:00
$extension = getExtension ( $file [ 'name' ]);
2014-04-25 08:13:43 +00:00
if ( ! in_array ( strtolower ( $extension ), $this -> validExtensions , true )) continue ;
# Verify image
$type = @ exif_imagetype ( $file [ 'tmp_name' ]);
if ( ! in_array ( $type , $this -> allowedTypes , true )) continue ;
2014-04-11 22:30:26 +00:00
2014-04-25 08:13:43 +00:00
# Generate id
2014-04-11 22:30:26 +00:00
$id = str_replace ( '.' , '' , microtime ( true ));
while ( strlen ( $id ) < 14 ) $id .= 0 ;
2014-08-22 20:02:58 +00:00
# Set paths
2014-04-11 22:30:26 +00:00
$tmp_name = $file [ 'tmp_name' ];
2014-04-26 15:05:42 +00:00
$photo_name = md5 ( $id ) . $extension ;
2014-04-13 12:08:18 +00:00
$path = LYCHEE_UPLOADS_BIG . $photo_name ;
2014-04-11 22:30:26 +00:00
2014-08-22 20:02:58 +00:00
# Calculate checksum
$checksum = sha1_file ( $tmp_name );
2014-08-27 19:17:05 +00:00
if ( $checksum === false ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , 'Could not calculate checksum for photo' );
exit ( 'Error: Could not calculate checksum for photo!' );
}
2014-08-22 20:02:58 +00:00
# Check if image exists based on checksum
if ( $checksum === false ) {
$checksum = '' ;
$exists = false ;
2014-04-11 22:30:26 +00:00
} else {
2014-08-22 20:02:58 +00:00
2014-08-22 20:14:50 +00:00
$exists = $this -> exists ( $checksum );
if ( $exists !== false ) {
$photo_name = $exists [ 'photo_name' ];
$path = $exists [ 'path' ];
$path_thumb = $exists [ 'path_thumb' ];
2014-08-22 20:02:58 +00:00
$exists = true ;
2014-05-08 18:50:18 +00:00
}
2014-08-22 20:02:58 +00:00
2014-04-11 22:30:26 +00:00
}
2014-08-22 20:02:58 +00:00
if ( $exists === false ) {
# Import if not uploaded via web
if ( ! is_uploaded_file ( $tmp_name )) {
if ( !@ copy ( $tmp_name , $path )) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , 'Could not copy photo to uploads' );
exit ( 'Error: Could not copy photo to uploads!' );
} else @ unlink ( $tmp_name );
} else {
if ( !@ move_uploaded_file ( $tmp_name , $path )) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , 'Could not move photo to uploads' );
exit ( 'Error: Could not move photo to uploads!' );
}
}
}
2014-07-20 14:45:30 +00:00
2014-04-11 22:30:26 +00:00
# Read infos
$info = $this -> getInfo ( $path );
# Use title of file if IPTC title missing
2014-08-29 19:16:10 +00:00
if ( $info [ 'title' ] === '' ) $info [ 'title' ] = substr ( basename ( $file [ 'name' ], $extension ), 0 , 30 );
2014-04-11 22:30:26 +00:00
# Use description parameter if set
if ( $description === '' ) $description = $info [ 'description' ];
2014-08-22 20:02:58 +00:00
if ( $exists === false ) {
# Set orientation based on EXIF data
2014-08-26 18:26:14 +00:00
if ( $file [ 'type' ] === 'image/jpeg' && isset ( $info [ 'orientation' ], $info [ 'width' ], $info [ 'height' ]) && $info [ 'orientation' ] !== '' ) {
2014-08-22 20:02:58 +00:00
if ( ! $this -> adjustFile ( $path , $info )) Log :: notice ( $this -> database , __METHOD__ , __LINE__ , 'Could not adjust photo (' . $info [ 'title' ] . ')' );
}
# Set original date
2014-10-08 20:55:36 +00:00
if ( $info [ 'takestamp' ] !== '' && $info [ 'takestamp' ] !== 0 ) @ touch ( $path , $info [ 'takestamp' ]);
2014-08-22 20:02:58 +00:00
# Create Thumb
if ( ! $this -> createThumb ( $path , $photo_name )) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , 'Could not create thumbnail for photo' );
exit ( 'Error: Could not create thumbnail for photo!' );
}
2014-04-11 22:30:26 +00:00
2014-10-10 22:52:15 +00:00
# Create Medium
if ( $this -> createMedium ( $path , $photo_name , $info [ 'width' ], $info [ 'height' ])) $medium = true ;
else $medium = false ;
2014-08-22 20:02:58 +00:00
# Set thumb url
$path_thumb = md5 ( $id ) . '.jpeg' ;
2014-04-13 10:10:49 +00:00
2014-05-08 18:50:18 +00:00
}
2014-04-11 22:30:26 +00:00
# Save to DB
2014-08-30 05:05:26 +00:00
$values = array ( LYCHEE_TABLE_PHOTOS , $id , $info [ 'title' ], $photo_name , $description , $tags , $info [ 'type' ], $info [ 'width' ], $info [ 'height' ], $info [ 'size' ], $info [ 'iso' ], $info [ 'aperture' ], $info [ 'make' ], $info [ 'model' ], $info [ 'shutter' ], $info [ 'focal' ], $info [ 'takestamp' ], $path_thumb , $albumID , $public , $star , $checksum );
2014-08-29 19:16:10 +00:00
$query = Database :: prepare ( $this -> database , " INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum) VALUES ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?') " , $values );
2014-04-11 22:30:26 +00:00
$result = $this -> database -> query ( $query );
2014-05-08 18:50:18 +00:00
if ( ! $result ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , $this -> database -> error );
exit ( 'Error: Could not save photo in database!' );
}
2014-04-11 22:30:26 +00:00
}
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
return true ;
}
2014-08-22 20:54:33 +00:00
private function exists ( $checksum , $photoID = null ) {
2014-08-22 20:14:50 +00:00
# Check dependencies
self :: dependencies ( isset ( $this -> database , $checksum ));
2014-08-22 20:54:33 +00:00
# Exclude $photoID from select when $photoID is set
2014-08-30 05:05:26 +00:00
if ( isset ( $photoID )) $query = Database :: prepare ( $this -> database , " SELECT id, url, thumbUrl FROM ? WHERE checksum = '?' AND id <> '?' LIMIT 1 " , array ( LYCHEE_TABLE_PHOTOS , $checksum , $photoID ));
else $query = Database :: prepare ( $this -> database , " SELECT id, url, thumbUrl FROM ? WHERE checksum = '?' LIMIT 1 " , array ( LYCHEE_TABLE_PHOTOS , $checksum ));
2014-08-22 20:54:33 +00:00
2014-08-22 20:14:50 +00:00
$result = $this -> database -> query ( $query );
if ( ! $result ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , 'Could not check for existing photos with the same checksum' );
return false ;
}
if ( $result -> num_rows === 1 ) {
2014-08-22 20:34:59 +00:00
$result = $result -> fetch_object ();
2014-08-22 20:14:50 +00:00
$return = array (
2014-08-22 20:34:59 +00:00
'photo_name' => $result -> url ,
'path' => LYCHEE_UPLOADS_BIG . $result -> url ,
'path_thumb' => $result -> thumbUrl
2014-08-22 20:14:50 +00:00
);
return $return ;
}
return false ;
}
2014-04-11 22:30:26 +00:00
private function createThumb ( $url , $filename , $width = 200 , $height = 200 ) {
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database , $this -> settings , $url , $filename ));
2014-04-11 22:30:26 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
$photoName = explode ( " . " , $filename );
2014-04-13 12:08:18 +00:00
$newUrl = LYCHEE_UPLOADS_THUMB . $photoName [ 0 ] . '.jpeg' ;
$newUrl2x = LYCHEE_UPLOADS_THUMB . $photoName [ 0 ] . '@2x.jpeg' ;
2014-04-11 22:30:26 +00:00
2014-10-10 22:52:15 +00:00
# Create thumbnails with Imagick
2014-08-29 22:11:26 +00:00
if ( extension_loaded ( 'imagick' ) && $this -> settings [ 'imagick' ] === '1' ) {
2014-04-11 22:30:26 +00:00
# Read image
$thumb = new Imagick ();
$thumb -> readImage ( $url );
$thumb -> setImageCompressionQuality ( $this -> settings [ 'thumbQuality' ]);
$thumb -> setImageFormat ( 'jpeg' );
# Copy image for 2nd thumb version
$thumb2x = clone $thumb ;
# Create 1st version
$thumb -> cropThumbnailImage ( $width , $height );
$thumb -> writeImage ( $newUrl );
2014-04-19 15:32:33 +00:00
$thumb -> clear ();
$thumb -> destroy ();
2014-04-11 22:30:26 +00:00
# Create 2nd version
$thumb2x -> cropThumbnailImage ( $width * 2 , $height * 2 );
$thumb2x -> writeImage ( $newUrl2x );
$thumb2x -> clear ();
$thumb2x -> destroy ();
} else {
2014-10-10 22:52:15 +00:00
# Get size of photo
$info = getimagesize ( $url );
2014-04-11 22:30:26 +00:00
# Set position and size
$thumb = imagecreatetruecolor ( $width , $height );
$thumb2x = imagecreatetruecolor ( $width * 2 , $height * 2 );
if ( $info [ 0 ] < $info [ 1 ]) {
$newSize = $info [ 0 ];
$startWidth = 0 ;
$startHeight = $info [ 1 ] / 2 - $info [ 0 ] / 2 ;
} else {
$newSize = $info [ 1 ];
$startWidth = $info [ 0 ] / 2 - $info [ 1 ] / 2 ;
$startHeight = 0 ;
}
# Create new image
switch ( $info [ 'mime' ]) {
case 'image/jpeg' : $sourceImg = imagecreatefromjpeg ( $url ); break ;
case 'image/png' : $sourceImg = imagecreatefrompng ( $url ); break ;
case 'image/gif' : $sourceImg = imagecreatefromgif ( $url ); break ;
2014-05-08 18:50:18 +00:00
default : Log :: error ( $this -> database , __METHOD__ , __LINE__ , 'Type of photo is not supported' );
return false ;
break ;
2014-04-11 22:30:26 +00:00
}
2014-04-19 15:32:33 +00:00
# Create thumb
2014-04-28 09:47:30 +00:00
fastimagecopyresampled ( $thumb , $sourceImg , 0 , 0 , $startWidth , $startHeight , $width , $height , $newSize , $newSize );
2014-04-11 22:30:26 +00:00
imagejpeg ( $thumb , $newUrl , $this -> settings [ 'thumbQuality' ]);
2014-04-19 15:32:33 +00:00
imagedestroy ( $thumb );
# Create retina thumb
2014-04-28 09:47:30 +00:00
fastimagecopyresampled ( $thumb2x , $sourceImg , 0 , 0 , $startWidth , $startHeight , $width * 2 , $height * 2 , $newSize , $newSize );
2014-04-11 22:30:26 +00:00
imagejpeg ( $thumb2x , $newUrl2x , $this -> settings [ 'thumbQuality' ]);
2014-04-19 15:32:33 +00:00
imagedestroy ( $thumb2x );
# Free memory
imagedestroy ( $sourceImg );
2014-04-11 22:30:26 +00:00
}
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
return true ;
}
2014-10-10 22:52:15 +00:00
private function createMedium ( $url , $filename , $width , $height , $newWidth = 1920 , $newHeight = 1080 ) {
# Check dependencies
self :: dependencies ( isset ( $this -> database , $this -> settings , $url , $filename , $width , $height ));
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
# Is photo big enough?
# is Imagick installed?
if (( $width > $newWidth || $height > $newHeight ) &&
( extension_loaded ( 'imagick' ) && $this -> settings [ 'imagick' ] === '1' )) {
# $info = getimagesize($url);
$newUrl = LYCHEE_UPLOADS_MEDIUM . $filename ;
# Read image
$medium = new Imagick ();
$medium -> readImage ( $url );
$medium -> scaleImage ( $newWidth , $newHeight , true );
$medium -> writeImage ( $newUrl );
$medium -> clear ();
$medium -> destroy ();
$error = false ;
} else {
# Photo too small or
# Imagick not installed
$error = true ;
}
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
if ( $error === true ) return false ;
return true ;
}
2014-08-26 18:26:14 +00:00
public function adjustFile ( $path , $info ) {
2014-04-12 12:15:21 +00:00
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $path , $info ));
2014-04-12 12:15:21 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
2014-08-29 22:11:26 +00:00
if ( extension_loaded ( 'imagick' ) && $this -> settings [ 'imagick' ] === '1' ) {
2014-04-12 12:15:21 +00:00
$rotateImage = 0 ;
switch ( $info [ 'orientation' ]) {
case 3 :
$rotateImage = 180 ;
$imageOrientation = 1 ;
break ;
case 6 :
$rotateImage = 90 ;
$imageOrientation = 1 ;
break ;
case 8 :
$rotateImage = 270 ;
$imageOrientation = 1 ;
break ;
}
2014-04-19 15:32:33 +00:00
if ( $rotateImage !== 0 ) {
2014-04-12 12:15:21 +00:00
$image = new Imagick ();
$image -> readImage ( $path );
$image -> rotateImage ( new ImagickPixel (), $rotateImage );
$image -> setImageOrientation ( $imageOrientation );
$image -> writeImage ( $path );
$image -> clear ();
$image -> destroy ();
}
} else {
2014-04-19 15:32:33 +00:00
$newWidth = $info [ 'width' ];
$newHeight = $info [ 'height' ];
$process = false ;
$sourceImg = imagecreatefromjpeg ( $path );
2014-04-12 12:15:21 +00:00
switch ( $info [ 'orientation' ]) {
case 2 :
# mirror
# not yet implemented
break ;
case 3 :
2014-04-19 15:32:33 +00:00
$process = true ;
$sourceImg = imagerotate ( $sourceImg , - 180 , 0 );
2014-04-12 12:15:21 +00:00
break ;
case 4 :
# rotate 180 and mirror
# not yet implemented
break ;
case 5 :
# rotate 90 and mirror
# not yet implemented
break ;
case 6 :
2014-04-19 15:32:33 +00:00
$process = true ;
$sourceImg = imagerotate ( $sourceImg , - 90 , 0 );
$newWidth = $info [ 'height' ];
$newHeight = $info [ 'width' ];
2014-04-12 12:15:21 +00:00
break ;
case 7 :
# rotate -90 and mirror
# not yet implemented
break ;
case 8 :
2014-04-19 15:32:33 +00:00
$process = true ;
$sourceImg = imagerotate ( $sourceImg , 90 , 0 );
$newWidth = $info [ 'height' ];
$newHeight = $info [ 'width' ];
2014-04-12 12:15:21 +00:00
break ;
}
2014-04-19 15:32:33 +00:00
# Need to adjust photo?
if ( $process === true ) {
2014-04-12 12:15:21 +00:00
2014-04-19 15:32:33 +00:00
# Recreate photo
$newSourceImg = imagecreatetruecolor ( $newWidth , $newHeight );
imagecopyresampled ( $newSourceImg , $sourceImg , 0 , 0 , 0 , 0 , $newWidth , $newHeight , $newWidth , $newHeight );
imagejpeg ( $newSourceImg , $path , 100 );
# Free memory
imagedestroy ( $sourceImg );
imagedestroy ( $newSourceImg );
}
2014-04-12 12:15:21 +00:00
}
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
return true ;
}
2014-04-05 14:02:53 +00:00
public function get ( $albumID ) {
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database , $this -> photoIDs ));
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
2014-04-05 14:02:53 +00:00
# Get photo
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " SELECT * FROM ? WHERE id = '?' LIMIT 1 " , array ( LYCHEE_TABLE_PHOTOS , $this -> photoIDs ));
2014-08-29 19:16:10 +00:00
$photos = $this -> database -> query ( $query );
2014-04-05 14:02:53 +00:00
$photo = $photos -> fetch_assoc ();
# Parse photo
2014-04-05 14:22:46 +00:00
$photo [ 'sysdate' ] = date ( 'd M. Y' , substr ( $photo [ 'id' ], 0 , - 4 ));
2014-04-13 10:35:59 +00:00
if ( strlen ( $photo [ 'takestamp' ]) > 1 ) $photo [ 'takedate' ] = date ( 'd M. Y' , $photo [ 'takestamp' ]);
2014-04-05 14:02:53 +00:00
2014-07-12 18:12:38 +00:00
# Parse url
2014-08-23 15:07:46 +00:00
$photo [ 'url' ] = LYCHEE_URL_UPLOADS_BIG . $photo [ 'url' ];
$photo [ 'thumbUrl' ] = LYCHEE_URL_UPLOADS_THUMB . $photo [ 'thumbUrl' ];
2014-07-12 18:12:38 +00:00
2014-04-05 14:02:53 +00:00
if ( $albumID != 'false' ) {
2014-08-29 19:16:10 +00:00
# Show photo as public when parent album is public
# Check if parent album is available and not photo not unsorted
2014-04-05 14:02:53 +00:00
if ( $photo [ 'album' ] != 0 ) {
# Get album
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " SELECT public FROM ? WHERE id = '?' LIMIT 1 " , array ( LYCHEE_TABLE_ALBUMS , $photo [ 'album' ]));
2014-08-29 19:16:10 +00:00
$albums = $this -> database -> query ( $query );
$album = $albums -> fetch_assoc ();
2014-04-05 14:02:53 +00:00
# Parse album
$photo [ 'public' ] = ( $album [ 'public' ] == '1' ? '2' : $photo [ 'public' ]);
}
$photo [ 'original_album' ] = $photo [ 'album' ];
2014-07-18 22:00:00 +00:00
$photo [ 'album' ] = $albumID ;
2014-04-05 14:02:53 +00:00
}
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
2014-04-05 14:02:53 +00:00
return $photo ;
}
2014-08-26 18:26:14 +00:00
public function getInfo ( $url ) {
2014-04-11 22:30:26 +00:00
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database , $url ));
2014-04-11 22:30:26 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
$iptcArray = array ();
$info = getimagesize ( $url , $iptcArray );
# General information
$return [ 'type' ] = $info [ 'mime' ];
$return [ 'width' ] = $info [ 0 ];
$return [ 'height' ] = $info [ 1 ];
# Size
$size = filesize ( $url ) / 1024 ;
if ( $size >= 1024 ) $return [ 'size' ] = round ( $size / 1024 , 1 ) . ' MB' ;
else $return [ 'size' ] = round ( $size , 1 ) . ' KB' ;
# IPTC Metadata Fallback
$return [ 'title' ] = '' ;
$return [ 'description' ] = '' ;
# IPTC Metadata
if ( isset ( $iptcArray [ 'APP13' ])) {
$iptcInfo = iptcparse ( $iptcArray [ 'APP13' ]);
if ( is_array ( $iptcInfo )) {
$temp = @ $iptcInfo [ '2#105' ][ 0 ];
if ( isset ( $temp ) && strlen ( $temp ) > 0 ) $return [ 'title' ] = $temp ;
$temp = @ $iptcInfo [ '2#120' ][ 0 ];
if ( isset ( $temp ) && strlen ( $temp ) > 0 ) $return [ 'description' ] = $temp ;
2014-08-26 14:07:59 +00:00
$temp = @ $iptcInfo [ '2#005' ][ 0 ];
if ( isset ( $temp ) && strlen ( $temp ) > 0 && $return [ 'title' ] === '' ) $return [ 'title' ] = $temp ;
2014-04-11 22:30:26 +00:00
}
}
# EXIF Metadata Fallback
$return [ 'orientation' ] = '' ;
$return [ 'iso' ] = '' ;
$return [ 'aperture' ] = '' ;
$return [ 'make' ] = '' ;
$return [ 'model' ] = '' ;
$return [ 'shutter' ] = '' ;
$return [ 'focal' ] = '' ;
2014-04-26 14:48:40 +00:00
$return [ 'takestamp' ] = 0 ;
2014-04-11 22:30:26 +00:00
# Read EXIF
if ( $info [ 'mime' ] == 'image/jpeg' ) $exif = @ exif_read_data ( $url , 'EXIF' , 0 );
else $exif = false ;
# EXIF Metadata
if ( $exif !== false ) {
if ( isset ( $exif [ 'Orientation' ])) $return [ 'orientation' ] = $exif [ 'Orientation' ];
else if ( isset ( $exif [ 'IFD0' ][ 'Orientation' ])) $return [ 'orientation' ] = $exif [ 'IFD0' ][ 'Orientation' ];
$temp = @ $exif [ 'ISOSpeedRatings' ];
if ( isset ( $temp )) $return [ 'iso' ] = $temp ;
$temp = @ $exif [ 'COMPUTED' ][ 'ApertureFNumber' ];
if ( isset ( $temp )) $return [ 'aperture' ] = $temp ;
$temp = @ $exif [ 'Make' ];
2014-04-25 14:36:31 +00:00
if ( isset ( $temp )) $return [ 'make' ] = trim ( $temp );
2014-04-11 22:30:26 +00:00
$temp = @ $exif [ 'Model' ];
2014-04-25 14:36:31 +00:00
if ( isset ( $temp )) $return [ 'model' ] = trim ( $temp );
2014-04-11 22:30:26 +00:00
$temp = @ $exif [ 'ExposureTime' ];
if ( isset ( $temp )) $return [ 'shutter' ] = $exif [ 'ExposureTime' ] . ' Sec.' ;
$temp = @ $exif [ 'FocalLength' ];
if ( isset ( $temp )) $return [ 'focal' ] = ( $temp / 1 ) . ' mm' ;
$temp = @ $exif [ 'DateTimeOriginal' ];
if ( isset ( $temp )) $return [ 'takestamp' ] = strtotime ( $temp );
}
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
return $return ;
}
2014-04-05 14:02:53 +00:00
public function getArchive () {
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database , $this -> photoIDs ));
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
2014-04-05 14:02:53 +00:00
# Get photo
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " SELECT title, url FROM ? WHERE id = '?' LIMIT 1 " , array ( LYCHEE_TABLE_PHOTOS , $this -> photoIDs ));
2014-08-29 19:16:10 +00:00
$photos = $this -> database -> query ( $query );
2014-04-05 14:02:53 +00:00
$photo = $photos -> fetch_object ();
# Get extension
2014-05-20 10:44:08 +00:00
$extension = getExtension ( $photo -> url );
2014-05-08 18:50:18 +00:00
if ( $extension === false ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , 'Invalid photo extension' );
return false ;
}
2014-04-05 14:02:53 +00:00
2014-08-30 17:18:09 +00:00
# Illicit chars
$badChars = array_merge (
array_map ( 'chr' , range ( 0 , 31 )),
array ( " < " , " > " , " : " , '"' , " / " , " \\ " , " | " , " ? " , " * " )
);
2014-04-05 14:02:53 +00:00
# Parse title
if ( $photo -> title == '' ) $photo -> title = 'Untitled' ;
2014-08-30 17:18:09 +00:00
# Escape title
2014-08-30 18:03:38 +00:00
$photo -> title = str_replace ( $badChars , '' , $photo -> title );
2014-08-30 17:18:09 +00:00
2014-04-05 14:02:53 +00:00
# Set headers
header ( " Content-Type: application/octet-stream " );
2014-05-20 10:31:48 +00:00
header ( " Content-Disposition: attachment; filename= \" " . $photo -> title . $extension . " \" " );
2014-04-13 12:08:18 +00:00
header ( " Content-Length: " . filesize ( LYCHEE_UPLOADS_BIG . $photo -> url ));
2014-04-05 14:02:53 +00:00
# Send file
2014-04-13 12:08:18 +00:00
readfile ( LYCHEE_UPLOADS_BIG . $photo -> url );
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
2014-04-05 14:02:53 +00:00
return true ;
}
2014-04-25 08:13:43 +00:00
public function setTitle ( $title ) {
2014-04-05 14:02:53 +00:00
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database , $this -> photoIDs ));
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
2014-04-05 14:02:53 +00:00
# Parse
if ( strlen ( $title ) > 50 ) $title = substr ( $title , 0 , 50 );
# Set title
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " UPDATE ? SET title = '?' WHERE id IN (?) " , array ( LYCHEE_TABLE_PHOTOS , $title , $this -> photoIDs ));
2014-08-29 19:16:10 +00:00
$result = $this -> database -> query ( $query );
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
2014-05-08 18:50:18 +00:00
if ( ! $result ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , $this -> database -> error );
return false ;
}
2014-04-05 14:02:53 +00:00
return true ;
}
2014-04-25 08:13:43 +00:00
public function setDescription ( $description ) {
2014-04-05 14:02:53 +00:00
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database , $this -> photoIDs ));
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
2014-04-05 14:02:53 +00:00
# Parse
2014-08-26 08:15:17 +00:00
$description = htmlentities ( $description , ENT_COMPAT | ENT_HTML401 , 'UTF-8' );
2014-04-05 14:02:53 +00:00
if ( strlen ( $description ) > 1000 ) $description = substr ( $description , 0 , 1000 );
# Set description
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " UPDATE ? SET description = '?' WHERE id IN ('?') " , array ( LYCHEE_TABLE_PHOTOS , $description , $this -> photoIDs ));
2014-08-29 19:16:10 +00:00
$result = $this -> database -> query ( $query );
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
2014-05-08 18:50:18 +00:00
if ( ! $result ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , $this -> database -> error );
return false ;
}
2014-04-05 14:02:53 +00:00
return true ;
}
public function setStar () {
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database , $this -> photoIDs ));
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
2014-04-05 14:02:53 +00:00
# Init vars
$error = false ;
# Get photos
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " SELECT id, star FROM ? WHERE id IN (?) " , array ( LYCHEE_TABLE_PHOTOS , $this -> photoIDs ));
2014-08-29 19:16:10 +00:00
$photos = $this -> database -> query ( $query );
2014-04-05 14:02:53 +00:00
# For each photo
while ( $photo = $photos -> fetch_object ()) {
# Invert star
$star = ( $photo -> star == 0 ? 1 : 0 );
# Set star
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " UPDATE ? SET star = '?' WHERE id = '?' " , array ( LYCHEE_TABLE_PHOTOS , $star , $photo -> id ));
2014-08-29 19:16:10 +00:00
$star = $this -> database -> query ( $query );
2014-04-05 14:02:53 +00:00
if ( ! $star ) $error = true ;
}
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
2014-05-30 14:57:15 +00:00
if ( $error === true ) {
2014-05-08 18:50:18 +00:00
Log :: error ( $this -> database , __METHOD__ , __LINE__ , $this -> database -> error );
return false ;
}
2014-04-05 14:02:53 +00:00
return true ;
}
2014-04-25 08:13:43 +00:00
public function getPublic ( $password ) {
2014-04-05 14:02:53 +00:00
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database , $this -> photoIDs ));
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
2014-04-05 14:02:53 +00:00
# Get photo
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " SELECT public, album FROM ? WHERE id = '?' LIMIT 1 " , array ( LYCHEE_TABLE_PHOTOS , $this -> photoIDs ));
2014-08-29 19:16:10 +00:00
$photos = $this -> database -> query ( $query );
2014-04-05 14:02:53 +00:00
$photo = $photos -> fetch_object ();
# Check if public
if ( $photo -> public == 1 ) return true ;
else {
$album = new Album ( $this -> database , null , null , $photo -> album );
2014-08-29 19:16:10 +00:00
$acP = $album -> checkPassword ( $password );
$agP = $album -> getPublic ();
2014-04-05 14:02:53 +00:00
if ( $acP === true && $agP === true ) return true ;
}
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
2014-04-05 14:02:53 +00:00
return false ;
}
public function setPublic () {
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database , $this -> photoIDs ));
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
2014-04-05 14:02:53 +00:00
# Get public
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " SELECT public FROM ? WHERE id = '?' LIMIT 1 " , array ( LYCHEE_TABLE_PHOTOS , $this -> photoIDs ));
2014-08-29 19:16:10 +00:00
$photos = $this -> database -> query ( $query );
2014-04-05 14:02:53 +00:00
$photo = $photos -> fetch_object ();
# Invert public
$public = ( $photo -> public == 0 ? 1 : 0 );
# Set public
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " UPDATE ? SET public = '?' WHERE id = '?' " , array ( LYCHEE_TABLE_PHOTOS , $public , $this -> photoIDs ));
2014-08-29 19:16:10 +00:00
$result = $this -> database -> query ( $query );
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
2014-05-08 18:50:18 +00:00
if ( ! $result ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , $this -> database -> error );
return false ;
}
2014-04-05 14:02:53 +00:00
return true ;
}
function setAlbum ( $albumID ) {
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database , $this -> photoIDs ));
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
2014-04-05 14:02:53 +00:00
# Set album
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " UPDATE ? SET album = '?' WHERE id IN (?) " , array ( LYCHEE_TABLE_PHOTOS , $albumID , $this -> photoIDs ));
2014-08-29 19:16:10 +00:00
$result = $this -> database -> query ( $query );
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
2014-05-08 18:50:18 +00:00
if ( ! $result ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , $this -> database -> error );
return false ;
}
2014-04-05 14:02:53 +00:00
return true ;
}
public function setTags ( $tags ) {
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database , $this -> photoIDs ));
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
2014-04-05 14:02:53 +00:00
# Parse tags
$tags = preg_replace ( '/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/' , ',' , $tags );
2014-04-18 19:27:52 +00:00
$tags = preg_replace ( '/,$|^,|(\ ){0,}$/' , '' , $tags );
2014-05-08 18:50:18 +00:00
if ( strlen ( $tags ) > 1000 ) {
2014-05-30 14:56:41 +00:00
Log :: notice ( $this -> database , __METHOD__ , __LINE__ , 'Length of tags higher than 1000' );
2014-05-08 18:50:18 +00:00
return false ;
}
2014-04-05 14:02:53 +00:00
# Set tags
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " UPDATE ? SET tags = '?' WHERE id IN (?) " , array ( LYCHEE_TABLE_PHOTOS , $tags , $this -> photoIDs ));
2014-08-29 19:16:10 +00:00
$result = $this -> database -> query ( $query );
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
2014-05-08 18:50:18 +00:00
if ( ! $result ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , $this -> database -> error );
return false ;
}
2014-04-05 14:02:53 +00:00
return true ;
}
2014-08-22 21:31:09 +00:00
public function duplicate () {
# Check dependencies
self :: dependencies ( isset ( $this -> database , $this -> photoIDs ));
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
# Get photos
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " SELECT id, checksum FROM ? WHERE id IN (?) " , array ( LYCHEE_TABLE_PHOTOS , $this -> photoIDs ));
2014-08-29 19:16:10 +00:00
$photos = $this -> database -> query ( $query );
2014-08-22 21:31:09 +00:00
if ( ! $photos ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , $this -> database -> error );
return false ;
}
# For each photo
while ( $photo = $photos -> fetch_object ()) {
# Generate id
$id = str_replace ( '.' , '' , microtime ( true ));
while ( strlen ( $id ) < 14 ) $id .= 0 ;
# Duplicate entry
2014-08-30 05:05:26 +00:00
$values = array ( LYCHEE_TABLE_PHOTOS , $id , LYCHEE_TABLE_PHOTOS , $photo -> id );
2014-08-29 19:16:10 +00:00
$query = Database :: prepare ( $this -> database , " INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum) SELECT '?' AS id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum FROM ? WHERE id = '?' " , $values );
$duplicate = $this -> database -> query ( $query );
2014-08-22 21:31:09 +00:00
if ( ! $duplicate ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , $this -> database -> error );
return false ;
}
}
return true ;
}
2014-04-05 14:02:53 +00:00
public function delete () {
2014-04-19 19:07:36 +00:00
# Check dependencies
2014-06-25 12:50:49 +00:00
self :: dependencies ( isset ( $this -> database , $this -> photoIDs ));
2014-04-05 14:02:53 +00:00
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 0 , func_get_args ());
2014-04-05 14:02:53 +00:00
# Get photos
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " SELECT id, url, thumbUrl, checksum FROM ? WHERE id IN (?) " , array ( LYCHEE_TABLE_PHOTOS , $this -> photoIDs ));
2014-08-29 19:16:10 +00:00
$photos = $this -> database -> query ( $query );
2014-05-08 18:50:18 +00:00
if ( ! $photos ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , $this -> database -> error );
return false ;
}
2014-04-05 14:02:53 +00:00
# For each photo
while ( $photo = $photos -> fetch_object ()) {
2014-08-22 20:54:33 +00:00
# Check if other photos are referring to this images
# If so, only delete the db entry
if ( $this -> exists ( $photo -> checksum , $photo -> id ) === false ) {
2014-04-05 14:02:53 +00:00
2014-08-22 20:54:33 +00:00
# Get retina thumb url
$thumbUrl2x = explode ( " . " , $photo -> thumbUrl );
$thumbUrl2x = $thumbUrl2x [ 0 ] . '@2x.' . $thumbUrl2x [ 1 ];
2014-05-08 18:50:18 +00:00
2014-08-22 20:54:33 +00:00
# Delete big
if ( file_exists ( LYCHEE_UPLOADS_BIG . $photo -> url ) &&! unlink ( LYCHEE_UPLOADS_BIG . $photo -> url )) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , 'Could not delete photo in uploads/big/' );
return false ;
}
# Delete thumb
if ( file_exists ( LYCHEE_UPLOADS_THUMB . $photo -> thumbUrl ) &&! unlink ( LYCHEE_UPLOADS_THUMB . $photo -> thumbUrl )) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , 'Could not delete photo in uploads/thumb/' );
return false ;
}
# Delete thumb@2x
if ( file_exists ( LYCHEE_UPLOADS_THUMB . $thumbUrl2x ) &&! unlink ( LYCHEE_UPLOADS_THUMB . $thumbUrl2x )) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , 'Could not delete high-res photo in uploads/thumb/' );
return false ;
}
2014-05-08 18:50:18 +00:00
}
2014-04-05 14:02:53 +00:00
# Delete db entry
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $this -> database , " DELETE FROM ? WHERE id = '?' " , array ( LYCHEE_TABLE_PHOTOS , $photo -> id ));
2014-08-29 19:16:10 +00:00
$delete = $this -> database -> query ( $query );
2014-05-08 18:50:18 +00:00
if ( ! $delete ) {
Log :: error ( $this -> database , __METHOD__ , __LINE__ , $this -> database -> error );
return false ;
}
2014-04-05 14:02:53 +00:00
}
2014-04-05 14:25:49 +00:00
# Call plugins
$this -> plugins ( __METHOD__ , 1 , func_get_args ());
2014-04-05 14:02:53 +00:00
return true ;
}
}
2014-04-28 08:17:26 +00:00
?>