X-Git-Url: https://git.nubati.net/cgi-bin/gitweb.cgi?p=phpfspot.git;a=blobdiff_plain;f=phpfspot.class.php;h=60521adf247c2a15ed98d3f6a6abc4de7917e05f;hp=b8f45a898e2bdb5a10264226fe8f15e59e362e03;hb=dcc26041d1dd86d47516e143fd5e475e588180cf;hpb=1bd68ab30d8e8a95581ff26da1f8fadf12ce5d8d diff --git a/phpfspot.class.php b/phpfspot.class.php index b8f45a8..60521ad 100644 --- a/phpfspot.class.php +++ b/phpfspot.class.php @@ -28,6 +28,9 @@ require_once "phpfspot_db.php"; /** * PHPFSPOT main class * + * this class contains the most functions which will to the major + * work for phpfspot. + * * @package phpfspot */ class PHPFSPOT { @@ -119,7 +122,7 @@ class PHPFSPOT { /* set application name and version information */ $this->cfg->product = "phpfspot"; - $this->cfg->version = "1.4"; + $this->cfg->version = "1.5"; $this->sort_orders= array( 'date_asc' => 'Date ↑', @@ -154,6 +157,7 @@ class PHPFSPOT { "); } + /* get F-Spot database version */ $this->dbver = $this->getFspotDBVersion(); if(!is_writeable($this->cfg->base_path ."/templates_c")) { @@ -198,6 +202,17 @@ class PHPFSPOT { require_once "phpfspot_tmpl.php"; $this->tmpl = new PHPFSPOT_TMPL(); + $this->tmpl->assign('web_path', $this->cfg->web_path); + + /* Starting with F-Spot 0.4.2, the rating-feature was available */ + if($this->dbver > 10) { + $this->tmpl->assign('has_rating', true); + $this->sort_orders = array_merge($this->sort_orders, array( + 'rate_asc' => 'Rate ↑', + 'rate_desc' => 'Rate ↓', + )); + } + /* check if all necessary indices exist */ $this->checkDbIndices(); @@ -218,6 +233,11 @@ class PHPFSPOT { if(isset($_SESSION['begin_with']) && $this->cfg->thumbs_per_page == 0) unset($_SESSION['begin_with']); + // if user-friendly-url's are enabled, set also a flag for the template handler + if($this->is_user_friendly_url()) { + $this->tmpl->assign('user_friendly_url', 'true'); + } + } // __construct() public function __destruct() @@ -241,6 +261,11 @@ class PHPFSPOT { $this->tmpl->assign('current_condition', $_SESSION['tag_condition']); $this->tmpl->assign('template_path', 'themes/'. $this->cfg->theme_name); + /* parse URL */ + if($this->is_user_friendly_url()) { + $content = $this->parse_user_friendly_url($_SERVER['REQUEST_URI']); + } + if(isset($_GET['mode'])) { $_SESSION['start_action'] = $_GET['mode']; @@ -274,11 +299,15 @@ class PHPFSPOT { } break; case 'export': - $this->tmpl->show("export.tpl"); + /* fetch export template */ + print $this->tmpl->fetch("export.tpl"); + /* no further execution necessary. */ return; break; case 'slideshow': - $this->tmpl->show("slideshow.tpl"); + /* fetch slideshow template */ + print $this->tmpl->show("slideshow.tpl"); + /* no further execution necessary. */ return; break; case 'rss': @@ -297,13 +326,36 @@ class PHPFSPOT { } } + /* if date-search variables are registered in the session, set the check + for "consider date-range" in the html output + */ if(isset($_SESSION['from_date']) && isset($_SESSION['to_date'])) $this->tmpl->assign('date_search_enabled', true); + /* if rate-search variables are registered in the session, set the check + for "consider rate-range" in the html output + */ + if(isset($_SESSION['rate_from']) && isset($_SESSION['rate_to'])) { + $this->tmpl->assign('rate_search_enabled', true); + } + $this->tmpl->register_function("sort_select_list", array(&$this, "smarty_sort_select_list"), false); - $this->tmpl->assign('from_date', $this->get_calendar('from')); - $this->tmpl->assign('to_date', $this->get_calendar('to')); - $this->tmpl->assign('content_page', 'welcome.tpl'); + $this->tmpl->assign('search_from_date', $this->get_calendar('from')); + $this->tmpl->assign('search_to_date', $this->get_calendar('to')); + + $this->tmpl->assign('preset_selected_tags', $this->getSelectedTags()); + $this->tmpl->assign('preset_available_tags', $this->getAvailableTags()); + $this->tmpl->assign('rate_search', $this->get_rate_search()); + + if(!isset($content)) { + if(isset($_SESSION['selected_tags']) && !empty($_SESSION['selected_tags'])) + $this->tmpl->assign('initial_content', $this->showPhotoIndex()); + else + $this->tmpl->assign('initial_content', $this->tmpl->fetch('welcome.tpl')); + } + else + $this->tmpl->assign('initial_content', $content); + $this->tmpl->show("index.tpl"); } // show() @@ -398,10 +450,19 @@ class PHPFSPOT { "; } else { - $query_str = " - SELECT p.id, p.uri, p.time, p.description - FROM photos p - "; + /* till F-Spot version 0.4.1 */ + if($this->dbver < 11) { + $query_str = " + SELECT p.id, p.uri, p.time, p.description + FROM photos p + "; + } + else { + $query_str = " + SELECT p.id, p.uri, p.time, p.description, p.rating + FROM photos p + "; + } } /* if show_tags is set, only return details for photos which @@ -461,6 +522,75 @@ class PHPFSPOT { } // getPhotoName() + /** + * get photo rating level + * + * this function will return the integer-based rating + * level of the photo. This can only be done, if the F-Spot + * database is at a specific level. If rating value can not + * be found, zero will be returned indicating no rating value + * is available. + * @param integer idx + * @return integer + */ + public function get_photo_rating($idx) + { + if($detail = $this->get_photo_details($idx)) { + if(isset($detail['rating'])) + return $detail['rating']; + } + + return 0; + + } // get_photo_rating() + + /** + * get rate-search bars + * + * this function will return the rating-bars for the + * search field. + * @return string + */ + public function get_rate_search() + { + $bar = ""; + + for($i = 1; $i <= 5; $i++) { + + $bar.= "cfg->web_path ."/resources/star.png"; + else + $bar.= $this->cfg->web_path ."/resources/empty_rate.png"; + + $bar.= "\" + onmouseover=\"show_rate('from', ". $i .");\" + onmouseout=\"reset_rate('from');\" + onclick=\"set_rate('from', ". $i .")\" />"; + } + + $bar.= "
\n"; + + for($i = 1; $i <= 5; $i++) { + + $bar.= "cfg->web_path ."/resources/star.png"; + else + $bar.= $this->cfg->web_path ."/resources/empty_rate.png"; + + $bar.= "\" + onmouseover=\"show_rate('to', ". $i .");\" + onmouseout=\"reset_rate('to');\" + onclick=\"set_rate('to', ". $i .");\" />"; + } + + return $bar; + + } // get_rate_search() + /** * shrink text according provided limit * @@ -540,7 +670,7 @@ class PHPFSPOT { return; } - $orig_path = $this->translate_path($this->parse_uri($details['uri'])); + $orig_path = $this->translate_path($this->parse_uri($details['uri'], 'fullpath')); $thumb_path = $this->get_thumb_path($this->cfg->photo_width, $photo); if(!file_exists($orig_path)) { @@ -563,7 +693,7 @@ class PHPFSPOT { $info = getimagesize($orig_path); /* get EXIF information if JPEG */ - if($info['mime'] == "image/jpeg") { + if(isset($info['mime']) && $info['mime'] == "image/jpeg") { $meta = $this->get_meta_informations($orig_path); } @@ -598,6 +728,7 @@ class PHPFSPOT { $this->tmpl->assign('description', $details['description']); $this->tmpl->assign('image_name', $this->parse_uri($details['uri'], 'filename')); + $this->tmpl->assign('image_rating', $this->get_photo_rating($photo)); $this->tmpl->assign('width', $info_thumb[0]); $this->tmpl->assign('height', $info_thumb[1]); @@ -606,29 +737,37 @@ class PHPFSPOT { $this->tmpl->assign('ExifOrigResolution', $meta_res); $this->tmpl->assign('ExifFileSize', $meta_size); - $this->tmpl->assign('image_url', 'phpfspot_img.php?idx='. $photo ."&width=". $this->cfg->photo_width); - $this->tmpl->assign('image_url_full', 'phpfspot_img.php?idx='. $photo); + if($this->is_user_friendly_url()) { + $this->tmpl->assign('image_url', '/photo/'. $photo ."/". $this->cfg->photo_width); + $this->tmpl->assign('image_url_full', '/photo/'. $photo); + } + else { + $this->tmpl->assign('image_url', 'phpfspot_img.php?idx='. $photo ."&width=". $this->cfg->photo_width); + $this->tmpl->assign('image_url_full', 'phpfspot_img.php?idx='. $photo); + } + $this->tmpl->assign('image_filename', $this->parse_uri($details['uri'], 'filename')); $this->tmpl->assign('tags', $this->get_photo_tags($photo)); $this->tmpl->assign('current_page', $this->getCurrentPage($current, $count)); $this->tmpl->assign('current_img', $photo); - if($previous_img) { - $this->tmpl->assign('previous_url', "javascript:showImage(". $previous_img .");"); + if(isset($previous_img)) { + $this->tmpl->assign('previous_url', "javascript:showPhoto(". $previous_img .");"); $this->tmpl->assign('prev_img', $previous_img); } - if($next_img) { - $this->tmpl->assign('next_url', "javascript:showImage(". $next_img .");"); + if(isset($next_img)) { + $this->tmpl->assign('next_url', "javascript:showPhoto(". $next_img .");"); $this->tmpl->assign('next_img', $next_img); } + $this->tmpl->assign('mini_width', $this->cfg->mini_width); $this->tmpl->assign('photo_width', $this->cfg->photo_width); $this->tmpl->assign('photo_number', $i); $this->tmpl->assign('photo_count', count($all_photos)); - $this->tmpl->show("single_photo.tpl"); + return $this->tmpl->fetch("single_photo.tpl"); } // showPhoto() @@ -705,13 +844,15 @@ class PHPFSPOT { $b = '88'; if(isset($this->tags[$key])) { - $output.= "". $this->tags[$key] .", "; + if($this->is_user_friendly_url()) + $output.= "cfg->web_path ."/tag/". $key ."\" onclick=\"Tags('add', ". $key ."); return false;\" class=\"tag\" style=\"font-size: ". $size ."%; color: #". $r.$g.$b .";\">". $this->tags[$key] .", "; + else + $output.= "cfg->web_path ."/index.php?mode=showpi\" onclick=\"Tags('add', ". $key ."); return false;\" class=\"tag\" style=\"font-size: ". $size ."%; color: #". $r.$g.$b .";\">". $this->tags[$key] .", "; } - } $output = substr($output, 0, strlen($output)-2); - print $output; + return $output; } // getAvailableTags() @@ -723,7 +864,7 @@ class PHPFSPOT { * session-variable $_SESSION['selected_tags'] * @return string */ - public function getSelectedTags() + public function getSelectedTags($type = 'link') { /* retrive tags from database */ $this->get_tags(); @@ -734,7 +875,22 @@ class PHPFSPOT { { // return all selected tags if(isset($_SESSION['selected_tags']) && in_array($tag, $_SESSION['selected_tags'])) { - $output.= "". $this->tags[$tag] .", "; + + switch($type) { + default: + case 'link': + $output.= "". $this->tags[$tag] .", "; + break; + case 'img': + $output.= " +
+ tags[$tag] ."\"> + cfg->web_path ."/phpfspot_img.php?tagidx=". $tag ."\" /> + +
+ "; + break; + } } } @@ -764,10 +920,15 @@ class PHPFSPOT { if(isset($_SESSION['searchfor_tag'])) unset($_SESSION['searchfor_tag']); + // has the user requested to hide this tag, and still someone, + // somehow tries to add it, don't allow this. + if(!isset($this->cfg->hide_tags) && + in_array($this->get_tag_name($tag), $this->cfg->hide_tags)) + return "ok"; + if(!in_array($tag, $_SESSION['selected_tags'])) array_push($_SESSION['selected_tags'], $tag); - return "ok"; } // addTag() @@ -809,7 +970,7 @@ class PHPFSPOT { } // resetTags() /** - * returns the value for the autocomplet tag-search + * returns the value for the autocomplete tag-search * @return string */ public function get_xml_tag_list() @@ -900,8 +1061,7 @@ class PHPFSPOT { /** * reset date search * - * if any date search has taken place, reset - * it now + * if any date search has taken place, reset it now. */ public function resetDateSearch() { @@ -912,6 +1072,20 @@ class PHPFSPOT { } // resetDateSearch(); + /** + * reset rate search + * + * if any rate search has taken place, reset it now. + */ + public function resetRateSearch() + { + if(isset($_SESSION['rate_from'])) + unset($_SESSION['rate_from']); + if(isset($_SESSION['rate_to'])) + unset($_SESSION['rate_to']); + + } // resetRateSearch(); + /** * return all photo according selection * @@ -937,6 +1111,12 @@ class PHPFSPOT { } if(isset($_SESSION['searchfor_name'])) { + + /* check for previous conditions. if so add 'AND' */ + if(!empty($additional_where_cond)) { + $additional_where_cond.= " AND "; + } + if($this->dbver < 9) { $additional_where_cond.= " ( @@ -957,6 +1137,24 @@ class PHPFSPOT { } } + /* limit result based on rate-search */ + if(isset($_SESSION['rate_from']) && isset($_SESSION['rate_to'])) { + + if($this->dbver > 10) { + + /* check for previous conditions. if so add 'AND' */ + if(!empty($additional_where_cond)) { + $additional_where_cond.= " AND "; + } + + $additional_where_cond.= " + p.rating >= ". $_SESSION['rate_from'] ." + AND + p.rating <= ". $_SESSION['rate_to'] ." + "; + } + } + if(isset($_SESSION['sort_order'])) { $order_str = $this->get_sort_order(); } @@ -976,7 +1174,7 @@ class PHPFSPOT { ON pt2.tag_id=t2.id WHERE t.name LIKE '%". $_SESSION['searchfor_tag'] ."%' "; - if(isset($additional_where_cond) && !empty($additional_where_cond)) + if(!empty($additional_where_cond)) $query_str.= "AND ". $additional_where_cond ." "; if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) { @@ -1013,7 +1211,7 @@ class PHPFSPOT { ON pt1.photo_id=p.id WHERE pt1.tag_id IN (". $selected .") "; - if(isset($additional_where_cond) && !empty($additional_where_cond)) + if(!empty($additional_where_cond)) $query_str.= "AND ". $additional_where_cond ." "; if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) { @@ -1069,7 +1267,7 @@ class PHPFSPOT { AND pt". ($i+2) .".tag_id=". $_SESSION['selected_tags'][$i] ." "; } - if(isset($additional_where_cond) && !empty($additional_where_cond)) + if(!empty($additional_where_cond)) $query_str.= "AND ". $additional_where_cond; if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) { @@ -1098,11 +1296,11 @@ class PHPFSPOT { ON pt.tag_id=t.id "; - if(isset($additional_where_cond) && !empty($additional_where_cond)) + if(!empty($additional_where_cond)) $query_str.= "WHERE ". $additional_where_cond ." "; if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) { - if(isset($additional_where_cond) && !empty($additional_where_cond)) + if(!empty($additional_where_cond)) $query_str.= "AND t.name IN ('".implode("','",$this->cfg->show_tags). "')"; else $query_str.= "WHERE t.name IN ('".implode("','",$this->cfg->show_tags). "')"; @@ -1124,10 +1322,12 @@ class PHPFSPOT { * * this function provides all the necessary information * for the photo index template. + * @return string */ public function showPhotoIndex() { $photos = $this->getPhotoSelection(); + $current_tags = $this->getCurrentTags(); $count = count($photos); @@ -1157,6 +1357,7 @@ class PHPFSPOT { $img_name[$thumbs] = Array(); $img_fullname[$thumbs] = Array(); $img_title = Array(); + $img_rating = Array(); for($i = $begin_with; $i < $end_with; $i++) { @@ -1167,6 +1368,7 @@ class PHPFSPOT { $img_name[$thumbs] = htmlspecialchars($this->getPhotoName($photos[$i], 15)); $img_fullname[$thumbs] = htmlspecialchars($this->getPhotoName($photos[$i], 0)); $img_title[$thumbs] = "Click to view photo ". htmlspecialchars($this->getPhotoName($photos[$i], 0)); + $img_rating[$thumbs] = $this->get_photo_rating($photos[$i]); $thumb_path = $this->get_thumb_path($this->cfg->thumb_width, $photos[$i]); @@ -1235,7 +1437,16 @@ class PHPFSPOT { else $style = ""; - $select = "is_user_friendly_url()) { + $select = "cfg->web_path ."/tag/205/". $start_with ."\""; + } + else { + $select = "cfg->web_path ."/index.php?mode=showpi tags=". $current_tags ." begin_with=". $begin_with ."\""; + } + $select.= " onclick=\"showPhotoIndex(". $start_with ."); return false;\""; + if($style != "") $select.= $style; $select.= ">". $i ." "; @@ -1273,9 +1484,7 @@ class PHPFSPOT { if($last_page > 1) $this->tmpl->assign('page_selector', $page_select); } - - $current_tags = $this->getCurrentTags(); $extern_link = "index.php?mode=showpi"; $rss_link = "index.php?mode=rss"; if($current_tags != "") { @@ -1306,19 +1515,23 @@ class PHPFSPOT { $this->tmpl->assign('img_name', $img_name); $this->tmpl->assign('img_fullname', $img_fullname); $this->tmpl->assign('img_title', $img_title); + $this->tmpl->assign('img_rating', $img_rating); $this->tmpl->assign('thumbs', $thumbs); + $this->tmpl->assign('selected_tags', $this->getSelectedTags('img')); - $this->tmpl->show("photo_index.tpl"); + $result = $this->tmpl->fetch("photo_index.tpl"); /* if we are returning to photo index from an photo-view, scroll the window to the last shown photo-thumbnail. after this, unset the last_photo session variable. */ if(isset($_SESSION['last_photo'])) { - print "\n"; + $result.= "\n"; unset($_SESSION['last_photo']); } + return $result; + } // showPhotoIndex() /** @@ -1334,7 +1547,7 @@ class PHPFSPOT { } // showCredits() /** - * create_thumbnails for the requested width + * create thumbnails for the requested width * * this function creates image thumbnails of $orig_image * stored as $thumb_image. It will check if the image is @@ -1351,13 +1564,13 @@ class PHPFSPOT { return false; } - $details = getimagesize($orig_image); - + $mime = $this->get_mime_info($orig_image); + /* check if original photo is a support image type */ - if(!$this->checkifImageSupported($details['mime'])) + if(!$this->checkifImageSupported($mime)) return false; - switch($details['mime']) { + switch($mime) { case 'image/jpeg': @@ -1367,52 +1580,88 @@ class PHPFSPOT { $flip_hori = false; $flip_vert = false; - switch($meta['Orientation']) { - case 1: /* top, left */ - /* nothing to do */ break; - case 2: /* top, right */ - $rotate = 0; $flip_hori = true; break; - case 3: /* bottom, left */ - $rotate = 180; break; - case 4: /* bottom, right */ - $flip_vert = true; break; - case 5: /* left side, top */ - $rotate = 90; $flip_vert = true; break; - case 6: /* right side, top */ - $rotate = 90; break; - case 7: /* left side, bottom */ - $rotate = 270; $flip_vert = true; break; - case 8: /* right side, bottom */ - $rotate = 270; break; + if(isset($meta['Orientation'])) { + switch($meta['Orientation']) { + case 1: /* top, left */ + /* nothing to do */ break; + case 2: /* top, right */ + $rotate = 0; $flip_hori = true; break; + case 3: /* bottom, left */ + $rotate = 180; break; + case 4: /* bottom, right */ + $flip_vert = true; break; + case 5: /* left side, top */ + $rotate = 90; $flip_vert = true; break; + case 6: /* right side, top */ + $rotate = 90; break; + case 7: /* left side, bottom */ + $rotate = 270; $flip_vert = true; break; + case 8: /* right side, bottom */ + $rotate = 270; break; + } } $src_img = @imagecreatefromjpeg($orig_image); + $handler = "gd"; break; case 'image/png': $src_img = @imagecreatefrompng($orig_image); + $handler = "gd"; + break; + + case 'image/x-portable-pixmap': + + $src_img = new Imagick($orig_image); + $handler = "imagick"; break; } - if(!$src_img) { + if(!isset($src_img) || empty($src_img)) { print "Can't load image from ". $orig_image ."\n"; return false; } - /* grabs the height and width */ - $cur_width = imagesx($src_img); - $cur_height = imagesy($src_img); + switch($handler) { + + case 'gd': + + /* grabs the height and width */ + $cur_width = imagesx($src_img); + $cur_height = imagesy($src_img); + + // If requested width is more then the actual image width, + // do not generate a thumbnail, instead safe the original + // as thumbnail but with lower quality. But if the image + // is to heigh too, then we still have to resize it. + if($width >= $cur_width && $cur_height < $this->cfg->thumb_height) { + $result = imagejpeg($src_img, $thumb_image, 75); + imagedestroy($src_img); + return true; + } + break; + + case 'imagick': + + $cur_width = $src_img->getImageWidth(); + $cur_height = $src_img->getImageHeight(); + + // If requested width is more then the actual image width, + // do not generate a thumbnail, instead safe the original + // as thumbnail but with lower quality. But if the image + // is to heigh too, then we still have to resize it. + if($width >= $cur_width && $cur_height < $this->cfg->thumb_height) { + $src_img->setCompressionQuality(75); + $src_img->setImageFormat('jpeg'); + $src_img->writeImage($thumb_image); + $src_img->clear(); + $src_img->destroy(); + return true; + } + break; - // If requested width is more then the actual image width, - // do not generate a thumbnail, instead safe the original - // as thumbnail but with lower quality. But if the image - // is to heigh too, then we still have to resize it. - if($width >= $cur_width && $cur_height < $this->cfg->thumb_height) { - $result = imagejpeg($src_img, $thumb_image, 75); - imagedestroy($src_img); - return true; } // If the image will be rotate because EXIF orientation said so @@ -1454,43 +1703,87 @@ class PHPFSPOT { } } - /* creates new image of that size */ - $dst_img = imagecreatetruecolor($new_w, $new_h); + switch($handler) { - imagefill($dst_img, 0, 0, ImageColorAllocate($dst_img, 255, 255, 255)); + case 'gd': - /* copies resized portion of original image into new image */ - imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $new_w, $new_h, imagesx($src_img), imagesy($src_img)); + /* creates new image of that size */ + $dst_img = imagecreatetruecolor($new_w, $new_h); - /* needs the image to be flipped horizontal? */ - if($flip_hori) { - $this->_debug("(FLIP)"); - $dst_img = $this->flipImage($dst_img, 'hori'); - } - /* needs the image to be flipped vertical? */ - if($flip_vert) { - $this->_debug("(FLIP)"); - $dst_img = $this->flipImage($dst_img, 'vert'); - } + imagefill($dst_img, 0, 0, ImageColorAllocate($dst_img, 255, 255, 255)); - if($rotate) { - $this->_debug("(ROTATE)"); - $dst_img = $this->rotateImage($dst_img, $rotate); - } + /* copies resized portion of original image into new image */ + imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $new_w, $new_h, imagesx($src_img), imagesy($src_img)); - /* write down new generated file */ - $result = imagejpeg($dst_img, $thumb_image, 75); + /* needs the image to be flipped horizontal? */ + if($flip_hori) { + $this->_debug("(FLIP)"); + $dst_img = $this->flipImage($dst_img, 'hori'); + } + /* needs the image to be flipped vertical? */ + if($flip_vert) { + $this->_debug("(FLIP)"); + $dst_img = $this->flipImage($dst_img, 'vert'); + } - /* free your mind */ - imagedestroy($dst_img); - imagedestroy($src_img); + if($rotate) { + $this->_debug("(ROTATE)"); + $dst_img = $this->rotateImage($dst_img, $rotate); + } - if($result === false) { - print "Can't write thumbnail ". $thumb_image ."\n"; - return false; - } + /* write down new generated file */ + $result = imagejpeg($dst_img, $thumb_image, 75); - return true; + /* free your mind */ + imagedestroy($dst_img); + imagedestroy($src_img); + + if($result === false) { + print "Can't write thumbnail ". $thumb_image ."\n"; + return false; + } + + return true; + + break; + + case 'imagick': + + $src_img->resizeImage($new_w, $new_h, Imagick::FILTER_LANCZOS, 1); + + /* needs the image to be flipped horizontal? */ + if($flip_hori) { + $this->_debug("(FLIP)"); + $src_img->rotateImage(new ImagickPixel(), 90); + $src_img->flipImage(); + $src_img->rotateImage(new ImagickPixel(), -90); + } + /* needs the image to be flipped vertical? */ + if($flip_vert) { + $this->_debug("(FLIP)"); + $src_img->flipImage(); + } + + if($rotate) { + $this->_debug("(ROTATE)"); + $src_img->rotateImage(new ImagickPixel(), $rotate); + } + + $src_img->setCompressionQuality(75); + $src_img->setImageFormat('jpeg'); + + if(!$src_img->writeImage($thumb_image)) { + print "Can't write thumbnail ". $thumb_image ."\n"; + return false; + } + + $src_img->clear(); + $src_img->destroy(); + return true; + + break; + + } } // create_thumbnail() @@ -1548,13 +1841,14 @@ class PHPFSPOT { $this->cfg->thumb_width, $this->cfg->photo_width, $this->cfg->mini_width, + 30, ); /* get details from F-Spot's database */ $details = $this->get_photo_details($idx); /* calculate file MD5 sum */ - $full_path = $this->translate_path($this->parse_uri($details['uri'])); + $full_path = $this->translate_path($this->parse_uri($details['uri'], 'fullpath')); if(!file_exists($full_path)) { $this->_error("File ". $full_path ." does not exist\n"); @@ -1566,10 +1860,27 @@ class PHPFSPOT { return; } - $file_md5 = md5_file($full_path); - $this->_debug("Image [". $idx ."] ". $this->shrink_text($this->parse_uri($details['uri'], 'filename'), 20) ." Thumbnails:"); + /* If Nikon NEF format, we need to treat it another way */ + if(isset($this->cfg->dcraw_bin) && + file_exists($this->cfg->dcraw_bin) && + is_executable($this->cfg->dcraw_bin) && + preg_match('/\.nef$/i', $details['uri'])) { + + $ppm_path = preg_replace('/\.nef$/i', '.ppm', $full_path); + + /* if PPM file does not exist, let dcraw convert it from NEF */ + if(!file_exists($ppm_path)) { + system($this->cfg->dcraw_bin ." -a ". $full_path); + } + + /* for now we handle the PPM instead of the NEF */ + $full_path = $ppm_path; + + } + + $file_md5 = md5_file($full_path); $changes = false; foreach($resolutions as $resolution) { @@ -1682,6 +1993,7 @@ class PHPFSPOT { */ public function startSearch() { + /* date search */ if(isset($_POST['from']) && $this->isValidDate($_POST['from'])) { $from = $_POST['from']; } @@ -1689,15 +2001,36 @@ class PHPFSPOT { $to = $_POST['to']; } + /* tag-name search */ if(isset($_POST['for_tag']) && is_string($_POST['for_tag'])) { $searchfor_tag = $_POST['for_tag']; $_SESSION['searchfor_tag'] = $_POST['for_tag']; } + else { + unset($_SESSION['searchfor_tag']); + } + /* file-name search */ if(isset($_POST['for_name']) && is_string($_POST['for_name'])) { - $searchfor_name = $_POST['for_name']; $_SESSION['searchfor_name'] = $_POST['for_name']; } + else { + unset($_SESSION['searchfor_name']); + } + + /* rate-search */ + if(isset($_POST['rate_from']) && is_numeric($_POST['rate_from'])) { + + $_SESSION['rate_from'] = $_POST['rate_from']; + + if(isset($_POST['rate_to']) && is_numeric($_POST['rate_to'])) { + $_SESSION['rate_to'] = $_POST['rate_to']; + } + } + else { + /* delete any previously set value */ + unset($_SESSION['rate_to'], $_SESSION['rate_from']); + } $this->get_tags(); @@ -1872,8 +2205,11 @@ class PHPFSPOT { $tags = Array(); - while($row = $this->db->db_fetch_object($result)) + while($row = $this->db->db_fetch_object($result)) { + if(isset($this->cfg->hide_tags) && in_array($row['name'], $this->cfg->hide_tags)) + continue; $tags[$row['id']] = $row['name']; + } return $tags; @@ -1962,7 +2298,7 @@ class PHPFSPOT { private function _debug($text) { - if($this->fromcmd) { + if(isset($this->fromcmd)) { print $text; } @@ -1975,7 +2311,14 @@ class PHPFSPOT { */ public function checkifImageSupported($mime) { - if(in_array($mime, Array("image/jpeg", "image/png"))) + $supported_types = Array( + "image/jpeg", + "image/png", + "image/x-portable-pixmap", + "image/tiff" + ); + + if(in_array($mime, $supported_types)) return true; return false; @@ -2126,7 +2469,7 @@ class PHPFSPOT { foreach($pictures as $picture) { - $orig_url = $this->get_phpfspot_url() ."index.php?mode=showp&id=". $picture; + $orig_url = $this->get_phpfspot_url() ."/index.php?mode=showp&id=". $picture; if($current_tags != "") { $orig_url.= "&tags=". $current_tags; } @@ -2134,7 +2477,12 @@ class PHPFSPOT { $orig_url.= "&from_date=". $_SESSION['from_date'] ."&to_date=". $_SESSION['to_date']; } - $thumb_url = $this->get_phpfspot_url() ."phpfspot_img.php?idx=". $picture ."&width=". $this->cfg->thumb_width; + if($this->is_user_friendly_url()) { + $thumb_url = $this->get_phpfspot_url() ."/photo/". $picture ."/". $this->cfg->thumb_width; + } + else { + $thumb_url = $this->get_phpfspot_url() ."/phpfspot_img.php?idx=". $picture ."&width=". $this->cfg->thumb_width; + } switch($mode) { @@ -2183,7 +2531,7 @@ class PHPFSPOT { foreach($pictures as $picture) { - $orig_url = $this->get_phpfspot_url() ."index.php?mode=showp&id=". $picture; + $orig_url = $this->get_phpfspot_url() ."/index.php?mode=showp&id=". $picture; if($current_tags != "") { $orig_url.= "&tags=". $current_tags; } @@ -2193,16 +2541,22 @@ class PHPFSPOT { $details = $this->get_photo_details($picture); - $thumb_url = $this->get_phpfspot_url() ."phpfspot_img.php?idx=". $picture ."&width=". $this->cfg->thumb_width; + if($this->is_user_friendly_url()) { + $thumb_url = $this->get_phpfspot_url() ."/photo/". $picture ."/". $this->cfg->thumb_width; + } + else { + $thumb_url = $this->get_phpfspot_url() ."/phpfspot_img.php?idx=". $picture ."&width=". $this->cfg->thumb_width; + } + $thumb_html = htmlspecialchars("
". $details['description']); - $orig_path = $this->translate_path($this->parse_uri($details['uri'])); + $orig_path = $this->translate_path($this->parse_uri($details['uri'], 'fullpath')); /* get EXIF information if JPEG */ - if($details['mime'] == "image/jpeg") { + if(isset($details['mime']) && $details['mime'] == "image/jpeg") { $meta = $this->get_meta_informations($orig_path); } @@ -2232,7 +2586,10 @@ class PHPFSPOT { /** - * return all selected tags as one string + * get all selected tags + * + * This function will return all selected tags as one string, seperated + * by a comma. * @return array */ private function getCurrentTags() @@ -2270,7 +2627,6 @@ class PHPFSPOT { public function whatToDo() { if(isset($_SESSION['current_photo']) && $_SESSION['start_action'] == 'showp') { - return "show_photo"; } elseif(isset($_SESSION['selected_tags']) && !empty($_SESSION['selected_tags'])) { return "showpi_tags"; @@ -2279,8 +2635,6 @@ class PHPFSPOT { return "showpi"; } - return "nothing special"; - } // whatToDo() /** @@ -2356,6 +2710,12 @@ class PHPFSPOT { case 'tags_desc': return " ORDER BY t.name DESC ,p.time ASC"; break; + case 'rate_asc': + return " ORDER BY t.name ASC, p.rating ASC"; + break; + case 'rate_desc': + return " ORDER BY t.name DESC, p.rating DESC"; + break; } } // get_sort_order() @@ -2376,7 +2736,11 @@ class PHPFSPOT { else $_SESSION['slideshow_img']++; - return $this->get_phpfspot_url() ."phpfspot_img.php?idx=". $all_photos[$_SESSION['slideshow_img']] ."&width=". $this->cfg->photo_width; + if($this->is_user_friendly_url()) { + return $this->get_phpfspot_url() ."/photo/". $all_photos[$_SESSION['slideshow_img']] ."/". $this->cfg->photo_width; + } + + return $this->get_phpfspot_url() ."/phpfspot_img.php?idx=". $all_photos[$_SESSION['slideshow_img']] ."&width=". $this->cfg->photo_width; } // getNextSlideShowImage() @@ -2396,7 +2760,11 @@ class PHPFSPOT { else $_SESSION['slideshow_img']--; - return $this->get_phpfspot_url() ."phpfspot_img.php?idx=". $all_photos[$_SESSION['slideshow_img']] ."&width=". $this->cfg->photo_width; + if($this->is_user_friendly_url()) { + return $this->get_phpfspot_url() ."/photo/". $all_photos[$_SESSION['slideshow_img']] ."/". $this->cfg->photo_width; + } + + return $this->get_phpfspot_url() ."/phpfspot_img.php?idx=". $all_photos[$_SESSION['slideshow_img']] ."&width=". $this->cfg->photo_width; } // getPrevSlideShowImage() @@ -2422,11 +2790,26 @@ class PHPFSPOT { { $all = Array(); - $result = $this->db->db_query(" - SELECT id - FROM photos - "); - + $query_str = " + SELECT p.id + FROM photos p + "; + + /* if show_tags is set, only return details for photos which + are specified to be shown + */ + if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) { + $query_str.= " + INNER JOIN photo_tags pt + ON p.id=pt.photo_id + INNER JOIN tags t + ON pt.tag_id=t.id + WHERE + t.name IN ('".implode("','",$this->cfg->show_tags)."')"; + } + + $result = $this->db->db_query($query_str); + while($row = $this->db->db_fetch_object($result)) { array_push($all, $row['id']); } @@ -2435,6 +2818,56 @@ class PHPFSPOT { } // get_random_photo() + /** + * get random photo tag photo + * + * this function will get all photos tagged with the requested + * tag from the fspot database and randomly return ONE entry + * + * saddly there is yet no sqlite3 function which returns + * the bulk result in array, so we have to fill up our + * own here. + * @return array + */ + public function get_random_tag_photo($tagidx) + { + $all = Array(); + + $query_str = " + SELECT p.id + FROM photos p + INNER JOIN photo_tags pt + ON p.id=pt.photo_id + "; + + if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) { + $query_str.= " + INNER JOIN tags t + ON pt.tag_id=t.id + "; + } + $query_str.= " + WHERE + pt.tag_id LIKE '". $tagidx ."' + "; + + /*if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) { + $query_str.= " + AND + t.name IN ('".implode("','",$this->cfg->show_tags)."') + "; + }*/ + + $result = $this->db->db_query($query_str); + + while($row = $this->db->db_fetch_object($result)) { + array_push($all, $row['id']); + } + + return $all[array_rand($all)]; + + } // get_random_tag_photo() + /** * validates provided date * @@ -2462,7 +2895,9 @@ class PHPFSPOT { */ private function ts2str($timestamp) { - return strftime("%Y-%m-%d", $timestamp); + if(!empty($timestamp) && is_numeric($timestamp)) + return strftime("%Y-%m-%d", $timestamp); + } // ts2str() /** @@ -2532,6 +2967,7 @@ class PHPFSPOT { private function get_phpfspot_url() { return $this->get_web_protocol() ."://". $this->get_server_name() . $this->cfg->web_path; + } // get_phpfspot_url() /** @@ -2563,7 +2999,7 @@ class PHPFSPOT { * error message * @param string $file * @param boolean $silent - * @retrun boolean + * @return boolean */ private function check_readable($file, $silent = null) { @@ -2724,9 +3160,11 @@ class PHPFSPOT { } - /* check for pending slash on web_path */ - if(!preg_match("/\/$/", $this->cfg->web_path)) - $this->cfg->web_path.= "/"; + /* remove trailing slash, if set */ + if($this->cfg->web_path == "/") + $this->cfg->web_path = ""; + elseif(preg_match('/\/$/', $this->cfg->web_path)) + $this->cfg->web_path = preg_replace('/\/$/', '', $this->cfg->web_path); return $this->runtime_error; @@ -2792,6 +3230,137 @@ class PHPFSPOT { } // getCurrentPage() + /** + * return mime info + * + * this function tries to find out the correct mime-type + * for the provided file. + * @param string $file + * @return string + */ + public function get_mime_info($file) + { + $details = getimagesize($file); + + /* if getimagesize() returns empty, try at least to find out the + mime type. + */ + if(empty($details) && function_exists('mime_content_type')) { + + // mime_content_type is marked as deprecated in the documentation, + // but is it really necessary to force users to install a PECL + // extension? + $details['mime'] = mime_content_type($file); + } + + return $details['mime']; + + } // get_mime_info() + + /** + * return tag-name by tag-idx + * + * this function returns the tag-name for the requested + * tag specified by tag-idx. + * @param integer $idx + * @return string + */ + public function get_tag_name($idx) + { + if($result = $this->db->db_fetchSingleRow(" + SELECT name + FROM tags + WHERE + id LIKE '". $idx ."'")) { + + return $result['name']; + + } + + return 0; + + } // get_tag_name() + + /** + * parse user friendly url which got rewritten by the websever + * @param string $request_uri + * @return string + */ + private function parse_user_friendly_url($request_uri) + { + if(preg_match('/\/photoview\/|\/photo\/|\/tag\//', $request_uri)) { + + $options = explode('/', $request_uri); + + switch($options[1]) { + case 'photoview': + if(is_numeric($options[2])) { + $this->session_cleanup(); + //unset($_SESSION['start_action']); + //unset($_SESSION['selected_tags']); + $_GET['mode'] = 'showp'; + return $this->showPhoto($options[2]); + } + break; + case 'photo': + if(is_numeric($options[2])) { + require_once "phpfspot_img.php"; + $img = new PHPFSPOT_IMG; + if(isset($options[3]) && is_numeric($options[3])) + $img->showImg($options[2], $options[3]); + else + $img->showImg($options[2]); + } + exit; + break; + case 'tag': + if(is_numeric($options[2])) { + $this->session_cleanup(); + $_GET['tags'] = $options[2]; + $_SESSION['selected_tags'] = Array($options[2]); + if(isset($options[3]) && is_numeric($options[3])) + $_SESSION['begin_with'] = $options[3]; + return $this->showPhotoIndex(); + } + break; + } + } + + } // parse_user_friendly_url() + + /** + * check if user-friendly-urls are enabled + * + * this function will return true, if the config option + * $user_friendly_url has been set. Otherwise false. + * @return boolean + */ + private function is_user_friendly_url() + { + if(isset($this->cfg->user_friendly_url) && $this->cfg->user_friendly_url) + return true; + + return false; + + } // is_user_friendly_url() + + /** + * session cleanup + * + * this function will cleanup user's session information + */ + private function session_cleanup() + { + unset($_SESSION['begin_with']); + $this->resetDateSearch(); + $this->resetPhotoView(); + $this->resetTagSearch(); + $this->resetNameSearch(); + $this->resetDateSearch(); + $this->resetTags(); + + } // session_cleanup() + } // class PHPFSPOT ?>