From 6198d8ac0ce0623ebb56dba2fed19e4e759682c0 Mon Sep 17 00:00:00 2001 From: Andreas Unterkircher Date: Fri, 15 Aug 2008 13:19:23 +0200 Subject: [PATCH 1/1] support for F-Spot photo versioning, refs #67 Signed-off-by: Andreas Unterkircher --- phpfspot.class.php | 592 ++++++++++++++++++---- phpfspot.js | 21 + phpfspot_db.php | 257 +++++++--- phpfspot_img.php | 35 +- rpc.php | 9 +- themes/default/templates/single_photo.tpl | 8 + 6 files changed, 729 insertions(+), 193 deletions(-) diff --git a/phpfspot.class.php b/phpfspot.class.php index d7a76c3..5d35210 100644 --- a/phpfspot.class.php +++ b/phpfspot.class.php @@ -123,6 +123,7 @@ class PHPFSPOT { /* set application name and version information */ $this->cfg->product = "phpfspot"; $this->cfg->version = "1.6"; + $this->cfg->db_version = 2; $this->sort_orders= array( 'date_asc' => 'Date ↑', @@ -200,7 +201,7 @@ class PHPFSPOT { } /* Check if some tables need to be created */ - $this->check_config_table(); + $this->check_phpfspot_db(); /* overload Smarty class with our own template handler */ require_once "phpfspot_tmpl.php"; @@ -293,6 +294,8 @@ class PHPFSPOT { $_SESSION['start_action'] = 'showp'; } if(isset($_GET['id']) && is_numeric($_GET['id'])) { + if($_SESSION['current_photo'] != $_GET['id']) + unset($_SESSION['current_version']); $_SESSION['current_photo'] = $_GET['id']; $_SESSION['start_action'] = 'showp'; } @@ -455,14 +458,19 @@ class PHPFSPOT { } // get_tags() /** - * extract all photo details + * get all photo details from F-Spot database * - * retrieve all available details from f-spot's - * database and return them as object + * this function queries the F-Spot database for all available + * details of the requested photo. It returns them as a object. + * + * Furthermore it takes care of the photo version to be requested. + * If photo version is not yet, it queries information for the + * original photo. + * * @param integer $idx * @return object|null */ - public function get_photo_details($idx) + public function get_photo_details($idx, $version_idx = NULL) { /* ~ F-Spot version 0.3.x */ if($this->dbver < 9) { @@ -480,6 +488,7 @@ class PHPFSPOT { "; } else { + /* rating value got introduced */ $query_str = " SELECT p.id, p.uri, p.time, p.description, p.rating FROM photos p @@ -505,24 +514,47 @@ class PHPFSPOT { "; } - if($result = $this->db->db_query($query_str)) { + if($row = $this->db->db_fetchSingleRow($query_str)) { - $row = $this->db->db_fetch_object($result); - - /* before F-Spot db version 9 there was no uri column but seperated - columns for directory_path and name (= filename). + /* before F-Spot db version 9 there was no uri column but + seperated fields for directory_path and name (= filename). */ if($this->dbver < 9) { $row['uri'] = "file://". $row['directory_path'] ."/". $row['name']; } + /* if version-idx has not yet been set, get the latest photo version */ + if(!isset($version_idx) || !$this->is_valid_version($idx, $version_idx)) + $version_idx = $this->get_latest_version($idx); + + /* if an alternative version has been requested */ + if($version_idx > 0) { + + /* check for alternative versions */ + if($version = $this->db->db_fetchSingleRow(" + SELECT + version_id, name, uri + FROM + photo_versions + WHERE + photo_id LIKE '". $idx ."' + AND + version_id LIKE '". $version_idx ."' + ")) { + + $row['name'] = $version['name']; + $row['uri'] = $version['uri']; + + } + } + return $row; } - + return null; - } // get_photo_details + } // get_photo_details() /** * returns aligned photo names @@ -697,7 +729,16 @@ class PHPFSPOT { } $orig_path = $this->translate_path($this->parse_uri($details['uri'], 'fullpath')); - $thumb_path = $this->get_thumb_path($this->cfg->photo_width, $photo); + + /* if current version is already set, use it */ + if($this->get_current_version() !== false) + $version = $this->get_current_version(); + + /* if version not set yet, we assume to display the latest version */ + if(!isset($version) || !$this->is_valid_version($photo, $version)) + $version = $this->get_latest_version($photo); + + $thumb_path = $this->get_thumb_path($this->cfg->photo_width, $photo, $version); if(!file_exists($orig_path)) { $this->_error("Photo ". $orig_path ." does not exist!
\n"); @@ -712,7 +753,7 @@ class PHPFSPOT { /* If the thumbnail doesn't exist yet, try to create it */ if(!file_exists($thumb_path)) { $this->gen_thumb($photo, true); - $thumb_path = $this->get_thumb_path($this->cfg->photo_width, $photo); + $thumb_path = $this->get_thumb_path($this->cfg->photo_width, $photo, $version); } /* get mime-type, height and width from the original photo */ @@ -763,11 +804,11 @@ class PHPFSPOT { $this->tmpl->assign('ExifFileSize', $meta_size); if($this->is_user_friendly_url()) { - $this->tmpl->assign('image_url', '/photo/'. $photo ."/". $this->cfg->photo_width); + $this->tmpl->assign('image_url', '/photo/'. $photo ."/". $this->cfg->photo_width .'/'. $version); $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', 'phpfspot_img.php?idx='. $photo ."&width=". $this->cfg->photo_width ."&version=". $version); $this->tmpl->assign('image_url_full', 'phpfspot_img.php?idx='. $photo); } @@ -791,6 +832,14 @@ class PHPFSPOT { $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->assign('photo', $photo); + $this->tmpl->assign('version', $version); + + /* if the photo as alternative versions, set a flag for the template */ + if($this->get_photo_versions($photo)) + $this->tmpl->assign('has_versions', true); + + $this->tmpl->register_function("photo_version_select_list", array(&$this, "smarty_photo_version_select_list"), false); return $this->tmpl->fetch("single_photo.tpl"); @@ -1070,6 +1119,9 @@ class PHPFSPOT { if(isset($_SESSION['current_photo'])) unset($_SESSION['current_photo']); + if(isset($_SESSION['current_version'])) + unset($_SESSION['current_version']); + } // resetPhotoView(); /** @@ -1408,7 +1460,7 @@ class PHPFSPOT { $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]); + $thumb_path = $this->get_thumb_path($this->cfg->thumb_width, $photos[$i], $this->get_latest_version($photos[$i])); if(file_exists($thumb_path)) { $info = getimagesize($thumb_path); @@ -1843,25 +1895,133 @@ class PHPFSPOT { * if it does not exist yet. this own is used to store * some necessary informations (md5 sum's, ...). */ - public function check_config_table() + public function check_phpfspot_db() { // if the config table doesn't exist yet, create it if(!$this->cfg_db->db_check_table_exists("images")) { $this->cfg_db->db_exec(" CREATE TABLE images ( - img_idx int primary key, - img_md5 varchar(32) + img_idx int, + img_version_idx int, + img_md5 varchar(32), + UNIQUE(img_idx, img_version_idx) + ) + "); + } + + if(!$this->cfg_db->db_check_table_exists("meta")) { + $this->cfg_db->db_exec(" + CREATE TABLE meta ( + meta_key varchar(255), + meta_value varchar(255) + ) + "); + + /* db_version was added with phpfspot 1.7, before changes + on the phpfspot database where not necessary. + */ + + $this->cfg_db->db_exec(" + INSERT INTO meta ( + meta_key, meta_value + ) VALUES ( + 'phpfspot Database Version', + '". $this->cfg->db_version ."' ) - "); + "); } - } // check_config_table + /* if version <= 2 and column img_version_idx does not exist yet */ + if($this->get_db_version() <= 2 && + !$this->cfg_db->db_check_column_exists("images", "img_version_idx")) { + + if(!$this->cfg_db->db_start_transaction()) + die("Can not start database transaction"); + + $result = $this->cfg_db->db_exec(" + CREATE TEMPORARY TABLE images_temp ( + img_idx int, + img_version_idx int, + img_md5 varchar(32), + UNIQUE(img_idx, img_version_idx) + ) + "); + + if(!$result) { + $this->cfg_db->db_rollback_transaction(); + die("Upgrade failed - transaction rollback"); + } + + $result = $this->cfg_db->db_exec(" + INSERT INTO images_temp + SELECT + img_idx, + 0, + img_md5 + FROM images + "); + + if(!$result) { + $this->cfg_db->db_rollback_transaction(); + die("Upgrade failed - transaction rollback"); + } + + $result = $this->cfg_db->db_exec(" + DROP TABLE images + "); + + if(!$result) { + $this->cfg_db->db_rollback_transaction(); + die("Upgrade failed - transaction rollback"); + } + + $result = $this->cfg_db->db_exec(" + CREATE TABLE images ( + img_idx int, + img_version_idx int, + img_md5 varchar(32), + UNIQUE(img_idx, img_version_idx) + ) + "); + + if(!$result) { + $this->cfg_db->db_rollback_transaction(); + die("Upgrade failed - transaction rollback"); + } + + $result = $this->cfg_db->db_exec(" + INSERT INTO images + SELECT * + FROM images_temp + "); + + if(!$result) { + $this->cfg_db->db_rollback_transaction(); + die("Upgrade failed - transaction rollback"); + } + + $result = $this->cfg_db->db_exec(" + DROP TABLE images_temp + "); + + if(!$result) { + $this->cfg_db->db_rollback_transaction(); + die("Upgrade failed - transaction rollback"); + } + + if(!$this->cfg_db->db_commit_transaction()) + die("Can not commit database transaction"); + + } + + } // check_phpfspot_db /** - * Generates a thumbnail from photo idx + * generates thumbnails * - * This function will generate JPEG thumbnails from provided F-Spot photo - * indizes. + * This function generates JPEG thumbnails from + * provided F-Spot photo indize and its alternative + * versions. * * 1. Check if all thumbnail generations (width) are already in place and * readable @@ -1874,6 +2034,7 @@ class PHPFSPOT { public function gen_thumb($idx = 0, $force = 0, $overwrite = false) { $error = 0; + $versions = Array(0); $resolutions = Array( $this->cfg->thumb_width, @@ -1882,110 +2043,125 @@ class PHPFSPOT { 30, ); - /* get details from F-Spot's database */ - $details = $this->get_photo_details($idx); + if($alt_versions = $this->get_photo_versions($idx)) + $versions = array_merge($versions, $alt_versions); - /* calculate file MD5 sum */ - $full_path = $this->translate_path($this->parse_uri($details['uri'], 'fullpath')); + foreach($versions as $version) { - if(!file_exists($full_path)) { - $this->_error("File ". $full_path ." does not exist\n"); - return; - } + /* get details from F-Spot's database */ + $details = $this->get_photo_details($idx, $version); - if(!is_readable($full_path)) { - $this->_error("File ". $full_path ." is not readable for ". $this->getuid() ."\n"); - return; - } + /* calculate file MD5 sum */ + $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"); + return; + } + + if(!is_readable($full_path)) { + $this->_error("File ". $full_path ." is not readable for ". $this->getuid() ."\n"); + return; + } - $this->_debug("Image [". $idx ."] ". $this->shrink_text($this->parse_uri($details['uri'], 'filename'), 20) ." Thumbnails:"); + $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'])) { + /* 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); + $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; - /* 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) { - $file_md5 = md5_file($full_path); - $changes = false; + $generate_it = false; - foreach($resolutions as $resolution) { - - $generate_it = false; + $thumb_sub_path = substr($file_md5, 0, 2); + $thumb_path = $this->cfg->thumb_path ."/". $thumb_sub_path ."/". $resolution ."_". $file_md5; - $thumb_sub_path = substr($file_md5, 0, 2); - $thumb_path = $this->cfg->thumb_path ."/". $thumb_sub_path ."/". $resolution ."_". $file_md5; + /* if thumbnail-subdirectory does not exist yet, create it */ + if(!file_exists(dirname($thumb_path))) { + mkdir(dirname($thumb_path), 0755); + } - /* if thumbnail-subdirectory does not exist yet, create it */ - if(!file_exists(dirname($thumb_path))) { - mkdir(dirname($thumb_path), 0755); - } + /* if the thumbnail file doesn't exist, create it */ + if(!file_exists($thumb_path) || $force) { + $generate_it = true; + } + elseif($file_md5 != $this->getMD5($idx, $version)) { + $generate_it = true; + } - /* if the thumbnail file doesn't exist, create it */ - if(!file_exists($thumb_path)) { - $generate_it = true; - } - /* if the file hasn't changed there is no need to regen the thumb */ - elseif($file_md5 != $this->getMD5($idx) || $force) { - $generate_it = true; - } + if($generate_it || $overwrite) { + + $this->_debug(" ". $resolution ."px"); + if(!$this->create_thumbnail($full_path, $thumb_path, $resolution)) + $error = 1; - if($generate_it || $overwrite) { + $changes = true; + } + } - $this->_debug(" ". $resolution ."px"); - if(!$this->create_thumbnail($full_path, $thumb_path, $resolution)) - $error = 1; + if(!$changes) { + $this->_debug(" already exist"); + } - $changes = true; + /* set the new/changed MD5 sum for the current photo */ + if(!$error) { + $this->setMD5($idx, $file_md5, $version); } - } - if(!$changes) { - $this->_debug(" already exist"); - } + $this->_debug("\n"); - /* set the new/changed MD5 sum for the current photo */ - if(!$error) { - $this->setMD5($idx, $file_md5); } - $this->_debug("\n"); - } // gen_thumb() /** * returns stored md5 sum for a specific photo * - * this function queries the phpfspot database for a - * stored MD5 checksum of the specified photo + * this function queries the phpfspot database for a stored MD5 + * checksum of the specified photo. It also takes care of the + * requested photo version - original or alternative photo. + * * @param integer $idx * @return string|null */ - public function getMD5($idx) + public function getMD5($idx, $version_idx = 0) { $result = $this->cfg_db->db_query(" - SELECT img_md5 - FROM images - WHERE img_idx='". $idx ."' + SELECT + img_md5 + FROM + images + WHERE + img_idx='". $idx ."' + AND + img_version_idx='". $version_idx ."' "); if(!$result) - return 0; + return NULL; - $img = $this->cfg_db->db_fetch_object($result); - return $img['img_md5']; + if($img = $this->cfg_db->db_fetch_object($result)) + return $img['img_md5']; + + return NULL; } // getMD5() @@ -1994,11 +2170,16 @@ class PHPFSPOT { * @param integer $idx * @param string $md5 */ - private function setMD5($idx, $md5) + private function setMD5($idx, $md5, $version_idx = 0) { $result = $this->cfg_db->db_exec(" - REPLACE INTO images (img_idx, img_md5) - VALUES ('". $idx ."', '". $md5 ."') + INSERT OR REPLACE INTO images ( + img_idx, img_version_idx, img_md5 + ) VALUES ( + '". $idx ."', + '". $version_idx ."', + '". $md5 ."' + ) "); } // setMD5() @@ -2114,6 +2295,25 @@ class PHPFSPOT { } // updateSortOrder() + /** + * update photo version in session variable + * + * this function is invoked by RPC and will set the requested + * photo version in the session variable. + * @param string $photo_version + * @return string + */ + public function update_photo_version($photo_idx, $photo_version) + { + if($this->is_valid_version($photo_idx, $photo_version)) { + $_SESSION['current_version'] = $photo_version; + return "ok"; + } + + return "incorrect photo version provided"; + + } // update_photo_version() + /** * rotate image * @@ -2642,12 +2842,52 @@ class PHPFSPOT { /** * return the current photo */ - public function getCurrentPhoto() + public function get_current_photo() { if(isset($_SESSION['current_photo'])) { - print $_SESSION['current_photo']; + return $_SESSION['current_photo']; } - } // getCurrentPhoto() + + return NULL; + + } // get_current_photo() + + /** + * current selected photo version + * + * this function returns the current selected photo version + * from the session variables. + * + * @return int + */ + public function get_current_version() + { + /* if current version is set, return it, if the photo really has that version */ + if(isset($_SESSION['current_version']) && is_numeric($_SESSION['current_version'])) + return $_SESSION['current_version']; + + return false; + + } // get_current_version() + + /** + * returns latest available photo version + * + * this function returns the latested available version + * for the requested photo. + * + * @return int + */ + public function get_latest_version($photo_idx) + { + /* try to get the lasted version for the current photo */ + if($versions = $this->get_photo_versions($photo_idx)) + return $versions[count($versions)-1]; + + /* if no alternative version were found, return original version */ + return 0; + + } // get_current_version() /** * tells the client browser what to do @@ -2688,6 +2928,37 @@ class PHPFSPOT { } // getuid() + /** + * photo version select list + * + * this function returns a HTML select list (drop down) + * to select a alternative photo version of the original photo. + * + * @param array $params + * @param smarty $smarty + * @return string + */ + public function smarty_photo_version_select_list($params, &$smarty) + { + if(!isset($params['photo']) || !isset($params['current'])) + return NULL; + + $output = ""; + $versions = $this->get_photo_versions($params['photo']); + + foreach($versions as $version) { + + $output.= ""; + } + + return $output; + + } // smarty_photo_version_select_list() + /** * returns a select-dropdown box to select photo index sort parameters * @param array $params @@ -2960,9 +3231,9 @@ class PHPFSPOT { * @param integer $photo * @return string */ - public function get_thumb_path($width, $photo) + public function get_thumb_path($width, $photo_idx, $version_idx) { - $md5 = $this->getMD5($photo); + $md5 = $this->getMD5($photo_idx, $version_idx); $sub_path = substr($md5, 0, 2); return $this->cfg->thumb_path . "/" @@ -3339,12 +3610,15 @@ class PHPFSPOT { break; case 'photo': if(is_numeric($options[2])) { + $width = NULL; + $version = NULL; + if(isset($options[3]) && is_numeric($options[3])) + $width = $options[3]; + if(isset($options[4]) && is_numeric($options[4])) + $version = $options[4]; 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]); + $img->showImg($options[2], $width, $version); } exit; break; @@ -3396,6 +3670,116 @@ class PHPFSPOT { } // session_cleanup() + /** + * get database version + * + * this function queries the meta table + * and returns the current database version. + * + * @return integer + */ + public function get_db_version() + { + if($row = $this->cfg_db->db_fetchSingleRow(" + SELECT meta_value + FROM + meta + WHERE + meta_key LIKE 'phpfspot Database Version' + ")) { + + return $row['meta_value']; + + } + + return 0; + + } // get_db_version() + + /** + * get photo versions + * + * this function returns an array of all available + * alterntaive versions of the provided photo id. + * has alternative photo versions available + * + * @param int $idx + * @return array + */ + public function get_photo_versions($idx) + { + $versions = Array(); + + $result = $this->db->db_query(" + SELECT + version_id + FROM + photo_versions + WHERE + photo_id LIKE '". $idx ."'"); + + while($row = $this->cfg_db->db_fetch_object($result)) { + array_push($versions, $row['version_id']); + } + + return $versions; + + } // get_photo_versions() + + /** + * check for invalid version of photo + * + * this function validates the provided photo-id and version-id + * + * @param int $photo_idx + * @param int $version_idx + * @return bool + */ + public function is_valid_version($photo_idx, $version_idx) + { + /* the original version is always valid */ + if($version_idx == 0) + return true; + + if($versions = $this->get_photo_versions($photo_idx)) { + if(in_array($version_idx, $versions)) + return true; + } + + return false; + + } // is_valid_version() + + /** + * get photo version name + * + * this function returns the name of the version + * identified by the photo-id and version-id. + * + * @param int $photo_idx + * @param int $version_idx + * @return string + */ + public function get_photo_version_name($photo_idx, $version_idx) + { + if($row = $this->db->db_fetchSingleRow(" + SELECT + name + FROM + photo_versions + WHERE + photo_id LIKE '". $photo_idx ."' + AND + version_id LIKE '". $version_idx ."'")) { + + return $row['name']; + + } + + return false; + + } // get_photo_version_name() + } // class PHPFSPOT ?> diff --git a/phpfspot.js b/phpfspot.js index 57345ab..54395e2 100644 --- a/phpfspot.js +++ b/phpfspot.js @@ -820,6 +820,27 @@ function update_sort_order(obj) } // update_sort_order() +/** + * if the photo-version ѕelect-box has changed, set the newly + * choosen photo version as the to-be-displayed photo version + */ +function update_photo_version(obj, current_photo) +{ + var objTemp = new Object(); + objTemp['photo_version'] = obj.options[obj.selectedIndex].value; + objTemp['photo_idx'] = current_photo; + + var retr = HTML_AJAX.post(web_path + '/rpc.php?action=update_photo_version', objTemp); + + if(retr == "ok") { + showPhoto(current_photo); + } + else { + window.alert("Server message: "+ retr); + } + +} // update_photo_version() + /** * show rate stars * diff --git a/phpfspot_db.php b/phpfspot_db.php index e0cf39f..339e023 100644 --- a/phpfspot_db.php +++ b/phpfspot_db.php @@ -127,32 +127,30 @@ class PHPFSPOT_DB { */ public function db_query($query = "") { - if($this->getConnStatus()) { + if(!$this->getConnStatus()) + return false; - $this->last_query = $query; - - switch($this->parent->cfg->db_access) { - case 'native': - if(($result = sqlite3_query($this->db, $query)) === false) - $this->ThrowError($this->getLastError()); - break; - case 'pdo': - try{ - $result = $this->db->query($query); - return $result; - } - catch (Exception $e) { - $this->ThrowError($e->getMessage()); - $result= NULL; - } - break; + $this->last_query = $query; + + switch($this->parent->cfg->db_access) { + case 'native': + if(($result = sqlite3_query($this->db, $query)) === false) + $this->ThrowError($this->getLastError()); + break; + case 'pdo': + try{ + $result = $this->db->query($query); + return $result; + } + catch (Exception $e) { + $this->ThrowError($e->getMessage()); + $result= NULL; + } + break; - } - - return $result; } - else - $this->ThrowError("Can't execute query - we are not connected!"); + + return $result; } // db_query() @@ -163,27 +161,30 @@ class PHPFSPOT_DB { */ public function db_exec($query = "") { - if($this->getConnStatus()) { - - $this->last_query = $query; - - switch($this->parent->cfg->db_access) { - case 'native': - if(($result = sqlite3_exec($this->db, $query)) === false) - $this->ThrowError($this->getLastError()); - break; - case 'pdo': - try { - $result = $this->db->query($query); - } - catch (Exception $e){ - $this->ThrowError($e->getLMessage()); - } - break; - } + if(!$this->getConnStatus()) + return false; + + $this->last_query = $query; + + switch($this->parent->cfg->db_access) { + case 'native': + if(($result = sqlite3_exec($this->db, $query)) === false) { + $this->ThrowError($this->getLastError()); + return false; + } + break; + case 'pdo': + try { + $result = $this->db->query($query); + } + catch (Exception $e){ + $this->ThrowError($e->getLMessage()); + return false; + } + break; } - else - $this->ThrowError("Can't execute query - we are not connected!"); + + return true; } // db_exec() @@ -206,21 +207,19 @@ class PHPFSPOT_DB { */ public function db_fetchSingleRow($query = "") { - if($this->getConnStatus()) { - - $result = $this->db_query($query); - switch($this->parent->cfg->db_access) { - case 'native': - $row = $this->db_fetch_object($result); - break; - case 'pdo': - $row = $result->fetch(); - break; - } - return $row; + if(!$this->getConnStatus()) + return false; + + $result = $this->db_query($query); + switch($this->parent->cfg->db_access) { + case 'native': + $row = $this->db_fetch_object($result); + break; + case 'pdo': + $row = $result->fetch(); + break; } - else - $this->ThrowError("Can't fetch row - we are not connected!"); + return $row; } // db_fetchSingleRow() @@ -253,31 +252,63 @@ class PHPFSPOT_DB { */ public function db_check_table_exists($table_name = "") { - if($this->getConnStatus()) { - - $result = $this->db_query("SELECT name FROM sqlite_master WHERE type='table'"); - switch($this->parent->cfg->db_access) { - case 'native': - while($table = $this->db_fetch_object($result)) { - if($table['name'] == $table_name) - return true; - } - break; - case 'pdo': - foreach($result as $table ){ - if($table['NAME'] == $table_name) - return true; - } - break; - } - + if(!$this->getConnStatus()) return false; - } - else - $this->ThrowError("Can't check table - we are not connected!"); + + $result = $this->db_query("SELECT name FROM sqlite_master WHERE type='table'"); + switch($this->parent->cfg->db_access) { + case 'native': + while($table = $this->db_fetch_object($result)) { + if($table['name'] == $table_name) + return true; + } + break; + case 'pdo': + foreach($result as $table ){ + if($table['NAME'] == $table_name) + return true; + } + break; + } + + return false; } // db_check_table_exists() + /** + * PHPFSPOT_DB check column exist + * + * This function checks if the given column exists within + * the specified table. + */ + public function db_check_column_exists($table_name, $column) + { + if(!$this->getConnStatus()) + return false; + + $result = $this->db_query(" + SELECT sql + FROM + (SELECT * FROM sqlite_master UNION ALL + SELECT * FROM sqlite_temp_master) + WHERE + tbl_name LIKE '". $table_name ."' + AND type!='meta' + AND sql NOT NULL + AND name NOT LIKE 'sqlite_%' + ORDER BY substr(type,2,1), name + "); + + while($row = $this->db_fetch_object($result)) { + /* CREATE TABLE xx ( col1 int, col2 bool, col3 ...) */ + if(strstr($row['sql'], " ". $column ." ") !== false) + return true; + } + + return false; + + } // db_check_column_exists() + /** * PHPFSPOT_DB get connection status * @@ -333,6 +364,74 @@ class PHPFSPOT_DB { } // getLastError() -} + /** + * start transaction + * + * this will start a transaction on ACID-supporting database + * systems. + * + * @return bool + */ + public function db_start_transaction() + { + if(!$this->getConnStatus()) + return false; + + $result = $this->db_exec("BEGIN"); + + /* Errors? */ + if(PEAR::isError($result)) + $this->throwError($result->getMessage() .' - '. $result->getUserInfo()); + + return true; + + } // db_start_transaction() + + /** + * commit transaction + * + * this will commit an ongoing transaction on ACID-supporting + * database systems + * + * @return bool + */ + public function db_commit_transaction() + { + if(!$this->getConnStatus()) + return false; + + $result = $this->db_exec("COMMIT"); + + /* Errors? */ + if(PEAR::isError($result)) + $this->throwError($result->getMessage() .' - '. $result->getUserInfo()); + + return true; + + } // db_commit_transaction() + + /** + * rollback transaction() + * + * this function aborts a on going transaction + * + * @return bool + */ + public function db_rollback_transaction() + { + if(!$this->getConnStatus()) + return false; + + $result = $this->db_exec("ROLLBACK"); + + /* Errors? */ + if(PEAR::isError($result)) + $this->throwError($result->getMessage() .' - '. $result->getUserInfo()); + + return true; + + } // db_rollback_transaction() + +} // PHPFSPOT_DB ?> diff --git a/phpfspot_img.php b/phpfspot_img.php index 3599b2b..5ef76b4 100644 --- a/phpfspot_img.php +++ b/phpfspot_img.php @@ -64,13 +64,17 @@ class PHPFSPOT_IMG { * @param integer $idx * @param integer $width */ - public function showImg($idx, $width = 0) + public function showImg($idx, $width = 0, $version = NULL) { if($idx == 'rand') $idx = $this->parent->get_random_photo(); - $details = $this->parent->get_photo_details($idx); - + /* display the lastest available version, if a wrong version has been requested */ + if(!isset($version) || !$this->parent->is_valid_version($idx, $version)) + $version = $this->parent->get_latest_version($idx); + + $details = $this->parent->get_photo_details($idx, $version); + if(!$details) { $this->parent->showTextImage("The image (". $idx .") you requested is unknown"); return; @@ -82,11 +86,15 @@ class PHPFSPOT_IMG { } /* show thumbnail */ else { - /* if no entry for this photo is yet in the database, create thumb */ + + /* check for an entry if we already handled this photo before. If not, + create a thumbnail for it. + */ if(!$this->parent->getMD5($idx)) { $this->parent->gen_thumb($idx); } - $fullpath = $this->parent->get_thumb_path($width, $idx); + /* get the full filesystem path to the thumbnail */ + $fullpath = $this->parent->get_thumb_path($width, $idx, $version); /* if the thumb file does not exist, create it */ if(!file_exists($fullpath)) { $this->parent->gen_thumb($idx); @@ -150,7 +158,10 @@ class PHPFSPOT_IMG { if(!$this->parent->getMD5($idx)) { $this->parent->gen_thumb($idx); } - $fullpath = $this->parent->get_thumb_path($width, $idx); + + $version = $this->parent­>get_latest_version($idx); + + $fullpath = $this->parent->get_thumb_path($width, $idx, $version); /* if the thumb file does not exist, create it */ if(!file_exists($fullpath)) { $this->parent->gen_thumb($idx); @@ -196,9 +207,16 @@ if(isset($_GET['idx']) && (is_numeric($_GET['idx']) || $_GET['idx'] == 'rand')) $img = new PHPFSPOT_IMG; if(isset($_GET['width']) && is_numeric($_GET['width'])) - $img->showImg($_GET['idx'], $_GET['width']); + $width = $_GET['width']; + else + $width = NULL; + + if(isset($_GET['version']) && is_numeric($_GET['version'])) + $version = $_GET['version']; else - $img->showImg($_GET['idx']); + $version = NULL; + + $img->showImg($_GET['idx'], $width, $version); exit(0); } @@ -212,5 +230,4 @@ if(isset($_GET['tagidx']) && is_numeric($_GET['tagidx'])) { } - ?> diff --git a/rpc.php b/rpc.php index ada2857..17af073 100644 --- a/rpc.php +++ b/rpc.php @@ -135,13 +135,20 @@ class PHPFSPOT_RPC { } break; + case 'update_photo_version': + if(isset($_POST['photo_version']) && is_numeric($_POST['photo_version']) && + isset($_POST['photo_idx']) && is_numeric($_POST['photo_idx'])) { + print $phpfspot->update_photo_version($_POST['photo_idx'], $_POST['photo_version']); + } + break; + case 'get_export': /* $_GET['mode'] will be validated by getExport() */ $phpfspot->getExport($_GET['mode']); break; case 'get_photo_to_show': - $phpfspot->getCurrentPhoto(); + print $phpfspot->get_current_photo(); break; case 'get_calendar_matrix': diff --git a/themes/default/templates/single_photo.tpl b/themes/default/templates/single_photo.tpl index e8e326d..572bef7 100644 --- a/themes/default/templates/single_photo.tpl +++ b/themes/default/templates/single_photo.tpl @@ -49,6 +49,14 @@ {/section}
{ /if } + { if $has_versions } +
+ Versions:
+ +
+ { /if } { if $tags }
available tags Tagged with:
-- 2.25.1